Update to OpenVPN 2.1rc17
[tomato.git] / release / src / router / openvpn / event.c
blob32b1c2330ee561ae0a0178d930bcd30f4eca7954
1 /*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single TCP/UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
8 * Copyright (C) 2002-2009 OpenVPN Technologies, Inc. <sales@openvpn.net>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program (see the file COPYING included with this
21 * distribution); if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "syshead.h"
27 #include "buffer.h"
28 #include "error.h"
29 #include "integer.h"
30 #include "event.h"
32 #include "memdbg.h"
35 * Some OSes will prefer select() over poll()
36 * when both are available.
38 #if defined(TARGET_DARWIN)
39 #define SELECT_PREFERRED_OVER_POLL
40 #endif
43 * All non-windows OSes are assumed to have select()
45 #ifdef WIN32
46 #define SELECT 0
47 #else
48 #define SELECT 1
49 #endif
52 * This should be set to the highest file descriptor
53 * which can be used in one of the FD_ macros.
55 #ifdef FD_SETSIZE
56 #define SELECT_MAX_FDS FD_SETSIZE
57 #else
58 #define SELECT_MAX_FDS 256
59 #endif
61 static inline int
62 tv_to_ms_timeout (const struct timeval *tv)
64 if (tv->tv_sec == 0 && tv->tv_usec == 0)
65 return 0;
66 else
67 return max_int (tv->tv_sec * 1000 + (tv->tv_usec + 500) / 1000, 1);
70 #ifdef WIN32
72 struct we_set
74 struct event_set_functions func;
75 bool fast;
76 HANDLE *events;
77 struct event_set_return *esr;
78 int n_events;
79 int capacity;
82 static inline void
83 we_set_event (struct we_set *wes, int i, event_t event, unsigned int rwflags, void *arg)
85 ASSERT (i >= 0 && i < wes->capacity);
87 if (rwflags == EVENT_READ)
89 ASSERT (event->read != NULL);
90 wes->events[i] = event->read;
92 else if (rwflags == EVENT_WRITE)
94 ASSERT (event->write != NULL);
95 wes->events[i] = event->write;
97 else
98 msg (M_FATAL, "fatal error in we_set_events: rwflags=%d", rwflags);
100 wes->esr[i].rwflags = rwflags;
101 wes->esr[i].arg = arg;
104 static inline bool
105 we_append_event (struct we_set *wes, event_t event, unsigned int rwflags, void *arg)
107 if (rwflags & EVENT_WRITE)
109 if (wes->n_events < wes->capacity)
111 we_set_event (wes, wes->n_events, event, EVENT_WRITE, arg);
112 ++wes->n_events;
114 else
115 return false;
117 if (rwflags & EVENT_READ)
119 if (wes->n_events < wes->capacity)
121 we_set_event (wes, wes->n_events, event, EVENT_READ, arg);
122 ++wes->n_events;
124 else
125 return false;
127 return true;
130 static void
131 we_del_event (struct we_set *wes, event_t event)
133 int i, j = 0;
134 const int len = wes->n_events;
136 for (i = 0; i < len; ++i)
138 const HANDLE h = wes->events[i];
139 if (h == event->read || h == event->write)
140 --wes->n_events;
141 else
143 if (i != j)
145 wes->events[j] = wes->events[i];
146 wes->esr[j] = wes->esr[i];
148 ++j;
153 static void
154 we_del_index (struct we_set *wes, int index)
156 int i;
157 ASSERT (index >= 0 && index < wes->n_events);
158 for (i = index; i < wes->n_events - 1; ++i)
160 wes->events[i] = wes->events[i+1];
161 wes->esr[i] = wes->esr[i+1];
163 --wes->n_events;
166 static void
167 we_get_rw_indices (struct we_set *wes, event_t event, int *ri, int *wi)
169 int i;
170 *ri = *wi = -1;
171 for (i = 0; i < wes->n_events; ++i)
173 const HANDLE h = wes->events[i];
174 if (h == event->read)
176 ASSERT (*ri == -1);
177 *ri = i;
179 else if (h == event->write)
181 ASSERT (*wi == -1);
182 *wi = i;
187 static void
188 we_free (struct event_set *es)
190 struct we_set *wes = (struct we_set *) es;
191 free (wes->events);
192 free (wes->esr);
193 free (wes);
196 static void
197 we_reset (struct event_set *es)
199 struct we_set *wes = (struct we_set *) es;
200 ASSERT (wes->fast);
201 wes->n_events = 0;
204 static void
205 we_del (struct event_set *es, event_t event)
207 struct we_set *wes = (struct we_set *) es;
208 ASSERT (!wes->fast);
209 we_del_event (wes, event);
212 static void
213 we_ctl (struct event_set *es, event_t event, unsigned int rwflags, void *arg)
215 struct we_set *wes = (struct we_set *) es;
217 dmsg (D_EVENT_WAIT, "WE_CTL n=%d ev=0x%08x rwflags=0x%04x arg=" ptr_format,
218 wes->n_events,
219 (unsigned int)event,
220 rwflags,
221 (ptr_type)arg);
223 if (wes->fast)
225 if (!we_append_event (wes, event, rwflags, arg))
226 goto err;
228 else
230 int ri, wi;
231 int one = -1;
232 int n = 0;
234 we_get_rw_indices (wes, event, &ri, &wi);
235 if (wi >= 0)
237 one = wi;
238 ++n;
240 if (ri >= 0)
242 one = ri;
243 ++n;
245 switch (rwflags)
247 case 0:
248 switch (n)
250 case 0:
251 break;
252 case 1:
253 we_del_index (wes, one);
254 break;
255 case 2:
256 we_del_event (wes, event);
257 break;
258 default:
259 ASSERT (0);
261 break;
262 case EVENT_READ:
263 switch (n)
265 case 0:
266 if (!we_append_event (wes, event, EVENT_READ, arg))
267 goto err;
268 break;
269 case 1:
270 we_set_event (wes, one, event, EVENT_READ, arg);
271 break;
272 case 2:
273 we_del_index (wes, wi);
274 break;
275 default:
276 ASSERT (0);
278 break;
279 case EVENT_WRITE:
280 switch (n)
282 case 0:
283 if (!we_append_event (wes, event, EVENT_WRITE, arg))
284 goto err;
285 break;
286 case 1:
287 we_set_event (wes, one, event, EVENT_WRITE, arg);
288 break;
289 case 2:
290 we_del_index (wes, ri);
291 break;
292 default:
293 ASSERT (0);
295 break;
296 case EVENT_READ|EVENT_WRITE:
297 switch (n)
299 case 0:
300 if (!we_append_event (wes, event, EVENT_READ|EVENT_WRITE, arg))
301 goto err;
302 break;
303 case 1:
304 if (ri == -1)
306 ASSERT (wi != -1);
307 if (!we_append_event (wes, event, EVENT_READ, arg))
308 goto err;
310 else if (wi == -1)
312 if (!we_append_event (wes, event, EVENT_WRITE, arg))
313 goto err;
315 else
316 ASSERT (0);
317 break;
318 case 2:
319 break;
320 default:
321 ASSERT (0);
323 break;
324 default:
325 msg (M_FATAL, "fatal error in we_ctl: rwflags=%d", rwflags);
328 return;
330 err:
331 msg (D_EVENT_ERRORS, "Error: Windows resource limit WSA_MAXIMUM_WAIT_EVENTS (%d) has been exceeded", WSA_MAXIMUM_WAIT_EVENTS);
334 static int
335 we_wait (struct event_set *es, const struct timeval *tv, struct event_set_return *out, int outlen)
337 struct we_set *wes = (struct we_set *) es;
338 const int timeout = tv_to_ms_timeout (tv);
339 DWORD status;
341 dmsg (D_EVENT_WAIT, "WE_WAIT enter n=%d to=%d", wes->n_events, timeout);
343 #ifdef ENABLE_DEBUG
344 if (check_debug_level (D_EVENT_WAIT)) {
345 int i;
346 for (i = 0; i < wes->n_events; ++i)
347 dmsg (D_EVENT_WAIT, "[%d] ev=0x%08x rwflags=0x%04x arg=" ptr_format,
349 (unsigned int)wes->events[i],
350 wes->esr[i].rwflags,
351 (ptr_type)wes->esr[i].arg);
353 #endif
356 * First poll our event list with 0 timeout
358 status = WSAWaitForMultipleEvents(
359 (DWORD) wes->n_events,
360 wes->events,
361 FALSE,
362 (DWORD) 0,
363 FALSE);
366 * If at least one event is already set, we must
367 * individually poll the whole list.
369 if (status >= WSA_WAIT_EVENT_0 && status < WSA_WAIT_EVENT_0 + (DWORD) wes->n_events)
371 int i;
372 int j = 0;
373 for (i = 0; i < wes->n_events; ++i)
375 if (j >= outlen)
376 break;
377 if (WaitForSingleObject (wes->events[i], 0) == WAIT_OBJECT_0)
379 *out = wes->esr[i];
380 dmsg (D_EVENT_WAIT, "WE_WAIT leave [%d,%d] rwflags=0x%04x arg=" ptr_format,
381 i, j, out->rwflags, (ptr_type)out->arg);
382 ++j;
383 ++out;
386 return j;
388 else
391 * If caller specified timeout > 0, we know at this point
392 * that no events are set, so wait only for the first event
393 * (or timeout) and return at most one event_set_return object.
395 * If caller specified timeout == 0, the second call to
396 * WSAWaitForMultipleEvents would be redundant -- just
397 * return 0 indicating timeout.
399 if (timeout > 0)
400 status = WSAWaitForMultipleEvents(
401 (DWORD) wes->n_events,
402 wes->events,
403 FALSE,
404 (DWORD) timeout,
405 FALSE);
407 if (outlen >= 1 && status >= WSA_WAIT_EVENT_0 && status < WSA_WAIT_EVENT_0 + (DWORD) wes->n_events)
409 *out = wes->esr[status - WSA_WAIT_EVENT_0];
410 dmsg (D_EVENT_WAIT, "WE_WAIT leave rwflags=0x%04x arg=" ptr_format,
411 out->rwflags, (ptr_type)out->arg);
412 return 1;
414 else if (status == WSA_WAIT_TIMEOUT)
415 return 0;
416 else
417 return -1;
421 static struct event_set *
422 we_init (int *maxevents, unsigned int flags)
424 struct we_set *wes;
426 dmsg (D_EVENT_WAIT, "WE_INIT maxevents=%d flags=0x%08x", *maxevents, flags);
428 ALLOC_OBJ_CLEAR (wes, struct we_set);
430 /* set dispatch functions */
431 wes->func.free = we_free;
432 wes->func.reset = we_reset;
433 wes->func.del = we_del;
434 wes->func.ctl = we_ctl;
435 wes->func.wait = we_wait;
437 if (flags & EVENT_METHOD_FAST)
438 wes->fast = true;
439 wes->n_events = 0;
441 /* Figure our event capacity */
442 ASSERT (*maxevents > 0);
443 wes->capacity = min_int (*maxevents * 2, WSA_MAXIMUM_WAIT_EVENTS);
444 *maxevents = min_int (*maxevents, WSA_MAXIMUM_WAIT_EVENTS);
446 /* Allocate space for Win32 event handles */
447 ALLOC_ARRAY_CLEAR (wes->events, HANDLE, wes->capacity);
449 /* Allocate space for event_set_return objects */
450 ALLOC_ARRAY_CLEAR (wes->esr, struct event_set_return, wes->capacity);
452 dmsg (D_EVENT_WAIT, "WE_INIT maxevents=%d capacity=%d",
453 *maxevents, wes->capacity);
455 return (struct event_set *) wes;
458 #endif /* WIN32 */
460 #if EPOLL
462 struct ep_set
464 struct event_set_functions func;
465 bool fast;
466 int epfd;
467 int maxevents;
468 struct epoll_event *events;
471 static void
472 ep_free (struct event_set *es)
474 struct ep_set *eps = (struct ep_set *) es;
475 close (eps->epfd);
476 free (eps->events);
477 free (eps);
480 static void
481 ep_reset (struct event_set *es)
483 const struct ep_set *eps = (struct ep_set *) es;
484 ASSERT (eps->fast);
487 static void
488 ep_del (struct event_set *es, event_t event)
490 struct epoll_event ev;
491 struct ep_set *eps = (struct ep_set *) es;
493 dmsg (D_EVENT_WAIT, "EP_DEL ev=%d", (int)event);
495 ASSERT (!eps->fast);
496 CLEAR (ev);
497 epoll_ctl (eps->epfd, EPOLL_CTL_DEL, event, &ev);
500 static void
501 ep_ctl (struct event_set *es, event_t event, unsigned int rwflags, void *arg)
503 struct ep_set *eps = (struct ep_set *) es;
504 struct epoll_event ev;
506 CLEAR (ev);
508 ev.data.ptr = arg;
509 if (rwflags & EVENT_READ)
510 ev.events |= EPOLLIN;
511 if (rwflags & EVENT_WRITE)
512 ev.events |= EPOLLOUT;
514 dmsg (D_EVENT_WAIT, "EP_CTL fd=%d rwflags=0x%04x ev=0x%08x arg=" ptr_format,
515 (int)event,
516 rwflags,
517 (unsigned int)ev.events,
518 (ptr_type)ev.data.ptr);
520 if (epoll_ctl (eps->epfd, EPOLL_CTL_MOD, event, &ev) < 0)
522 if (errno == ENOENT)
524 if (epoll_ctl (eps->epfd, EPOLL_CTL_ADD, event, &ev) < 0)
525 msg (M_ERR, "EVENT: epoll_ctl EPOLL_CTL_ADD failed");
527 else
528 msg (M_ERR, "EVENT: epoll_ctl EPOLL_CTL_MOD failed");
532 static int
533 ep_wait (struct event_set *es, const struct timeval *tv, struct event_set_return *out, int outlen)
535 struct ep_set *eps = (struct ep_set *) es;
536 int stat;
538 if (outlen > eps->maxevents)
539 outlen = eps->maxevents;
541 stat = epoll_wait (eps->epfd, eps->events, outlen, tv_to_ms_timeout (tv));
542 ASSERT (stat <= outlen);
544 if (stat > 0)
546 int i;
547 const struct epoll_event *ev = eps->events;
548 struct event_set_return *esr = out;
549 for (i = 0; i < stat; ++i)
551 esr->rwflags = 0;
552 if (ev->events & (EPOLLIN|EPOLLPRI|EPOLLERR|EPOLLHUP))
553 esr->rwflags |= EVENT_READ;
554 if (ev->events & EPOLLOUT)
555 esr->rwflags |= EVENT_WRITE;
556 esr->arg = ev->data.ptr;
557 dmsg (D_EVENT_WAIT, "EP_WAIT[%d] rwflags=0x%04x ev=0x%08x arg=" ptr_format,
558 i, esr->rwflags, ev->events, (ptr_type)ev->data.ptr);
559 ++ev;
560 ++esr;
563 return stat;
566 static struct event_set *
567 ep_init (int *maxevents, unsigned int flags)
569 struct ep_set *eps;
570 int fd;
572 dmsg (D_EVENT_WAIT, "EP_INIT maxevents=%d flags=0x%08x", *maxevents, flags);
574 /* open epoll file descriptor */
575 fd = epoll_create (*maxevents);
576 if (fd < 0)
577 return NULL;
579 ALLOC_OBJ_CLEAR (eps, struct ep_set);
581 /* set dispatch functions */
582 eps->func.free = ep_free;
583 eps->func.reset = ep_reset;
584 eps->func.del = ep_del;
585 eps->func.ctl = ep_ctl;
586 eps->func.wait = ep_wait;
588 /* fast method ("sort of") corresponds to epoll one-shot */
589 if (flags & EVENT_METHOD_FAST)
590 eps->fast = true;
592 /* allocate space for epoll_wait return */
593 ASSERT (*maxevents > 0);
594 eps->maxevents = *maxevents;
595 ALLOC_ARRAY_CLEAR (eps->events, struct epoll_event, eps->maxevents);
597 /* set epoll control fd */
598 eps->epfd = fd;
600 return (struct event_set *) eps;
602 #endif /* EPOLL */
604 #if POLL
606 struct po_set
608 struct event_set_functions func;
609 bool fast;
610 struct pollfd *events;
611 void **args;
612 int n_events;
613 int capacity;
616 static void
617 po_free (struct event_set *es)
619 struct po_set *pos = (struct po_set *) es;
620 free (pos->events);
621 free (pos->args);
622 free (pos);
625 static void
626 po_reset (struct event_set *es)
628 struct po_set *pos = (struct po_set *) es;
629 ASSERT (pos->fast);
630 pos->n_events = 0;
633 static void
634 po_del (struct event_set *es, event_t event)
636 struct po_set *pos = (struct po_set *) es;
637 int i;
639 dmsg (D_EVENT_WAIT, "PO_DEL ev=%d", (int)event);
641 ASSERT (!pos->fast);
642 for (i = 0; i < pos->n_events; ++i)
644 if (pos->events[i].fd == event)
646 int j;
647 for (j = i; j < pos->n_events - 1; ++j)
649 pos->events[j] = pos->events[j+1];
650 pos->args[j] = pos->args[j+1];
652 --pos->n_events;
653 break;
658 static inline void
659 po_set_pollfd_events (struct pollfd *pfdp, unsigned int rwflags)
661 pfdp->events = 0;
662 if (rwflags & EVENT_WRITE)
663 pfdp->events |= POLLOUT;
664 if (rwflags & EVENT_READ)
665 pfdp->events |= (POLLIN|POLLPRI);
668 static inline bool
669 po_append_event (struct po_set *pos, event_t event, unsigned int rwflags, void *arg)
671 if (pos->n_events < pos->capacity)
673 struct pollfd *pfdp = &pos->events[pos->n_events];
674 pfdp->fd = event;
675 pos->args[pos->n_events] = arg;
676 po_set_pollfd_events (pfdp, rwflags);
677 ++pos->n_events;
678 return true;
680 else
681 return false;
684 static void
685 po_ctl (struct event_set *es, event_t event, unsigned int rwflags, void *arg)
687 struct po_set *pos = (struct po_set *) es;
689 dmsg (D_EVENT_WAIT, "PO_CTL rwflags=0x%04x ev=%d arg=" ptr_format,
690 rwflags, (int)event, (ptr_type)arg);
692 if (pos->fast)
694 if (!po_append_event (pos, event, rwflags, arg))
695 goto err;
697 else
699 int i;
700 for (i = 0; i < pos->n_events; ++i)
702 struct pollfd *pfdp = &pos->events[i];
703 if (pfdp->fd == event)
705 pos->args[i] = arg;
706 po_set_pollfd_events (pfdp, rwflags);
707 goto done;
710 if (!po_append_event (pos, event, rwflags, arg))
711 goto err;
714 done:
715 return;
717 err:
718 msg (D_EVENT_ERRORS, "Error: poll: too many I/O wait events");
721 static int
722 po_wait (struct event_set *es, const struct timeval *tv, struct event_set_return *out, int outlen)
724 struct po_set *pos = (struct po_set *) es;
725 int stat;
727 stat = poll (pos->events, pos->n_events, tv_to_ms_timeout (tv));
729 ASSERT (stat <= pos->n_events);
731 if (stat > 0)
733 int i, j=0;
734 const struct pollfd *pfdp = pos->events;
735 for (i = 0; i < pos->n_events && j < outlen; ++i)
737 if (pfdp->revents & (POLLIN|POLLPRI|POLLERR|POLLHUP|POLLOUT))
739 out->rwflags = 0;
740 if (pfdp->revents & (POLLIN|POLLPRI|POLLERR|POLLHUP))
741 out->rwflags |= EVENT_READ;
742 if (pfdp->revents & POLLOUT)
743 out->rwflags |= EVENT_WRITE;
744 out->arg = pos->args[i];
745 dmsg (D_EVENT_WAIT, "PO_WAIT[%d,%d] fd=%d rev=0x%08x rwflags=0x%04x arg=" ptr_format " %s",
746 i, j, pfdp->fd, pfdp->revents, out->rwflags, (ptr_type)out->arg, pos->fast ? "" : "[scalable]");
747 ++out;
748 ++j;
750 else if (pfdp->revents)
752 msg (D_EVENT_ERRORS, "Error: poll: unknown revents=0x%04x", (unsigned int)pfdp->revents);
754 ++pfdp;
756 return j;
758 return stat;
761 static struct event_set *
762 po_init (int *maxevents, unsigned int flags)
764 struct po_set *pos;
766 dmsg (D_EVENT_WAIT, "PO_INIT maxevents=%d flags=0x%08x", *maxevents, flags);
768 ALLOC_OBJ_CLEAR (pos, struct po_set);
770 /* set dispatch functions */
771 pos->func.free = po_free;
772 pos->func.reset = po_reset;
773 pos->func.del = po_del;
774 pos->func.ctl = po_ctl;
775 pos->func.wait = po_wait;
777 if (flags & EVENT_METHOD_FAST)
778 pos->fast = true;
780 pos->n_events = 0;
782 /* Figure our event capacity */
783 ASSERT (*maxevents > 0);
784 pos->capacity = *maxevents;
786 /* Allocate space for pollfd structures to be passed to poll() */
787 ALLOC_ARRAY_CLEAR (pos->events, struct pollfd, pos->capacity);
789 /* Allocate space for event_set_return objects */
790 ALLOC_ARRAY_CLEAR (pos->args, void *, pos->capacity);
792 return (struct event_set *) pos;
794 #endif /* POLL */
796 #if SELECT
798 struct se_set
800 struct event_set_functions func;
801 bool fast;
802 fd_set readfds;
803 fd_set writefds;
804 void **args; /* allocated to capacity size */
805 int maxfd; /* largest fd seen so far, always < capacity */
806 int capacity; /* fixed largest fd + 1 */
809 static void
810 se_free (struct event_set *es)
812 struct se_set *ses = (struct se_set *) es;
813 free (ses->args);
814 free (ses);
817 static void
818 se_reset (struct event_set *es)
820 struct se_set *ses = (struct se_set *) es;
821 int i;
822 ASSERT (ses->fast);
824 dmsg (D_EVENT_WAIT, "SE_RESET");
826 FD_ZERO (&ses->readfds);
827 FD_ZERO (&ses->writefds);
828 for (i = 0; i <= ses->maxfd; ++i)
829 ses->args[i] = NULL;
830 ses->maxfd = -1;
833 static void
834 se_del (struct event_set *es, event_t event)
836 struct se_set *ses = (struct se_set *) es;
837 ASSERT (!ses->fast);
839 dmsg (D_EVENT_WAIT, "SE_DEL ev=%d", (int)event);
841 if (event >= 0 && event < ses->capacity)
843 FD_CLR (event, &ses->readfds);
844 FD_CLR (event, &ses->writefds);
845 ses->args[event] = NULL;
847 else
848 msg (D_EVENT_ERRORS, "Error: select/se_del: too many I/O wait events");
849 return;
852 static void
853 se_ctl (struct event_set *es, event_t event, unsigned int rwflags, void *arg)
855 struct se_set *ses = (struct se_set *) es;
857 dmsg (D_EVENT_WAIT, "SE_CTL rwflags=0x%04x ev=%d fast=%d cap=%d maxfd=%d arg=" ptr_format,
858 rwflags, (int)event, (int)ses->fast, ses->capacity, ses->maxfd, (ptr_type)arg);
860 if (event >= 0 && event < ses->capacity)
862 ses->maxfd = max_int (event, ses->maxfd);
863 ses->args[event] = arg;
864 if (ses->fast)
866 if (rwflags & EVENT_READ)
867 FD_SET (event, &ses->readfds);
868 if (rwflags & EVENT_WRITE)
869 FD_SET (event, &ses->writefds);
871 else
873 if (rwflags & EVENT_READ)
874 FD_SET (event, &ses->readfds);
875 else
876 FD_CLR (event, &ses->readfds);
877 if (rwflags & EVENT_WRITE)
878 FD_SET (event, &ses->writefds);
879 else
880 FD_CLR (event, &ses->writefds);
883 else
885 msg (D_EVENT_ERRORS, "Error: select: too many I/O wait events, fd=%d cap=%d",
886 (int) event,
887 ses->capacity);
891 static int
892 se_wait_return (struct se_set *ses,
893 fd_set *read,
894 fd_set *write,
895 struct event_set_return *out,
896 int outlen)
898 int i, j = 0;
899 for (i = 0; i <= ses->maxfd && j < outlen; ++i)
901 const bool r = FD_ISSET (i, read);
902 const bool w = FD_ISSET (i, write);
903 if (r || w)
905 out->rwflags = 0;
906 if (r)
907 out->rwflags |= EVENT_READ;
908 if (w)
909 out->rwflags |= EVENT_WRITE;
910 out->arg = ses->args[i];
911 dmsg (D_EVENT_WAIT, "SE_WAIT[%d,%d] rwflags=0x%04x arg=" ptr_format,
912 i, j, out->rwflags, (ptr_type)out->arg);
913 ++out;
914 ++j;
917 return j;
920 static int
921 se_wait_fast (struct event_set *es, const struct timeval *tv, struct event_set_return *out, int outlen)
923 struct se_set *ses = (struct se_set *) es;
924 struct timeval tv_tmp = *tv;
925 int stat;
927 dmsg (D_EVENT_WAIT, "SE_WAIT_FAST maxfd=%d tv=%d/%d",
928 ses->maxfd,
929 (int)tv_tmp.tv_sec,
930 (int)tv_tmp.tv_usec);
932 stat = select (ses->maxfd + 1, &ses->readfds, &ses->writefds, NULL, &tv_tmp);
934 if (stat > 0)
935 stat = se_wait_return (ses, &ses->readfds, &ses->writefds, out, outlen);
937 return stat;
940 static int
941 se_wait_scalable (struct event_set *es, const struct timeval *tv, struct event_set_return *out, int outlen)
943 struct se_set *ses = (struct se_set *) es;
944 struct timeval tv_tmp = *tv;
945 fd_set read = ses->readfds;
946 fd_set write = ses->writefds;
947 int stat;
949 dmsg (D_EVENT_WAIT, "SE_WAIT_SCALEABLE maxfd=%d tv=%d/%d",
950 ses->maxfd, (int)tv_tmp.tv_sec, (int)tv_tmp.tv_usec);
952 stat = select (ses->maxfd + 1, &read, &write, NULL, &tv_tmp);
954 if (stat > 0)
955 stat = se_wait_return (ses, &read, &write, out, outlen);
957 return stat;
960 static struct event_set *
961 se_init (int *maxevents, unsigned int flags)
963 struct se_set *ses;
965 dmsg (D_EVENT_WAIT, "SE_INIT maxevents=%d flags=0x%08x", *maxevents, flags);
967 ALLOC_OBJ_CLEAR (ses, struct se_set);
969 /* set dispatch functions */
970 ses->func.free = se_free;
971 ses->func.reset = se_reset;
972 ses->func.del = se_del;
973 ses->func.ctl = se_ctl;
974 ses->func.wait = se_wait_scalable;
976 if (flags & EVENT_METHOD_FAST)
978 ses->fast = true;
979 ses->func.wait = se_wait_fast;
982 /* Select needs to be passed this value + 1 */
983 ses->maxfd = -1;
985 /* Set our event capacity */
986 ASSERT (*maxevents > 0);
987 *maxevents = min_int (*maxevents, SELECT_MAX_FDS);
988 ses->capacity = SELECT_MAX_FDS;
990 /* Allocate space for event_set_return void * args */
991 ALLOC_ARRAY_CLEAR (ses->args, void *, ses->capacity);
993 return (struct event_set *) ses;
995 #endif /* SELECT */
997 static struct event_set *
998 event_set_init_simple (int *maxevents, unsigned int flags)
1000 struct event_set *ret = NULL;
1001 #ifdef WIN32
1002 ret = we_init (maxevents, flags);
1003 #elif POLL && SELECT
1004 #if 0 /* Define to 1 if EVENT_METHOD_US_TIMEOUT should cause select to be favored over poll */
1005 if (flags & EVENT_METHOD_US_TIMEOUT)
1006 ret = se_init (maxevents, flags);
1007 #endif
1008 # ifdef SELECT_PREFERRED_OVER_POLL
1009 if (!ret)
1010 ret = se_init (maxevents, flags);
1011 if (!ret)
1012 ret = po_init (maxevents, flags);
1013 # else
1014 if (!ret)
1015 ret = po_init (maxevents, flags);
1016 if (!ret)
1017 ret = se_init (maxevents, flags);
1018 # endif
1019 #elif POLL
1020 ret = po_init (maxevents, flags);
1021 #elif SELECT
1022 ret = se_init (maxevents, flags);
1023 #else
1024 #error At least one of poll, select, or WSAWaitForMultipleEvents must be supported by the kernel
1025 #endif
1026 ASSERT (ret);
1027 return ret;
1030 static struct event_set *
1031 event_set_init_scalable (int *maxevents, unsigned int flags)
1033 struct event_set *ret = NULL;
1034 #if EPOLL
1035 ret = ep_init (maxevents, flags);
1036 if (!ret)
1038 msg (M_WARN, "Note: sys_epoll API is unavailable, falling back to poll/select API");
1039 ret = event_set_init_simple (maxevents, flags);
1041 #else
1042 ret = event_set_init_simple (maxevents, flags);
1043 #endif
1044 ASSERT (ret);
1045 return ret;
1048 struct event_set *
1049 event_set_init (int *maxevents, unsigned int flags)
1051 if (flags & EVENT_METHOD_FAST)
1052 return event_set_init_simple (maxevents, flags);
1053 else
1054 return event_set_init_scalable (maxevents, flags);