45#if defined(TARGET_DARWIN)
46#define SELECT_PREFERRED_OVER_POLL
63#define SELECT_MAX_FDS FD_SETSIZE
65#define SELECT_MAX_FDS 256
80 if (tv->tv_sec == 0 && tv->tv_usec == 0)
87 return max_int((
int)(tv->tv_sec * 1000 + (tv->tv_usec + 500) / 1000), 1);
106 ASSERT(i >= 0 && i < wes->capacity);
111 wes->
events[i] =
event->read;
116 wes->
events[i] =
event->write;
163 for (i = 0; i < len; ++i)
165 const HANDLE h = wes->
events[i];
166 if (h == event->
read || h == event->
write)
175 wes->
esr[j] = wes->
esr[i];
186 ASSERT(index >= 0 && index < wes->n_events);
187 for (i = index; i < wes->
n_events - 1; ++i)
190 wes->
esr[i] = wes->
esr[i + 1];
202 const HANDLE h = wes->
events[i];
203 if (h == event->
read)
208 else if (h == event->
write)
381 msg(
M_FATAL,
"fatal error in we_ctl: rwflags=%d", rwflags);
388 "Error: Windows resource limit WSA_MAXIMUM_WAIT_EVENTS (%d) has been exceeded",
389 WSA_MAXIMUM_WAIT_EVENTS);
416#pragma GCC diagnostic push
417#pragma GCC diagnostic ignored "-Wtype-limits"
439 if (WaitForSingleObject(wes->
events[i], 0) == WAIT_OBJECT_0)
464 (DWORD)timeout, FALSE);
467 if (outlen >= 1 &&
status >= WSA_WAIT_EVENT_0
470 *out = wes->
esr[
status - WSA_WAIT_EVENT_0];
475 else if (
status == WSA_WAIT_TIMEOUT)
485#pragma GCC diagnostic pop
514 *maxevents =
min_int(*maxevents, WSA_MAXIMUM_WAIT_EVENTS);
537 struct epoll_event *events;
543 struct ep_set *eps = (
struct ep_set *)
es;
552 const struct ep_set *eps = (
struct ep_set *)
es;
559 struct epoll_event ev;
560 struct ep_set *eps = (
struct ep_set *)
es;
566 if (epoll_ctl(eps->epfd, EPOLL_CTL_DEL, event, &ev) < 0)
568 msg(
M_WARN |
M_ERRNO,
"EVENT: epoll_ctl EPOLL_CTL_DEL failed, sd=%d", (
int)event);
575 struct ep_set *eps = (
struct ep_set *)
es;
576 struct epoll_event ev;
583 ev.events |= EPOLLIN;
587 ev.events |= EPOLLOUT;
591 (
unsigned int)ev.events, (
ptr_type)ev.data.ptr);
593 if (epoll_ctl(eps->epfd, EPOLL_CTL_MOD, event, &ev) < 0)
597 if (epoll_ctl(eps->epfd, EPOLL_CTL_ADD, event, &ev) < 0)
599 msg(
M_ERR,
"EVENT: epoll_ctl EPOLL_CTL_ADD failed, sd=%d", (
int)event);
604 msg(
M_ERR,
"EVENT: epoll_ctl EPOLL_CTL_MOD failed, sd=%d", (
int)event);
612 struct ep_set *eps = (
struct ep_set *)
es;
615 if (outlen > eps->maxevents)
617 outlen = eps->maxevents;
626 const struct epoll_event *ev = eps->events;
628 for (i = 0; i < stat; ++i)
631 if (ev->events & (EPOLLIN | EPOLLPRI | EPOLLERR | EPOLLHUP))
635 if (ev->events & EPOLLOUT)
639 esr->
arg = ev->data.ptr;
650ep_init(
int *maxevents,
unsigned int flags)
658 fd = epoll_create(*maxevents);
669 eps->func.free = ep_free;
670 eps->func.reset = ep_reset;
671 eps->func.del = ep_del;
672 eps->func.ctl = ep_ctl;
673 eps->func.wait = ep_wait;
683 eps->maxevents = *maxevents;
699 struct pollfd *events;
708 struct po_set *
pos = (
struct po_set *)
es;
717 struct po_set *
pos = (
struct po_set *)
es;
725 struct po_set *
pos = (
struct po_set *)
es;
731 for (i = 0; i <
pos->n_events; ++i)
733 if (
pos->events[i].fd == event)
736 for (j = i; j <
pos->n_events - 1; ++j)
738 pos->events[j] =
pos->events[j + 1];
739 pos->args[j] =
pos->args[j + 1];
748po_set_pollfd_events(
struct pollfd *pfdp,
unsigned int rwflags)
753 pfdp->events |= POLLOUT;
757 pfdp->events |= (POLLIN | POLLPRI);
762po_append_event(
struct po_set *
pos,
event_t event,
unsigned int rwflags,
void *arg)
764 if (
pos->n_events <
pos->capacity)
766 struct pollfd *pfdp = &
pos->events[
pos->n_events];
768 pos->args[
pos->n_events] = arg;
769 po_set_pollfd_events(pfdp, rwflags);
782 struct po_set *
pos = (
struct po_set *)
es;
789 if (!po_append_event(
pos, event, rwflags, arg))
797 for (i = 0; i <
pos->n_events; ++i)
799 struct pollfd *pfdp = &
pos->events[i];
800 if (pfdp->fd == event)
803 po_set_pollfd_events(pfdp, rwflags);
807 if (!po_append_event(
pos, event, rwflags, arg))
823 struct po_set *
pos = (
struct po_set *)
es;
828 ASSERT(stat <= pos->n_events);
833 const struct pollfd *pfdp =
pos->events;
834 for (i = 0; i <
pos->n_events && j < outlen; ++i)
836 if (pfdp->revents & (POLLIN | POLLPRI | POLLERR | POLLHUP | POLLOUT))
839 if (pfdp->revents & (POLLIN | POLLPRI | POLLERR | POLLHUP))
843 if (pfdp->revents & POLLOUT)
849 "PO_WAIT[%d,%d] fd=%d rev=0x%08x rwflags=0x%04x arg=" ptr_format " %s", i, j,
851 pos->fast ?
"" :
"[scalable]");
855 else if (pfdp->revents)
858 (
unsigned int)pfdp->revents, pfdp->fd);
868po_init(
int *maxevents,
unsigned int flags)
877 pos->func.free = po_free;
878 pos->func.reset = po_reset;
879 pos->func.del = po_del;
880 pos->func.ctl = po_ctl;
881 pos->func.wait = po_wait;
892 pos->capacity = *maxevents;
920 struct se_set *ses = (
struct se_set *)
es;
928 struct se_set *ses = (
struct se_set *)
es;
934 FD_ZERO(&ses->readfds);
935 FD_ZERO(&ses->writefds);
936 for (i = 0; i <= ses->maxfd; ++i)
946 struct se_set *ses = (
struct se_set *)
es;
951 if (event >= 0 && event < ses->capacity)
953 FD_CLR(event, &ses->readfds);
954 FD_CLR(event, &ses->writefds);
955 ses->args[event] = NULL;
967 struct se_set *ses = (
struct se_set *)
es;
970 rwflags, (
int)event, (
int)ses->fast, ses->capacity, ses->maxfd, (
ptr_type)arg);
972 if (event >= 0 && event < ses->capacity)
974 ses->maxfd =
max_int(event, ses->maxfd);
975 ses->args[event] = arg;
995 FD_CLR(event, &ses->readfds);
1003 FD_CLR(event, &ses->writefds);
1009 msg(
D_EVENT_ERRORS,
"Error: select: too many I/O wait events, fd=%d cap=%d", (
int)event,
1019 for (i = 0; i <= ses->maxfd && j < outlen; ++i)
1021 const bool r = FD_ISSET(i,
read);
1022 const bool w = FD_ISSET(i,
write);
1034 out->
arg = ses->args[i];
1048 struct se_set *ses = (
struct se_set *)
es;
1049 struct timeval tv_tmp = *tv;
1053 (int64_t)tv_tmp.tv_sec, (
long)tv_tmp.tv_usec);
1055 stat = select(ses->maxfd + 1, &ses->readfds, &ses->writefds, NULL, &tv_tmp);
1059 stat = se_wait_return(ses, &ses->readfds, &ses->writefds, out, outlen);
1069 struct se_set *ses = (
struct se_set *)
es;
1070 struct timeval tv_tmp = *tv;
1071 fd_set
read = ses->readfds;
1072 fd_set
write = ses->writefds;
1075 dmsg(
D_EVENT_WAIT,
"SE_WAIT_SCALEABLE maxfd=%d tv=%" PRIi64
"/%ld", ses->maxfd,
1076 (int64_t)tv_tmp.tv_sec, (
long)tv_tmp.tv_usec);
1078 stat = select(ses->maxfd + 1, &
read, &
write, NULL, &tv_tmp);
1082 stat = se_wait_return(ses, &
read, &
write, out, outlen);
1089se_init(
int *maxevents,
unsigned int flags)
1093 dmsg(
D_EVENT_WAIT,
"SE_INIT maxevents=%d flags=0x%08x", *maxevents, flags);
1098 ses->func.free = se_free;
1099 ses->func.reset = se_reset;
1100 ses->func.del = se_del;
1101 ses->func.ctl = se_ctl;
1102 ses->func.wait = se_wait_scalable;
1107 ses->func.wait = se_wait_fast;
1130 ret =
we_init(maxevents, flags);
1135 ret = se_init(maxevents, flags);
1138#ifdef SELECT_PREFERRED_OVER_POLL
1141 ret = se_init(maxevents, flags);
1145 ret = po_init(maxevents, flags);
1150 ret = po_init(maxevents, flags);
1154 ret = se_init(maxevents, flags);
1158 ret = po_init(maxevents, flags);
1160 ret = se_init(maxevents, flags);
1162#error At least one of poll, select, or WSAWaitForMultipleEvents must be supported by the kernel
1173 ret = ep_init(maxevents, flags);
1176 msg(
M_WARN,
"Note: sys_epoll API is unavailable, falling back to poll/select API");
#define ALLOC_ARRAY_CLEAR(dptr, type, n)
#define ALLOC_OBJ_CLEAR(dptr, type)
static bool we_append_event(struct we_set *wes, event_t event, unsigned int rwflags, void *arg)
static struct event_set * event_set_init_simple(int *maxevents, unsigned int flags)
static void we_free(struct event_set *es)
static void we_get_rw_indices(struct we_set *wes, event_t event, int *ri, int *wi)
static void we_del_index(struct we_set *wes, int index)
static int tv_to_ms_timeout(const struct timeval *tv)
Convert timeval value (which is in seconds and microseconds) to a value of milliseconds which is requ...
static struct event_set * event_set_init_scalable(int *maxevents, unsigned int flags)
static void we_del(struct event_set *es, event_t event)
static int we_wait(struct event_set *es, const struct timeval *tv, struct event_set_return *out, int outlen)
static void we_ctl(struct event_set *es, event_t event, unsigned int rwflags, void *arg)
static struct event_set * we_init(int *maxevents, unsigned int flags)
struct event_set * event_set_init(int *maxevents, unsigned int flags)
static void we_del_event(struct we_set *wes, event_t event)
static void we_set_event(struct we_set *wes, int i, event_t event, unsigned int rwflags, void *arg)
static void we_reset(struct event_set *es)
#define EVENT_METHOD_FAST
#define EVENT_METHOD_US_TIMEOUT
void set_cloexec(socket_descriptor_t fd)
static void openvpn_fd_set(socket_descriptor_t fd, fd_set *setp)
static int min_int(int x, int y)
static int max_int(int x, int y)
static SERVICE_STATUS status
static bool check_debug_level(msglvl_t level)
void(* ctl)(struct event_set *es, event_t event, unsigned int rwflags, void *arg)
int(* wait)(struct event_set *es, const struct timeval *tv, struct event_set_return *out, int outlen)
void(* del)(struct event_set *es, event_t event)
void(* reset)(struct event_set *es)
void(* free)(struct event_set *es)
struct event_set_return * esr
struct event_set_functions func