tests/linux: use Akaros's CFLAGS
[akaros.git] / user / iplib / select.c
1 /* Copyright (c) 2016 Google Inc.
2  * Barret Rhoden <brho@cs.berkeley.edu>
3  * See LICENSE for details.
4  *
5  * select()
6  *
7  * Our select() is a bit rough and only works with FDs where fstat can return
8  * S_READABLE or S_WRITABLE.  For the most part, this applies to qio queues,
9  * which are the basis for a lot of the network stack and pipes.  FDs where
10  * fstat doesn't tell us the readiness will have races.
11  *
12  * Under the hood, our select() is implemented with epoll (and under that, FD
13  * taps).  Those can only detect edges (e.g. a socket becomes readable).
14  *
15  * The problem is that we want to detect a level status (e.g. socket is
16  * readable) with an edge event (e.g. socket *becomes* readable).  To do this,
17  * when someone initially selects, the FD gets tracked with epoll and we
18  * manually poll the FDs with fstat.  Subsequent selects() will still be tracked
19  * in the epoll set, but since apps can select() even on FDs they didn't drain
20  * to the point of blocking, we still need to poll every FD on every select()
21  * call.
22  *
23  * We maintain one FD set per program.  It tracks *any* FD being tracked by
24  * *any* select call.  This is because you can only have one tap per FD.
25  * Regardless of whether the user asked for read/write/except, the FD gets
26  * watched for anything until it closes.
27  *
28  * One issue with the global FD set is that one thread may consume the epoll
29  * events intended for another thread (or even for itself at another call
30  * site!).  To get around this, only one thread is the actual epoller, and the
31  * others block on a mutex.  TLS isn't an option for two reasons: not all 2LSs
32  * use TLS (minor concern, maybe they should) and there are some threads who
33  * make multiple select calls - we actually want per-call-site-and-thread fd
34  * sets.
35  *
36  * Notes:
37  * - pselect might be racy
38  * - if the user has no read/write/except sets, we won't wait.  some users of
39  *   select use it as a timer only.  if that comes up, we can expand this.
40  * - if you epoll or FD tap an FD, then try to use select on it, you'll get an
41  *   error (only one tap per FD).  select() only knows about the FDs in its set.
42  * - if you select() on a readfd that is a disk file, it'll always say it is
43  *   available for I/O.
44  */
45
46 #include <sys/select.h>
47 #include <sys/stat.h>
48 #include <sys/time.h>
49 #include <sys/types.h>
50 #include <unistd.h>
51
52 #include <errno.h>
53 #include <malloc.h>
54 #include <parlib/arch/arch.h>
55 #include <parlib/uthread.h>
56 #include <parlib/parlib.h>
57 #include <ros/common.h>
58 #include <ros/fs.h>
59 #include <signal.h>
60 #include <stdlib.h>
61 #include <sys/close_cb.h>
62 #include <sys/epoll.h>
63 #include <sys/fork_cb.h>
64
65 static int epoll_fd;
66 static fd_set all_fds;
67 static fd_set working_read_fds;
68 static fd_set working_write_fds;
69 static fd_set working_except_fds;
70 static uth_mutex_t *epoll_mtx;
71
72 static bool fd_is_set(unsigned int fd, fd_set *set)
73 {
74         if (fd > FD_SETSIZE)
75                 return FALSE;
76         if (!set)
77                 return FALSE;
78         return FD_ISSET(fd, set);
79 }
80
81 static void select_fd_closed(int fd)
82 {
83         /* Slightly racy, but anything concurrently added will be closed later,
84          * and after it is_set. */
85         if (!fd_is_set(fd, &all_fds))
86                 return;
87         /* We just need to stop tracking FD.  We do not need to remove it from
88          * the epoll set, since that will happen automatically on close(). */
89         uth_mutex_lock(epoll_mtx);
90         FD_CLR(fd, &all_fds);
91         uth_mutex_unlock(epoll_mtx);
92 }
93
94 static void select_forked(void)
95 {
96         struct epoll_event ep_ev;
97
98         uth_mutex_lock(epoll_mtx);
99         for (int i = 0; i < FD_SETSIZE; i++) {
100                 if (fd_is_set(i, &all_fds)) {
101                         ep_ev.events = EPOLLET | EPOLLIN | EPOLLOUT | EPOLLHUP |
102                                        EPOLLERR;
103                         ep_ev.data.fd = i;
104                         /* Discard error.  The underlying tap is gone, and the
105                          * epoll ctlr might also have been emptied.  We just
106                          * want to make sure there is no epoll/tap so that a
107                          * future CTL_ADD doesn't fail. */
108                         epoll_ctl(epoll_fd, EPOLL_CTL_DEL, i, &ep_ev);
109                         FD_CLR(i, &all_fds);
110                 }
111         }
112         uth_mutex_unlock(epoll_mtx);
113 }
114
115 static void select_init(void *arg)
116 {
117         static struct close_cb select_close_cb = {.func = select_fd_closed};
118         static struct fork_cb select_fork_cb = {.func = select_forked};
119
120         register_close_cb(&select_close_cb);
121         epoll_fd = epoll_create(FD_SETSIZE);
122         if (epoll_fd < 0) {
123                 perror("select failed epoll_create");
124                 exit(-1);
125         }
126         epoll_mtx = uth_mutex_alloc();
127         register_fork_cb(&select_fork_cb);
128 }
129
130 static int select_tv_to_ep_timeout(struct timeval *tv)
131 {
132         if (!tv)
133                 return -1;
134         return tv->tv_sec * 1000 + DIV_ROUND_UP(tv->tv_usec, 1000);
135 }
136
137 /* Helper: check with the kernel if FD is readable/writable or not.  Some apps
138  * will call select() on something even if it is already actionable, and not
139  * wait until they get the EAGAIN.
140  *
141  * This modifies the global working_ fd sets by setting bits of actionable FDs
142  * and will return the number of bits turned on.  So basically, 1 for readable
143  * xor writable, 2 for both.
144  *
145  * TODO: this *won't* work for disk based files.  It only works on qids that are
146  * backed with qio queues or something similar, where the device has support for
147  * setting DMREADABLE/DMWRITABLE. */
148 static unsigned int fd_set_actionable(int fd, fd_set *readfds, fd_set *writefds)
149 {
150         struct stat stat_buf;
151         int ret;
152
153         /* Avoid the stat call on FDs we're not tracking (which should trigger
154          * an error, or give us the stat for FD 0). */
155         if (!(fd_is_set(fd, readfds) || fd_is_set(fd, writefds)))
156                 return 0;
157         ret = fstat(fd, &stat_buf);
158         assert(!ret);
159         ret = 0;
160         if (fd_is_set(fd, readfds)) {
161                 if (S_READABLE(stat_buf.st_mode)) {
162                         ret++;
163                         FD_SET(fd, &working_read_fds);
164                 }
165         }
166         if (fd_is_set(fd, writefds)) {
167                 if (S_WRITABLE(stat_buf.st_mode)) {
168                         ret++;
169                         FD_SET(fd, &working_write_fds);
170                 }
171         }
172         return ret;
173 }
174
175 /* Helper: extracts events from ep_result for types ep_event_types, and sets
176  * their bits in ret_fds if the FD was watched.  Returns the number of bits set.
177  */
178 static int extract_bits_for_events(struct epoll_event *ep_result,
179                                    uint32_t ep_event_types,
180                                    fd_set *watched_fds, fd_set *ret_fds)
181 {
182         int ret = 0;
183         int fd = ep_result->data.fd;
184
185         if (ep_result->events & ep_event_types) {
186                 if (fd_is_set(fd, watched_fds) && !FD_ISSET(fd, ret_fds)) {
187                         FD_SET(fd, ret_fds);
188                         ret++;
189                 }
190         }
191         return ret;
192 }
193
194 int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
195            struct timeval *timeout)
196 {
197         struct epoll_event ep_ev;
198         struct epoll_event *ep_results;
199         int ret, ep_ret, ep_timeout;
200         static parlib_once_t once = PARLIB_ONCE_INIT;
201         struct timeval start_tv[1], end_tv[1];
202
203         parlib_run_once(&once, select_init, NULL);
204         /* good thing nfds is a signed int... */
205         if (nfds < 0) {
206                 errno = EINVAL;
207                 return -1;
208         }
209 loop:
210         if (timeout)
211                 gettimeofday(start_tv, NULL);
212         ep_timeout = select_tv_to_ep_timeout(timeout);
213         uth_mutex_lock(epoll_mtx);
214         for (int i = 0; i < nfds; i++) {
215                 if ((fd_is_set(i, readfds) || fd_is_set(i, writefds) ||
216                      fd_is_set(i, exceptfds)) &&
217                     !fd_is_set(i, &all_fds)) {
218
219                         FD_SET(i, &all_fds);
220                         /* FDs that we track for *any* reason with select will
221                          * be tracked for *all* reasons with epoll. */
222                         ep_ev.events = EPOLLET | EPOLLIN | EPOLLOUT | EPOLLHUP |
223                                        EPOLLERR;
224                         ep_ev.data.fd = i;
225                         if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, i, &ep_ev)) {
226                                 /* We might have failed because we tried to set
227                                  * up too many FD tap types.  Listen FDs, for
228                                  * instance, can only be tapped for READABLE and
229                                  * HANGUP.  Let's try for one of those. */
230                                 if (errno == ENOSYS) {
231                                         ep_ev.events = EPOLLET | EPOLLIN |
232                                                        EPOLLHUP;
233                                         if (!epoll_ctl(epoll_fd, EPOLL_CTL_ADD,
234                                                        i, &ep_ev))
235                                                 continue;
236                                 }
237                                 /* Careful to unlock before calling perror.
238                                  * perror calls close, which calls our CB, which
239                                  * grabs the lock. */
240                                 uth_mutex_unlock(epoll_mtx);
241                                 perror("select epoll_ctl failed");
242                                 return -1;
243                         }
244                 }
245         }
246         /* Since we just added some FDs to our tracking set, we don't know if
247          * they are readable or not.  We'll only catch edge-triggered changes in
248          * the future.
249          *
250          * Similarly, it is legal to select on a readable FD even if you didn't
251          * consume all of the data yet; similarly for writers on non-full FDs.
252          *
253          * Additionally, since there is a global epoll set, we could have
254          * multiple threads epolling concurrently and one thread could consume
255          * the events that should wake another thread.  Also, keep in mind we
256          * could also have a single thread that selects multiple times on
257          * separate FD sets.
258          *
259          * Due to any of these cases, we need to check every FD this select call
260          * cares about (i.e. in an fd_set) to see if it is actionable.  We do it
261          * while holding the mutex to prevent other threads from consuming our
262          * epoll events. */
263         ret = 0;
264         FD_ZERO(&working_read_fds);
265         FD_ZERO(&working_write_fds);
266         FD_ZERO(&working_except_fds);
267         /* Note the helper sets bits in the working_ fd sets */
268         for (int i = 0; i < nfds; i++)
269                 ret += fd_set_actionable(i, readfds, writefds);
270         if (ret) {
271                 if (readfds)
272                         *readfds = working_read_fds;
273                 if (writefds)
274                         *writefds = working_write_fds;
275                 uth_mutex_unlock(epoll_mtx);
276                 return ret;
277         }
278         /* Need to check for up to FD_SETSIZE - nfds isn't the size of all FDs
279          * tracked; it's the size of only our current select call */
280         ep_results = malloc(sizeof(struct epoll_event) * FD_SETSIZE);
281         if (!ep_results) {
282                 uth_mutex_unlock(epoll_mtx);
283                 errno = ENOMEM;
284                 return -1;
285         }
286         ep_ret = epoll_wait(epoll_fd, ep_results, FD_SETSIZE, ep_timeout);
287         /* We need to hold the mtx during all of this processing since we're
288          * using the global working_ fds sets.  We can't modify the
289          * readfds/writefds/exceptfds until we're sure we are done. */
290         ret = 0;
291         /* Note that ret can be > ep_ret.  An FD that is both readable and
292          * writable counts as one event for epoll, but as two bits for select.
293          * */
294         for (int i = 0; i < ep_ret; i++) {
295                 ret += extract_bits_for_events(&ep_results[i],
296                                                EPOLLIN | EPOLLHUP,
297                                                readfds, &working_read_fds);
298                 ret += extract_bits_for_events(&ep_results[i],
299                                                EPOLLOUT | EPOLLHUP,
300                                                writefds, &working_write_fds);
301                 ret += extract_bits_for_events(&ep_results[i], EPOLLERR,
302                                                exceptfds, &working_except_fds);
303         }
304         free(ep_results);
305         if (ret) {
306                 if (readfds)
307                         *readfds = working_read_fds;
308                 if (writefds)
309                         *writefds = working_write_fds;
310                 if (exceptfds)
311                         *exceptfds = working_except_fds;
312         }
313         uth_mutex_unlock(epoll_mtx);
314         /* TODO: Consider updating timeval for non-timeouts.  It's not mandatory
315          * (POSIX). */
316         if (ret)
317                 return ret;
318         /* If we have no rets at this point, there are a few options: we could
319          * have timed out (if requested), or we could have consumed someone
320          * else's event.  No one could have consumed our event, since we were
321          * the only epoller (while holding the mtx).  In the latter case, we'll
322          * need to try again, but with an updated timeout. */
323         if (timeout) {
324                 gettimeofday(end_tv, NULL);
325                 timersub(end_tv, start_tv, end_tv);     /* diff in end_tv */
326                 if (timercmp(timeout, end_tv, >))
327                         timersub(timeout, end_tv, timeout);
328                 else
329                         return 0;       /* select timed out */
330         }
331         goto loop;
332 }
333
334 int pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
335             const struct timespec *timeout, const sigset_t *sigmask)
336 {
337         int ready;
338         sigset_t origmask;
339         struct timeval local_tv, *tv = &local_tv;
340
341         if (!timeout) {
342                 tv = 0;
343         } else {
344                 tv->tv_sec = timeout->tv_sec;
345                 tv->tv_usec = DIV_ROUND_UP(timeout->tv_nsec, 1000);
346         }
347         /* TODO: this is probably racy */
348         sigprocmask(SIG_SETMASK, sigmask, &origmask);
349         ready = select(nfds, readfds, writefds, exceptfds, tv);
350         sigprocmask(SIG_SETMASK, &origmask, NULL);
351         return ready;
352 }