Ejemplo n.º 1
0
static void do_kick_all(grpc_exec_ctx *exec_ctx, void *arg,
                        grpc_error *error_unused) {
  grpc_error *error = GRPC_ERROR_NONE;
  grpc_pollset *pollset = arg;
  gpr_mu_lock(&pollset->pollable.po.mu);
  if (pollset->root_worker != NULL) {
    grpc_pollset_worker *worker = pollset->root_worker;
    do {
      if (worker->pollable != &pollset->pollable) {
        gpr_mu_lock(&worker->pollable->po.mu);
      }
      if (worker->initialized_cv) {
        worker->kicked = true;
        gpr_cv_signal(&worker->cv);
      } else {
        append_error(&error, grpc_wakeup_fd_wakeup(&worker->pollable->wakeup),
                     "pollset_shutdown");
      }
      if (worker->pollable != &pollset->pollable) {
        gpr_mu_unlock(&worker->pollable->po.mu);
      }

      worker = worker->links[PWL_POLLSET].next;
    } while (worker != pollset->root_worker);
  }
  pollset->kick_alls_pending--;
  pollset_maybe_finish_shutdown(exec_ctx, pollset);
  gpr_mu_unlock(&pollset->pollable.po.mu);
  GRPC_LOG_IF_ERROR("kick_all", error);
}
Ejemplo n.º 2
0
static void wakeup(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) {
  GPR_TIMER_MARK("workqueue.wakeup", 0);
  grpc_error *err = grpc_wakeup_fd_wakeup(&workqueue->wakeup_fd);
  if (!GRPC_LOG_IF_ERROR("wakeupfd_wakeup", err)) {
    drain(exec_ctx, workqueue);
  }
}
Ejemplo n.º 3
0
static void test_threading_wakeup(grpc_exec_ctx *exec_ctx, void *arg,
                                  grpc_error *error) {
  threading_shared *shared = arg;
  ++shared->wakeups;
  ++thread_wakeups;
  if (error == GRPC_ERROR_NONE) {
    GPR_ASSERT(GRPC_LOG_IF_ERROR(
        "consume_wakeup", grpc_wakeup_fd_consume_wakeup(shared->wakeup_fd)));
    grpc_fd_notify_on_read(exec_ctx, shared->wakeup_desc, &shared->on_wakeup);
    GPR_ASSERT(GRPC_LOG_IF_ERROR("wakeup_next",
                                 grpc_wakeup_fd_wakeup(shared->wakeup_fd)));
  }
}
Ejemplo n.º 4
0
void grpc_pollset_kick(grpc_pollset *p, grpc_pollset_worker *specific_worker) {
  /* pollset->mu already held */
  if (specific_worker != NULL) {
    if (specific_worker == GRPC_POLLSET_KICK_BROADCAST) {
      for (specific_worker = p->root_worker.next;
           specific_worker != &p->root_worker;
           specific_worker = specific_worker->next) {
        grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd);
      }
      p->kicked_without_pollers = 1;
    } else if (gpr_tls_get(&g_current_thread_worker) !=
               (gpr_intptr)specific_worker) {
      grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd);
    }
  } else if (gpr_tls_get(&g_current_thread_poller) != (gpr_intptr)p) {
    specific_worker = pop_front_worker(p);
    if (specific_worker != NULL) {
      push_back_worker(p, specific_worker);
      grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd);
    } else {
      p->kicked_without_pollers = 1;
    }
  }
}
Ejemplo n.º 5
0
static void test_threading(void) {
  threading_shared shared;
  shared.pollset = gpr_zalloc(grpc_pollset_size());
  grpc_pollset_init(shared.pollset, &shared.mu);

  gpr_thd_id thds[10];
  for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) {
    gpr_thd_options opt = gpr_thd_options_default();
    gpr_thd_options_set_joinable(&opt);
    gpr_thd_new(&thds[i], test_threading_loop, &shared, &opt);
  }
  grpc_wakeup_fd fd;
  GPR_ASSERT(GRPC_LOG_IF_ERROR("wakeup_fd_init", grpc_wakeup_fd_init(&fd)));
  shared.wakeup_fd = &fd;
  shared.wakeup_desc = grpc_fd_create(fd.read_fd, "wakeup");
  shared.wakeups = 0;
  {
    grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
    grpc_pollset_add_fd(&exec_ctx, shared.pollset, shared.wakeup_desc);
    grpc_fd_notify_on_read(
        &exec_ctx, shared.wakeup_desc,
        GRPC_CLOSURE_INIT(&shared.on_wakeup, test_threading_wakeup, &shared,
                          grpc_schedule_on_exec_ctx));
    grpc_exec_ctx_finish(&exec_ctx);
  }
  GPR_ASSERT(GRPC_LOG_IF_ERROR("wakeup_first",
                               grpc_wakeup_fd_wakeup(shared.wakeup_fd)));
  for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) {
    gpr_thd_join(thds[i]);
  }
  fd.read_fd = 0;
  grpc_wakeup_fd_destroy(&fd);
  {
    grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
    grpc_fd_shutdown(&exec_ctx, shared.wakeup_desc, GRPC_ERROR_CANCELLED);
    grpc_fd_orphan(&exec_ctx, shared.wakeup_desc, NULL, NULL,
                   false /* already_closed */, "done");
    grpc_pollset_shutdown(&exec_ctx, shared.pollset,
                          GRPC_CLOSURE_CREATE(destroy_pollset, shared.pollset,
                                              grpc_schedule_on_exec_ctx));
    grpc_exec_ctx_finish(&exec_ctx);
  }
  gpr_free(shared.pollset);
}
Ejemplo n.º 6
0
void grpc_kick_poller(void) {
    grpc_wakeup_fd_wakeup(&grpc_global_wakeup_fd);
}
Ejemplo n.º 7
0
void grpc_pollset_kick_ext(grpc_pollset *p,
                           grpc_pollset_worker *specific_worker,
                           uint32_t flags) {
    GPR_TIMER_BEGIN("grpc_pollset_kick_ext", 0);

    /* pollset->mu already held */
    if (specific_worker != NULL) {
        if (specific_worker == GRPC_POLLSET_KICK_BROADCAST) {
            GPR_TIMER_BEGIN("grpc_pollset_kick_ext.broadcast", 0);
            GPR_ASSERT((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) == 0);
            for (specific_worker = p->root_worker.next;
                    specific_worker != &p->root_worker;
                    specific_worker = specific_worker->next) {
                grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd);
            }
            p->kicked_without_pollers = 1;
            GPR_TIMER_END("grpc_pollset_kick_ext.broadcast", 0);
        } else if (gpr_tls_get(&g_current_thread_worker) !=
                   (intptr_t)specific_worker) {
            GPR_TIMER_MARK("different_thread_worker", 0);
            if ((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) != 0) {
                specific_worker->reevaluate_polling_on_wakeup = 1;
            }
            specific_worker->kicked_specifically = 1;
            grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd);
        } else if ((flags & GRPC_POLLSET_CAN_KICK_SELF) != 0) {
            GPR_TIMER_MARK("kick_yoself", 0);
            if ((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) != 0) {
                specific_worker->reevaluate_polling_on_wakeup = 1;
            }
            specific_worker->kicked_specifically = 1;
            grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd);
        }
    } else if (gpr_tls_get(&g_current_thread_poller) != (intptr_t)p) {
        GPR_ASSERT((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) == 0);
        GPR_TIMER_MARK("kick_anonymous", 0);
        specific_worker = pop_front_worker(p);
        if (specific_worker != NULL) {
            if (gpr_tls_get(&g_current_thread_worker) == (intptr_t)specific_worker) {
                GPR_TIMER_MARK("kick_anonymous_not_self", 0);
                push_back_worker(p, specific_worker);
                specific_worker = pop_front_worker(p);
                if ((flags & GRPC_POLLSET_CAN_KICK_SELF) == 0 &&
                        gpr_tls_get(&g_current_thread_worker) ==
                        (intptr_t)specific_worker) {
                    push_back_worker(p, specific_worker);
                    specific_worker = NULL;
                }
            }
            if (specific_worker != NULL) {
                GPR_TIMER_MARK("finally_kick", 0);
                push_back_worker(p, specific_worker);
                grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd);
            }
        } else {
            GPR_TIMER_MARK("kicked_no_pollers", 0);
            p->kicked_without_pollers = 1;
        }
    }

    GPR_TIMER_END("grpc_pollset_kick_ext", 0);
}
Ejemplo n.º 8
0
void test_poll_cv_trigger(void) {
  grpc_wakeup_fd cvfd1, cvfd2, cvfd3;
  struct pollfd pfds[6];
  poll_args pargs;
  gpr_thd_id t_id;
  gpr_thd_options opt;

  GPR_ASSERT(grpc_wakeup_fd_init(&cvfd1) == GRPC_ERROR_NONE);
  GPR_ASSERT(grpc_wakeup_fd_init(&cvfd2) == GRPC_ERROR_NONE);
  GPR_ASSERT(grpc_wakeup_fd_init(&cvfd3) == GRPC_ERROR_NONE);
  GPR_ASSERT(cvfd1.read_fd < 0);
  GPR_ASSERT(cvfd2.read_fd < 0);
  GPR_ASSERT(cvfd3.read_fd < 0);
  GPR_ASSERT(cvfd1.read_fd != cvfd2.read_fd);
  GPR_ASSERT(cvfd2.read_fd != cvfd3.read_fd);
  GPR_ASSERT(cvfd1.read_fd != cvfd3.read_fd);

  pfds[0].fd = cvfd1.read_fd;
  pfds[1].fd = cvfd2.read_fd;
  pfds[2].fd = 20;
  pfds[3].fd = 30;
  pfds[4].fd = cvfd3.read_fd;
  pfds[5].fd = 50;

  pfds[0].events = 0;
  pfds[1].events = POLLIN;
  pfds[2].events = POLLIN | POLLHUP;
  pfds[3].events = POLLIN | POLLHUP;
  pfds[4].events = POLLIN;
  pfds[5].events = POLLIN;

  pargs.fds = pfds;
  pargs.nfds = 6;
  pargs.timeout = 1000;
  pargs.result = -2;

  opt = gpr_thd_options_default();
  gpr_thd_options_set_joinable(&opt);
  gpr_thd_new(&t_id, &background_poll, &pargs, &opt);

  // Wakeup wakeup_fd not listening for events
  GPR_ASSERT(grpc_wakeup_fd_wakeup(&cvfd1) == GRPC_ERROR_NONE);
  gpr_thd_join(t_id);
  GPR_ASSERT(pargs.result == 0);
  GPR_ASSERT(pfds[0].revents == 0);
  GPR_ASSERT(pfds[1].revents == 0);
  GPR_ASSERT(pfds[2].revents == 0);
  GPR_ASSERT(pfds[3].revents == 0);
  GPR_ASSERT(pfds[4].revents == 0);
  GPR_ASSERT(pfds[5].revents == 0);

  // Pollin on socket fd
  pargs.timeout = -1;
  pargs.result = -2;
  gpr_thd_new(&t_id, &background_poll, &pargs, &opt);
  trigger_socket_event();
  gpr_thd_join(t_id);
  GPR_ASSERT(pargs.result == 1);
  GPR_ASSERT(pfds[0].revents == 0);
  GPR_ASSERT(pfds[1].revents == 0);
  GPR_ASSERT(pfds[2].revents == POLLIN);
  GPR_ASSERT(pfds[3].revents == 0);
  GPR_ASSERT(pfds[4].revents == 0);
  GPR_ASSERT(pfds[5].revents == 0);

  // Pollin on wakeup fd
  reset_socket_event();
  pargs.result = -2;
  gpr_thd_new(&t_id, &background_poll, &pargs, &opt);
  GPR_ASSERT(grpc_wakeup_fd_wakeup(&cvfd2) == GRPC_ERROR_NONE);
  gpr_thd_join(t_id);

  GPR_ASSERT(pargs.result == 1);
  GPR_ASSERT(pfds[0].revents == 0);
  GPR_ASSERT(pfds[1].revents == POLLIN);
  GPR_ASSERT(pfds[2].revents == 0);
  GPR_ASSERT(pfds[3].revents == 0);
  GPR_ASSERT(pfds[4].revents == 0);
  GPR_ASSERT(pfds[5].revents == 0);

  // Pollin on wakeupfd before poll()
  pargs.result = -2;
  gpr_thd_new(&t_id, &background_poll, &pargs, &opt);
  gpr_thd_join(t_id);

  GPR_ASSERT(pargs.result == 1);
  GPR_ASSERT(pfds[0].revents == 0);
  GPR_ASSERT(pfds[1].revents == POLLIN);
  GPR_ASSERT(pfds[2].revents == 0);
  GPR_ASSERT(pfds[3].revents == 0);
  GPR_ASSERT(pfds[4].revents == 0);
  GPR_ASSERT(pfds[5].revents == 0);

  // No Events
  pargs.result = -2;
  pargs.timeout = 1000;
  reset_socket_event();
  GPR_ASSERT(grpc_wakeup_fd_consume_wakeup(&cvfd1) == GRPC_ERROR_NONE);
  GPR_ASSERT(grpc_wakeup_fd_consume_wakeup(&cvfd2) == GRPC_ERROR_NONE);
  gpr_thd_new(&t_id, &background_poll, &pargs, &opt);
  gpr_thd_join(t_id);

  GPR_ASSERT(pargs.result == 0);
  GPR_ASSERT(pfds[0].revents == 0);
  GPR_ASSERT(pfds[1].revents == 0);
  GPR_ASSERT(pfds[2].revents == 0);
  GPR_ASSERT(pfds[3].revents == 0);
  GPR_ASSERT(pfds[4].revents == 0);
  GPR_ASSERT(pfds[5].revents == 0);
}
Ejemplo n.º 9
0
static void make_test_fds_readable(test_fd *tfds, const int num_fds) {
  for (int i = 0; i < num_fds; i++) {
    GPR_ASSERT(GRPC_ERROR_NONE == grpc_wakeup_fd_wakeup(&tfds[i].wakeup_fd));
  }
}
static void epoll_kick(grpc_pollset *pollset) {
  pollset_hdr *h = pollset->data.ptr;
  grpc_wakeup_fd_wakeup(&h->wakeup_fd);
}
Ejemplo n.º 11
0
static grpc_error *pollset_kick_inner(grpc_pollset *pollset, pollable *p,
                                      grpc_pollset_worker *specific_worker) {
  if (GRPC_TRACER_ON(grpc_polling_trace)) {
    gpr_log(GPR_DEBUG,
            "PS:%p kick %p tls_pollset=%p tls_worker=%p "
            "root_worker=(pollset:%p pollable:%p)",
            p, specific_worker, (void *)gpr_tls_get(&g_current_thread_pollset),
            (void *)gpr_tls_get(&g_current_thread_worker), pollset->root_worker,
            p->root_worker);
  }
  if (specific_worker == NULL) {
    if (gpr_tls_get(&g_current_thread_pollset) != (intptr_t)pollset) {
      if (pollset->root_worker == NULL) {
        if (GRPC_TRACER_ON(grpc_polling_trace)) {
          gpr_log(GPR_DEBUG, "PS:%p kicked_any_without_poller", p);
        }
        pollset->kicked_without_poller = true;
        return GRPC_ERROR_NONE;
      } else {
        if (GRPC_TRACER_ON(grpc_polling_trace)) {
          gpr_log(GPR_DEBUG, "PS:%p kicked_any_via_wakeup_fd", p);
        }
        grpc_error *err = pollable_materialize(p);
        if (err != GRPC_ERROR_NONE) return err;
        return grpc_wakeup_fd_wakeup(&p->wakeup);
      }
    } else {
      if (GRPC_TRACER_ON(grpc_polling_trace)) {
        gpr_log(GPR_DEBUG, "PS:%p kicked_any_but_awake", p);
      }
      return GRPC_ERROR_NONE;
    }
  } else if (specific_worker->kicked) {
    if (GRPC_TRACER_ON(grpc_polling_trace)) {
      gpr_log(GPR_DEBUG, "PS:%p kicked_specific_but_already_kicked", p);
    }
    return GRPC_ERROR_NONE;
  } else if (gpr_tls_get(&g_current_thread_worker) ==
             (intptr_t)specific_worker) {
    if (GRPC_TRACER_ON(grpc_polling_trace)) {
      gpr_log(GPR_DEBUG, "PS:%p kicked_specific_but_awake", p);
    }
    specific_worker->kicked = true;
    return GRPC_ERROR_NONE;
  } else if (specific_worker == p->root_worker) {
    if (GRPC_TRACER_ON(grpc_polling_trace)) {
      gpr_log(GPR_DEBUG, "PS:%p kicked_specific_via_wakeup_fd", p);
    }
    grpc_error *err = pollable_materialize(p);
    if (err != GRPC_ERROR_NONE) return err;
    specific_worker->kicked = true;
    return grpc_wakeup_fd_wakeup(&p->wakeup);
  } else {
    if (GRPC_TRACER_ON(grpc_polling_trace)) {
      gpr_log(GPR_DEBUG, "PS:%p kicked_specific_via_cv", p);
    }
    specific_worker->kicked = true;
    gpr_cv_signal(&specific_worker->cv);
    return GRPC_ERROR_NONE;
  }
}