diff --git a/src/eventloop_epoll.c b/src/eventloop_epoll.c index a0797ef..2bbb0fd 100644 --- a/src/eventloop_epoll.c +++ b/src/eventloop_epoll.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -57,7 +58,57 @@ int owd_platform_el_wait( uint32_t *flags_out, const struct timespec *timeout) { + struct epoll_event ev; + struct owd_event *e; + int res; + + do { + res = epoll_pwait2(el->epoll_fd, &ev, 1, timeout, NULL); + } while ((res < 0) && (errno == EINTR)); + + if (res <= 0) { + if (!res) + errno = ETIMEDOUT; + return -1; + } + + e = (struct owd_event *)ev.data.ptr; + + *id_out = e->id; + *flags_out = 0; + if (ev.events & EPOLLIN) + *flags_out |= OWD_EVENT_READABLE; + if (ev.events & EPOLLOUT) + *flags_out |= OWD_EVENT_WRITABLE; + + return 0; +} + +static int el_epoll_add( + struct owd_eventloop *el, + struct owd_event *e, + int fd, + enum owd_event_source source, + uint32_t events, + bool owned) +{ + struct epoll_event ev; + + memset(&ev, 0, sizeof(ev)); + ev.events = events; + ev.data.fd = fd; + ev.data.ptr = e; + + if (epoll_ctl(el->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) + return -1; + + e->id.obj = (uintptr_t)fd; + e->id.source = source; + e->epoll_registered_fd = fd; + e->epoll_fd_owned = owned; + + return 0; } int owd_platform_el_add_timer( diff --git a/src/eventloop_kqueue.c b/src/eventloop_kqueue.c index 3f3d89d..8efa84c 100644 --- a/src/eventloop_kqueue.c +++ b/src/eventloop_kqueue.c @@ -81,13 +81,11 @@ void owd_platform_el_event_remove(struct owd_eventloop *el, struct owd_event *e) kevent(el->kqueue_fd, kevs, filters_len, NULL, 0, NULL); } -// TODO: close timerfd on linux void owd_platform_el_event_cleanup(struct owd_eventloop *el, struct owd_event *e) { (void)el; (void)e; } -// TODO: read timerfd on linux int owd_platform_el_event_clear(struct owd_eventloop *el, struct owd_event *e) { (void)el; (void)e; @@ -101,6 +99,7 @@ int owd_platform_el_wait( const struct timespec *timeout) { struct kevent kev; + struct owd_event *e; int res; do { @@ -113,19 +112,21 @@ int owd_platform_el_wait( return -1; } - id_out->obj = kev.ident; + e = (struct owd_event *)kev.udata; + + *id_out = e->id; *flags_out = 0; - if (kev.filter & EVFILT_TIMER) { - id_out->source = OWD_EVENT_SOURCE_TIMER; - *flags_out |= OWD_EVENT_READABLE; - } - else { - id_out->source = OWD_EVENT_SOURCE_FD; - if (kev.filter & EVFILT_READ) + switch (kev.filter) { + case EVFILT_TIMER: + case EVFILT_READ: *flags_out |= OWD_EVENT_READABLE; - if (kev.filter & EVFILT_WRITE) + break; + case EVFILT_WRITE: *flags_out |= OWD_EVENT_WRITABLE; + break; + default: + break; } return 0; @@ -135,6 +136,7 @@ static int el_kqueue_add( struct owd_eventloop *el, struct owd_event *e, uintptr_t ident, + enum owd_event_source source, const struct el_kqueue_add_params *params, uint8_t params_len) { @@ -152,12 +154,14 @@ static int el_kqueue_add( kevs[i].filter = params[i].filter; kevs[i].flags = EV_ADD | params[i].flags; kevs[i].data = params[i].data; + kevs[i].udata = e; } if (kevent(el->kqueue_fd, kevs, params_len, NULL, 0, NULL)) return -1; e->id.obj = ident; + e->id.source = source; e->kqueue_ident = ident; e->kqueue_filters_len = params_len; for (i = 0; i < params_len; i++) @@ -182,7 +186,7 @@ int owd_platform_el_add_timer( if (oneshot) params.flags |= EV_ONESHOT; - if ((res = el_kqueue_add(el, e, el->kqueue_timer_next, ¶ms, 1))) + if ((res = el_kqueue_add(el, e, el->kqueue_timer_next, OWD_EVENT_SOURCE_TIMER, ¶ms, 1))) return res; el->kqueue_timer_next++; @@ -217,5 +221,5 @@ int owd_platform_el_add_fd( }; } - return el_kqueue_add(el, e, (uintptr_t)fd, params, params_len); + return el_kqueue_add(el, e, (uintptr_t)fd, OWD_EVENT_SOURCE_FD, params, params_len); }