blob: 39785f6d564b1dc36a94f8f36f7492b65f994a21 [file] [log] [blame]
Craig Tillerc67cc992017-04-27 10:15:51 -07001/*
2 *
Craig Tillerd4838a92017-04-27 12:08:18 -07003 * Copyright 2017, Google Inc.
Craig Tillerc67cc992017-04-27 10:15:51 -07004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34#include "src/core/lib/iomgr/port.h"
35
36/* This polling engine is only relevant on linux kernels supporting epoll() */
37#ifdef GRPC_LINUX_EPOLL
38
Craig Tiller4509c472017-04-27 19:05:13 +000039#include "src/core/lib/iomgr/ev_epoll1_linux.h"
Craig Tillerc67cc992017-04-27 10:15:51 -070040
41#include <assert.h>
42#include <errno.h>
43#include <poll.h>
44#include <pthread.h>
45#include <string.h>
46#include <sys/epoll.h>
47#include <sys/socket.h>
48#include <unistd.h>
49
50#include <grpc/support/alloc.h>
Craig Tiller6de05932017-04-28 09:17:38 -070051#include <grpc/support/cpu.h>
Craig Tillerc67cc992017-04-27 10:15:51 -070052#include <grpc/support/log.h>
53#include <grpc/support/string_util.h>
54#include <grpc/support/tls.h>
55#include <grpc/support/useful.h>
56
57#include "src/core/lib/iomgr/ev_posix.h"
58#include "src/core/lib/iomgr/iomgr_internal.h"
59#include "src/core/lib/iomgr/lockfree_event.h"
Craig Tillerc67cc992017-04-27 10:15:51 -070060#include "src/core/lib/iomgr/wakeup_fd_posix.h"
Craig Tillerc67cc992017-04-27 10:15:51 -070061#include "src/core/lib/profiling/timers.h"
62#include "src/core/lib/support/block_annotate.h"
63
Craig Tillerc67cc992017-04-27 10:15:51 -070064static grpc_wakeup_fd global_wakeup_fd;
65static int g_epfd;
66
67/*******************************************************************************
68 * Fd Declarations
69 */
70
71struct grpc_fd {
72 int fd;
73
Craig Tillerc67cc992017-04-27 10:15:51 -070074 gpr_atm read_closure;
75 gpr_atm write_closure;
76
77 struct grpc_fd *freelist_next;
Craig Tillerc67cc992017-04-27 10:15:51 -070078
79 /* The pollset that last noticed that the fd is readable. The actual type
80 * stored in this is (grpc_pollset *) */
81 gpr_atm read_notifier_pollset;
82
83 grpc_iomgr_object iomgr_object;
84};
85
86static void fd_global_init(void);
87static void fd_global_shutdown(void);
88
89/*******************************************************************************
90 * Pollset Declarations
91 */
92
Craig Tiller43bf2592017-04-28 23:21:01 +000093typedef enum { UNKICKED, KICKED, DESIGNATED_POLLER } kick_state;
Craig Tillerc67cc992017-04-27 10:15:51 -070094
95struct grpc_pollset_worker {
Craig Tiller32f90ee2017-04-28 12:46:41 -070096 kick_state kick_state;
Craig Tillerc67cc992017-04-27 10:15:51 -070097 bool initialized_cv;
Craig Tiller32f90ee2017-04-28 12:46:41 -070098 grpc_pollset_worker *next;
99 grpc_pollset_worker *prev;
Craig Tillerc67cc992017-04-27 10:15:51 -0700100 gpr_cv cv;
Craig Tiller50da5ec2017-05-01 13:51:14 -0700101 grpc_closure_list schedule_on_end_work;
Craig Tillerc67cc992017-04-27 10:15:51 -0700102};
103
Craig Tillerba550da2017-05-01 14:26:31 +0000104#define MAX_NEIGHBOURHOODS 1024
105
Craig Tiller6de05932017-04-28 09:17:38 -0700106typedef struct pollset_neighbourhood {
107 gpr_mu mu;
108 grpc_pollset *active_root;
Craig Tiller6de05932017-04-28 09:17:38 -0700109 char pad[GPR_CACHELINE_SIZE];
110} pollset_neighbourhood;
111
Craig Tillerc67cc992017-04-27 10:15:51 -0700112struct grpc_pollset {
Craig Tiller6de05932017-04-28 09:17:38 -0700113 gpr_mu mu;
114 pollset_neighbourhood *neighbourhood;
Craig Tillere00d7332017-05-01 15:43:51 +0000115 bool reassigning_neighbourhood;
Craig Tiller4509c472017-04-27 19:05:13 +0000116 grpc_pollset_worker *root_worker;
117 bool kicked_without_poller;
Craig Tiller6de05932017-04-28 09:17:38 -0700118 bool seen_inactive;
Craig Tillerc67cc992017-04-27 10:15:51 -0700119 bool shutting_down; /* Is the pollset shutting down ? */
120 bool finish_shutdown_called; /* Is the 'finish_shutdown_locked()' called ? */
Craig Tiller4509c472017-04-27 19:05:13 +0000121 grpc_closure *shutdown_closure; /* Called after after shutdown is complete */
Craig Tillerba550da2017-05-01 14:26:31 +0000122 int begin_refs;
Craig Tiller6de05932017-04-28 09:17:38 -0700123
124 grpc_pollset *next;
125 grpc_pollset *prev;
Craig Tillerc67cc992017-04-27 10:15:51 -0700126};
127
128/*******************************************************************************
129 * Pollset-set Declarations
130 */
Craig Tiller6de05932017-04-28 09:17:38 -0700131
Craig Tiller61f96c12017-05-12 13:36:39 -0700132struct grpc_pollset_set {
133 char unused;
134};
Craig Tillerc67cc992017-04-27 10:15:51 -0700135
136/*******************************************************************************
137 * Common helpers
138 */
139
140static bool append_error(grpc_error **composite, grpc_error *error,
141 const char *desc) {
142 if (error == GRPC_ERROR_NONE) return true;
143 if (*composite == GRPC_ERROR_NONE) {
144 *composite = GRPC_ERROR_CREATE_FROM_COPIED_STRING(desc);
145 }
146 *composite = grpc_error_add_child(*composite, error);
147 return false;
148}
149
150/*******************************************************************************
151 * Fd Definitions
152 */
153
154/* We need to keep a freelist not because of any concerns of malloc performance
155 * but instead so that implementations with multiple threads in (for example)
156 * epoll_wait deal with the race between pollset removal and incoming poll
157 * notifications.
158 *
159 * The problem is that the poller ultimately holds a reference to this
160 * object, so it is very difficult to know when is safe to free it, at least
161 * without some expensive synchronization.
162 *
163 * If we keep the object freelisted, in the worst case losing this race just
164 * becomes a spurious read notification on a reused fd.
165 */
166
167/* The alarm system needs to be able to wakeup 'some poller' sometimes
168 * (specifically when a new alarm needs to be triggered earlier than the next
169 * alarm 'epoch'). This wakeup_fd gives us something to alert on when such a
170 * case occurs. */
171
172static grpc_fd *fd_freelist = NULL;
173static gpr_mu fd_freelist_mu;
174
Craig Tillerc67cc992017-04-27 10:15:51 -0700175static void fd_global_init(void) { gpr_mu_init(&fd_freelist_mu); }
176
177static void fd_global_shutdown(void) {
178 gpr_mu_lock(&fd_freelist_mu);
179 gpr_mu_unlock(&fd_freelist_mu);
180 while (fd_freelist != NULL) {
181 grpc_fd *fd = fd_freelist;
182 fd_freelist = fd_freelist->freelist_next;
Craig Tillerc67cc992017-04-27 10:15:51 -0700183 gpr_free(fd);
184 }
185 gpr_mu_destroy(&fd_freelist_mu);
186}
187
188static grpc_fd *fd_create(int fd, const char *name) {
189 grpc_fd *new_fd = NULL;
190
191 gpr_mu_lock(&fd_freelist_mu);
192 if (fd_freelist != NULL) {
193 new_fd = fd_freelist;
194 fd_freelist = fd_freelist->freelist_next;
195 }
196 gpr_mu_unlock(&fd_freelist_mu);
197
198 if (new_fd == NULL) {
199 new_fd = gpr_malloc(sizeof(grpc_fd));
Craig Tillerc67cc992017-04-27 10:15:51 -0700200 }
201
Craig Tillerc67cc992017-04-27 10:15:51 -0700202 new_fd->fd = fd;
Craig Tillerc67cc992017-04-27 10:15:51 -0700203 grpc_lfev_init(&new_fd->read_closure);
204 grpc_lfev_init(&new_fd->write_closure);
205 gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL);
206
207 new_fd->freelist_next = NULL;
Craig Tillerc67cc992017-04-27 10:15:51 -0700208
209 char *fd_name;
210 gpr_asprintf(&fd_name, "%s fd=%d", name, fd);
211 grpc_iomgr_register_object(&new_fd->iomgr_object, fd_name);
212#ifdef GRPC_FD_REF_COUNT_DEBUG
213 gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, (void *)new_fd, fd_name);
214#endif
215 gpr_free(fd_name);
Craig Tiller9ddb3152017-04-27 21:32:56 +0000216
217 struct epoll_event ev = {.events = (uint32_t)(EPOLLIN | EPOLLOUT | EPOLLET),
218 .data.ptr = new_fd};
219 if (epoll_ctl(g_epfd, EPOLL_CTL_ADD, fd, &ev) != 0) {
220 gpr_log(GPR_ERROR, "epoll_ctl failed: %s", strerror(errno));
221 }
222
Craig Tillerc67cc992017-04-27 10:15:51 -0700223 return new_fd;
224}
225
Craig Tiller4509c472017-04-27 19:05:13 +0000226static int fd_wrapped_fd(grpc_fd *fd) { return fd->fd; }
Craig Tillerc67cc992017-04-27 10:15:51 -0700227
Craig Tiller9ddb3152017-04-27 21:32:56 +0000228/* Might be called multiple times */
229static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *why) {
230 if (grpc_lfev_set_shutdown(exec_ctx, &fd->read_closure,
231 GRPC_ERROR_REF(why))) {
232 shutdown(fd->fd, SHUT_RDWR);
233 grpc_lfev_set_shutdown(exec_ctx, &fd->write_closure, GRPC_ERROR_REF(why));
234 }
235 GRPC_ERROR_UNREF(why);
236}
237
Craig Tillerc67cc992017-04-27 10:15:51 -0700238static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
239 grpc_closure *on_done, int *release_fd,
240 const char *reason) {
Craig Tillerc67cc992017-04-27 10:15:51 -0700241 grpc_error *error = GRPC_ERROR_NONE;
Craig Tillerc67cc992017-04-27 10:15:51 -0700242
Craig Tiller9ddb3152017-04-27 21:32:56 +0000243 if (!grpc_lfev_is_shutdown(&fd->read_closure)) {
244 fd_shutdown(exec_ctx, fd, GRPC_ERROR_CREATE_FROM_COPIED_STRING(reason));
245 }
246
Craig Tillerc67cc992017-04-27 10:15:51 -0700247 /* If release_fd is not NULL, we should be relinquishing control of the file
248 descriptor fd->fd (but we still own the grpc_fd structure). */
249 if (release_fd != NULL) {
250 *release_fd = fd->fd;
251 } else {
252 close(fd->fd);
Craig Tillerc67cc992017-04-27 10:15:51 -0700253 }
254
Craig Tiller4509c472017-04-27 19:05:13 +0000255 grpc_closure_sched(exec_ctx, on_done, GRPC_ERROR_REF(error));
Craig Tillerc67cc992017-04-27 10:15:51 -0700256
Craig Tiller4509c472017-04-27 19:05:13 +0000257 grpc_iomgr_unregister_object(&fd->iomgr_object);
258 grpc_lfev_destroy(&fd->read_closure);
259 grpc_lfev_destroy(&fd->write_closure);
Craig Tillerc67cc992017-04-27 10:15:51 -0700260
Craig Tiller4509c472017-04-27 19:05:13 +0000261 gpr_mu_lock(&fd_freelist_mu);
262 fd->freelist_next = fd_freelist;
263 fd_freelist = fd;
264 gpr_mu_unlock(&fd_freelist_mu);
Craig Tillerc67cc992017-04-27 10:15:51 -0700265}
266
267static grpc_pollset *fd_get_read_notifier_pollset(grpc_exec_ctx *exec_ctx,
268 grpc_fd *fd) {
269 gpr_atm notifier = gpr_atm_acq_load(&fd->read_notifier_pollset);
270 return (grpc_pollset *)notifier;
271}
272
273static bool fd_is_shutdown(grpc_fd *fd) {
274 return grpc_lfev_is_shutdown(&fd->read_closure);
275}
276
Craig Tillerc67cc992017-04-27 10:15:51 -0700277static void fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
278 grpc_closure *closure) {
279 grpc_lfev_notify_on(exec_ctx, &fd->read_closure, closure);
280}
281
282static void fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
283 grpc_closure *closure) {
284 grpc_lfev_notify_on(exec_ctx, &fd->write_closure, closure);
285}
286
Craig Tiller4509c472017-04-27 19:05:13 +0000287static void fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
288 grpc_pollset *notifier) {
289 grpc_lfev_set_ready(exec_ctx, &fd->read_closure);
290
291 /* Note, it is possible that fd_become_readable might be called twice with
292 different 'notifier's when an fd becomes readable and it is in two epoll
293 sets (This can happen briefly during polling island merges). In such cases
294 it does not really matter which notifer is set as the read_notifier_pollset
295 (They would both point to the same polling island anyway) */
296 /* Use release store to match with acquire load in fd_get_read_notifier */
297 gpr_atm_rel_store(&fd->read_notifier_pollset, (gpr_atm)notifier);
298}
299
300static void fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
301 grpc_lfev_set_ready(exec_ctx, &fd->write_closure);
Craig Tillerc67cc992017-04-27 10:15:51 -0700302}
303
304/*******************************************************************************
305 * Pollset Definitions
306 */
307
Craig Tiller6de05932017-04-28 09:17:38 -0700308GPR_TLS_DECL(g_current_thread_pollset);
309GPR_TLS_DECL(g_current_thread_worker);
310static gpr_atm g_active_poller;
311static pollset_neighbourhood *g_neighbourhoods;
Craig Tiller32f90ee2017-04-28 12:46:41 -0700312static size_t g_num_neighbourhoods;
Craig Tiller6de05932017-04-28 09:17:38 -0700313
Craig Tillerc67cc992017-04-27 10:15:51 -0700314/* Return true if first in list */
Craig Tiller32f90ee2017-04-28 12:46:41 -0700315static bool worker_insert(grpc_pollset *pollset, grpc_pollset_worker *worker) {
316 if (pollset->root_worker == NULL) {
317 pollset->root_worker = worker;
318 worker->next = worker->prev = worker;
Craig Tillerc67cc992017-04-27 10:15:51 -0700319 return true;
320 } else {
Craig Tiller32f90ee2017-04-28 12:46:41 -0700321 worker->next = pollset->root_worker;
322 worker->prev = worker->next->prev;
323 worker->next->prev = worker;
324 worker->prev->next = worker;
Craig Tillerc67cc992017-04-27 10:15:51 -0700325 return false;
326 }
327}
328
329/* Return true if last in list */
330typedef enum { EMPTIED, NEW_ROOT, REMOVED } worker_remove_result;
331
Craig Tiller32f90ee2017-04-28 12:46:41 -0700332static worker_remove_result worker_remove(grpc_pollset *pollset,
Craig Tillerc67cc992017-04-27 10:15:51 -0700333 grpc_pollset_worker *worker) {
Craig Tiller32f90ee2017-04-28 12:46:41 -0700334 if (worker == pollset->root_worker) {
335 if (worker == worker->next) {
336 pollset->root_worker = NULL;
Craig Tillerc67cc992017-04-27 10:15:51 -0700337 return EMPTIED;
338 } else {
Craig Tiller32f90ee2017-04-28 12:46:41 -0700339 pollset->root_worker = worker->next;
340 worker->prev->next = worker->next;
341 worker->next->prev = worker->prev;
Craig Tillerc67cc992017-04-27 10:15:51 -0700342 return NEW_ROOT;
343 }
344 } else {
Craig Tiller32f90ee2017-04-28 12:46:41 -0700345 worker->prev->next = worker->next;
346 worker->next->prev = worker->prev;
Craig Tillerc67cc992017-04-27 10:15:51 -0700347 return REMOVED;
348 }
349}
350
Craig Tillerba550da2017-05-01 14:26:31 +0000351static size_t choose_neighbourhood(void) {
352 return (size_t)gpr_cpu_current_cpu() % g_num_neighbourhoods;
353}
354
Craig Tiller4509c472017-04-27 19:05:13 +0000355static grpc_error *pollset_global_init(void) {
Craig Tiller4509c472017-04-27 19:05:13 +0000356 gpr_tls_init(&g_current_thread_pollset);
357 gpr_tls_init(&g_current_thread_worker);
Craig Tiller6de05932017-04-28 09:17:38 -0700358 gpr_atm_no_barrier_store(&g_active_poller, 0);
Craig Tiller375eb252017-04-27 23:29:12 +0000359 global_wakeup_fd.read_fd = -1;
360 grpc_error *err = grpc_wakeup_fd_init(&global_wakeup_fd);
361 if (err != GRPC_ERROR_NONE) return err;
Craig Tiller4509c472017-04-27 19:05:13 +0000362 struct epoll_event ev = {.events = (uint32_t)(EPOLLIN | EPOLLET),
363 .data.ptr = &global_wakeup_fd};
364 if (epoll_ctl(g_epfd, EPOLL_CTL_ADD, global_wakeup_fd.read_fd, &ev) != 0) {
365 return GRPC_OS_ERROR(errno, "epoll_ctl");
366 }
Craig Tillerba550da2017-05-01 14:26:31 +0000367 g_num_neighbourhoods = GPR_CLAMP(gpr_cpu_num_cores(), 1, MAX_NEIGHBOURHOODS);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700368 g_neighbourhoods =
369 gpr_zalloc(sizeof(*g_neighbourhoods) * g_num_neighbourhoods);
370 for (size_t i = 0; i < g_num_neighbourhoods; i++) {
371 gpr_mu_init(&g_neighbourhoods[i].mu);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700372 }
Craig Tiller4509c472017-04-27 19:05:13 +0000373 return GRPC_ERROR_NONE;
374}
375
376static void pollset_global_shutdown(void) {
Craig Tiller4509c472017-04-27 19:05:13 +0000377 gpr_tls_destroy(&g_current_thread_pollset);
378 gpr_tls_destroy(&g_current_thread_worker);
Craig Tiller375eb252017-04-27 23:29:12 +0000379 if (global_wakeup_fd.read_fd != -1) grpc_wakeup_fd_destroy(&global_wakeup_fd);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700380 for (size_t i = 0; i < g_num_neighbourhoods; i++) {
381 gpr_mu_destroy(&g_neighbourhoods[i].mu);
382 }
383 gpr_free(g_neighbourhoods);
Craig Tiller4509c472017-04-27 19:05:13 +0000384}
385
386static void pollset_init(grpc_pollset *pollset, gpr_mu **mu) {
Craig Tiller6de05932017-04-28 09:17:38 -0700387 gpr_mu_init(&pollset->mu);
388 *mu = &pollset->mu;
Craig Tillerba550da2017-05-01 14:26:31 +0000389 pollset->neighbourhood = &g_neighbourhoods[choose_neighbourhood()];
Craig Tiller6de05932017-04-28 09:17:38 -0700390 pollset->seen_inactive = true;
Craig Tiller6de05932017-04-28 09:17:38 -0700391}
392
Craig Tillerc6109852017-05-01 14:26:49 -0700393static void pollset_destroy(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset) {
Craig Tillere00d7332017-05-01 15:43:51 +0000394 gpr_mu_lock(&pollset->mu);
Craig Tillerba550da2017-05-01 14:26:31 +0000395 if (!pollset->seen_inactive) {
Craig Tillere00d7332017-05-01 15:43:51 +0000396 pollset_neighbourhood *neighbourhood = pollset->neighbourhood;
397 gpr_mu_unlock(&pollset->mu);
Craig Tillera95bacf2017-05-01 12:51:24 -0700398 retry_lock_neighbourhood:
Craig Tillere00d7332017-05-01 15:43:51 +0000399 gpr_mu_lock(&neighbourhood->mu);
400 gpr_mu_lock(&pollset->mu);
401 if (!pollset->seen_inactive) {
402 if (pollset->neighbourhood != neighbourhood) {
403 gpr_mu_unlock(&neighbourhood->mu);
404 neighbourhood = pollset->neighbourhood;
405 gpr_mu_unlock(&pollset->mu);
406 goto retry_lock_neighbourhood;
407 }
408 pollset->prev->next = pollset->next;
409 pollset->next->prev = pollset->prev;
410 if (pollset == pollset->neighbourhood->active_root) {
411 pollset->neighbourhood->active_root =
412 pollset->next == pollset ? NULL : pollset->next;
413 }
Craig Tillerba550da2017-05-01 14:26:31 +0000414 }
415 gpr_mu_unlock(&pollset->neighbourhood->mu);
Craig Tiller6de05932017-04-28 09:17:38 -0700416 }
Craig Tillere00d7332017-05-01 15:43:51 +0000417 gpr_mu_unlock(&pollset->mu);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700418 gpr_mu_destroy(&pollset->mu);
Craig Tiller4509c472017-04-27 19:05:13 +0000419}
420
421static grpc_error *pollset_kick_all(grpc_pollset *pollset) {
422 grpc_error *error = GRPC_ERROR_NONE;
423 if (pollset->root_worker != NULL) {
424 grpc_pollset_worker *worker = pollset->root_worker;
425 do {
426 if (worker->initialized_cv) {
Craig Tiller32f90ee2017-04-28 12:46:41 -0700427 worker->kick_state = KICKED;
Craig Tiller4509c472017-04-27 19:05:13 +0000428 gpr_cv_signal(&worker->cv);
429 } else {
Craig Tiller32f90ee2017-04-28 12:46:41 -0700430 worker->kick_state = KICKED;
Craig Tiller4509c472017-04-27 19:05:13 +0000431 append_error(&error, grpc_wakeup_fd_wakeup(&global_wakeup_fd),
432 "pollset_shutdown");
433 }
434
Craig Tiller32f90ee2017-04-28 12:46:41 -0700435 worker = worker->next;
Craig Tiller4509c472017-04-27 19:05:13 +0000436 } while (worker != pollset->root_worker);
437 }
438 return error;
439}
440
441static void pollset_maybe_finish_shutdown(grpc_exec_ctx *exec_ctx,
442 grpc_pollset *pollset) {
Craig Tillerba550da2017-05-01 14:26:31 +0000443 if (pollset->shutdown_closure != NULL && pollset->root_worker == NULL &&
444 pollset->begin_refs == 0) {
Craig Tiller4509c472017-04-27 19:05:13 +0000445 grpc_closure_sched(exec_ctx, pollset->shutdown_closure, GRPC_ERROR_NONE);
446 pollset->shutdown_closure = NULL;
447 }
448}
449
450static void pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
451 grpc_closure *closure) {
452 GPR_ASSERT(pollset->shutdown_closure == NULL);
453 pollset->shutdown_closure = closure;
454 GRPC_LOG_IF_ERROR("pollset_shutdown", pollset_kick_all(pollset));
455 pollset_maybe_finish_shutdown(exec_ctx, pollset);
456}
457
Craig Tillera95bacf2017-05-01 12:51:24 -0700458#define MAX_EPOLL_EVENTS 100
Craig Tiller4509c472017-04-27 19:05:13 +0000459
460static int poll_deadline_to_millis_timeout(gpr_timespec deadline,
461 gpr_timespec now) {
462 gpr_timespec timeout;
463 if (gpr_time_cmp(deadline, gpr_inf_future(deadline.clock_type)) == 0) {
464 return -1;
465 }
466
467 if (gpr_time_cmp(deadline, now) <= 0) {
468 return 0;
469 }
470
471 static const gpr_timespec round_up = {
472 .clock_type = GPR_TIMESPAN, .tv_sec = 0, .tv_nsec = GPR_NS_PER_MS - 1};
473 timeout = gpr_time_sub(deadline, now);
474 int millis = gpr_time_to_millis(gpr_time_add(timeout, round_up));
475 return millis >= 1 ? millis : 1;
476}
477
478static grpc_error *pollset_epoll(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
479 gpr_timespec now, gpr_timespec deadline) {
480 struct epoll_event events[MAX_EPOLL_EVENTS];
481 static const char *err_desc = "pollset_poll";
482
483 int timeout = poll_deadline_to_millis_timeout(deadline, now);
484
485 if (timeout != 0) {
486 GRPC_SCHEDULING_START_BLOCKING_REGION;
487 }
488 int r;
489 do {
490 r = epoll_wait(g_epfd, events, MAX_EPOLL_EVENTS, timeout);
491 } while (r < 0 && errno == EINTR);
492 if (timeout != 0) {
493 GRPC_SCHEDULING_END_BLOCKING_REGION;
494 }
495
496 if (r < 0) return GRPC_OS_ERROR(errno, "epoll_wait");
497
498 grpc_error *error = GRPC_ERROR_NONE;
499 for (int i = 0; i < r; i++) {
500 void *data_ptr = events[i].data.ptr;
501 if (data_ptr == &global_wakeup_fd) {
Craig Tiller4509c472017-04-27 19:05:13 +0000502 append_error(&error, grpc_wakeup_fd_consume_wakeup(&global_wakeup_fd),
503 err_desc);
504 } else {
505 grpc_fd *fd = (grpc_fd *)(data_ptr);
506 bool cancel = (events[i].events & (EPOLLERR | EPOLLHUP)) != 0;
507 bool read_ev = (events[i].events & (EPOLLIN | EPOLLPRI)) != 0;
508 bool write_ev = (events[i].events & EPOLLOUT) != 0;
509 if (read_ev || cancel) {
510 fd_become_readable(exec_ctx, fd, pollset);
511 }
512 if (write_ev || cancel) {
513 fd_become_writable(exec_ctx, fd);
514 }
515 }
516 }
517
518 return error;
519}
520
521static bool begin_worker(grpc_pollset *pollset, grpc_pollset_worker *worker,
522 grpc_pollset_worker **worker_hdl, gpr_timespec *now,
523 gpr_timespec deadline) {
Craig Tiller4509c472017-04-27 19:05:13 +0000524 if (worker_hdl != NULL) *worker_hdl = worker;
525 worker->initialized_cv = false;
Craig Tiller32f90ee2017-04-28 12:46:41 -0700526 worker->kick_state = UNKICKED;
Craig Tiller50da5ec2017-05-01 13:51:14 -0700527 worker->schedule_on_end_work = (grpc_closure_list)GRPC_CLOSURE_LIST_INIT;
Craig Tillerba550da2017-05-01 14:26:31 +0000528 pollset->begin_refs++;
Craig Tiller4509c472017-04-27 19:05:13 +0000529
Craig Tiller32f90ee2017-04-28 12:46:41 -0700530 if (pollset->seen_inactive) {
531 // pollset has been observed to be inactive, we need to move back to the
532 // active list
Craig Tillere00d7332017-05-01 15:43:51 +0000533 bool is_reassigning = false;
534 if (!pollset->reassigning_neighbourhood) {
535 is_reassigning = true;
536 pollset->reassigning_neighbourhood = true;
537 pollset->neighbourhood = &g_neighbourhoods[choose_neighbourhood()];
538 }
539 pollset_neighbourhood *neighbourhood = pollset->neighbourhood;
Craig Tiller32f90ee2017-04-28 12:46:41 -0700540 gpr_mu_unlock(&pollset->mu);
Craig Tillerba550da2017-05-01 14:26:31 +0000541 // pollset unlocked: state may change (even worker->kick_state)
542 retry_lock_neighbourhood:
Craig Tiller32f90ee2017-04-28 12:46:41 -0700543 gpr_mu_lock(&neighbourhood->mu);
544 gpr_mu_lock(&pollset->mu);
545 if (pollset->seen_inactive) {
Craig Tiller2acab6e2017-04-30 23:06:33 +0000546 if (neighbourhood != pollset->neighbourhood) {
547 gpr_mu_unlock(&neighbourhood->mu);
548 neighbourhood = pollset->neighbourhood;
549 gpr_mu_unlock(&pollset->mu);
550 goto retry_lock_neighbourhood;
551 }
Craig Tiller32f90ee2017-04-28 12:46:41 -0700552 pollset->seen_inactive = false;
Craig Tiller2acab6e2017-04-30 23:06:33 +0000553 if (neighbourhood->active_root == NULL) {
554 neighbourhood->active_root = pollset->next = pollset->prev = pollset;
Craig Tiller32f90ee2017-04-28 12:46:41 -0700555 if (gpr_atm_no_barrier_cas(&g_active_poller, 0, (gpr_atm)worker)) {
Craig Tiller43bf2592017-04-28 23:21:01 +0000556 worker->kick_state = DESIGNATED_POLLER;
Craig Tiller32f90ee2017-04-28 12:46:41 -0700557 }
Craig Tiller2acab6e2017-04-30 23:06:33 +0000558 } else {
559 pollset->next = neighbourhood->active_root;
560 pollset->prev = pollset->next->prev;
561 pollset->next->prev = pollset->prev->next = pollset;
Craig Tiller4509c472017-04-27 19:05:13 +0000562 }
563 }
Craig Tillere00d7332017-05-01 15:43:51 +0000564 if (is_reassigning) {
565 GPR_ASSERT(pollset->reassigning_neighbourhood);
566 pollset->reassigning_neighbourhood = false;
567 }
Craig Tiller32f90ee2017-04-28 12:46:41 -0700568 gpr_mu_unlock(&neighbourhood->mu);
569 }
570 worker_insert(pollset, worker);
Craig Tillerba550da2017-05-01 14:26:31 +0000571 pollset->begin_refs--;
Craig Tiller32f90ee2017-04-28 12:46:41 -0700572 if (worker->kick_state == UNKICKED) {
Craig Tillera4b8eb02017-04-29 00:13:52 +0000573 GPR_ASSERT(gpr_atm_no_barrier_load(&g_active_poller) != (gpr_atm)worker);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700574 worker->initialized_cv = true;
575 gpr_cv_init(&worker->cv);
Craig Tillerba550da2017-05-01 14:26:31 +0000576 while (worker->kick_state == UNKICKED &&
577 pollset->shutdown_closure == NULL) {
Craig Tiller32f90ee2017-04-28 12:46:41 -0700578 if (gpr_cv_wait(&worker->cv, &pollset->mu, deadline) &&
579 worker->kick_state == UNKICKED) {
580 worker->kick_state = KICKED;
581 }
Craig Tillerba550da2017-05-01 14:26:31 +0000582 }
Craig Tiller4509c472017-04-27 19:05:13 +0000583 *now = gpr_now(now->clock_type);
584 }
585
Craig Tiller43bf2592017-04-28 23:21:01 +0000586 return worker->kick_state == DESIGNATED_POLLER &&
Craig Tiller32f90ee2017-04-28 12:46:41 -0700587 pollset->shutdown_closure == NULL;
Craig Tiller4509c472017-04-27 19:05:13 +0000588}
589
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700590static bool check_neighbourhood_for_available_poller(
Craig Tillera4b8eb02017-04-29 00:13:52 +0000591 pollset_neighbourhood *neighbourhood) {
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700592 bool found_worker = false;
593 do {
594 grpc_pollset *inspect = neighbourhood->active_root;
595 if (inspect == NULL) {
596 break;
597 }
598 gpr_mu_lock(&inspect->mu);
599 GPR_ASSERT(!inspect->seen_inactive);
600 grpc_pollset_worker *inspect_worker = inspect->root_worker;
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700601 if (inspect_worker != NULL) {
Craig Tillera4b8eb02017-04-29 00:13:52 +0000602 do {
Craig Tillerba550da2017-05-01 14:26:31 +0000603 switch (inspect_worker->kick_state) {
604 case UNKICKED:
605 if (gpr_atm_no_barrier_cas(&g_active_poller, 0,
606 (gpr_atm)inspect_worker)) {
607 inspect_worker->kick_state = DESIGNATED_POLLER;
608 if (inspect_worker->initialized_cv) {
609 gpr_cv_signal(&inspect_worker->cv);
610 }
Craig Tillera4b8eb02017-04-29 00:13:52 +0000611 }
Craig Tillerba550da2017-05-01 14:26:31 +0000612 // even if we didn't win the cas, there's a worker, we can stop
613 found_worker = true;
614 break;
615 case KICKED:
616 break;
617 case DESIGNATED_POLLER:
618 found_worker = true; // ok, so someone else found the worker, but
619 // we'll accept that
620 break;
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700621 }
Craig Tillera4b8eb02017-04-29 00:13:52 +0000622 inspect_worker = inspect_worker->next;
623 } while (inspect_worker != inspect->root_worker);
624 }
625 if (!found_worker) {
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700626 inspect->seen_inactive = true;
Craig Tiller2acab6e2017-04-30 23:06:33 +0000627 if (inspect == neighbourhood->active_root) {
Craig Tillera95bacf2017-05-01 12:51:24 -0700628 neighbourhood->active_root =
629 inspect->next == inspect ? NULL : inspect->next;
Craig Tiller2acab6e2017-04-30 23:06:33 +0000630 }
631 inspect->next->prev = inspect->prev;
632 inspect->prev->next = inspect->next;
Craig Tillere00d7332017-05-01 15:43:51 +0000633 inspect->next = inspect->prev = NULL;
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700634 }
635 gpr_mu_unlock(&inspect->mu);
636 } while (!found_worker);
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700637 return found_worker;
638}
639
Craig Tiller4509c472017-04-27 19:05:13 +0000640static void end_worker(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
641 grpc_pollset_worker *worker,
642 grpc_pollset_worker **worker_hdl) {
Craig Tiller8502ecb2017-04-28 14:22:01 -0700643 if (worker_hdl != NULL) *worker_hdl = NULL;
Craig Tillera4b8eb02017-04-29 00:13:52 +0000644 worker->kick_state = KICKED;
Craig Tiller50da5ec2017-05-01 13:51:14 -0700645 grpc_closure_list_move(&worker->schedule_on_end_work,
646 &exec_ctx->closure_list);
Craig Tiller8502ecb2017-04-28 14:22:01 -0700647 if (gpr_atm_no_barrier_load(&g_active_poller) == (gpr_atm)worker) {
Craig Tillera4b8eb02017-04-29 00:13:52 +0000648 if (worker->next != worker && worker->next->kick_state == UNKICKED) {
Craig Tiller2acab6e2017-04-30 23:06:33 +0000649 GPR_ASSERT(worker->next->initialized_cv);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700650 gpr_atm_no_barrier_store(&g_active_poller, (gpr_atm)worker->next);
Craig Tiller43bf2592017-04-28 23:21:01 +0000651 worker->next->kick_state = DESIGNATED_POLLER;
Craig Tiller32f90ee2017-04-28 12:46:41 -0700652 gpr_cv_signal(&worker->next->cv);
Craig Tiller8502ecb2017-04-28 14:22:01 -0700653 if (grpc_exec_ctx_has_work(exec_ctx)) {
654 gpr_mu_unlock(&pollset->mu);
655 grpc_exec_ctx_flush(exec_ctx);
656 gpr_mu_lock(&pollset->mu);
657 }
Craig Tiller32f90ee2017-04-28 12:46:41 -0700658 } else {
659 gpr_atm_no_barrier_store(&g_active_poller, 0);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700660 gpr_mu_unlock(&pollset->mu);
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700661 size_t poller_neighbourhood_idx =
662 (size_t)(pollset->neighbourhood - g_neighbourhoods);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700663 bool found_worker = false;
Craig Tillerba550da2017-05-01 14:26:31 +0000664 bool scan_state[MAX_NEIGHBOURHOODS];
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700665 for (size_t i = 0; !found_worker && i < g_num_neighbourhoods; i++) {
666 pollset_neighbourhood *neighbourhood =
667 &g_neighbourhoods[(poller_neighbourhood_idx + i) %
668 g_num_neighbourhoods];
669 if (gpr_mu_trylock(&neighbourhood->mu)) {
670 found_worker =
Craig Tillera4b8eb02017-04-29 00:13:52 +0000671 check_neighbourhood_for_available_poller(neighbourhood);
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700672 gpr_mu_unlock(&neighbourhood->mu);
Craig Tillerba550da2017-05-01 14:26:31 +0000673 scan_state[i] = true;
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700674 } else {
Craig Tillerba550da2017-05-01 14:26:31 +0000675 scan_state[i] = false;
Craig Tiller32f90ee2017-04-28 12:46:41 -0700676 }
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700677 }
Craig Tiller2acab6e2017-04-30 23:06:33 +0000678 for (size_t i = 0; !found_worker && i < g_num_neighbourhoods; i++) {
Craig Tillerba550da2017-05-01 14:26:31 +0000679 if (scan_state[i]) continue;
Craig Tiller2acab6e2017-04-30 23:06:33 +0000680 pollset_neighbourhood *neighbourhood =
681 &g_neighbourhoods[(poller_neighbourhood_idx + i) %
682 g_num_neighbourhoods];
683 gpr_mu_lock(&neighbourhood->mu);
Craig Tillerba550da2017-05-01 14:26:31 +0000684 found_worker = check_neighbourhood_for_available_poller(neighbourhood);
Craig Tiller2acab6e2017-04-30 23:06:33 +0000685 gpr_mu_unlock(&neighbourhood->mu);
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700686 }
Craig Tiller8502ecb2017-04-28 14:22:01 -0700687 grpc_exec_ctx_flush(exec_ctx);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700688 gpr_mu_lock(&pollset->mu);
689 }
Craig Tiller50da5ec2017-05-01 13:51:14 -0700690 } else if (grpc_exec_ctx_has_work(exec_ctx)) {
691 gpr_mu_unlock(&pollset->mu);
692 grpc_exec_ctx_flush(exec_ctx);
693 gpr_mu_lock(&pollset->mu);
Craig Tiller4509c472017-04-27 19:05:13 +0000694 }
695 if (worker->initialized_cv) {
696 gpr_cv_destroy(&worker->cv);
697 }
Craig Tiller32f90ee2017-04-28 12:46:41 -0700698 if (EMPTIED == worker_remove(pollset, worker)) {
Craig Tiller4509c472017-04-27 19:05:13 +0000699 pollset_maybe_finish_shutdown(exec_ctx, pollset);
700 }
Craig Tillera4b8eb02017-04-29 00:13:52 +0000701 GPR_ASSERT(gpr_atm_no_barrier_load(&g_active_poller) != (gpr_atm)worker);
Craig Tiller4509c472017-04-27 19:05:13 +0000702}
703
704/* pollset->po.mu lock must be held by the caller before calling this.
705 The function pollset_work() may temporarily release the lock (pollset->po.mu)
706 during the course of its execution but it will always re-acquire the lock and
707 ensure that it is held by the time the function returns */
708static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
709 grpc_pollset_worker **worker_hdl,
710 gpr_timespec now, gpr_timespec deadline) {
711 grpc_pollset_worker worker;
712 grpc_error *error = GRPC_ERROR_NONE;
713 static const char *err_desc = "pollset_work";
714 if (pollset->kicked_without_poller) {
715 pollset->kicked_without_poller = false;
716 return GRPC_ERROR_NONE;
717 }
Craig Tiller8502ecb2017-04-28 14:22:01 -0700718 gpr_tls_set(&g_current_thread_pollset, (intptr_t)pollset);
Craig Tiller4509c472017-04-27 19:05:13 +0000719 if (begin_worker(pollset, &worker, worker_hdl, &now, deadline)) {
Craig Tiller4509c472017-04-27 19:05:13 +0000720 gpr_tls_set(&g_current_thread_worker, (intptr_t)&worker);
721 GPR_ASSERT(!pollset->shutdown_closure);
Craig Tiller2acab6e2017-04-30 23:06:33 +0000722 GPR_ASSERT(!pollset->seen_inactive);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700723 gpr_mu_unlock(&pollset->mu);
Craig Tiller4509c472017-04-27 19:05:13 +0000724 append_error(&error, pollset_epoll(exec_ctx, pollset, now, deadline),
725 err_desc);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700726 gpr_mu_lock(&pollset->mu);
Craig Tiller4509c472017-04-27 19:05:13 +0000727 gpr_tls_set(&g_current_thread_worker, 0);
Craig Tiller4509c472017-04-27 19:05:13 +0000728 }
729 end_worker(exec_ctx, pollset, &worker, worker_hdl);
Craig Tiller8502ecb2017-04-28 14:22:01 -0700730 gpr_tls_set(&g_current_thread_pollset, 0);
Craig Tiller4509c472017-04-27 19:05:13 +0000731 return error;
732}
733
734static grpc_error *pollset_kick(grpc_pollset *pollset,
735 grpc_pollset_worker *specific_worker) {
736 if (specific_worker == NULL) {
737 if (gpr_tls_get(&g_current_thread_pollset) != (intptr_t)pollset) {
Craig Tiller375eb252017-04-27 23:29:12 +0000738 grpc_pollset_worker *root_worker = pollset->root_worker;
739 if (root_worker == NULL) {
Craig Tiller4509c472017-04-27 19:05:13 +0000740 pollset->kicked_without_poller = true;
741 return GRPC_ERROR_NONE;
Craig Tiller375eb252017-04-27 23:29:12 +0000742 }
Craig Tiller32f90ee2017-04-28 12:46:41 -0700743 grpc_pollset_worker *next_worker = root_worker->next;
744 if (root_worker == next_worker &&
745 root_worker == (grpc_pollset_worker *)gpr_atm_no_barrier_load(
746 &g_active_poller)) {
747 root_worker->kick_state = KICKED;
Craig Tiller4509c472017-04-27 19:05:13 +0000748 return grpc_wakeup_fd_wakeup(&global_wakeup_fd);
Craig Tiller8502ecb2017-04-28 14:22:01 -0700749 } else if (next_worker->kick_state == UNKICKED) {
750 GPR_ASSERT(next_worker->initialized_cv);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700751 next_worker->kick_state = KICKED;
Craig Tiller375eb252017-04-27 23:29:12 +0000752 gpr_cv_signal(&next_worker->cv);
753 return GRPC_ERROR_NONE;
Craig Tiller8502ecb2017-04-28 14:22:01 -0700754 } else {
755 return GRPC_ERROR_NONE;
Craig Tiller4509c472017-04-27 19:05:13 +0000756 }
757 } else {
758 return GRPC_ERROR_NONE;
759 }
Craig Tiller43bf2592017-04-28 23:21:01 +0000760 } else if (specific_worker->kick_state == KICKED) {
Craig Tiller4509c472017-04-27 19:05:13 +0000761 return GRPC_ERROR_NONE;
762 } else if (gpr_tls_get(&g_current_thread_worker) ==
763 (intptr_t)specific_worker) {
Craig Tiller32f90ee2017-04-28 12:46:41 -0700764 specific_worker->kick_state = KICKED;
Craig Tiller4509c472017-04-27 19:05:13 +0000765 return GRPC_ERROR_NONE;
Craig Tiller32f90ee2017-04-28 12:46:41 -0700766 } else if (specific_worker ==
767 (grpc_pollset_worker *)gpr_atm_no_barrier_load(&g_active_poller)) {
768 specific_worker->kick_state = KICKED;
Craig Tiller4509c472017-04-27 19:05:13 +0000769 return grpc_wakeup_fd_wakeup(&global_wakeup_fd);
Craig Tiller8502ecb2017-04-28 14:22:01 -0700770 } else if (specific_worker->initialized_cv) {
Craig Tiller32f90ee2017-04-28 12:46:41 -0700771 specific_worker->kick_state = KICKED;
Craig Tiller4509c472017-04-27 19:05:13 +0000772 gpr_cv_signal(&specific_worker->cv);
773 return GRPC_ERROR_NONE;
Craig Tiller8502ecb2017-04-28 14:22:01 -0700774 } else {
775 specific_worker->kick_state = KICKED;
776 return GRPC_ERROR_NONE;
Craig Tiller4509c472017-04-27 19:05:13 +0000777 }
778}
779
780static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
781 grpc_fd *fd) {}
782
Craig Tiller4509c472017-04-27 19:05:13 +0000783/*******************************************************************************
Craig Tillerc67cc992017-04-27 10:15:51 -0700784 * Pollset-set Definitions
785 */
786
787static grpc_pollset_set *pollset_set_create(void) {
788 return (grpc_pollset_set *)((intptr_t)0xdeafbeef);
789}
790
791static void pollset_set_destroy(grpc_exec_ctx *exec_ctx,
792 grpc_pollset_set *pss) {}
793
794static void pollset_set_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pss,
795 grpc_fd *fd) {}
796
797static void pollset_set_del_fd(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pss,
798 grpc_fd *fd) {}
799
800static void pollset_set_add_pollset(grpc_exec_ctx *exec_ctx,
801 grpc_pollset_set *pss, grpc_pollset *ps) {}
802
803static void pollset_set_del_pollset(grpc_exec_ctx *exec_ctx,
804 grpc_pollset_set *pss, grpc_pollset *ps) {}
805
806static void pollset_set_add_pollset_set(grpc_exec_ctx *exec_ctx,
807 grpc_pollset_set *bag,
808 grpc_pollset_set *item) {}
809
810static void pollset_set_del_pollset_set(grpc_exec_ctx *exec_ctx,
811 grpc_pollset_set *bag,
812 grpc_pollset_set *item) {}
813
814/*******************************************************************************
815 * Event engine binding
816 */
817
818static void shutdown_engine(void) {
819 fd_global_shutdown();
820 pollset_global_shutdown();
Craig Tillerc67cc992017-04-27 10:15:51 -0700821}
822
823static const grpc_event_engine_vtable vtable = {
824 .pollset_size = sizeof(grpc_pollset),
825
826 .fd_create = fd_create,
827 .fd_wrapped_fd = fd_wrapped_fd,
828 .fd_orphan = fd_orphan,
829 .fd_shutdown = fd_shutdown,
830 .fd_is_shutdown = fd_is_shutdown,
831 .fd_notify_on_read = fd_notify_on_read,
832 .fd_notify_on_write = fd_notify_on_write,
833 .fd_get_read_notifier_pollset = fd_get_read_notifier_pollset,
Craig Tillerc67cc992017-04-27 10:15:51 -0700834
835 .pollset_init = pollset_init,
836 .pollset_shutdown = pollset_shutdown,
837 .pollset_destroy = pollset_destroy,
838 .pollset_work = pollset_work,
839 .pollset_kick = pollset_kick,
840 .pollset_add_fd = pollset_add_fd,
841
842 .pollset_set_create = pollset_set_create,
843 .pollset_set_destroy = pollset_set_destroy,
844 .pollset_set_add_pollset = pollset_set_add_pollset,
845 .pollset_set_del_pollset = pollset_set_del_pollset,
846 .pollset_set_add_pollset_set = pollset_set_add_pollset_set,
847 .pollset_set_del_pollset_set = pollset_set_del_pollset_set,
848 .pollset_set_add_fd = pollset_set_add_fd,
849 .pollset_set_del_fd = pollset_set_del_fd,
850
Craig Tillerc67cc992017-04-27 10:15:51 -0700851 .shutdown_engine = shutdown_engine,
852};
853
854/* It is possible that GLIBC has epoll but the underlying kernel doesn't.
855 * Create a dummy epoll_fd to make sure epoll support is available */
Craig Tiller6f0af492017-04-27 19:26:16 +0000856const grpc_event_engine_vtable *grpc_init_epoll1_linux(bool explicit_request) {
Craig Tiller924353a2017-05-05 17:36:31 +0000857 /* TODO(ctiller): temporary, until this stabilizes */
858 if (!explicit_request) return NULL;
859
Craig Tillerc67cc992017-04-27 10:15:51 -0700860 if (!grpc_has_wakeup_fd()) {
861 return NULL;
862 }
863
Craig Tiller4509c472017-04-27 19:05:13 +0000864 g_epfd = epoll_create1(EPOLL_CLOEXEC);
865 if (g_epfd < 0) {
866 gpr_log(GPR_ERROR, "epoll unavailable");
Craig Tillerc67cc992017-04-27 10:15:51 -0700867 return NULL;
868 }
869
Craig Tillerc67cc992017-04-27 10:15:51 -0700870 fd_global_init();
871
872 if (!GRPC_LOG_IF_ERROR("pollset_global_init", pollset_global_init())) {
Craig Tiller4509c472017-04-27 19:05:13 +0000873 close(g_epfd);
874 fd_global_shutdown();
Craig Tillerc67cc992017-04-27 10:15:51 -0700875 return NULL;
876 }
877
878 return &vtable;
879}
880
881#else /* defined(GRPC_LINUX_EPOLL) */
882#if defined(GRPC_POSIX_SOCKET)
883#include "src/core/lib/iomgr/ev_posix.h"
884/* If GRPC_LINUX_EPOLL is not defined, it means epoll is not available. Return
885 * NULL */
Craig Tiller9ddb3152017-04-27 21:32:56 +0000886const grpc_event_engine_vtable *grpc_init_epoll1_linux(bool explicit_request) {
887 return NULL;
888}
Craig Tillerc67cc992017-04-27 10:15:51 -0700889#endif /* defined(GRPC_POSIX_SOCKET) */
890#endif /* !defined(GRPC_LINUX_EPOLL) */