blob: 532d2887edae918cc1415362eb311ca02eec9580 [file] [log] [blame]
Craig Tillerc67cc992017-04-27 10:15:51 -07001/*
2 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003 * Copyright 2017 gRPC authors.
Craig Tillerc67cc992017-04-27 10:15:51 -07004 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02005 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
Craig Tillerc67cc992017-04-27 10:15:51 -07008 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009 * http://www.apache.org/licenses/LICENSE-2.0
Craig Tillerc67cc992017-04-27 10:15:51 -070010 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +020011 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
Craig Tillerc67cc992017-04-27 10:15:51 -070016 *
17 */
18
19#include "src/core/lib/iomgr/port.h"
20
21/* This polling engine is only relevant on linux kernels supporting epoll() */
22#ifdef GRPC_LINUX_EPOLL
23
Craig Tiller4509c472017-04-27 19:05:13 +000024#include "src/core/lib/iomgr/ev_epoll1_linux.h"
Craig Tillerc67cc992017-04-27 10:15:51 -070025
26#include <assert.h>
27#include <errno.h>
28#include <poll.h>
29#include <pthread.h>
30#include <string.h>
31#include <sys/epoll.h>
32#include <sys/socket.h>
33#include <unistd.h>
34
35#include <grpc/support/alloc.h>
Craig Tiller6de05932017-04-28 09:17:38 -070036#include <grpc/support/cpu.h>
Craig Tillerc67cc992017-04-27 10:15:51 -070037#include <grpc/support/log.h>
38#include <grpc/support/string_util.h>
39#include <grpc/support/tls.h>
40#include <grpc/support/useful.h>
41
Craig Tillerb4bb1cd2017-07-20 14:18:17 -070042#include "src/core/lib/debug/stats.h"
Craig Tillerc67cc992017-04-27 10:15:51 -070043#include "src/core/lib/iomgr/ev_posix.h"
44#include "src/core/lib/iomgr/iomgr_internal.h"
45#include "src/core/lib/iomgr/lockfree_event.h"
Craig Tillerc67cc992017-04-27 10:15:51 -070046#include "src/core/lib/iomgr/wakeup_fd_posix.h"
Craig Tillerc67cc992017-04-27 10:15:51 -070047#include "src/core/lib/profiling/timers.h"
48#include "src/core/lib/support/block_annotate.h"
49
Craig Tillerc67cc992017-04-27 10:15:51 -070050static grpc_wakeup_fd global_wakeup_fd;
51static int g_epfd;
52
53/*******************************************************************************
54 * Fd Declarations
55 */
56
57struct grpc_fd {
58 int fd;
59
Craig Tillerc67cc992017-04-27 10:15:51 -070060 gpr_atm read_closure;
61 gpr_atm write_closure;
62
63 struct grpc_fd *freelist_next;
Craig Tillerc67cc992017-04-27 10:15:51 -070064
65 /* The pollset that last noticed that the fd is readable. The actual type
66 * stored in this is (grpc_pollset *) */
67 gpr_atm read_notifier_pollset;
68
69 grpc_iomgr_object iomgr_object;
70};
71
72static void fd_global_init(void);
73static void fd_global_shutdown(void);
74
75/*******************************************************************************
76 * Pollset Declarations
77 */
78
Craig Tiller43bf2592017-04-28 23:21:01 +000079typedef enum { UNKICKED, KICKED, DESIGNATED_POLLER } kick_state;
Craig Tillerc67cc992017-04-27 10:15:51 -070080
81struct grpc_pollset_worker {
Craig Tiller32f90ee2017-04-28 12:46:41 -070082 kick_state kick_state;
Craig Tillerc67cc992017-04-27 10:15:51 -070083 bool initialized_cv;
Craig Tiller32f90ee2017-04-28 12:46:41 -070084 grpc_pollset_worker *next;
85 grpc_pollset_worker *prev;
Craig Tillerc67cc992017-04-27 10:15:51 -070086 gpr_cv cv;
Craig Tiller50da5ec2017-05-01 13:51:14 -070087 grpc_closure_list schedule_on_end_work;
Craig Tillerc67cc992017-04-27 10:15:51 -070088};
89
Craig Tillerba550da2017-05-01 14:26:31 +000090#define MAX_NEIGHBOURHOODS 1024
91
Craig Tiller6de05932017-04-28 09:17:38 -070092typedef struct pollset_neighbourhood {
93 gpr_mu mu;
94 grpc_pollset *active_root;
Craig Tiller6de05932017-04-28 09:17:38 -070095 char pad[GPR_CACHELINE_SIZE];
96} pollset_neighbourhood;
97
Craig Tillerc67cc992017-04-27 10:15:51 -070098struct grpc_pollset {
Craig Tiller6de05932017-04-28 09:17:38 -070099 gpr_mu mu;
100 pollset_neighbourhood *neighbourhood;
Craig Tillere00d7332017-05-01 15:43:51 +0000101 bool reassigning_neighbourhood;
Craig Tiller4509c472017-04-27 19:05:13 +0000102 grpc_pollset_worker *root_worker;
103 bool kicked_without_poller;
Craig Tiller6de05932017-04-28 09:17:38 -0700104 bool seen_inactive;
Craig Tillerc67cc992017-04-27 10:15:51 -0700105 bool shutting_down; /* Is the pollset shutting down ? */
106 bool finish_shutdown_called; /* Is the 'finish_shutdown_locked()' called ? */
Craig Tiller4509c472017-04-27 19:05:13 +0000107 grpc_closure *shutdown_closure; /* Called after after shutdown is complete */
Craig Tillerba550da2017-05-01 14:26:31 +0000108 int begin_refs;
Craig Tiller6de05932017-04-28 09:17:38 -0700109
110 grpc_pollset *next;
111 grpc_pollset *prev;
Craig Tillerc67cc992017-04-27 10:15:51 -0700112};
113
114/*******************************************************************************
115 * Pollset-set Declarations
116 */
Craig Tiller6de05932017-04-28 09:17:38 -0700117
Craig Tiller61f96c12017-05-12 13:36:39 -0700118struct grpc_pollset_set {
119 char unused;
120};
Craig Tillerc67cc992017-04-27 10:15:51 -0700121
122/*******************************************************************************
123 * Common helpers
124 */
125
126static bool append_error(grpc_error **composite, grpc_error *error,
127 const char *desc) {
128 if (error == GRPC_ERROR_NONE) return true;
129 if (*composite == GRPC_ERROR_NONE) {
130 *composite = GRPC_ERROR_CREATE_FROM_COPIED_STRING(desc);
131 }
132 *composite = grpc_error_add_child(*composite, error);
133 return false;
134}
135
136/*******************************************************************************
137 * Fd Definitions
138 */
139
140/* We need to keep a freelist not because of any concerns of malloc performance
141 * but instead so that implementations with multiple threads in (for example)
142 * epoll_wait deal with the race between pollset removal and incoming poll
143 * notifications.
144 *
145 * The problem is that the poller ultimately holds a reference to this
146 * object, so it is very difficult to know when is safe to free it, at least
147 * without some expensive synchronization.
148 *
149 * If we keep the object freelisted, in the worst case losing this race just
150 * becomes a spurious read notification on a reused fd.
151 */
152
153/* The alarm system needs to be able to wakeup 'some poller' sometimes
154 * (specifically when a new alarm needs to be triggered earlier than the next
155 * alarm 'epoch'). This wakeup_fd gives us something to alert on when such a
156 * case occurs. */
157
158static grpc_fd *fd_freelist = NULL;
159static gpr_mu fd_freelist_mu;
160
Craig Tillerc67cc992017-04-27 10:15:51 -0700161static void fd_global_init(void) { gpr_mu_init(&fd_freelist_mu); }
162
163static void fd_global_shutdown(void) {
164 gpr_mu_lock(&fd_freelist_mu);
165 gpr_mu_unlock(&fd_freelist_mu);
166 while (fd_freelist != NULL) {
167 grpc_fd *fd = fd_freelist;
168 fd_freelist = fd_freelist->freelist_next;
Craig Tillerc67cc992017-04-27 10:15:51 -0700169 gpr_free(fd);
170 }
171 gpr_mu_destroy(&fd_freelist_mu);
172}
173
174static grpc_fd *fd_create(int fd, const char *name) {
175 grpc_fd *new_fd = NULL;
176
177 gpr_mu_lock(&fd_freelist_mu);
178 if (fd_freelist != NULL) {
179 new_fd = fd_freelist;
180 fd_freelist = fd_freelist->freelist_next;
181 }
182 gpr_mu_unlock(&fd_freelist_mu);
183
184 if (new_fd == NULL) {
185 new_fd = gpr_malloc(sizeof(grpc_fd));
Craig Tillerc67cc992017-04-27 10:15:51 -0700186 }
187
Craig Tillerc67cc992017-04-27 10:15:51 -0700188 new_fd->fd = fd;
Craig Tillerc67cc992017-04-27 10:15:51 -0700189 grpc_lfev_init(&new_fd->read_closure);
190 grpc_lfev_init(&new_fd->write_closure);
191 gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL);
192
193 new_fd->freelist_next = NULL;
Craig Tillerc67cc992017-04-27 10:15:51 -0700194
195 char *fd_name;
196 gpr_asprintf(&fd_name, "%s fd=%d", name, fd);
197 grpc_iomgr_register_object(&new_fd->iomgr_object, fd_name);
Noah Eisen264879f2017-06-20 17:14:47 -0700198#ifndef NDEBUG
199 if (GRPC_TRACER_ON(grpc_trace_fd_refcount)) {
200 gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, new_fd, fd_name);
201 }
Craig Tillerc67cc992017-04-27 10:15:51 -0700202#endif
203 gpr_free(fd_name);
Craig Tiller9ddb3152017-04-27 21:32:56 +0000204
205 struct epoll_event ev = {.events = (uint32_t)(EPOLLIN | EPOLLOUT | EPOLLET),
206 .data.ptr = new_fd};
207 if (epoll_ctl(g_epfd, EPOLL_CTL_ADD, fd, &ev) != 0) {
208 gpr_log(GPR_ERROR, "epoll_ctl failed: %s", strerror(errno));
209 }
210
Craig Tillerc67cc992017-04-27 10:15:51 -0700211 return new_fd;
212}
213
Craig Tiller4509c472017-04-27 19:05:13 +0000214static int fd_wrapped_fd(grpc_fd *fd) { return fd->fd; }
Craig Tillerc67cc992017-04-27 10:15:51 -0700215
Craig Tiller9ddb3152017-04-27 21:32:56 +0000216/* Might be called multiple times */
217static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *why) {
218 if (grpc_lfev_set_shutdown(exec_ctx, &fd->read_closure,
219 GRPC_ERROR_REF(why))) {
220 shutdown(fd->fd, SHUT_RDWR);
221 grpc_lfev_set_shutdown(exec_ctx, &fd->write_closure, GRPC_ERROR_REF(why));
222 }
223 GRPC_ERROR_UNREF(why);
224}
225
Craig Tillerc67cc992017-04-27 10:15:51 -0700226static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
227 grpc_closure *on_done, int *release_fd,
228 const char *reason) {
Craig Tillerc67cc992017-04-27 10:15:51 -0700229 grpc_error *error = GRPC_ERROR_NONE;
Craig Tillerc67cc992017-04-27 10:15:51 -0700230
Craig Tiller9ddb3152017-04-27 21:32:56 +0000231 if (!grpc_lfev_is_shutdown(&fd->read_closure)) {
232 fd_shutdown(exec_ctx, fd, GRPC_ERROR_CREATE_FROM_COPIED_STRING(reason));
233 }
234
Craig Tillerc67cc992017-04-27 10:15:51 -0700235 /* If release_fd is not NULL, we should be relinquishing control of the file
236 descriptor fd->fd (but we still own the grpc_fd structure). */
237 if (release_fd != NULL) {
238 *release_fd = fd->fd;
239 } else {
240 close(fd->fd);
Craig Tillerc67cc992017-04-27 10:15:51 -0700241 }
242
ncteisen969b46e2017-06-08 14:57:11 -0700243 GRPC_CLOSURE_SCHED(exec_ctx, on_done, GRPC_ERROR_REF(error));
Craig Tillerc67cc992017-04-27 10:15:51 -0700244
Craig Tiller4509c472017-04-27 19:05:13 +0000245 grpc_iomgr_unregister_object(&fd->iomgr_object);
246 grpc_lfev_destroy(&fd->read_closure);
247 grpc_lfev_destroy(&fd->write_closure);
Craig Tillerc67cc992017-04-27 10:15:51 -0700248
Craig Tiller4509c472017-04-27 19:05:13 +0000249 gpr_mu_lock(&fd_freelist_mu);
250 fd->freelist_next = fd_freelist;
251 fd_freelist = fd;
252 gpr_mu_unlock(&fd_freelist_mu);
Craig Tillerc67cc992017-04-27 10:15:51 -0700253}
254
255static grpc_pollset *fd_get_read_notifier_pollset(grpc_exec_ctx *exec_ctx,
256 grpc_fd *fd) {
257 gpr_atm notifier = gpr_atm_acq_load(&fd->read_notifier_pollset);
258 return (grpc_pollset *)notifier;
259}
260
261static bool fd_is_shutdown(grpc_fd *fd) {
262 return grpc_lfev_is_shutdown(&fd->read_closure);
263}
264
Craig Tillerc67cc992017-04-27 10:15:51 -0700265static void fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
266 grpc_closure *closure) {
267 grpc_lfev_notify_on(exec_ctx, &fd->read_closure, closure);
268}
269
270static void fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
271 grpc_closure *closure) {
272 grpc_lfev_notify_on(exec_ctx, &fd->write_closure, closure);
273}
274
Craig Tiller4509c472017-04-27 19:05:13 +0000275static void fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
276 grpc_pollset *notifier) {
277 grpc_lfev_set_ready(exec_ctx, &fd->read_closure);
278
279 /* Note, it is possible that fd_become_readable might be called twice with
280 different 'notifier's when an fd becomes readable and it is in two epoll
281 sets (This can happen briefly during polling island merges). In such cases
282 it does not really matter which notifer is set as the read_notifier_pollset
283 (They would both point to the same polling island anyway) */
284 /* Use release store to match with acquire load in fd_get_read_notifier */
285 gpr_atm_rel_store(&fd->read_notifier_pollset, (gpr_atm)notifier);
286}
287
288static void fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
289 grpc_lfev_set_ready(exec_ctx, &fd->write_closure);
Craig Tillerc67cc992017-04-27 10:15:51 -0700290}
291
292/*******************************************************************************
293 * Pollset Definitions
294 */
295
Craig Tiller6de05932017-04-28 09:17:38 -0700296GPR_TLS_DECL(g_current_thread_pollset);
297GPR_TLS_DECL(g_current_thread_worker);
298static gpr_atm g_active_poller;
299static pollset_neighbourhood *g_neighbourhoods;
Craig Tiller32f90ee2017-04-28 12:46:41 -0700300static size_t g_num_neighbourhoods;
Craig Tiller6de05932017-04-28 09:17:38 -0700301
Craig Tillerc67cc992017-04-27 10:15:51 -0700302/* Return true if first in list */
Craig Tiller32f90ee2017-04-28 12:46:41 -0700303static bool worker_insert(grpc_pollset *pollset, grpc_pollset_worker *worker) {
304 if (pollset->root_worker == NULL) {
305 pollset->root_worker = worker;
306 worker->next = worker->prev = worker;
Craig Tillerc67cc992017-04-27 10:15:51 -0700307 return true;
308 } else {
Craig Tiller32f90ee2017-04-28 12:46:41 -0700309 worker->next = pollset->root_worker;
310 worker->prev = worker->next->prev;
311 worker->next->prev = worker;
312 worker->prev->next = worker;
Craig Tillerc67cc992017-04-27 10:15:51 -0700313 return false;
314 }
315}
316
317/* Return true if last in list */
318typedef enum { EMPTIED, NEW_ROOT, REMOVED } worker_remove_result;
319
Craig Tiller32f90ee2017-04-28 12:46:41 -0700320static worker_remove_result worker_remove(grpc_pollset *pollset,
Craig Tillerc67cc992017-04-27 10:15:51 -0700321 grpc_pollset_worker *worker) {
Craig Tiller32f90ee2017-04-28 12:46:41 -0700322 if (worker == pollset->root_worker) {
323 if (worker == worker->next) {
324 pollset->root_worker = NULL;
Craig Tillerc67cc992017-04-27 10:15:51 -0700325 return EMPTIED;
326 } else {
Craig Tiller32f90ee2017-04-28 12:46:41 -0700327 pollset->root_worker = worker->next;
328 worker->prev->next = worker->next;
329 worker->next->prev = worker->prev;
Craig Tillerc67cc992017-04-27 10:15:51 -0700330 return NEW_ROOT;
331 }
332 } else {
Craig Tiller32f90ee2017-04-28 12:46:41 -0700333 worker->prev->next = worker->next;
334 worker->next->prev = worker->prev;
Craig Tillerc67cc992017-04-27 10:15:51 -0700335 return REMOVED;
336 }
337}
338
Craig Tillerba550da2017-05-01 14:26:31 +0000339static size_t choose_neighbourhood(void) {
340 return (size_t)gpr_cpu_current_cpu() % g_num_neighbourhoods;
341}
342
Craig Tiller4509c472017-04-27 19:05:13 +0000343static grpc_error *pollset_global_init(void) {
Craig Tiller4509c472017-04-27 19:05:13 +0000344 gpr_tls_init(&g_current_thread_pollset);
345 gpr_tls_init(&g_current_thread_worker);
Craig Tiller6de05932017-04-28 09:17:38 -0700346 gpr_atm_no_barrier_store(&g_active_poller, 0);
Craig Tiller375eb252017-04-27 23:29:12 +0000347 global_wakeup_fd.read_fd = -1;
348 grpc_error *err = grpc_wakeup_fd_init(&global_wakeup_fd);
349 if (err != GRPC_ERROR_NONE) return err;
Craig Tiller4509c472017-04-27 19:05:13 +0000350 struct epoll_event ev = {.events = (uint32_t)(EPOLLIN | EPOLLET),
351 .data.ptr = &global_wakeup_fd};
352 if (epoll_ctl(g_epfd, EPOLL_CTL_ADD, global_wakeup_fd.read_fd, &ev) != 0) {
353 return GRPC_OS_ERROR(errno, "epoll_ctl");
354 }
Craig Tillerba550da2017-05-01 14:26:31 +0000355 g_num_neighbourhoods = GPR_CLAMP(gpr_cpu_num_cores(), 1, MAX_NEIGHBOURHOODS);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700356 g_neighbourhoods =
357 gpr_zalloc(sizeof(*g_neighbourhoods) * g_num_neighbourhoods);
358 for (size_t i = 0; i < g_num_neighbourhoods; i++) {
359 gpr_mu_init(&g_neighbourhoods[i].mu);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700360 }
Craig Tiller4509c472017-04-27 19:05:13 +0000361 return GRPC_ERROR_NONE;
362}
363
364static void pollset_global_shutdown(void) {
Craig Tiller4509c472017-04-27 19:05:13 +0000365 gpr_tls_destroy(&g_current_thread_pollset);
366 gpr_tls_destroy(&g_current_thread_worker);
Craig Tiller375eb252017-04-27 23:29:12 +0000367 if (global_wakeup_fd.read_fd != -1) grpc_wakeup_fd_destroy(&global_wakeup_fd);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700368 for (size_t i = 0; i < g_num_neighbourhoods; i++) {
369 gpr_mu_destroy(&g_neighbourhoods[i].mu);
370 }
371 gpr_free(g_neighbourhoods);
Craig Tiller4509c472017-04-27 19:05:13 +0000372}
373
374static void pollset_init(grpc_pollset *pollset, gpr_mu **mu) {
Craig Tiller6de05932017-04-28 09:17:38 -0700375 gpr_mu_init(&pollset->mu);
376 *mu = &pollset->mu;
Craig Tillerba550da2017-05-01 14:26:31 +0000377 pollset->neighbourhood = &g_neighbourhoods[choose_neighbourhood()];
Craig Tiller6de05932017-04-28 09:17:38 -0700378 pollset->seen_inactive = true;
Craig Tiller6de05932017-04-28 09:17:38 -0700379}
380
Craig Tillerc6109852017-05-01 14:26:49 -0700381static void pollset_destroy(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset) {
Craig Tillere00d7332017-05-01 15:43:51 +0000382 gpr_mu_lock(&pollset->mu);
Craig Tillerba550da2017-05-01 14:26:31 +0000383 if (!pollset->seen_inactive) {
Craig Tillere00d7332017-05-01 15:43:51 +0000384 pollset_neighbourhood *neighbourhood = pollset->neighbourhood;
385 gpr_mu_unlock(&pollset->mu);
Craig Tillera95bacf2017-05-01 12:51:24 -0700386 retry_lock_neighbourhood:
Craig Tillere00d7332017-05-01 15:43:51 +0000387 gpr_mu_lock(&neighbourhood->mu);
388 gpr_mu_lock(&pollset->mu);
389 if (!pollset->seen_inactive) {
390 if (pollset->neighbourhood != neighbourhood) {
391 gpr_mu_unlock(&neighbourhood->mu);
392 neighbourhood = pollset->neighbourhood;
393 gpr_mu_unlock(&pollset->mu);
394 goto retry_lock_neighbourhood;
395 }
396 pollset->prev->next = pollset->next;
397 pollset->next->prev = pollset->prev;
398 if (pollset == pollset->neighbourhood->active_root) {
399 pollset->neighbourhood->active_root =
400 pollset->next == pollset ? NULL : pollset->next;
401 }
Craig Tillerba550da2017-05-01 14:26:31 +0000402 }
403 gpr_mu_unlock(&pollset->neighbourhood->mu);
Craig Tiller6de05932017-04-28 09:17:38 -0700404 }
Craig Tillere00d7332017-05-01 15:43:51 +0000405 gpr_mu_unlock(&pollset->mu);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700406 gpr_mu_destroy(&pollset->mu);
Craig Tiller4509c472017-04-27 19:05:13 +0000407}
408
409static grpc_error *pollset_kick_all(grpc_pollset *pollset) {
410 grpc_error *error = GRPC_ERROR_NONE;
411 if (pollset->root_worker != NULL) {
412 grpc_pollset_worker *worker = pollset->root_worker;
413 do {
414 if (worker->initialized_cv) {
Craig Tiller32f90ee2017-04-28 12:46:41 -0700415 worker->kick_state = KICKED;
Craig Tiller4509c472017-04-27 19:05:13 +0000416 gpr_cv_signal(&worker->cv);
417 } else {
Craig Tiller32f90ee2017-04-28 12:46:41 -0700418 worker->kick_state = KICKED;
Craig Tiller4509c472017-04-27 19:05:13 +0000419 append_error(&error, grpc_wakeup_fd_wakeup(&global_wakeup_fd),
420 "pollset_shutdown");
421 }
422
Craig Tiller32f90ee2017-04-28 12:46:41 -0700423 worker = worker->next;
Craig Tiller4509c472017-04-27 19:05:13 +0000424 } while (worker != pollset->root_worker);
425 }
426 return error;
427}
428
429static void pollset_maybe_finish_shutdown(grpc_exec_ctx *exec_ctx,
430 grpc_pollset *pollset) {
Craig Tillerba550da2017-05-01 14:26:31 +0000431 if (pollset->shutdown_closure != NULL && pollset->root_worker == NULL &&
432 pollset->begin_refs == 0) {
ncteisen969b46e2017-06-08 14:57:11 -0700433 GRPC_CLOSURE_SCHED(exec_ctx, pollset->shutdown_closure, GRPC_ERROR_NONE);
Craig Tiller4509c472017-04-27 19:05:13 +0000434 pollset->shutdown_closure = NULL;
435 }
436}
437
438static void pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
439 grpc_closure *closure) {
440 GPR_ASSERT(pollset->shutdown_closure == NULL);
441 pollset->shutdown_closure = closure;
442 GRPC_LOG_IF_ERROR("pollset_shutdown", pollset_kick_all(pollset));
443 pollset_maybe_finish_shutdown(exec_ctx, pollset);
444}
445
Craig Tillera95bacf2017-05-01 12:51:24 -0700446#define MAX_EPOLL_EVENTS 100
Craig Tiller4509c472017-04-27 19:05:13 +0000447
448static int poll_deadline_to_millis_timeout(gpr_timespec deadline,
449 gpr_timespec now) {
450 gpr_timespec timeout;
451 if (gpr_time_cmp(deadline, gpr_inf_future(deadline.clock_type)) == 0) {
452 return -1;
453 }
454
455 if (gpr_time_cmp(deadline, now) <= 0) {
456 return 0;
457 }
458
459 static const gpr_timespec round_up = {
460 .clock_type = GPR_TIMESPAN, .tv_sec = 0, .tv_nsec = GPR_NS_PER_MS - 1};
461 timeout = gpr_time_sub(deadline, now);
462 int millis = gpr_time_to_millis(gpr_time_add(timeout, round_up));
463 return millis >= 1 ? millis : 1;
464}
465
466static grpc_error *pollset_epoll(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
467 gpr_timespec now, gpr_timespec deadline) {
468 struct epoll_event events[MAX_EPOLL_EVENTS];
469 static const char *err_desc = "pollset_poll";
470
471 int timeout = poll_deadline_to_millis_timeout(deadline, now);
472
473 if (timeout != 0) {
474 GRPC_SCHEDULING_START_BLOCKING_REGION;
475 }
476 int r;
477 do {
Craig Tillerb4bb1cd2017-07-20 14:18:17 -0700478 GRPC_STATS_INC_SYSCALL_POLL(exec_ctx);
Craig Tiller4509c472017-04-27 19:05:13 +0000479 r = epoll_wait(g_epfd, events, MAX_EPOLL_EVENTS, timeout);
480 } while (r < 0 && errno == EINTR);
481 if (timeout != 0) {
482 GRPC_SCHEDULING_END_BLOCKING_REGION;
483 }
484
485 if (r < 0) return GRPC_OS_ERROR(errno, "epoll_wait");
486
487 grpc_error *error = GRPC_ERROR_NONE;
488 for (int i = 0; i < r; i++) {
489 void *data_ptr = events[i].data.ptr;
490 if (data_ptr == &global_wakeup_fd) {
Craig Tiller4509c472017-04-27 19:05:13 +0000491 append_error(&error, grpc_wakeup_fd_consume_wakeup(&global_wakeup_fd),
492 err_desc);
493 } else {
494 grpc_fd *fd = (grpc_fd *)(data_ptr);
495 bool cancel = (events[i].events & (EPOLLERR | EPOLLHUP)) != 0;
496 bool read_ev = (events[i].events & (EPOLLIN | EPOLLPRI)) != 0;
497 bool write_ev = (events[i].events & EPOLLOUT) != 0;
498 if (read_ev || cancel) {
499 fd_become_readable(exec_ctx, fd, pollset);
500 }
501 if (write_ev || cancel) {
502 fd_become_writable(exec_ctx, fd);
503 }
504 }
505 }
506
507 return error;
508}
509
510static bool begin_worker(grpc_pollset *pollset, grpc_pollset_worker *worker,
511 grpc_pollset_worker **worker_hdl, gpr_timespec *now,
512 gpr_timespec deadline) {
Craig Tiller4509c472017-04-27 19:05:13 +0000513 if (worker_hdl != NULL) *worker_hdl = worker;
514 worker->initialized_cv = false;
Craig Tiller32f90ee2017-04-28 12:46:41 -0700515 worker->kick_state = UNKICKED;
Craig Tiller50da5ec2017-05-01 13:51:14 -0700516 worker->schedule_on_end_work = (grpc_closure_list)GRPC_CLOSURE_LIST_INIT;
Craig Tillerba550da2017-05-01 14:26:31 +0000517 pollset->begin_refs++;
Craig Tiller4509c472017-04-27 19:05:13 +0000518
Craig Tiller32f90ee2017-04-28 12:46:41 -0700519 if (pollset->seen_inactive) {
520 // pollset has been observed to be inactive, we need to move back to the
521 // active list
Craig Tillere00d7332017-05-01 15:43:51 +0000522 bool is_reassigning = false;
523 if (!pollset->reassigning_neighbourhood) {
524 is_reassigning = true;
525 pollset->reassigning_neighbourhood = true;
526 pollset->neighbourhood = &g_neighbourhoods[choose_neighbourhood()];
527 }
528 pollset_neighbourhood *neighbourhood = pollset->neighbourhood;
Craig Tiller32f90ee2017-04-28 12:46:41 -0700529 gpr_mu_unlock(&pollset->mu);
Craig Tillerba550da2017-05-01 14:26:31 +0000530 // pollset unlocked: state may change (even worker->kick_state)
531 retry_lock_neighbourhood:
Craig Tiller32f90ee2017-04-28 12:46:41 -0700532 gpr_mu_lock(&neighbourhood->mu);
533 gpr_mu_lock(&pollset->mu);
534 if (pollset->seen_inactive) {
Craig Tiller2acab6e2017-04-30 23:06:33 +0000535 if (neighbourhood != pollset->neighbourhood) {
536 gpr_mu_unlock(&neighbourhood->mu);
537 neighbourhood = pollset->neighbourhood;
538 gpr_mu_unlock(&pollset->mu);
539 goto retry_lock_neighbourhood;
540 }
Craig Tiller32f90ee2017-04-28 12:46:41 -0700541 pollset->seen_inactive = false;
Craig Tiller2acab6e2017-04-30 23:06:33 +0000542 if (neighbourhood->active_root == NULL) {
543 neighbourhood->active_root = pollset->next = pollset->prev = pollset;
Craig Tiller32f90ee2017-04-28 12:46:41 -0700544 if (gpr_atm_no_barrier_cas(&g_active_poller, 0, (gpr_atm)worker)) {
Craig Tiller43bf2592017-04-28 23:21:01 +0000545 worker->kick_state = DESIGNATED_POLLER;
Craig Tiller32f90ee2017-04-28 12:46:41 -0700546 }
Craig Tiller2acab6e2017-04-30 23:06:33 +0000547 } else {
548 pollset->next = neighbourhood->active_root;
549 pollset->prev = pollset->next->prev;
550 pollset->next->prev = pollset->prev->next = pollset;
Craig Tiller4509c472017-04-27 19:05:13 +0000551 }
552 }
Craig Tillere00d7332017-05-01 15:43:51 +0000553 if (is_reassigning) {
554 GPR_ASSERT(pollset->reassigning_neighbourhood);
555 pollset->reassigning_neighbourhood = false;
556 }
Craig Tiller32f90ee2017-04-28 12:46:41 -0700557 gpr_mu_unlock(&neighbourhood->mu);
558 }
559 worker_insert(pollset, worker);
Craig Tillerba550da2017-05-01 14:26:31 +0000560 pollset->begin_refs--;
Craig Tiller32f90ee2017-04-28 12:46:41 -0700561 if (worker->kick_state == UNKICKED) {
Craig Tillera4b8eb02017-04-29 00:13:52 +0000562 GPR_ASSERT(gpr_atm_no_barrier_load(&g_active_poller) != (gpr_atm)worker);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700563 worker->initialized_cv = true;
564 gpr_cv_init(&worker->cv);
Craig Tillerba550da2017-05-01 14:26:31 +0000565 while (worker->kick_state == UNKICKED &&
566 pollset->shutdown_closure == NULL) {
Craig Tiller32f90ee2017-04-28 12:46:41 -0700567 if (gpr_cv_wait(&worker->cv, &pollset->mu, deadline) &&
568 worker->kick_state == UNKICKED) {
569 worker->kick_state = KICKED;
570 }
Craig Tillerba550da2017-05-01 14:26:31 +0000571 }
Craig Tiller4509c472017-04-27 19:05:13 +0000572 *now = gpr_now(now->clock_type);
573 }
574
Craig Tiller43bf2592017-04-28 23:21:01 +0000575 return worker->kick_state == DESIGNATED_POLLER &&
Craig Tiller32f90ee2017-04-28 12:46:41 -0700576 pollset->shutdown_closure == NULL;
Craig Tiller4509c472017-04-27 19:05:13 +0000577}
578
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700579static bool check_neighbourhood_for_available_poller(
Craig Tillera4b8eb02017-04-29 00:13:52 +0000580 pollset_neighbourhood *neighbourhood) {
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700581 bool found_worker = false;
582 do {
583 grpc_pollset *inspect = neighbourhood->active_root;
584 if (inspect == NULL) {
585 break;
586 }
587 gpr_mu_lock(&inspect->mu);
588 GPR_ASSERT(!inspect->seen_inactive);
589 grpc_pollset_worker *inspect_worker = inspect->root_worker;
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700590 if (inspect_worker != NULL) {
Craig Tillera4b8eb02017-04-29 00:13:52 +0000591 do {
Craig Tillerba550da2017-05-01 14:26:31 +0000592 switch (inspect_worker->kick_state) {
593 case UNKICKED:
594 if (gpr_atm_no_barrier_cas(&g_active_poller, 0,
595 (gpr_atm)inspect_worker)) {
596 inspect_worker->kick_state = DESIGNATED_POLLER;
597 if (inspect_worker->initialized_cv) {
598 gpr_cv_signal(&inspect_worker->cv);
599 }
Craig Tillera4b8eb02017-04-29 00:13:52 +0000600 }
Craig Tillerba550da2017-05-01 14:26:31 +0000601 // even if we didn't win the cas, there's a worker, we can stop
602 found_worker = true;
603 break;
604 case KICKED:
605 break;
606 case DESIGNATED_POLLER:
607 found_worker = true; // ok, so someone else found the worker, but
608 // we'll accept that
609 break;
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700610 }
Craig Tillera4b8eb02017-04-29 00:13:52 +0000611 inspect_worker = inspect_worker->next;
612 } while (inspect_worker != inspect->root_worker);
613 }
614 if (!found_worker) {
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700615 inspect->seen_inactive = true;
Craig Tiller2acab6e2017-04-30 23:06:33 +0000616 if (inspect == neighbourhood->active_root) {
Craig Tillera95bacf2017-05-01 12:51:24 -0700617 neighbourhood->active_root =
618 inspect->next == inspect ? NULL : inspect->next;
Craig Tiller2acab6e2017-04-30 23:06:33 +0000619 }
620 inspect->next->prev = inspect->prev;
621 inspect->prev->next = inspect->next;
Craig Tillere00d7332017-05-01 15:43:51 +0000622 inspect->next = inspect->prev = NULL;
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700623 }
624 gpr_mu_unlock(&inspect->mu);
625 } while (!found_worker);
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700626 return found_worker;
627}
628
Craig Tiller4509c472017-04-27 19:05:13 +0000629static void end_worker(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
630 grpc_pollset_worker *worker,
631 grpc_pollset_worker **worker_hdl) {
Craig Tiller8502ecb2017-04-28 14:22:01 -0700632 if (worker_hdl != NULL) *worker_hdl = NULL;
Craig Tillera4b8eb02017-04-29 00:13:52 +0000633 worker->kick_state = KICKED;
Craig Tiller50da5ec2017-05-01 13:51:14 -0700634 grpc_closure_list_move(&worker->schedule_on_end_work,
635 &exec_ctx->closure_list);
Craig Tiller8502ecb2017-04-28 14:22:01 -0700636 if (gpr_atm_no_barrier_load(&g_active_poller) == (gpr_atm)worker) {
Craig Tillera4b8eb02017-04-29 00:13:52 +0000637 if (worker->next != worker && worker->next->kick_state == UNKICKED) {
Craig Tiller2acab6e2017-04-30 23:06:33 +0000638 GPR_ASSERT(worker->next->initialized_cv);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700639 gpr_atm_no_barrier_store(&g_active_poller, (gpr_atm)worker->next);
Craig Tiller43bf2592017-04-28 23:21:01 +0000640 worker->next->kick_state = DESIGNATED_POLLER;
Craig Tiller32f90ee2017-04-28 12:46:41 -0700641 gpr_cv_signal(&worker->next->cv);
Craig Tiller8502ecb2017-04-28 14:22:01 -0700642 if (grpc_exec_ctx_has_work(exec_ctx)) {
643 gpr_mu_unlock(&pollset->mu);
644 grpc_exec_ctx_flush(exec_ctx);
645 gpr_mu_lock(&pollset->mu);
646 }
Craig Tiller32f90ee2017-04-28 12:46:41 -0700647 } else {
648 gpr_atm_no_barrier_store(&g_active_poller, 0);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700649 gpr_mu_unlock(&pollset->mu);
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700650 size_t poller_neighbourhood_idx =
651 (size_t)(pollset->neighbourhood - g_neighbourhoods);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700652 bool found_worker = false;
Craig Tillerba550da2017-05-01 14:26:31 +0000653 bool scan_state[MAX_NEIGHBOURHOODS];
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700654 for (size_t i = 0; !found_worker && i < g_num_neighbourhoods; i++) {
655 pollset_neighbourhood *neighbourhood =
656 &g_neighbourhoods[(poller_neighbourhood_idx + i) %
657 g_num_neighbourhoods];
658 if (gpr_mu_trylock(&neighbourhood->mu)) {
659 found_worker =
Craig Tillera4b8eb02017-04-29 00:13:52 +0000660 check_neighbourhood_for_available_poller(neighbourhood);
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700661 gpr_mu_unlock(&neighbourhood->mu);
Craig Tillerba550da2017-05-01 14:26:31 +0000662 scan_state[i] = true;
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700663 } else {
Craig Tillerba550da2017-05-01 14:26:31 +0000664 scan_state[i] = false;
Craig Tiller32f90ee2017-04-28 12:46:41 -0700665 }
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700666 }
Craig Tiller2acab6e2017-04-30 23:06:33 +0000667 for (size_t i = 0; !found_worker && i < g_num_neighbourhoods; i++) {
Craig Tillerba550da2017-05-01 14:26:31 +0000668 if (scan_state[i]) continue;
Craig Tiller2acab6e2017-04-30 23:06:33 +0000669 pollset_neighbourhood *neighbourhood =
670 &g_neighbourhoods[(poller_neighbourhood_idx + i) %
671 g_num_neighbourhoods];
672 gpr_mu_lock(&neighbourhood->mu);
Craig Tillerba550da2017-05-01 14:26:31 +0000673 found_worker = check_neighbourhood_for_available_poller(neighbourhood);
Craig Tiller2acab6e2017-04-30 23:06:33 +0000674 gpr_mu_unlock(&neighbourhood->mu);
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700675 }
Craig Tiller8502ecb2017-04-28 14:22:01 -0700676 grpc_exec_ctx_flush(exec_ctx);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700677 gpr_mu_lock(&pollset->mu);
678 }
Craig Tiller50da5ec2017-05-01 13:51:14 -0700679 } else if (grpc_exec_ctx_has_work(exec_ctx)) {
680 gpr_mu_unlock(&pollset->mu);
681 grpc_exec_ctx_flush(exec_ctx);
682 gpr_mu_lock(&pollset->mu);
Craig Tiller4509c472017-04-27 19:05:13 +0000683 }
684 if (worker->initialized_cv) {
685 gpr_cv_destroy(&worker->cv);
686 }
Craig Tiller32f90ee2017-04-28 12:46:41 -0700687 if (EMPTIED == worker_remove(pollset, worker)) {
Craig Tiller4509c472017-04-27 19:05:13 +0000688 pollset_maybe_finish_shutdown(exec_ctx, pollset);
689 }
Craig Tillera4b8eb02017-04-29 00:13:52 +0000690 GPR_ASSERT(gpr_atm_no_barrier_load(&g_active_poller) != (gpr_atm)worker);
Craig Tiller4509c472017-04-27 19:05:13 +0000691}
692
693/* pollset->po.mu lock must be held by the caller before calling this.
694 The function pollset_work() may temporarily release the lock (pollset->po.mu)
695 during the course of its execution but it will always re-acquire the lock and
696 ensure that it is held by the time the function returns */
697static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
698 grpc_pollset_worker **worker_hdl,
699 gpr_timespec now, gpr_timespec deadline) {
700 grpc_pollset_worker worker;
701 grpc_error *error = GRPC_ERROR_NONE;
702 static const char *err_desc = "pollset_work";
703 if (pollset->kicked_without_poller) {
704 pollset->kicked_without_poller = false;
705 return GRPC_ERROR_NONE;
706 }
Craig Tiller8502ecb2017-04-28 14:22:01 -0700707 gpr_tls_set(&g_current_thread_pollset, (intptr_t)pollset);
Craig Tiller4509c472017-04-27 19:05:13 +0000708 if (begin_worker(pollset, &worker, worker_hdl, &now, deadline)) {
Craig Tiller4509c472017-04-27 19:05:13 +0000709 gpr_tls_set(&g_current_thread_worker, (intptr_t)&worker);
710 GPR_ASSERT(!pollset->shutdown_closure);
Craig Tiller2acab6e2017-04-30 23:06:33 +0000711 GPR_ASSERT(!pollset->seen_inactive);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700712 gpr_mu_unlock(&pollset->mu);
Craig Tiller4509c472017-04-27 19:05:13 +0000713 append_error(&error, pollset_epoll(exec_ctx, pollset, now, deadline),
714 err_desc);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700715 gpr_mu_lock(&pollset->mu);
Craig Tiller4509c472017-04-27 19:05:13 +0000716 gpr_tls_set(&g_current_thread_worker, 0);
Craig Tiller4509c472017-04-27 19:05:13 +0000717 }
718 end_worker(exec_ctx, pollset, &worker, worker_hdl);
Craig Tiller8502ecb2017-04-28 14:22:01 -0700719 gpr_tls_set(&g_current_thread_pollset, 0);
Craig Tiller4509c472017-04-27 19:05:13 +0000720 return error;
721}
722
723static grpc_error *pollset_kick(grpc_pollset *pollset,
724 grpc_pollset_worker *specific_worker) {
725 if (specific_worker == NULL) {
726 if (gpr_tls_get(&g_current_thread_pollset) != (intptr_t)pollset) {
Craig Tiller375eb252017-04-27 23:29:12 +0000727 grpc_pollset_worker *root_worker = pollset->root_worker;
728 if (root_worker == NULL) {
Craig Tiller4509c472017-04-27 19:05:13 +0000729 pollset->kicked_without_poller = true;
730 return GRPC_ERROR_NONE;
Craig Tiller375eb252017-04-27 23:29:12 +0000731 }
Craig Tiller32f90ee2017-04-28 12:46:41 -0700732 grpc_pollset_worker *next_worker = root_worker->next;
733 if (root_worker == next_worker &&
734 root_worker == (grpc_pollset_worker *)gpr_atm_no_barrier_load(
735 &g_active_poller)) {
736 root_worker->kick_state = KICKED;
Craig Tiller4509c472017-04-27 19:05:13 +0000737 return grpc_wakeup_fd_wakeup(&global_wakeup_fd);
Craig Tiller8502ecb2017-04-28 14:22:01 -0700738 } else if (next_worker->kick_state == UNKICKED) {
739 GPR_ASSERT(next_worker->initialized_cv);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700740 next_worker->kick_state = KICKED;
Craig Tiller375eb252017-04-27 23:29:12 +0000741 gpr_cv_signal(&next_worker->cv);
742 return GRPC_ERROR_NONE;
Craig Tiller8502ecb2017-04-28 14:22:01 -0700743 } else {
744 return GRPC_ERROR_NONE;
Craig Tiller4509c472017-04-27 19:05:13 +0000745 }
746 } else {
747 return GRPC_ERROR_NONE;
748 }
Craig Tiller43bf2592017-04-28 23:21:01 +0000749 } else if (specific_worker->kick_state == KICKED) {
Craig Tiller4509c472017-04-27 19:05:13 +0000750 return GRPC_ERROR_NONE;
751 } else if (gpr_tls_get(&g_current_thread_worker) ==
752 (intptr_t)specific_worker) {
Craig Tiller32f90ee2017-04-28 12:46:41 -0700753 specific_worker->kick_state = KICKED;
Craig Tiller4509c472017-04-27 19:05:13 +0000754 return GRPC_ERROR_NONE;
Craig Tiller32f90ee2017-04-28 12:46:41 -0700755 } else if (specific_worker ==
756 (grpc_pollset_worker *)gpr_atm_no_barrier_load(&g_active_poller)) {
757 specific_worker->kick_state = KICKED;
Craig Tiller4509c472017-04-27 19:05:13 +0000758 return grpc_wakeup_fd_wakeup(&global_wakeup_fd);
Craig Tiller8502ecb2017-04-28 14:22:01 -0700759 } else if (specific_worker->initialized_cv) {
Craig Tiller32f90ee2017-04-28 12:46:41 -0700760 specific_worker->kick_state = KICKED;
Craig Tiller4509c472017-04-27 19:05:13 +0000761 gpr_cv_signal(&specific_worker->cv);
762 return GRPC_ERROR_NONE;
Craig Tiller8502ecb2017-04-28 14:22:01 -0700763 } else {
764 specific_worker->kick_state = KICKED;
765 return GRPC_ERROR_NONE;
Craig Tiller4509c472017-04-27 19:05:13 +0000766 }
767}
768
769static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
770 grpc_fd *fd) {}
771
Craig Tiller4509c472017-04-27 19:05:13 +0000772/*******************************************************************************
Craig Tillerc67cc992017-04-27 10:15:51 -0700773 * Pollset-set Definitions
774 */
775
776static grpc_pollset_set *pollset_set_create(void) {
777 return (grpc_pollset_set *)((intptr_t)0xdeafbeef);
778}
779
780static void pollset_set_destroy(grpc_exec_ctx *exec_ctx,
781 grpc_pollset_set *pss) {}
782
783static void pollset_set_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pss,
784 grpc_fd *fd) {}
785
786static void pollset_set_del_fd(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pss,
787 grpc_fd *fd) {}
788
789static void pollset_set_add_pollset(grpc_exec_ctx *exec_ctx,
790 grpc_pollset_set *pss, grpc_pollset *ps) {}
791
792static void pollset_set_del_pollset(grpc_exec_ctx *exec_ctx,
793 grpc_pollset_set *pss, grpc_pollset *ps) {}
794
795static void pollset_set_add_pollset_set(grpc_exec_ctx *exec_ctx,
796 grpc_pollset_set *bag,
797 grpc_pollset_set *item) {}
798
799static void pollset_set_del_pollset_set(grpc_exec_ctx *exec_ctx,
800 grpc_pollset_set *bag,
801 grpc_pollset_set *item) {}
802
803/*******************************************************************************
804 * Event engine binding
805 */
806
807static void shutdown_engine(void) {
808 fd_global_shutdown();
809 pollset_global_shutdown();
Craig Tillerc67cc992017-04-27 10:15:51 -0700810}
811
812static const grpc_event_engine_vtable vtable = {
813 .pollset_size = sizeof(grpc_pollset),
814
815 .fd_create = fd_create,
816 .fd_wrapped_fd = fd_wrapped_fd,
817 .fd_orphan = fd_orphan,
818 .fd_shutdown = fd_shutdown,
819 .fd_is_shutdown = fd_is_shutdown,
820 .fd_notify_on_read = fd_notify_on_read,
821 .fd_notify_on_write = fd_notify_on_write,
822 .fd_get_read_notifier_pollset = fd_get_read_notifier_pollset,
Craig Tillerc67cc992017-04-27 10:15:51 -0700823
824 .pollset_init = pollset_init,
825 .pollset_shutdown = pollset_shutdown,
826 .pollset_destroy = pollset_destroy,
827 .pollset_work = pollset_work,
828 .pollset_kick = pollset_kick,
829 .pollset_add_fd = pollset_add_fd,
830
831 .pollset_set_create = pollset_set_create,
832 .pollset_set_destroy = pollset_set_destroy,
833 .pollset_set_add_pollset = pollset_set_add_pollset,
834 .pollset_set_del_pollset = pollset_set_del_pollset,
835 .pollset_set_add_pollset_set = pollset_set_add_pollset_set,
836 .pollset_set_del_pollset_set = pollset_set_del_pollset_set,
837 .pollset_set_add_fd = pollset_set_add_fd,
838 .pollset_set_del_fd = pollset_set_del_fd,
839
Craig Tillerc67cc992017-04-27 10:15:51 -0700840 .shutdown_engine = shutdown_engine,
841};
842
843/* It is possible that GLIBC has epoll but the underlying kernel doesn't.
844 * Create a dummy epoll_fd to make sure epoll support is available */
Craig Tiller6f0af492017-04-27 19:26:16 +0000845const grpc_event_engine_vtable *grpc_init_epoll1_linux(bool explicit_request) {
Craig Tiller924353a2017-05-05 17:36:31 +0000846 /* TODO(ctiller): temporary, until this stabilizes */
847 if (!explicit_request) return NULL;
848
Craig Tillerc67cc992017-04-27 10:15:51 -0700849 if (!grpc_has_wakeup_fd()) {
850 return NULL;
851 }
852
Craig Tiller4509c472017-04-27 19:05:13 +0000853 g_epfd = epoll_create1(EPOLL_CLOEXEC);
854 if (g_epfd < 0) {
855 gpr_log(GPR_ERROR, "epoll unavailable");
Craig Tillerc67cc992017-04-27 10:15:51 -0700856 return NULL;
857 }
858
Craig Tillerc67cc992017-04-27 10:15:51 -0700859 fd_global_init();
860
861 if (!GRPC_LOG_IF_ERROR("pollset_global_init", pollset_global_init())) {
Craig Tiller4509c472017-04-27 19:05:13 +0000862 close(g_epfd);
863 fd_global_shutdown();
Craig Tillerc67cc992017-04-27 10:15:51 -0700864 return NULL;
865 }
866
867 return &vtable;
868}
869
870#else /* defined(GRPC_LINUX_EPOLL) */
871#if defined(GRPC_POSIX_SOCKET)
872#include "src/core/lib/iomgr/ev_posix.h"
873/* If GRPC_LINUX_EPOLL is not defined, it means epoll is not available. Return
874 * NULL */
Craig Tiller9ddb3152017-04-27 21:32:56 +0000875const grpc_event_engine_vtable *grpc_init_epoll1_linux(bool explicit_request) {
876 return NULL;
877}
Craig Tillerc67cc992017-04-27 10:15:51 -0700878#endif /* defined(GRPC_POSIX_SOCKET) */
879#endif /* !defined(GRPC_LINUX_EPOLL) */