blob: 92d6fb724142a64f4b6553c3a2191e34db89991e [file] [log] [blame]
ctiller58393c22015-01-07 14:03:30 -08001/*
2 *
murgatroid993466c4b2016-01-12 10:26:04 -08003 * Copyright 2015-2016, Google Inc.
ctiller58393c22015-01-07 14:03:30 -08004 * 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 <grpc/support/port_platform.h>
35
Craig Tiller1a6f7552015-05-29 13:56:44 -070036#ifdef GPR_POSIX_SOCKET
ctiller58393c22015-01-07 14:03:30 -080037
38#include "src/core/iomgr/pollset_posix.h"
39
40#include <errno.h>
41#include <poll.h>
42#include <stdlib.h>
43#include <string.h>
44
ctiller58393c22015-01-07 14:03:30 -080045#include <grpc/support/alloc.h>
46#include <grpc/support/log.h>
47#include <grpc/support/useful.h>
48
Craig Tiller69b093b2016-02-25 19:04:07 -080049#include "src/core/iomgr/fd_posix.h"
50#include "src/core/iomgr/iomgr_internal.h"
51#include "src/core/iomgr/pollset_posix.h"
52#include "src/core/support/block_annotate.h"
53
Craig Tillera82950e2015-09-22 12:33:20 -070054typedef struct {
ctiller58393c22015-01-07 14:03:30 -080055 /* all polled fds */
56 size_t fd_count;
57 size_t fd_capacity;
58 grpc_fd **fds;
ctiller58393c22015-01-07 14:03:30 -080059 /* fds that have been removed from the pollset explicitly */
60 size_t del_count;
61 size_t del_capacity;
62 grpc_fd **dels;
63} pollset_hdr;
64
Craig Tillera82950e2015-09-22 12:33:20 -070065static void multipoll_with_poll_pollset_add_fd(grpc_exec_ctx *exec_ctx,
66 grpc_pollset *pollset,
67 grpc_fd *fd,
68 int and_unlock_pollset) {
ctiller58393c22015-01-07 14:03:30 -080069 size_t i;
70 pollset_hdr *h = pollset->data.ptr;
71 /* TODO(ctiller): this is O(num_fds^2); maybe switch to a hash set here */
Craig Tillera82950e2015-09-22 12:33:20 -070072 for (i = 0; i < h->fd_count; i++) {
73 if (h->fds[i] == fd) goto exit;
74 }
75 if (h->fd_count == h->fd_capacity) {
76 h->fd_capacity = GPR_MAX(h->fd_capacity + 8, h->fd_count * 3 / 2);
77 h->fds = gpr_realloc(h->fds, sizeof(grpc_fd *) * h->fd_capacity);
78 }
ctiller58393c22015-01-07 14:03:30 -080079 h->fds[h->fd_count++] = fd;
Craig Tillera82950e2015-09-22 12:33:20 -070080 GRPC_FD_REF(fd, "multipoller");
Craig Tillerd6c98df2015-08-18 09:33:44 -070081exit:
Craig Tillera82950e2015-09-22 12:33:20 -070082 if (and_unlock_pollset) {
Craig Tiller85371a22016-02-25 13:55:13 -080083 gpr_mu_unlock(&pollset->mu);
Craig Tillera82950e2015-09-22 12:33:20 -070084 }
ctiller58393c22015-01-07 14:03:30 -080085}
86
Craig Tillera82950e2015-09-22 12:33:20 -070087static void multipoll_with_poll_pollset_maybe_work_and_unlock(
88 grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker *worker,
89 gpr_timespec deadline, gpr_timespec now) {
Craig Tiller58d05a62015-10-02 13:59:31 -070090#define POLLOUT_CHECK (POLLOUT | POLLHUP | POLLERR)
Craig Tiller57f79d62015-10-02 14:00:12 -070091#define POLLIN_CHECK (POLLIN | POLLHUP | POLLERR)
Craig Tiller58d05a62015-10-02 13:59:31 -070092
ctiller58393c22015-01-07 14:03:30 -080093 int timeout;
94 int r;
Craig Tillerebc7ef22015-09-10 22:19:25 -070095 size_t i, j, fd_count;
96 nfds_t pfd_count;
ctiller58393c22015-01-07 14:03:30 -080097 pollset_hdr *h;
Craig Tiller5ddbb9d2015-07-29 15:58:11 -070098 /* TODO(ctiller): inline some elements to avoid an allocation */
99 grpc_fd_watcher *watchers;
100 struct pollfd *pfds;
ctiller58393c22015-01-07 14:03:30 -0800101
ctiller58393c22015-01-07 14:03:30 -0800102 h = pollset->data.ptr;
Craig Tillera82950e2015-09-22 12:33:20 -0700103 timeout = grpc_poll_deadline_to_millis_timeout(deadline, now);
Craig Tiller5ddbb9d2015-07-29 15:58:11 -0700104 /* TODO(ctiller): perform just one malloc here if we exceed the inline case */
Craig Tiller8afeec82015-09-28 17:03:34 -0700105 pfds = gpr_malloc(sizeof(*pfds) * (h->fd_count + 2));
106 watchers = gpr_malloc(sizeof(*watchers) * (h->fd_count + 2));
Craig Tiller5ddbb9d2015-07-29 15:58:11 -0700107 fd_count = 0;
Craig Tiller8afeec82015-09-28 17:03:34 -0700108 pfd_count = 2;
109 pfds[0].fd = GRPC_WAKEUP_FD_GET_READ_FD(&grpc_global_wakeup_fd);
Craig Tiller5ddbb9d2015-07-29 15:58:11 -0700110 pfds[0].events = POLLIN;
Craig Tiller8afeec82015-09-28 17:03:34 -0700111 pfds[0].revents = 0;
Craig Tillere8b5f622015-11-02 14:15:03 -0800112 pfds[1].fd = GRPC_WAKEUP_FD_GET_READ_FD(&worker->wakeup_fd->fd);
Craig Tiller8afeec82015-09-28 17:03:34 -0700113 pfds[1].events = POLLIN;
114 pfds[1].revents = 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700115 for (i = 0; i < h->fd_count; i++) {
116 int remove = grpc_fd_is_orphaned(h->fds[i]);
117 for (j = 0; !remove && j < h->del_count; j++) {
118 if (h->fds[i] == h->dels[j]) remove = 1;
ctiller58393c22015-01-07 14:03:30 -0800119 }
Craig Tillera82950e2015-09-22 12:33:20 -0700120 if (remove) {
121 GRPC_FD_UNREF(h->fds[i], "multipoller");
122 } else {
123 h->fds[fd_count++] = h->fds[i];
124 watchers[pfd_count].fd = h->fds[i];
Craig Tillerb3320fc2016-03-04 14:52:06 -0800125 GRPC_FD_REF(watchers[pfd_count].fd, "multipoller_start");
Craig Tillera82950e2015-09-22 12:33:20 -0700126 pfds[pfd_count].fd = h->fds[i]->fd;
127 pfds[pfd_count].revents = 0;
128 pfd_count++;
ctiller58393c22015-01-07 14:03:30 -0800129 }
Craig Tillera82950e2015-09-22 12:33:20 -0700130 }
131 for (j = 0; j < h->del_count; j++) {
132 GRPC_FD_UNREF(h->dels[j], "multipoller_del");
133 }
ctiller58393c22015-01-07 14:03:30 -0800134 h->del_count = 0;
Craig Tiller5ddbb9d2015-07-29 15:58:11 -0700135 h->fd_count = fd_count;
Craig Tiller85371a22016-02-25 13:55:13 -0800136 gpr_mu_unlock(&pollset->mu);
ctiller58393c22015-01-07 14:03:30 -0800137
Craig Tiller8afeec82015-09-28 17:03:34 -0700138 for (i = 2; i < pfd_count; i++) {
Craig Tillerb3320fc2016-03-04 14:52:06 -0800139 grpc_fd *fd = watchers[i].fd;
Craig Tillerf1b6d612016-03-04 15:00:02 -0800140 pfds[i].events = (short)grpc_fd_begin_poll(fd, pollset, worker, POLLIN,
141 POLLOUT, &watchers[i]);
Craig Tillerb3320fc2016-03-04 14:52:06 -0800142 GRPC_FD_UNREF(fd, "multipoller_start");
Craig Tillera82950e2015-09-22 12:33:20 -0700143 }
Craig Tiller5ddbb9d2015-07-29 15:58:11 -0700144
Vijay Pai8c7665e2015-09-25 21:40:19 -0700145 /* TODO(vpai): Consider first doing a 0 timeout poll here to avoid
146 even going into the blocking annotation if possible */
vjpai9839d282015-09-24 17:55:18 -0700147 GRPC_SCHEDULING_START_BLOCKING_REGION;
Craig Tillera82950e2015-09-22 12:33:20 -0700148 r = grpc_poll_function(pfds, pfd_count, timeout);
vjpai9839d282015-09-24 17:55:18 -0700149 GRPC_SCHEDULING_END_BLOCKING_REGION;
Craig Tiller45724b32015-09-22 10:42:19 -0700150
Craig Tillera82950e2015-09-22 12:33:20 -0700151 if (r < 0) {
Craig Tiller4c219e62016-01-06 16:52:28 -0800152 if (errno != EINTR) {
153 gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno));
154 }
Craig Tiller58d05a62015-10-02 13:59:31 -0700155 for (i = 2; i < pfd_count; i++) {
156 grpc_fd_end_poll(exec_ctx, &watchers[i], 0, 0);
Craig Tiller45724b32015-09-22 10:42:19 -0700157 }
Craig Tillera82950e2015-09-22 12:33:20 -0700158 } else if (r == 0) {
Craig Tiller58d05a62015-10-02 13:59:31 -0700159 for (i = 2; i < pfd_count; i++) {
160 grpc_fd_end_poll(exec_ctx, &watchers[i], 0, 0);
161 }
Craig Tillera82950e2015-09-22 12:33:20 -0700162 } else {
Craig Tiller58d05a62015-10-02 13:59:31 -0700163 if (pfds[0].revents & POLLIN_CHECK) {
Craig Tiller8afeec82015-09-28 17:03:34 -0700164 grpc_wakeup_fd_consume_wakeup(&grpc_global_wakeup_fd);
165 }
Craig Tiller58d05a62015-10-02 13:59:31 -0700166 if (pfds[1].revents & POLLIN_CHECK) {
Craig Tillere8b5f622015-11-02 14:15:03 -0800167 grpc_wakeup_fd_consume_wakeup(&worker->wakeup_fd->fd);
Craig Tiller45724b32015-09-22 10:42:19 -0700168 }
Craig Tiller8afeec82015-09-28 17:03:34 -0700169 for (i = 2; i < pfd_count; i++) {
Craig Tillera82950e2015-09-22 12:33:20 -0700170 if (watchers[i].fd == NULL) {
Craig Tiller58d05a62015-10-02 13:59:31 -0700171 grpc_fd_end_poll(exec_ctx, &watchers[i], 0, 0);
Craig Tillera82950e2015-09-22 12:33:20 -0700172 continue;
173 }
Craig Tiller58d05a62015-10-02 13:59:31 -0700174 grpc_fd_end_poll(exec_ctx, &watchers[i], pfds[i].revents & POLLIN_CHECK,
175 pfds[i].revents & POLLOUT_CHECK);
Craig Tiller45724b32015-09-22 10:42:19 -0700176 }
Craig Tillera82950e2015-09-22 12:33:20 -0700177 }
Craig Tiller45724b32015-09-22 10:42:19 -0700178
Craig Tillera82950e2015-09-22 12:33:20 -0700179 gpr_free(pfds);
180 gpr_free(watchers);
David Klempnerbaced4d2015-02-10 17:10:15 -0800181}
182
Craig Tillera82950e2015-09-22 12:33:20 -0700183static void multipoll_with_poll_pollset_finish_shutdown(grpc_pollset *pollset) {
ctiller58393c22015-01-07 14:03:30 -0800184 size_t i;
185 pollset_hdr *h = pollset->data.ptr;
Craig Tillera82950e2015-09-22 12:33:20 -0700186 for (i = 0; i < h->fd_count; i++) {
187 GRPC_FD_UNREF(h->fds[i], "multipoller");
188 }
189 for (i = 0; i < h->del_count; i++) {
190 GRPC_FD_UNREF(h->dels[i], "multipoller_del");
191 }
Craig Tiller5ef27542015-06-01 08:24:35 -0700192 h->fd_count = 0;
193 h->del_count = 0;
194}
195
Craig Tillera82950e2015-09-22 12:33:20 -0700196static void multipoll_with_poll_pollset_destroy(grpc_pollset *pollset) {
Craig Tiller5ef27542015-06-01 08:24:35 -0700197 pollset_hdr *h = pollset->data.ptr;
Craig Tillera82950e2015-09-22 12:33:20 -0700198 multipoll_with_poll_pollset_finish_shutdown(pollset);
199 gpr_free(h->fds);
200 gpr_free(h->dels);
201 gpr_free(h);
ctiller58393c22015-01-07 14:03:30 -0800202}
203
204static const grpc_pollset_vtable multipoll_with_poll_pollset = {
Craig Tiller88a33ef2015-12-11 13:17:40 -0800205 multipoll_with_poll_pollset_add_fd,
Craig Tillera82950e2015-09-22 12:33:20 -0700206 multipoll_with_poll_pollset_maybe_work_and_unlock,
207 multipoll_with_poll_pollset_finish_shutdown,
208 multipoll_with_poll_pollset_destroy};
ctiller58393c22015-01-07 14:03:30 -0800209
Craig Tillera82950e2015-09-22 12:33:20 -0700210void grpc_poll_become_multipoller(grpc_exec_ctx *exec_ctx,
211 grpc_pollset *pollset, grpc_fd **fds,
212 size_t nfds) {
ctiller58393c22015-01-07 14:03:30 -0800213 size_t i;
Craig Tillera82950e2015-09-22 12:33:20 -0700214 pollset_hdr *h = gpr_malloc(sizeof(pollset_hdr));
ctiller58393c22015-01-07 14:03:30 -0800215 pollset->vtable = &multipoll_with_poll_pollset;
216 pollset->data.ptr = h;
217 h->fd_count = nfds;
218 h->fd_capacity = nfds;
Craig Tillera82950e2015-09-22 12:33:20 -0700219 h->fds = gpr_malloc(nfds * sizeof(grpc_fd *));
ctiller58393c22015-01-07 14:03:30 -0800220 h->del_count = 0;
221 h->del_capacity = 0;
222 h->dels = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700223 for (i = 0; i < nfds; i++) {
224 h->fds[i] = fds[i];
225 GRPC_FD_REF(fds[i], "multipoller");
226 }
ctiller58393c22015-01-07 14:03:30 -0800227}
228
Craig Tiller1a6f7552015-05-29 13:56:44 -0700229#endif /* GPR_POSIX_SOCKET */
230
231#ifdef GPR_POSIX_MULTIPOLL_WITH_POLL
Craig Tillera82950e2015-09-22 12:33:20 -0700232grpc_platform_become_multipoller_type grpc_platform_become_multipoller =
233 grpc_poll_become_multipoller;
Craig Tiller190d3602015-02-18 09:23:38 -0800234#endif