blob: 4eaaaa06dda71550fdafc87a06a4c174352067a2 [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>
Craig Tiller20397792017-07-18 11:35:27 -070028#include <limits.h>
Craig Tillerc67cc992017-04-27 10:15:51 -070029#include <poll.h>
30#include <pthread.h>
31#include <string.h>
32#include <sys/epoll.h>
33#include <sys/socket.h>
34#include <unistd.h>
35
36#include <grpc/support/alloc.h>
Craig Tiller6de05932017-04-28 09:17:38 -070037#include <grpc/support/cpu.h>
Craig Tillerc67cc992017-04-27 10:15:51 -070038#include <grpc/support/log.h>
39#include <grpc/support/string_util.h>
40#include <grpc/support/tls.h>
41#include <grpc/support/useful.h>
42
43#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
Craig Tiller20397792017-07-18 11:35:27 -0700448static int poll_deadline_to_millis_timeout(grpc_exec_ctx *exec_ctx,
449 grpc_millis millis) {
450 if (millis == GRPC_MILLIS_INF_FUTURE) return -1;
451 grpc_millis delta = millis - grpc_exec_ctx_now(exec_ctx);
452 if (delta > INT_MAX)
453 return INT_MAX;
454 else if (delta < 0)
Craig Tiller4509c472017-04-27 19:05:13 +0000455 return 0;
Craig Tiller20397792017-07-18 11:35:27 -0700456 else
457 return (int)delta;
Craig Tiller4509c472017-04-27 19:05:13 +0000458}
459
460static grpc_error *pollset_epoll(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
Craig Tiller20397792017-07-18 11:35:27 -0700461 grpc_millis deadline) {
Craig Tiller4509c472017-04-27 19:05:13 +0000462 struct epoll_event events[MAX_EPOLL_EVENTS];
463 static const char *err_desc = "pollset_poll";
464
Craig Tiller20397792017-07-18 11:35:27 -0700465 int timeout = poll_deadline_to_millis_timeout(exec_ctx, deadline);
Craig Tiller4509c472017-04-27 19:05:13 +0000466
467 if (timeout != 0) {
468 GRPC_SCHEDULING_START_BLOCKING_REGION;
469 }
470 int r;
471 do {
472 r = epoll_wait(g_epfd, events, MAX_EPOLL_EVENTS, timeout);
473 } while (r < 0 && errno == EINTR);
474 if (timeout != 0) {
Craig Tiller781e91a2017-07-17 16:21:00 -0700475 GRPC_SCHEDULING_END_BLOCKING_REGION_WITH_EXEC_CTX(exec_ctx);
Craig Tiller4509c472017-04-27 19:05:13 +0000476 }
477
478 if (r < 0) return GRPC_OS_ERROR(errno, "epoll_wait");
479
480 grpc_error *error = GRPC_ERROR_NONE;
481 for (int i = 0; i < r; i++) {
482 void *data_ptr = events[i].data.ptr;
483 if (data_ptr == &global_wakeup_fd) {
Craig Tiller4509c472017-04-27 19:05:13 +0000484 append_error(&error, grpc_wakeup_fd_consume_wakeup(&global_wakeup_fd),
485 err_desc);
486 } else {
487 grpc_fd *fd = (grpc_fd *)(data_ptr);
488 bool cancel = (events[i].events & (EPOLLERR | EPOLLHUP)) != 0;
489 bool read_ev = (events[i].events & (EPOLLIN | EPOLLPRI)) != 0;
490 bool write_ev = (events[i].events & EPOLLOUT) != 0;
491 if (read_ev || cancel) {
492 fd_become_readable(exec_ctx, fd, pollset);
493 }
494 if (write_ev || cancel) {
495 fd_become_writable(exec_ctx, fd);
496 }
497 }
498 }
499
500 return error;
501}
502
Craig Tiller20397792017-07-18 11:35:27 -0700503static bool begin_worker(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
504 grpc_pollset_worker *worker,
505 grpc_pollset_worker **worker_hdl,
506 grpc_millis deadline) {
Craig Tiller4509c472017-04-27 19:05:13 +0000507 if (worker_hdl != NULL) *worker_hdl = worker;
508 worker->initialized_cv = false;
Craig Tiller32f90ee2017-04-28 12:46:41 -0700509 worker->kick_state = UNKICKED;
Craig Tiller50da5ec2017-05-01 13:51:14 -0700510 worker->schedule_on_end_work = (grpc_closure_list)GRPC_CLOSURE_LIST_INIT;
Craig Tillerba550da2017-05-01 14:26:31 +0000511 pollset->begin_refs++;
Craig Tiller4509c472017-04-27 19:05:13 +0000512
Craig Tiller32f90ee2017-04-28 12:46:41 -0700513 if (pollset->seen_inactive) {
514 // pollset has been observed to be inactive, we need to move back to the
515 // active list
Craig Tillere00d7332017-05-01 15:43:51 +0000516 bool is_reassigning = false;
517 if (!pollset->reassigning_neighbourhood) {
518 is_reassigning = true;
519 pollset->reassigning_neighbourhood = true;
520 pollset->neighbourhood = &g_neighbourhoods[choose_neighbourhood()];
521 }
522 pollset_neighbourhood *neighbourhood = pollset->neighbourhood;
Craig Tiller32f90ee2017-04-28 12:46:41 -0700523 gpr_mu_unlock(&pollset->mu);
Craig Tillerba550da2017-05-01 14:26:31 +0000524 // pollset unlocked: state may change (even worker->kick_state)
525 retry_lock_neighbourhood:
Craig Tiller32f90ee2017-04-28 12:46:41 -0700526 gpr_mu_lock(&neighbourhood->mu);
527 gpr_mu_lock(&pollset->mu);
528 if (pollset->seen_inactive) {
Craig Tiller2acab6e2017-04-30 23:06:33 +0000529 if (neighbourhood != pollset->neighbourhood) {
530 gpr_mu_unlock(&neighbourhood->mu);
531 neighbourhood = pollset->neighbourhood;
532 gpr_mu_unlock(&pollset->mu);
533 goto retry_lock_neighbourhood;
534 }
Craig Tiller32f90ee2017-04-28 12:46:41 -0700535 pollset->seen_inactive = false;
Craig Tiller2acab6e2017-04-30 23:06:33 +0000536 if (neighbourhood->active_root == NULL) {
537 neighbourhood->active_root = pollset->next = pollset->prev = pollset;
Craig Tiller32f90ee2017-04-28 12:46:41 -0700538 if (gpr_atm_no_barrier_cas(&g_active_poller, 0, (gpr_atm)worker)) {
Craig Tiller43bf2592017-04-28 23:21:01 +0000539 worker->kick_state = DESIGNATED_POLLER;
Craig Tiller32f90ee2017-04-28 12:46:41 -0700540 }
Craig Tiller2acab6e2017-04-30 23:06:33 +0000541 } else {
542 pollset->next = neighbourhood->active_root;
543 pollset->prev = pollset->next->prev;
544 pollset->next->prev = pollset->prev->next = pollset;
Craig Tiller4509c472017-04-27 19:05:13 +0000545 }
546 }
Craig Tillere00d7332017-05-01 15:43:51 +0000547 if (is_reassigning) {
548 GPR_ASSERT(pollset->reassigning_neighbourhood);
549 pollset->reassigning_neighbourhood = false;
550 }
Craig Tiller32f90ee2017-04-28 12:46:41 -0700551 gpr_mu_unlock(&neighbourhood->mu);
552 }
553 worker_insert(pollset, worker);
Craig Tillerba550da2017-05-01 14:26:31 +0000554 pollset->begin_refs--;
Craig Tiller32f90ee2017-04-28 12:46:41 -0700555 if (worker->kick_state == UNKICKED) {
Craig Tillera4b8eb02017-04-29 00:13:52 +0000556 GPR_ASSERT(gpr_atm_no_barrier_load(&g_active_poller) != (gpr_atm)worker);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700557 worker->initialized_cv = true;
558 gpr_cv_init(&worker->cv);
Craig Tillerba550da2017-05-01 14:26:31 +0000559 while (worker->kick_state == UNKICKED &&
560 pollset->shutdown_closure == NULL) {
Craig Tiller20397792017-07-18 11:35:27 -0700561 if (gpr_cv_wait(&worker->cv, &pollset->mu,
562 grpc_millis_to_timespec(deadline, GPR_CLOCK_REALTIME)) &&
Craig Tiller32f90ee2017-04-28 12:46:41 -0700563 worker->kick_state == UNKICKED) {
564 worker->kick_state = KICKED;
565 }
Craig Tillerba550da2017-05-01 14:26:31 +0000566 }
Craig Tiller20397792017-07-18 11:35:27 -0700567 grpc_exec_ctx_invalidate_now(exec_ctx);
Craig Tiller4509c472017-04-27 19:05:13 +0000568 }
569
Craig Tiller43bf2592017-04-28 23:21:01 +0000570 return worker->kick_state == DESIGNATED_POLLER &&
Craig Tiller32f90ee2017-04-28 12:46:41 -0700571 pollset->shutdown_closure == NULL;
Craig Tiller4509c472017-04-27 19:05:13 +0000572}
573
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700574static bool check_neighbourhood_for_available_poller(
Craig Tillera4b8eb02017-04-29 00:13:52 +0000575 pollset_neighbourhood *neighbourhood) {
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700576 bool found_worker = false;
577 do {
578 grpc_pollset *inspect = neighbourhood->active_root;
579 if (inspect == NULL) {
580 break;
581 }
582 gpr_mu_lock(&inspect->mu);
583 GPR_ASSERT(!inspect->seen_inactive);
584 grpc_pollset_worker *inspect_worker = inspect->root_worker;
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700585 if (inspect_worker != NULL) {
Craig Tillera4b8eb02017-04-29 00:13:52 +0000586 do {
Craig Tillerba550da2017-05-01 14:26:31 +0000587 switch (inspect_worker->kick_state) {
588 case UNKICKED:
589 if (gpr_atm_no_barrier_cas(&g_active_poller, 0,
590 (gpr_atm)inspect_worker)) {
591 inspect_worker->kick_state = DESIGNATED_POLLER;
592 if (inspect_worker->initialized_cv) {
593 gpr_cv_signal(&inspect_worker->cv);
594 }
Craig Tillera4b8eb02017-04-29 00:13:52 +0000595 }
Craig Tillerba550da2017-05-01 14:26:31 +0000596 // even if we didn't win the cas, there's a worker, we can stop
597 found_worker = true;
598 break;
599 case KICKED:
600 break;
601 case DESIGNATED_POLLER:
602 found_worker = true; // ok, so someone else found the worker, but
603 // we'll accept that
604 break;
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700605 }
Craig Tillera4b8eb02017-04-29 00:13:52 +0000606 inspect_worker = inspect_worker->next;
607 } while (inspect_worker != inspect->root_worker);
608 }
609 if (!found_worker) {
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700610 inspect->seen_inactive = true;
Craig Tiller2acab6e2017-04-30 23:06:33 +0000611 if (inspect == neighbourhood->active_root) {
Craig Tillera95bacf2017-05-01 12:51:24 -0700612 neighbourhood->active_root =
613 inspect->next == inspect ? NULL : inspect->next;
Craig Tiller2acab6e2017-04-30 23:06:33 +0000614 }
615 inspect->next->prev = inspect->prev;
616 inspect->prev->next = inspect->next;
Craig Tillere00d7332017-05-01 15:43:51 +0000617 inspect->next = inspect->prev = NULL;
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700618 }
619 gpr_mu_unlock(&inspect->mu);
620 } while (!found_worker);
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700621 return found_worker;
622}
623
Craig Tiller4509c472017-04-27 19:05:13 +0000624static void end_worker(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
625 grpc_pollset_worker *worker,
626 grpc_pollset_worker **worker_hdl) {
Craig Tiller8502ecb2017-04-28 14:22:01 -0700627 if (worker_hdl != NULL) *worker_hdl = NULL;
Craig Tillera4b8eb02017-04-29 00:13:52 +0000628 worker->kick_state = KICKED;
Craig Tiller50da5ec2017-05-01 13:51:14 -0700629 grpc_closure_list_move(&worker->schedule_on_end_work,
630 &exec_ctx->closure_list);
Craig Tiller8502ecb2017-04-28 14:22:01 -0700631 if (gpr_atm_no_barrier_load(&g_active_poller) == (gpr_atm)worker) {
Craig Tillera4b8eb02017-04-29 00:13:52 +0000632 if (worker->next != worker && worker->next->kick_state == UNKICKED) {
Craig Tiller2acab6e2017-04-30 23:06:33 +0000633 GPR_ASSERT(worker->next->initialized_cv);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700634 gpr_atm_no_barrier_store(&g_active_poller, (gpr_atm)worker->next);
Craig Tiller43bf2592017-04-28 23:21:01 +0000635 worker->next->kick_state = DESIGNATED_POLLER;
Craig Tiller32f90ee2017-04-28 12:46:41 -0700636 gpr_cv_signal(&worker->next->cv);
Craig Tiller8502ecb2017-04-28 14:22:01 -0700637 if (grpc_exec_ctx_has_work(exec_ctx)) {
638 gpr_mu_unlock(&pollset->mu);
639 grpc_exec_ctx_flush(exec_ctx);
640 gpr_mu_lock(&pollset->mu);
641 }
Craig Tiller32f90ee2017-04-28 12:46:41 -0700642 } else {
643 gpr_atm_no_barrier_store(&g_active_poller, 0);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700644 gpr_mu_unlock(&pollset->mu);
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700645 size_t poller_neighbourhood_idx =
646 (size_t)(pollset->neighbourhood - g_neighbourhoods);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700647 bool found_worker = false;
Craig Tillerba550da2017-05-01 14:26:31 +0000648 bool scan_state[MAX_NEIGHBOURHOODS];
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700649 for (size_t i = 0; !found_worker && i < g_num_neighbourhoods; i++) {
650 pollset_neighbourhood *neighbourhood =
651 &g_neighbourhoods[(poller_neighbourhood_idx + i) %
652 g_num_neighbourhoods];
653 if (gpr_mu_trylock(&neighbourhood->mu)) {
654 found_worker =
Craig Tillera4b8eb02017-04-29 00:13:52 +0000655 check_neighbourhood_for_available_poller(neighbourhood);
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700656 gpr_mu_unlock(&neighbourhood->mu);
Craig Tillerba550da2017-05-01 14:26:31 +0000657 scan_state[i] = true;
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700658 } else {
Craig Tillerba550da2017-05-01 14:26:31 +0000659 scan_state[i] = false;
Craig Tiller32f90ee2017-04-28 12:46:41 -0700660 }
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700661 }
Craig Tiller2acab6e2017-04-30 23:06:33 +0000662 for (size_t i = 0; !found_worker && i < g_num_neighbourhoods; i++) {
Craig Tillerba550da2017-05-01 14:26:31 +0000663 if (scan_state[i]) continue;
Craig Tiller2acab6e2017-04-30 23:06:33 +0000664 pollset_neighbourhood *neighbourhood =
665 &g_neighbourhoods[(poller_neighbourhood_idx + i) %
666 g_num_neighbourhoods];
667 gpr_mu_lock(&neighbourhood->mu);
Craig Tillerba550da2017-05-01 14:26:31 +0000668 found_worker = check_neighbourhood_for_available_poller(neighbourhood);
Craig Tiller2acab6e2017-04-30 23:06:33 +0000669 gpr_mu_unlock(&neighbourhood->mu);
Craig Tillerbbf4c7a2017-04-28 15:12:10 -0700670 }
Craig Tiller8502ecb2017-04-28 14:22:01 -0700671 grpc_exec_ctx_flush(exec_ctx);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700672 gpr_mu_lock(&pollset->mu);
673 }
Craig Tiller50da5ec2017-05-01 13:51:14 -0700674 } else if (grpc_exec_ctx_has_work(exec_ctx)) {
675 gpr_mu_unlock(&pollset->mu);
676 grpc_exec_ctx_flush(exec_ctx);
677 gpr_mu_lock(&pollset->mu);
Craig Tiller4509c472017-04-27 19:05:13 +0000678 }
679 if (worker->initialized_cv) {
680 gpr_cv_destroy(&worker->cv);
681 }
Craig Tiller32f90ee2017-04-28 12:46:41 -0700682 if (EMPTIED == worker_remove(pollset, worker)) {
Craig Tiller4509c472017-04-27 19:05:13 +0000683 pollset_maybe_finish_shutdown(exec_ctx, pollset);
684 }
Craig Tillera4b8eb02017-04-29 00:13:52 +0000685 GPR_ASSERT(gpr_atm_no_barrier_load(&g_active_poller) != (gpr_atm)worker);
Craig Tiller4509c472017-04-27 19:05:13 +0000686}
687
688/* pollset->po.mu lock must be held by the caller before calling this.
689 The function pollset_work() may temporarily release the lock (pollset->po.mu)
690 during the course of its execution but it will always re-acquire the lock and
691 ensure that it is held by the time the function returns */
692static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
693 grpc_pollset_worker **worker_hdl,
Craig Tiller20397792017-07-18 11:35:27 -0700694 grpc_millis deadline) {
Craig Tiller4509c472017-04-27 19:05:13 +0000695 grpc_pollset_worker worker;
696 grpc_error *error = GRPC_ERROR_NONE;
697 static const char *err_desc = "pollset_work";
698 if (pollset->kicked_without_poller) {
699 pollset->kicked_without_poller = false;
700 return GRPC_ERROR_NONE;
701 }
Craig Tiller8502ecb2017-04-28 14:22:01 -0700702 gpr_tls_set(&g_current_thread_pollset, (intptr_t)pollset);
Craig Tiller20397792017-07-18 11:35:27 -0700703 if (begin_worker(exec_ctx, pollset, &worker, worker_hdl, deadline)) {
Craig Tiller4509c472017-04-27 19:05:13 +0000704 gpr_tls_set(&g_current_thread_worker, (intptr_t)&worker);
705 GPR_ASSERT(!pollset->shutdown_closure);
Craig Tiller2acab6e2017-04-30 23:06:33 +0000706 GPR_ASSERT(!pollset->seen_inactive);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700707 gpr_mu_unlock(&pollset->mu);
Craig Tiller20397792017-07-18 11:35:27 -0700708 append_error(&error, pollset_epoll(exec_ctx, pollset, deadline), err_desc);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700709 gpr_mu_lock(&pollset->mu);
Craig Tiller4509c472017-04-27 19:05:13 +0000710 gpr_tls_set(&g_current_thread_worker, 0);
Craig Tiller4509c472017-04-27 19:05:13 +0000711 }
712 end_worker(exec_ctx, pollset, &worker, worker_hdl);
Craig Tiller8502ecb2017-04-28 14:22:01 -0700713 gpr_tls_set(&g_current_thread_pollset, 0);
Craig Tiller4509c472017-04-27 19:05:13 +0000714 return error;
715}
716
717static grpc_error *pollset_kick(grpc_pollset *pollset,
718 grpc_pollset_worker *specific_worker) {
719 if (specific_worker == NULL) {
720 if (gpr_tls_get(&g_current_thread_pollset) != (intptr_t)pollset) {
Craig Tiller375eb252017-04-27 23:29:12 +0000721 grpc_pollset_worker *root_worker = pollset->root_worker;
722 if (root_worker == NULL) {
Craig Tiller4509c472017-04-27 19:05:13 +0000723 pollset->kicked_without_poller = true;
724 return GRPC_ERROR_NONE;
Craig Tiller375eb252017-04-27 23:29:12 +0000725 }
Craig Tiller32f90ee2017-04-28 12:46:41 -0700726 grpc_pollset_worker *next_worker = root_worker->next;
727 if (root_worker == next_worker &&
728 root_worker == (grpc_pollset_worker *)gpr_atm_no_barrier_load(
729 &g_active_poller)) {
730 root_worker->kick_state = KICKED;
Craig Tiller4509c472017-04-27 19:05:13 +0000731 return grpc_wakeup_fd_wakeup(&global_wakeup_fd);
Craig Tiller8502ecb2017-04-28 14:22:01 -0700732 } else if (next_worker->kick_state == UNKICKED) {
733 GPR_ASSERT(next_worker->initialized_cv);
Craig Tiller32f90ee2017-04-28 12:46:41 -0700734 next_worker->kick_state = KICKED;
Craig Tiller375eb252017-04-27 23:29:12 +0000735 gpr_cv_signal(&next_worker->cv);
736 return GRPC_ERROR_NONE;
Craig Tiller8502ecb2017-04-28 14:22:01 -0700737 } else {
738 return GRPC_ERROR_NONE;
Craig Tiller4509c472017-04-27 19:05:13 +0000739 }
740 } else {
741 return GRPC_ERROR_NONE;
742 }
Craig Tiller43bf2592017-04-28 23:21:01 +0000743 } else if (specific_worker->kick_state == KICKED) {
Craig Tiller4509c472017-04-27 19:05:13 +0000744 return GRPC_ERROR_NONE;
745 } else if (gpr_tls_get(&g_current_thread_worker) ==
746 (intptr_t)specific_worker) {
Craig Tiller32f90ee2017-04-28 12:46:41 -0700747 specific_worker->kick_state = KICKED;
Craig Tiller4509c472017-04-27 19:05:13 +0000748 return GRPC_ERROR_NONE;
Craig Tiller32f90ee2017-04-28 12:46:41 -0700749 } else if (specific_worker ==
750 (grpc_pollset_worker *)gpr_atm_no_barrier_load(&g_active_poller)) {
751 specific_worker->kick_state = KICKED;
Craig Tiller4509c472017-04-27 19:05:13 +0000752 return grpc_wakeup_fd_wakeup(&global_wakeup_fd);
Craig Tiller8502ecb2017-04-28 14:22:01 -0700753 } else if (specific_worker->initialized_cv) {
Craig Tiller32f90ee2017-04-28 12:46:41 -0700754 specific_worker->kick_state = KICKED;
Craig Tiller4509c472017-04-27 19:05:13 +0000755 gpr_cv_signal(&specific_worker->cv);
756 return GRPC_ERROR_NONE;
Craig Tiller8502ecb2017-04-28 14:22:01 -0700757 } else {
758 specific_worker->kick_state = KICKED;
759 return GRPC_ERROR_NONE;
Craig Tiller4509c472017-04-27 19:05:13 +0000760 }
761}
762
763static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
764 grpc_fd *fd) {}
765
Craig Tiller4509c472017-04-27 19:05:13 +0000766/*******************************************************************************
Craig Tillerc67cc992017-04-27 10:15:51 -0700767 * Pollset-set Definitions
768 */
769
770static grpc_pollset_set *pollset_set_create(void) {
771 return (grpc_pollset_set *)((intptr_t)0xdeafbeef);
772}
773
774static void pollset_set_destroy(grpc_exec_ctx *exec_ctx,
775 grpc_pollset_set *pss) {}
776
777static void pollset_set_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pss,
778 grpc_fd *fd) {}
779
780static void pollset_set_del_fd(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pss,
781 grpc_fd *fd) {}
782
783static void pollset_set_add_pollset(grpc_exec_ctx *exec_ctx,
784 grpc_pollset_set *pss, grpc_pollset *ps) {}
785
786static void pollset_set_del_pollset(grpc_exec_ctx *exec_ctx,
787 grpc_pollset_set *pss, grpc_pollset *ps) {}
788
789static void pollset_set_add_pollset_set(grpc_exec_ctx *exec_ctx,
790 grpc_pollset_set *bag,
791 grpc_pollset_set *item) {}
792
793static void pollset_set_del_pollset_set(grpc_exec_ctx *exec_ctx,
794 grpc_pollset_set *bag,
795 grpc_pollset_set *item) {}
796
797/*******************************************************************************
798 * Event engine binding
799 */
800
801static void shutdown_engine(void) {
802 fd_global_shutdown();
803 pollset_global_shutdown();
Craig Tillerc67cc992017-04-27 10:15:51 -0700804}
805
806static const grpc_event_engine_vtable vtable = {
807 .pollset_size = sizeof(grpc_pollset),
808
809 .fd_create = fd_create,
810 .fd_wrapped_fd = fd_wrapped_fd,
811 .fd_orphan = fd_orphan,
812 .fd_shutdown = fd_shutdown,
813 .fd_is_shutdown = fd_is_shutdown,
814 .fd_notify_on_read = fd_notify_on_read,
815 .fd_notify_on_write = fd_notify_on_write,
816 .fd_get_read_notifier_pollset = fd_get_read_notifier_pollset,
Craig Tillerc67cc992017-04-27 10:15:51 -0700817
818 .pollset_init = pollset_init,
819 .pollset_shutdown = pollset_shutdown,
820 .pollset_destroy = pollset_destroy,
821 .pollset_work = pollset_work,
822 .pollset_kick = pollset_kick,
823 .pollset_add_fd = pollset_add_fd,
824
825 .pollset_set_create = pollset_set_create,
826 .pollset_set_destroy = pollset_set_destroy,
827 .pollset_set_add_pollset = pollset_set_add_pollset,
828 .pollset_set_del_pollset = pollset_set_del_pollset,
829 .pollset_set_add_pollset_set = pollset_set_add_pollset_set,
830 .pollset_set_del_pollset_set = pollset_set_del_pollset_set,
831 .pollset_set_add_fd = pollset_set_add_fd,
832 .pollset_set_del_fd = pollset_set_del_fd,
833
Craig Tillerc67cc992017-04-27 10:15:51 -0700834 .shutdown_engine = shutdown_engine,
835};
836
837/* It is possible that GLIBC has epoll but the underlying kernel doesn't.
838 * Create a dummy epoll_fd to make sure epoll support is available */
Craig Tiller6f0af492017-04-27 19:26:16 +0000839const grpc_event_engine_vtable *grpc_init_epoll1_linux(bool explicit_request) {
Craig Tiller924353a2017-05-05 17:36:31 +0000840 /* TODO(ctiller): temporary, until this stabilizes */
841 if (!explicit_request) return NULL;
842
Craig Tillerc67cc992017-04-27 10:15:51 -0700843 if (!grpc_has_wakeup_fd()) {
844 return NULL;
845 }
846
Craig Tiller4509c472017-04-27 19:05:13 +0000847 g_epfd = epoll_create1(EPOLL_CLOEXEC);
848 if (g_epfd < 0) {
849 gpr_log(GPR_ERROR, "epoll unavailable");
Craig Tillerc67cc992017-04-27 10:15:51 -0700850 return NULL;
851 }
852
Craig Tillerc67cc992017-04-27 10:15:51 -0700853 fd_global_init();
854
855 if (!GRPC_LOG_IF_ERROR("pollset_global_init", pollset_global_init())) {
Craig Tiller4509c472017-04-27 19:05:13 +0000856 close(g_epfd);
857 fd_global_shutdown();
Craig Tillerc67cc992017-04-27 10:15:51 -0700858 return NULL;
859 }
860
861 return &vtable;
862}
863
864#else /* defined(GRPC_LINUX_EPOLL) */
865#if defined(GRPC_POSIX_SOCKET)
866#include "src/core/lib/iomgr/ev_posix.h"
867/* If GRPC_LINUX_EPOLL is not defined, it means epoll is not available. Return
868 * NULL */
Craig Tiller9ddb3152017-04-27 21:32:56 +0000869const grpc_event_engine_vtable *grpc_init_epoll1_linux(bool explicit_request) {
870 return NULL;
871}
Craig Tillerc67cc992017-04-27 10:15:51 -0700872#endif /* defined(GRPC_POSIX_SOCKET) */
873#endif /* !defined(GRPC_LINUX_EPOLL) */