diff --git a/src/core/lib/iomgr/ev_epoll1_linux.c b/src/core/lib/iomgr/ev_epoll1_linux.c index dfe2d143a50..f579b16fa58 100644 --- a/src/core/lib/iomgr/ev_epoll1_linux.c +++ b/src/core/lib/iomgr/ev_epoll1_linux.c @@ -120,10 +120,15 @@ struct grpc_pollset { bool reassigning_neighbourhood; grpc_pollset_worker *root_worker; bool kicked_without_poller; + + /* Set to true if the pollset is observed to have no workers available to + * poll */ bool seen_inactive; - bool shutting_down; /* Is the pollset shutting down ? */ - bool finish_shutdown_called; /* Is the 'finish_shutdown_locked()' called ? */ + bool shutting_down; /* Is the pollset shutting down ? */ grpc_closure *shutdown_closure; /* Called after after shutdown is complete */ + + /* Number of workers who are *about-to* attach themselves to the pollset + * worker list */ int begin_refs; grpc_pollset *next; @@ -294,12 +299,6 @@ static void fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd, static void fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_pollset *notifier) { grpc_lfev_set_ready(exec_ctx, &fd->read_closure, "read"); - - /* Note, it is possible that fd_become_readable might be called twice with - different 'notifier's when an fd becomes readable and it is in two epoll - sets (This can happen briefly during polling island merges). In such cases - it does not really matter which notifer is set as the read_notifier_pollset - (They would both point to the same polling island anyway) */ /* Use release store to match with acquire load in fd_get_read_notifier */ gpr_atm_rel_store(&fd->read_notifier_pollset, (gpr_atm)notifier); } @@ -442,13 +441,16 @@ static grpc_error *pollset_kick_all(grpc_pollset *pollset) { case DESIGNATED_POLLER: SET_KICK_STATE(worker, KICKED); append_error(&error, grpc_wakeup_fd_wakeup(&global_wakeup_fd), - "pollset_shutdown"); + "pollset_kick_all"); break; } worker = worker->next; } while (worker != pollset->root_worker); } + // TODO: sreek. Check if we need to set 'kicked_without_poller' to true here + // in the else case + return error; } @@ -577,6 +579,11 @@ static bool begin_worker(grpc_pollset *pollset, grpc_pollset_worker *worker, pollset->seen_inactive = false; if (neighbourhood->active_root == NULL) { neighbourhood->active_root = pollset->next = pollset->prev = pollset; + /* TODO: sreek. Why would this worker state be other than UNKICKED + * here ? (since the worker isn't added to the pollset yet, there is no + * way it can be "found" by other threads to get kicked). */ + + /* If there is no designated poller, make this the designated poller */ if (worker->kick_state == UNKICKED && gpr_atm_no_barrier_cas(&g_active_poller, 0, (gpr_atm)worker)) { SET_KICK_STATE(worker, DESIGNATED_POLLER); @@ -605,8 +612,11 @@ static bool begin_worker(grpc_pollset *pollset, grpc_pollset_worker *worker, pollset, worker, kick_state_string(worker->kick_state), pollset->shutting_down); } + if (gpr_cv_wait(&worker->cv, &pollset->mu, deadline) && worker->kick_state == UNKICKED) { + /* If gpr_cv_wait returns true (i.e a timeout), pretend that the worker + received a kick */ SET_KICK_STATE(worker, KICKED); } }