From 17f4e41ecb80f70c14493b4518e6eabec9faff7b Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 4 Jan 2013 03:17:51 +0100 Subject: [PATCH] uloop: improve edge trigger reliability on mac os x Sometimes after re-arming a fd, an initial event for reads is not generated, even though there is data pending. Work around this by making the trigger level-triggered first, then switching to edge trigger after processing the first event. Signed-off-by: Felix Fietkau --- uloop.c | 22 ++++++++++++++++++++-- uloop.h | 6 ++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/uloop.c b/uloop.c index bf17219..2d7b2c9 100644 --- a/uloop.c +++ b/uloop.c @@ -90,7 +90,7 @@ static uint16_t get_flags(unsigned int flags, unsigned int mask) static struct kevent events[ULOOP_MAX_EVENTS]; -static int register_poll(struct uloop_fd *fd, unsigned int flags) +static int register_kevent(struct uloop_fd *fd, unsigned int flags) { struct timespec timeout = { 0, 0 }; struct kevent ev[2]; @@ -98,6 +98,9 @@ static int register_poll(struct uloop_fd *fd, unsigned int flags) unsigned int fl = 0; uint16_t kflags; + if (flags & ULOOP_EDGE_DEFER) + flags &= ~ULOOP_EDGE_TRIGGER; + kflags = get_flags(flags, ULOOP_READ); EV_SET(&ev[nev++], fd->fd, EVFILT_READ, kflags, 0, 0, fd); @@ -107,12 +110,23 @@ static int register_poll(struct uloop_fd *fd, unsigned int flags) if (!flags) fl |= EV_DELETE; - if (nev && (kevent(poll_fd, ev, nev, NULL, fl, &timeout) == -1)) + if (kevent(poll_fd, ev, nev, NULL, fl, &timeout) == -1) return -1; return 0; } +static int register_poll(struct uloop_fd *fd, unsigned int flags) +{ + if (flags & ULOOP_EDGE_TRIGGER) + flags |= ULOOP_EDGE_DEFER; + else + flags &= ~ULOOP_EDGE_DEFER; + + fd->flags = flags; + return register_kevent(fd, flags); +} + int uloop_fd_delete(struct uloop_fd *sock) { int i; @@ -166,6 +180,10 @@ static void uloop_run_events(int timeout) cur_fd = n; cur_nfds = nfds; u->cb(u, ev); + if (u->flags & ULOOP_EDGE_DEFER) { + u->flags &= ~ULOOP_EDGE_DEFER; + register_kevent(u, u->flags); + } } } cur_nfds = 0; diff --git a/uloop.h b/uloop.h index 4be2913..b5cd0d4 100644 --- a/uloop.h +++ b/uloop.h @@ -46,6 +46,9 @@ typedef void (*uloop_process_handler)(struct uloop_process *c, int ret); #define ULOOP_WRITE (1 << 1) #define ULOOP_EDGE_TRIGGER (1 << 2) #define ULOOP_BLOCKING (1 << 3) +#ifdef USE_KQUEUE +#define ULOOP_EDGE_DEFER (1 << 4) +#endif struct uloop_fd { @@ -54,6 +57,9 @@ struct uloop_fd bool eof; bool error; bool registered; +#ifdef USE_KQUEUE + bool flags; +#endif }; struct uloop_timeout -- 2.25.1