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);
163 for (
i = 0;
i < len; ++
i)
165 const HANDLE h = wes->
events[
i];
166 if (h == event->
read || h == event->
write)
186 ASSERT(index >= 0 && index < wes->n_events);
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);
432 if (WaitForSingleObject(wes->
events[
i], 0) == WAIT_OBJECT_0)
457 (DWORD)timeout, FALSE);
460 if (outlen >= 1 &&
status >= WSA_WAIT_EVENT_0
463 *out = wes->
esr[
status - WSA_WAIT_EVENT_0];
468 else if (
status == WSA_WAIT_TIMEOUT)
504 *maxevents =
min_int(*maxevents, WSA_MAXIMUM_WAIT_EVENTS);
527 struct epoll_event *events;
533 struct ep_set *eps = (
struct ep_set *)
es;
542 const struct ep_set *eps = (
struct ep_set *)
es;
549 struct epoll_event ev;
550 struct ep_set *eps = (
struct ep_set *)
es;
556 if (epoll_ctl(eps->epfd, EPOLL_CTL_DEL, event, &ev) < 0)
558 msg(
M_WARN |
M_ERRNO,
"EVENT: epoll_ctl EPOLL_CTL_DEL failed, sd=%d", (
int)event);
565 struct ep_set *eps = (
struct ep_set *)
es;
566 struct epoll_event ev;
573 ev.events |= EPOLLIN;
577 ev.events |= EPOLLOUT;
581 (
unsigned int)ev.events, (
ptr_type)ev.data.ptr);
583 if (epoll_ctl(eps->epfd, EPOLL_CTL_MOD, event, &ev) < 0)
587 if (epoll_ctl(eps->epfd, EPOLL_CTL_ADD, event, &ev) < 0)
589 msg(
M_ERR,
"EVENT: epoll_ctl EPOLL_CTL_ADD failed, sd=%d", (
int)event);
594 msg(
M_ERR,
"EVENT: epoll_ctl EPOLL_CTL_MOD failed, sd=%d", (
int)event);
602 struct ep_set *eps = (
struct ep_set *)
es;
605 if (outlen > eps->maxevents)
607 outlen = eps->maxevents;
616 const struct epoll_event *ev = eps->events;
618 for (
i = 0;
i < stat; ++
i)
621 if (ev->events & (EPOLLIN | EPOLLPRI | EPOLLERR | EPOLLHUP))
625 if (ev->events & EPOLLOUT)
629 esr->
arg = ev->data.ptr;
640ep_init(
int *maxevents,
unsigned int flags)
648 fd = epoll_create(*maxevents);
659 eps->func.free = ep_free;
660 eps->func.reset = ep_reset;
661 eps->func.del = ep_del;
662 eps->func.ctl = ep_ctl;
663 eps->func.wait = ep_wait;
673 eps->maxevents = *maxevents;
689 struct pollfd *events;
698 struct po_set *
pos = (
struct po_set *)
es;
707 struct po_set *
pos = (
struct po_set *)
es;
715 struct po_set *
pos = (
struct po_set *)
es;
721 for (
i = 0;
i <
pos->n_events; ++
i)
723 if (
pos->events[
i].fd == event)
726 for (j =
i; j <
pos->n_events - 1; ++j)
728 pos->events[j] =
pos->events[j + 1];
729 pos->args[j] =
pos->args[j + 1];
738po_set_pollfd_events(
struct pollfd *pfdp,
unsigned int rwflags)
743 pfdp->events |= POLLOUT;
747 pfdp->events |= (POLLIN | POLLPRI);
752po_append_event(
struct po_set *
pos,
event_t event,
unsigned int rwflags,
void *arg)
754 if (
pos->n_events <
pos->capacity)
756 struct pollfd *pfdp = &
pos->events[
pos->n_events];
758 pos->args[
pos->n_events] = arg;
759 po_set_pollfd_events(pfdp, rwflags);
772 struct po_set *
pos = (
struct po_set *)
es;
779 if (!po_append_event(
pos, event, rwflags, arg))
787 for (
i = 0;
i <
pos->n_events; ++
i)
789 struct pollfd *pfdp = &
pos->events[
i];
790 if (pfdp->fd == event)
793 po_set_pollfd_events(pfdp, rwflags);
797 if (!po_append_event(
pos, event, rwflags, arg))
813 struct po_set *
pos = (
struct po_set *)
es;
818 ASSERT(stat <= pos->n_events);
823 const struct pollfd *pfdp =
pos->events;
824 for (
i = 0;
i <
pos->n_events && j < outlen; ++
i)
826 if (pfdp->revents & (POLLIN | POLLPRI | POLLERR | POLLHUP | POLLOUT))
829 if (pfdp->revents & (POLLIN | POLLPRI | POLLERR | POLLHUP))
833 if (pfdp->revents & POLLOUT)
839 "PO_WAIT[%d,%d] fd=%d rev=0x%08x rwflags=0x%04x arg=" ptr_format " %s",
i, j,
841 pos->fast ?
"" :
"[scalable]");
845 else if (pfdp->revents)
848 (
unsigned int)pfdp->revents, pfdp->fd);
858po_init(
int *maxevents,
unsigned int flags)
867 pos->func.free = po_free;
868 pos->func.reset = po_reset;
869 pos->func.del = po_del;
870 pos->func.ctl = po_ctl;
871 pos->func.wait = po_wait;
882 pos->capacity = *maxevents;
910 struct se_set *ses = (
struct se_set *)
es;
918 struct se_set *ses = (
struct se_set *)
es;
924 FD_ZERO(&ses->readfds);
925 FD_ZERO(&ses->writefds);
926 for (
i = 0;
i <= ses->maxfd; ++
i)
936 struct se_set *ses = (
struct se_set *)
es;
941 if (event >= 0 && event < ses->capacity)
943 FD_CLR(event, &ses->readfds);
944 FD_CLR(event, &ses->writefds);
945 ses->args[event] = NULL;
957 struct se_set *ses = (
struct se_set *)
es;
960 rwflags, (
int)event, (
int)ses->fast, ses->capacity, ses->maxfd, (
ptr_type)arg);
962 if (event >= 0 && event < ses->capacity)
964 ses->maxfd =
max_int(event, ses->maxfd);
965 ses->args[event] = arg;
985 FD_CLR(event, &ses->readfds);
993 FD_CLR(event, &ses->writefds);
999 msg(
D_EVENT_ERRORS,
"Error: select: too many I/O wait events, fd=%d cap=%d", (
int)event,
1009 for (
i = 0;
i <= ses->maxfd && j < outlen; ++
i)
1011 const bool r = FD_ISSET(
i,
read);
1012 const bool w = FD_ISSET(
i,
write);
1024 out->
arg = ses->args[
i];
1038 struct se_set *ses = (
struct se_set *)
es;
1039 struct timeval tv_tmp = *tv;
1043 (int64_t)tv_tmp.tv_sec, (
long)tv_tmp.tv_usec);
1045 stat = select(ses->maxfd + 1, &ses->readfds, &ses->writefds, NULL, &tv_tmp);
1049 stat = se_wait_return(ses, &ses->readfds, &ses->writefds, out, outlen);
1059 struct se_set *ses = (
struct se_set *)
es;
1060 struct timeval tv_tmp = *tv;
1061 fd_set
read = ses->readfds;
1062 fd_set
write = ses->writefds;
1065 dmsg(
D_EVENT_WAIT,
"SE_WAIT_SCALEABLE maxfd=%d tv=%" PRIi64
"/%ld", ses->maxfd,
1066 (int64_t)tv_tmp.tv_sec, (
long)tv_tmp.tv_usec);
1068 stat = select(ses->maxfd + 1, &
read, &
write, NULL, &tv_tmp);
1072 stat = se_wait_return(ses, &
read, &
write, out, outlen);
1079se_init(
int *maxevents,
unsigned int flags)
1083 dmsg(
D_EVENT_WAIT,
"SE_INIT maxevents=%d flags=0x%08x", *maxevents, flags);
1088 ses->func.free = se_free;
1089 ses->func.reset = se_reset;
1090 ses->func.del = se_del;
1091 ses->func.ctl = se_ctl;
1092 ses->func.wait = se_wait_scalable;
1097 ses->func.wait = se_wait_fast;
1120 ret =
we_init(maxevents, flags);
1125 ret = se_init(maxevents, flags);
1128#ifdef SELECT_PREFERRED_OVER_POLL
1131 ret = se_init(maxevents, flags);
1135 ret = po_init(maxevents, flags);
1140 ret = po_init(maxevents, flags);
1144 ret = se_init(maxevents, flags);
1148 ret = po_init(maxevents, flags);
1150 ret = se_init(maxevents, flags);
1152#error At least one of poll, select, or WSAWaitForMultipleEvents must be supported by the kernel
1163 ret = ep_init(maxevents, flags);
1166 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