Exemplo n.º 1
0
static void basic_pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
                                 grpc_fd *fd, int and_unlock_pollset) {
  grpc_unary_promote_args *up_args;
  GPR_ASSERT(fd);
  if (fd == pollset->data.ptr) goto exit;

  if (!grpc_pollset_has_workers(pollset)) {
    /* Fast path -- no in flight cbs */
    /* TODO(klempner): Comment this out and fix any test failures or establish
     * they are due to timing issues */
    grpc_fd *fds[2];
    fds[0] = pollset->data.ptr;
    fds[1] = fd;

    if (fds[0] == NULL) {
      pollset->data.ptr = fd;
      GRPC_FD_REF(fd, "basicpoll");
    } else if (!grpc_fd_is_orphaned(fds[0])) {
      grpc_platform_become_multipoller(exec_ctx, pollset, fds,
                                       GPR_ARRAY_SIZE(fds));
      GRPC_FD_UNREF(fds[0], "basicpoll");
    } else {
      /* old fd is orphaned and we haven't cleaned it up until now, so remain a
       * unary poller */
      GRPC_FD_UNREF(fds[0], "basicpoll");
      pollset->data.ptr = fd;
      GRPC_FD_REF(fd, "basicpoll");
    }
    goto exit;
  }

  /* Now we need to promote. This needs to happen when we're not polling. Since
   * this may be called from poll, the wait needs to happen asynchronously. */
  GRPC_FD_REF(fd, "basicpoll_add");
  pollset->in_flight_cbs++;
  up_args = gpr_malloc(sizeof(*up_args));
  up_args->fd = fd;
  up_args->original_vtable = pollset->vtable;
  up_args->pollset = pollset;
  up_args->promotion_closure.cb = basic_do_promote;
  up_args->promotion_closure.cb_arg = up_args;

  grpc_closure_list_add(&pollset->idle_jobs, &up_args->promotion_closure, 1);
  grpc_pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST);

exit:
  if (and_unlock_pollset) {
    gpr_mu_unlock(&pollset->mu);
  }
}
Exemplo n.º 2
0
void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
                           grpc_closure *closure) {
    GPR_ASSERT(!pollset->shutting_down);
    pollset->shutting_down = 1;
    pollset->shutdown_done = closure;
    grpc_pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST);
    if (!grpc_pollset_has_workers(pollset)) {
        grpc_exec_ctx_enqueue_list(exec_ctx, &pollset->idle_jobs, NULL);
    }
    if (!pollset->called_shutdown && pollset->in_flight_cbs == 0 &&
            !grpc_pollset_has_workers(pollset)) {
        pollset->called_shutdown = 1;
        finish_shutdown(exec_ctx, pollset);
    }
}
Exemplo n.º 3
0
static void on_finish(grpc_exec_ctx *exec_ctx, void *arg,
                      const grpc_httpcli_response *response) {
  const char *expect =
      "<html><head><title>Hello world!</title></head>"
      "<body><p>This is a test</p></body></html>";
  GPR_ASSERT(arg == (void *)42);
  GPR_ASSERT(response);
  GPR_ASSERT(response->status == 200);
  GPR_ASSERT(response->body_length == strlen(expect));
  GPR_ASSERT(0 == memcmp(expect, response->body, response->body_length));
  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
  g_done = 1;
  grpc_pollset_kick(&g_pollset, NULL);
  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
}
Exemplo n.º 4
0
static void on_finish(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
  const char *expect =
      "<html><head><title>Hello world!</title></head>"
      "<body><p>This is a test</p></body></html>";
  grpc_http_response *response = arg;
  GPR_ASSERT(response);
  GPR_ASSERT(response->status == 200);
  GPR_ASSERT(response->body_length == strlen(expect));
  GPR_ASSERT(0 == memcmp(expect, response->body, response->body_length));
  gpr_mu_lock(g_mu);
  g_done = 1;
  GPR_ASSERT(GRPC_LOG_IF_ERROR(
      "pollset_kick",
      grpc_pollset_kick(grpc_polling_entity_pollset(&g_pops), NULL)));
  gpr_mu_unlock(g_mu);
}
Exemplo n.º 5
0
static void on_read(grpc_exec_ctx *exec_ctx, grpc_fd *emfd,
                    grpc_server *server) {
  char read_buffer[512];
  ssize_t byte_count;

  gpr_mu_lock(g_mu);
  byte_count =
      recv(grpc_fd_wrapped_fd(emfd), read_buffer, sizeof(read_buffer), 0);

  g_number_of_reads++;
  g_number_of_bytes_read += (int)byte_count;

  GPR_ASSERT(
      GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(g_pollset, NULL)));
  gpr_mu_unlock(g_mu);
}
Exemplo n.º 6
0
static void on_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp,
                       grpc_pollset *pollset,
                       grpc_tcp_server_acceptor *acceptor) {
  grpc_endpoint_shutdown(exec_ctx, tcp);
  grpc_endpoint_destroy(exec_ctx, tcp);

  on_connect_result temp_result;
  on_connect_result_set(&temp_result, acceptor);
  gpr_free(acceptor);

  gpr_mu_lock(g_mu);
  g_result = temp_result;
  g_nconnects++;
  GPR_ASSERT(
      GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(g_pollset, NULL)));
  gpr_mu_unlock(g_mu);
}
Exemplo n.º 7
0
static void shutdown_during_write_test_write_handler(
    void *user_data, grpc_endpoint_cb_status error) {
    shutdown_during_write_test_state *st = user_data;
    gpr_log(GPR_INFO, "shutdown_during_write_test_write_handler: error = %d",
            error);
    if (error == 0) {
        /* This happens about 0.5% of the time when run under TSAN, and is entirely
           legitimate, but means we aren't testing the path we think we are. */
        /* TODO(klempner): Change this test to retry the write in that case */
        gpr_log(GPR_ERROR,
                "shutdown_during_write_test_write_handler completed unexpectedly");
    }
    gpr_mu_lock(GRPC_POLLSET_MU(g_pollset));
    st->done = 1;
    grpc_pollset_kick(g_pollset);
    gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset));
}
Exemplo n.º 8
0
static void read_and_write_test_read_handler(grpc_exec_ctx *exec_ctx,
                                             void *data, bool success) {
  struct read_and_write_test_state *state = data;

  state->bytes_read += count_slices(
      state->incoming.slices, state->incoming.count, &state->current_read_data);
  if (state->bytes_read == state->target_bytes || !success) {
    gpr_log(GPR_INFO, "Read handler done");
    gpr_mu_lock(GRPC_POLLSET_MU(g_pollset));
    state->read_done = 1 + success;
    grpc_pollset_kick(g_pollset, NULL);
    gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset));
  } else if (success) {
    grpc_endpoint_read(exec_ctx, state->read_ep, &state->incoming,
                       &state->done_read);
  }
}
Exemplo n.º 9
0
static void read_and_write_test_read_handler(grpc_exec_ctx *exec_ctx,
                                             void *data, grpc_error *error) {
  struct read_and_write_test_state *state = data;

  state->bytes_read += count_slices(
      state->incoming.slices, state->incoming.count, &state->current_read_data);
  if (state->bytes_read == state->target_bytes || error != GRPC_ERROR_NONE) {
    gpr_log(GPR_INFO, "Read handler done");
    gpr_mu_lock(g_mu);
    state->read_done = 1 + (error == GRPC_ERROR_NONE);
    GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(g_pollset, NULL));
    gpr_mu_unlock(g_mu);
  } else if (error == GRPC_ERROR_NONE) {
    grpc_endpoint_read(exec_ctx, state->read_ep, &state->incoming,
                       &state->done_read);
  }
}
Exemplo n.º 10
0
static void got_port_from_server(grpc_exec_ctx *exec_ctx, void *arg,
                                 const grpc_httpcli_response *response) {
  size_t i;
  int port = 0;
  portreq *pr = arg;
  int failed = 0;

  if (!response) {
    failed = 1;
    gpr_log(GPR_DEBUG,
            "failed port pick from server: retrying [response=NULL]");
  } else if (response->status != 200) {
    failed = 1;
    gpr_log(GPR_DEBUG, "failed port pick from server: status=%d",
            response->status);
  }

  if (failed) {
    grpc_httpcli_request req;
    memset(&req, 0, sizeof(req));
    GPR_ASSERT(pr->retries < 10);
    gpr_sleep_until(gpr_time_add(
        gpr_now(GPR_CLOCK_REALTIME),
        gpr_time_from_millis(
            (int64_t)(1000.0 * (1 + pow(1.3, pr->retries) * rand() / RAND_MAX)),
            GPR_TIMESPAN)));
    pr->retries++;
    req.host = pr->server;
    req.http.path = "/get";
    grpc_httpcli_get(exec_ctx, pr->ctx, &pr->pops, &req,
                     GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10), got_port_from_server,
                     pr);
    return;
  }
  GPR_ASSERT(response);
  GPR_ASSERT(response->status == 200);
  for (i = 0; i < response->body_length; i++) {
    GPR_ASSERT(response->body[i] >= '0' && response->body[i] <= '9');
    port = port * 10 + response->body[i] - '0';
  }
  GPR_ASSERT(port > 1024);
  gpr_mu_lock(pr->mu);
  pr->port = port;
  grpc_pollset_kick(grpc_polling_entity_pollset(&pr->pops), NULL);
  gpr_mu_unlock(pr->mu);
}
Exemplo n.º 11
0
static void on_metadata_response(grpc_exec_ctx *exec_ctx, void *user_data,
                                 grpc_credentials_md *md_elems, size_t num_md,
                                 grpc_credentials_status status) {
  synchronizer *sync = user_data;
  if (status == GRPC_CREDENTIALS_ERROR) {
    fprintf(stderr, "Fetching token failed.\n");
  } else {
    char *token;
    GPR_ASSERT(num_md == 1);
    token = gpr_dump_slice(md_elems[0].value, GPR_DUMP_ASCII);
    printf("\nGot token: %s\n\n", token);
    gpr_free(token);
  }
  gpr_mu_lock(GRPC_POLLSET_MU(&sync->pollset));
  sync->is_done = 1;
  grpc_pollset_kick(&sync->pollset, NULL);
  gpr_mu_unlock(GRPC_POLLSET_MU(&sync->pollset));
}
Exemplo n.º 12
0
static void read_and_write_test_write_handler(void *data, int success) {
  struct read_and_write_test_state *state = data;
  gpr_slice *slices = NULL;
  size_t nslices;
  grpc_endpoint_op_status write_status;

  if (success) {
    for (;;) {
      /* Need to do inline writes until they don't succeed synchronously or we
         finish writing */
      state->bytes_written += state->current_write_size;
      if (state->target_bytes - state->bytes_written <
          state->current_write_size) {
        state->current_write_size = state->target_bytes - state->bytes_written;
      }
      if (state->current_write_size == 0) {
        break;
      }

      slices = allocate_blocks(state->current_write_size, 8192, &nslices,
                               &state->current_write_data);
      gpr_slice_buffer_reset_and_unref(&state->outgoing);
      gpr_slice_buffer_addn(&state->outgoing, slices, nslices);
      write_status = grpc_endpoint_write(state->write_ep, &state->outgoing,
                                         &state->done_write);
      free(slices);
      if (write_status == GRPC_ENDPOINT_PENDING) {
        return;
      } else if (write_status == GRPC_ENDPOINT_ERROR) {
        goto cleanup;
      }
    }
    GPR_ASSERT(state->bytes_written == state->target_bytes);
  }

cleanup:
  gpr_log(GPR_INFO, "Write handler done");
  gpr_mu_lock(GRPC_POLLSET_MU(g_pollset));
  state->write_done = 1 + success;
  grpc_pollset_kick(g_pollset, NULL);
  gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset));
}
Exemplo n.º 13
0
/* Queue a GRPC_OP_COMPLETED operation */
void grpc_cq_end_op(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cc,
                    void *tag, int success,
                    void (*done)(grpc_exec_ctx *exec_ctx, void *done_arg,
                                 grpc_cq_completion *storage),
                    void *done_arg, grpc_cq_completion *storage) {
  int shutdown;
  int i;
  grpc_pollset_worker *pluck_worker;

  storage->tag = tag;
  storage->done = done;
  storage->done_arg = done_arg;
  storage->next =
      ((gpr_uintptr)&cc->completed_head) | ((gpr_uintptr)(success != 0));

  gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
  shutdown = gpr_unref(&cc->pending_events);
  if (!shutdown) {
    cc->completed_tail->next =
        ((gpr_uintptr)storage) | (1u & (gpr_uintptr)cc->completed_tail->next);
    cc->completed_tail = storage;
    pluck_worker = NULL;
    for (i = 0; i < cc->num_pluckers; i++) {
      if (cc->pluckers[i].tag == tag) {
        pluck_worker = cc->pluckers[i].worker;
        break;
      }
    }
    grpc_pollset_kick(&cc->pollset, pluck_worker);
    gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
  } else {
    cc->completed_tail->next =
        ((gpr_uintptr)storage) | (1u & (gpr_uintptr)cc->completed_tail->next);
    cc->completed_tail = storage;
    GPR_ASSERT(!cc->shutdown);
    GPR_ASSERT(cc->shutdown_called);
    cc->shutdown = 1;
    gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
    grpc_pollset_shutdown(exec_ctx, &cc->pollset, &cc->pollset_destroy_done);
  }
}
Exemplo n.º 14
0
void grpc_pollset_shutdown(grpc_pollset *pollset,
                           void (*shutdown_done)(void *arg),
                           void *shutdown_done_arg) {
  int call_shutdown = 0;
  gpr_mu_lock(&pollset->mu);
  GPR_ASSERT(!pollset->shutting_down);
  pollset->shutting_down = 1;
  if (!pollset->called_shutdown && pollset->in_flight_cbs == 0 &&
      !grpc_pollset_has_workers(pollset)) {
    pollset->called_shutdown = 1;
    call_shutdown = 1;
  }
  pollset->shutdown_done_cb = shutdown_done;
  pollset->shutdown_done_arg = shutdown_done_arg;
  grpc_pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST);
  gpr_mu_unlock(&pollset->mu);

  if (call_shutdown) {
    finish_shutdown(pollset);
  }
}
Exemplo n.º 15
0
static void on_oauth2_response(void *user_data, grpc_credentials_md *md_elems,
                               size_t num_md, grpc_credentials_status status) {
  oauth2_request *request = user_data;
  char *token = NULL;
  gpr_slice token_slice;
  if (status == GRPC_CREDENTIALS_ERROR) {
    gpr_log(GPR_ERROR, "Fetching token failed.");
  } else {
    GPR_ASSERT(num_md == 1);
    token_slice = md_elems[0].value;
    token = gpr_malloc(GPR_SLICE_LENGTH(token_slice) + 1);
    memcpy(token, GPR_SLICE_START_PTR(token_slice),
           GPR_SLICE_LENGTH(token_slice));
    token[GPR_SLICE_LENGTH(token_slice)] = '\0';
  }
  gpr_mu_lock(GRPC_POLLSET_MU(&request->pollset));
  request->is_done = 1;
  request->token = token;
  grpc_pollset_kick(&request->pollset);
  gpr_mu_unlock(GRPC_POLLSET_MU(&request->pollset));
}
Exemplo n.º 16
0
static void shutdown_during_write_test_read_handler(
    void *user_data, gpr_slice *slices, size_t nslices,
    grpc_endpoint_cb_status error) {
    size_t i;
    shutdown_during_write_test_state *st = user_data;

    for (i = 0; i < nslices; i++) {
        gpr_slice_unref(slices[i]);
    }

    if (error != GRPC_ENDPOINT_CB_OK) {
        grpc_endpoint_destroy(st->ep);
        gpr_mu_lock(GRPC_POLLSET_MU(g_pollset));
        st->done = error;
        grpc_pollset_kick(g_pollset);
        gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset));
    } else {
        grpc_endpoint_notify_on_read(
            st->ep, shutdown_during_write_test_read_handler, user_data);
    }
}
Exemplo n.º 17
0
void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
                           grpc_closure *closure) {
  int call_shutdown = 0;
  gpr_mu_lock(&pollset->mu);
  GPR_ASSERT(!pollset->shutting_down);
  pollset->shutting_down = 1;
  if (!pollset->called_shutdown && pollset->in_flight_cbs == 0 &&
      !grpc_pollset_has_workers(pollset)) {
    pollset->called_shutdown = 1;
    call_shutdown = 1;
  }
  if (!grpc_pollset_has_workers(pollset)) {
    grpc_exec_ctx_enqueue_list(exec_ctx, &pollset->idle_jobs);
  }
  pollset->shutdown_done = closure;
  grpc_pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST);
  gpr_mu_unlock(&pollset->mu);

  if (call_shutdown) {
    finish_shutdown(exec_ctx, pollset);
  }
}
Exemplo n.º 18
0
static void on_compute_engine_detection_http_response(
    grpc_exec_ctx *exec_ctx, void *user_data,
    const grpc_httpcli_response *response) {
  compute_engine_detector *detector = (compute_engine_detector *)user_data;
  if (response != NULL && response->status == 200 && response->hdr_count > 0) {
    /* Internet providers can return a generic response to all requests, so
       it is necessary to check that metadata header is present also. */
    size_t i;
    for (i = 0; i < response->hdr_count; i++) {
      grpc_httpcli_header *header = &response->hdrs[i];
      if (strcmp(header->key, "Metadata-Flavor") == 0 &&
          strcmp(header->value, "Google") == 0) {
        detector->success = 1;
        break;
      }
    }
  }
  gpr_mu_lock(GRPC_POLLSET_MU(&detector->pollset));
  detector->is_done = 1;
  grpc_pollset_kick(&detector->pollset, NULL);
  gpr_mu_unlock(GRPC_POLLSET_MU(&detector->pollset));
}
Exemplo n.º 19
0
void grpc_pollset_kick(grpc_pollset *p, grpc_pollset_worker *specific_worker) {
  if (specific_worker != NULL) {
    if (specific_worker == GRPC_POLLSET_KICK_BROADCAST) {
      for (specific_worker =
               p->root_worker.links[GRPC_POLLSET_WORKER_LINK_POLLSET].next;
           specific_worker != &p->root_worker;
           specific_worker =
               specific_worker->links[GRPC_POLLSET_WORKER_LINK_POLLSET].next) {
        specific_worker->kicked = 1;
        gpr_cv_signal(&specific_worker->cv);
      }
      p->kicked_without_pollers = 1;
      if (p->is_iocp_worker) {
        grpc_iocp_kick();
      }
    } else {
      if (p->is_iocp_worker) {
        if (g_active_poller == specific_worker) {
          grpc_iocp_kick();
        }
      } else {
        specific_worker->kicked = 1;
        gpr_cv_signal(&specific_worker->cv);
      }
    }
  } else {
    specific_worker =
        pop_front_worker(&p->root_worker, GRPC_POLLSET_WORKER_LINK_POLLSET);
    if (specific_worker != NULL) {
      grpc_pollset_kick(p, specific_worker);
    } else if (p->is_iocp_worker) {
      grpc_iocp_kick();
    } else {
      p->kicked_without_pollers = 1;
    }
  }
}
Exemplo n.º 20
0
static void finish_connection() {
  gpr_mu_lock(g_mu);
  g_connections_complete++;
  grpc_pollset_kick(g_pollset, NULL);
  gpr_mu_unlock(g_mu);
}
Exemplo n.º 21
0
void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
                       grpc_pollset_worker **worker_hdl, gpr_timespec now,
                       gpr_timespec deadline) {
    grpc_pollset_worker worker;
    *worker_hdl = &worker;

    /* pollset->mu already held */
    int added_worker = 0;
    int locked = 1;
    int queued_work = 0;
    int keep_polling = 0;
    GPR_TIMER_BEGIN("grpc_pollset_work", 0);
    /* this must happen before we (potentially) drop pollset->mu */
    worker.next = worker.prev = NULL;
    worker.reevaluate_polling_on_wakeup = 0;
    if (pollset->local_wakeup_cache != NULL) {
        worker.wakeup_fd = pollset->local_wakeup_cache;
        pollset->local_wakeup_cache = worker.wakeup_fd->next;
    } else {
        worker.wakeup_fd = gpr_malloc(sizeof(*worker.wakeup_fd));
        grpc_wakeup_fd_init(&worker.wakeup_fd->fd);
    }
    worker.kicked_specifically = 0;
    /* If there's work waiting for the pollset to be idle, and the
       pollset is idle, then do that work */
    if (!grpc_pollset_has_workers(pollset) &&
            !grpc_closure_list_empty(pollset->idle_jobs)) {
        GPR_TIMER_MARK("grpc_pollset_work.idle_jobs", 0);
        grpc_exec_ctx_enqueue_list(exec_ctx, &pollset->idle_jobs, NULL);
        goto done;
    }
    /* If we're shutting down then we don't execute any extended work */
    if (pollset->shutting_down) {
        GPR_TIMER_MARK("grpc_pollset_work.shutting_down", 0);
        goto done;
    }
    /* Give do_promote priority so we don't starve it out */
    if (pollset->in_flight_cbs) {
        GPR_TIMER_MARK("grpc_pollset_work.in_flight_cbs", 0);
        gpr_mu_unlock(&pollset->mu);
        locked = 0;
        goto done;
    }
    /* Start polling, and keep doing so while we're being asked to
       re-evaluate our pollers (this allows poll() based pollers to
       ensure they don't miss wakeups) */
    keep_polling = 1;
    while (keep_polling) {
        keep_polling = 0;
        if (!pollset->kicked_without_pollers) {
            if (!added_worker) {
                push_front_worker(pollset, &worker);
                added_worker = 1;
                gpr_tls_set(&g_current_thread_worker, (intptr_t)&worker);
            }
            gpr_tls_set(&g_current_thread_poller, (intptr_t)pollset);
            GPR_TIMER_BEGIN("maybe_work_and_unlock", 0);
            pollset->vtable->maybe_work_and_unlock(exec_ctx, pollset, &worker,
                                                   deadline, now);
            GPR_TIMER_END("maybe_work_and_unlock", 0);
            locked = 0;
            gpr_tls_set(&g_current_thread_poller, 0);
        } else {
            GPR_TIMER_MARK("grpc_pollset_work.kicked_without_pollers", 0);
            pollset->kicked_without_pollers = 0;
        }
        /* Finished execution - start cleaning up.
           Note that we may arrive here from outside the enclosing while() loop.
           In that case we won't loop though as we haven't added worker to the
           worker list, which means nobody could ask us to re-evaluate polling). */
done:
        if (!locked) {
            queued_work |= grpc_exec_ctx_flush(exec_ctx);
            gpr_mu_lock(&pollset->mu);
            locked = 1;
        }
        /* If we're forced to re-evaluate polling (via grpc_pollset_kick with
           GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) then we land here and force
           a loop */
        if (worker.reevaluate_polling_on_wakeup) {
            worker.reevaluate_polling_on_wakeup = 0;
            pollset->kicked_without_pollers = 0;
            if (queued_work || worker.kicked_specifically) {
                /* If there's queued work on the list, then set the deadline to be
                   immediate so we get back out of the polling loop quickly */
                deadline = gpr_inf_past(GPR_CLOCK_MONOTONIC);
            }
            keep_polling = 1;
        }
    }
    if (added_worker) {
        remove_worker(pollset, &worker);
        gpr_tls_set(&g_current_thread_worker, 0);
    }
    /* release wakeup fd to the local pool */
    worker.wakeup_fd->next = pollset->local_wakeup_cache;
    pollset->local_wakeup_cache = worker.wakeup_fd;
    /* check shutdown conditions */
    if (pollset->shutting_down) {
        if (grpc_pollset_has_workers(pollset)) {
            grpc_pollset_kick(pollset, NULL);
        } else if (!pollset->called_shutdown && pollset->in_flight_cbs == 0) {
            pollset->called_shutdown = 1;
            gpr_mu_unlock(&pollset->mu);
            finish_shutdown(exec_ctx, pollset);
            grpc_exec_ctx_flush(exec_ctx);
            /* Continuing to access pollset here is safe -- it is the caller's
             * responsibility to not destroy when it has outstanding calls to
             * grpc_pollset_work.
             * TODO(dklempner): Can we refactor the shutdown logic to avoid this? */
            gpr_mu_lock(&pollset->mu);
        } else if (!grpc_closure_list_empty(pollset->idle_jobs)) {
            grpc_exec_ctx_enqueue_list(exec_ctx, &pollset->idle_jobs, NULL);
            gpr_mu_unlock(&pollset->mu);
            grpc_exec_ctx_flush(exec_ctx);
            gpr_mu_lock(&pollset->mu);
        }
    }
    *worker_hdl = NULL;
    GPR_TIMER_END("grpc_pollset_work", 0);
}
Exemplo n.º 22
0
static void finish_connection() {
  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
  g_connections_complete++;
  grpc_pollset_kick(&g_pollset, NULL);
  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
}
Exemplo n.º 23
0
void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
                       grpc_pollset_worker *worker, gpr_timespec now,
                       gpr_timespec deadline) {
  /* pollset->mu already held */
  int added_worker = 0;
  int locked = 1;
  /* this must happen before we (potentially) drop pollset->mu */
  worker->next = worker->prev = NULL;
  /* TODO(ctiller): pool these */
  grpc_wakeup_fd_init(&worker->wakeup_fd);
  if (!grpc_pollset_has_workers(pollset) &&
      !grpc_closure_list_empty(pollset->idle_jobs)) {
    grpc_exec_ctx_enqueue_list(exec_ctx, &pollset->idle_jobs);
    goto done;
  }
  if (grpc_alarm_check(exec_ctx, now, &deadline)) {
    gpr_mu_unlock(&pollset->mu);
    locked = 0;
    goto done;
  }
  if (pollset->shutting_down) {
    goto done;
  }
  if (pollset->in_flight_cbs) {
    /* Give do_promote priority so we don't starve it out */
    gpr_mu_unlock(&pollset->mu);
    locked = 0;
    goto done;
  }
  if (!pollset->kicked_without_pollers) {
    push_front_worker(pollset, worker);
    added_worker = 1;
    gpr_tls_set(&g_current_thread_poller, (gpr_intptr)pollset);
    gpr_tls_set(&g_current_thread_worker, (gpr_intptr)worker);
    pollset->vtable->maybe_work_and_unlock(exec_ctx, pollset, worker, deadline,
                                           now);
    locked = 0;
    gpr_tls_set(&g_current_thread_poller, 0);
    gpr_tls_set(&g_current_thread_worker, 0);
  } else {
    pollset->kicked_without_pollers = 0;
  }
done:
  if (!locked) {
    grpc_exec_ctx_flush(exec_ctx);
    gpr_mu_lock(&pollset->mu);
    locked = 1;
  }
  grpc_wakeup_fd_destroy(&worker->wakeup_fd);
  if (added_worker) {
    remove_worker(pollset, worker);
  }
  if (pollset->shutting_down) {
    if (grpc_pollset_has_workers(pollset)) {
      grpc_pollset_kick(pollset, NULL);
    } else if (!pollset->called_shutdown && pollset->in_flight_cbs == 0) {
      pollset->called_shutdown = 1;
      gpr_mu_unlock(&pollset->mu);
      finish_shutdown(exec_ctx, pollset);
      grpc_exec_ctx_flush(exec_ctx);
      /* Continuing to access pollset here is safe -- it is the caller's
       * responsibility to not destroy when it has outstanding calls to
       * grpc_pollset_work.
       * TODO(dklempner): Can we refactor the shutdown logic to avoid this? */
      gpr_mu_lock(&pollset->mu);
    } else if (!grpc_closure_list_empty(pollset->idle_jobs)) {
      gpr_mu_unlock(&pollset->mu);
      grpc_exec_ctx_enqueue_list(exec_ctx, &pollset->idle_jobs);
      grpc_exec_ctx_flush(exec_ctx);
      gpr_mu_lock(&pollset->mu);
    }
  }
}
Exemplo n.º 24
0
static void pollset_kick_locked(grpc_pollset *pollset) {
    gpr_mu_lock(GRPC_POLLSET_MU(pollset));
    grpc_pollset_kick(pollset, NULL);
    gpr_mu_unlock(GRPC_POLLSET_MU(pollset));
}
Exemplo n.º 25
0
void on_fd_released(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *errors) {
  int *done = arg;
  *done = 1;
  GPR_ASSERT(
      GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(g_pollset, NULL)));
}
Exemplo n.º 26
0
static void test_code(void) {
  /* iomgr.h */
  grpc_iomgr_init();
  grpc_iomgr_shutdown();

  /* closure.h */
  grpc_closure closure;
  closure.cb = NULL;
  closure.cb_arg = NULL;
  closure.final_data = 0;

  grpc_closure_list closure_list = GRPC_CLOSURE_LIST_INIT;
  closure_list.head = NULL;
  closure_list.tail = NULL;

  grpc_closure_init(&closure, NULL, NULL);

  grpc_closure_create(NULL, NULL);

  grpc_closure_list_move(NULL, NULL);
  grpc_closure_list_add(NULL, NULL, true);
  bool x = grpc_closure_list_empty(closure_list);
  grpc_closure_next(&closure);

  /* exec_ctx.h */
  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  grpc_exec_ctx_flush(&exec_ctx);
  grpc_exec_ctx_finish(&exec_ctx);
  grpc_exec_ctx_enqueue(&exec_ctx, &closure, x, NULL);
  grpc_exec_ctx_enqueue_list(&exec_ctx, &closure_list, NULL);

  /* endpoint.h */
  grpc_endpoint endpoint;
  grpc_endpoint_vtable vtable = {
      grpc_endpoint_read,           grpc_endpoint_write,
      grpc_endpoint_add_to_pollset, grpc_endpoint_add_to_pollset_set,
      grpc_endpoint_shutdown,       grpc_endpoint_destroy,
      grpc_endpoint_get_peer};
  endpoint.vtable = &vtable;

  grpc_endpoint_read(&exec_ctx, &endpoint, NULL, NULL);
  grpc_endpoint_get_peer(&endpoint);
  grpc_endpoint_write(&exec_ctx, &endpoint, NULL, NULL);
  grpc_endpoint_shutdown(&exec_ctx, &endpoint);
  grpc_endpoint_destroy(&exec_ctx, &endpoint);
  grpc_endpoint_add_to_pollset(&exec_ctx, &endpoint, NULL);
  grpc_endpoint_add_to_pollset_set(&exec_ctx, &endpoint, NULL);

  /* executor.h */
  grpc_executor_init();
  grpc_executor_enqueue(&closure, x);
  grpc_executor_shutdown();

  /* pollset.h */
  grpc_pollset_size();
  grpc_pollset_init(NULL, NULL);
  grpc_pollset_shutdown(NULL, NULL, NULL);
  grpc_pollset_reset(NULL);
  grpc_pollset_destroy(NULL);
  grpc_pollset_work(NULL, NULL, NULL, gpr_now(GPR_CLOCK_REALTIME),
                    gpr_now(GPR_CLOCK_MONOTONIC));
  grpc_pollset_kick(NULL, NULL);
}
Exemplo n.º 27
0
void on_fd_released(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
  int *done = arg;
  *done = 1;
  grpc_pollset_kick(&g_pollset, NULL);
}
Exemplo n.º 28
0
Arquivo: iomgr.c Projeto: gnirodi/grpc
static void test_code(void) {
  /* iomgr.h */
  grpc_iomgr_init();
  grpc_iomgr_shutdown();

  /* closure.h */
  grpc_closure closure;
  closure.cb = NULL;
  closure.cb_arg = NULL;
  closure.next_data.scratch = 0;

  grpc_closure_list closure_list = GRPC_CLOSURE_LIST_INIT;
  closure_list.head = NULL;
  closure_list.tail = NULL;

  grpc_closure_init(&closure, NULL, NULL);

  grpc_closure_create(NULL, NULL);

  grpc_closure_list_move(NULL, NULL);
  grpc_closure_list_append(NULL, NULL, GRPC_ERROR_CREATE("Foo"));
  grpc_closure_list_empty(closure_list);

  /* exec_ctx.h */
  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  grpc_exec_ctx_flush(&exec_ctx);
  grpc_exec_ctx_finish(&exec_ctx);
  grpc_exec_ctx_sched(&exec_ctx, &closure, GRPC_ERROR_CREATE("Foo"), NULL);
  grpc_exec_ctx_enqueue_list(&exec_ctx, &closure_list, NULL);

  /* endpoint.h */
  grpc_endpoint endpoint;
  grpc_endpoint_vtable vtable = {grpc_endpoint_read,
                                 grpc_endpoint_write,
                                 grpc_endpoint_get_workqueue,
                                 grpc_endpoint_add_to_pollset,
                                 grpc_endpoint_add_to_pollset_set,
                                 grpc_endpoint_shutdown,
                                 grpc_endpoint_destroy,
                                 grpc_endpoint_get_resource_user,
                                 grpc_endpoint_get_peer};
  endpoint.vtable = &vtable;

  grpc_endpoint_read(&exec_ctx, &endpoint, NULL, NULL);
  grpc_endpoint_get_peer(&endpoint);
  grpc_endpoint_write(&exec_ctx, &endpoint, NULL, NULL);
  grpc_endpoint_shutdown(&exec_ctx, &endpoint);
  grpc_endpoint_destroy(&exec_ctx, &endpoint);
  grpc_endpoint_add_to_pollset(&exec_ctx, &endpoint, NULL);
  grpc_endpoint_add_to_pollset_set(&exec_ctx, &endpoint, NULL);

  /* executor.h */
  grpc_executor_init();
  grpc_executor_push(&closure, GRPC_ERROR_CREATE("Phi"));
  grpc_executor_shutdown();

  /* pollset.h */
  grpc_pollset_size();
  grpc_pollset_init(NULL, NULL);
  grpc_pollset_shutdown(NULL, NULL, NULL);
  grpc_pollset_reset(NULL);
  grpc_pollset_destroy(NULL);
  GRPC_ERROR_UNREF(grpc_pollset_work(NULL, NULL, NULL,
                                     gpr_now(GPR_CLOCK_REALTIME),
                                     gpr_now(GPR_CLOCK_MONOTONIC)));
  GRPC_ERROR_UNREF(grpc_pollset_kick(NULL, NULL));
}
Exemplo n.º 29
0
static void basic_do_promote(void *args, int success) {
  grpc_unary_promote_args *up_args = args;
  const grpc_pollset_vtable *original_vtable = up_args->original_vtable;
  grpc_pollset *pollset = up_args->pollset;
  grpc_fd *fd = up_args->fd;
  int do_shutdown_cb = 0;

  /*
   * This is quite tricky. There are a number of cases to keep in mind here:
   * 1. fd may have been orphaned
   * 2. The pollset may no longer be a unary poller (and we can't let case #1
   * leak to other pollset types!)
   * 3. pollset's fd (which may have changed) may have been orphaned
   * 4. The pollset may be shutting down.
   */

  gpr_mu_lock(&pollset->mu);
  /* First we need to ensure that nobody is polling concurrently */
  if (grpc_pollset_has_workers(pollset)) {
    grpc_pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST);
    grpc_iomgr_add_callback(&up_args->promotion_closure);
    gpr_mu_unlock(&pollset->mu);
    return;
  }

  gpr_free(up_args);
  /* At this point the pollset may no longer be a unary poller. In that case
   * we should just call the right add function and be done. */
  /* TODO(klempner): If we're not careful this could cause infinite recursion.
   * That's not a problem for now because empty_pollset has a trivial poller
   * and we don't have any mechanism to unbecome multipoller. */
  pollset->in_flight_cbs--;
  if (pollset->shutting_down) {
    /* We don't care about this pollset anymore. */
    if (pollset->in_flight_cbs == 0 && !pollset->called_shutdown) {
      GPR_ASSERT(!grpc_pollset_has_workers(pollset));
      pollset->called_shutdown = 1;
      do_shutdown_cb = 1;
    }
  } else if (grpc_fd_is_orphaned(fd)) {
    /* Don't try to add it to anything, we'll drop our ref on it below */
  } else if (pollset->vtable != original_vtable) {
    pollset->vtable->add_fd(pollset, fd, 0);
  } else if (fd != pollset->data.ptr) {
    grpc_fd *fds[2];
    fds[0] = pollset->data.ptr;
    fds[1] = fd;

    if (fds[0] && !grpc_fd_is_orphaned(fds[0])) {
      grpc_platform_become_multipoller(pollset, fds, GPR_ARRAY_SIZE(fds));
      GRPC_FD_UNREF(fds[0], "basicpoll");
    } else {
      /* old fd is orphaned and we haven't cleaned it up until now, so remain a
       * unary poller */
      /* Note that it is possible that fds[1] is also orphaned at this point.
       * That's okay, we'll correct it at the next add or poll. */
      if (fds[0]) GRPC_FD_UNREF(fds[0], "basicpoll");
      pollset->data.ptr = fd;
      GRPC_FD_REF(fd, "basicpoll");
    }
  }

  gpr_mu_unlock(&pollset->mu);

  if (do_shutdown_cb) {
    pollset->shutdown_done_cb(pollset->shutdown_done_arg);
  }

  /* Matching ref in basic_pollset_add_fd */
  GRPC_FD_UNREF(fd, "basicpoll_add");
}