From: Nick Mathewson Date: Fri, 30 May 2008 16:56:34 +0000 (+0000) Subject: Patch from Valery Kholodkov: support for edge-triggered events with epoll and kqueue... X-Git-Tag: release-2.0.1-alpha~276 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=39400e68b6202dc40545b5ac26468fc3f7a11184;p=libevent Patch from Valery Kholodkov: support for edge-triggered events with epoll and kqueue. Changed from original patch: made test into a regression test, with explicit success/failure for edge-triggered and non-edge-triggered cases. Closes SF request 1968284. svn:r840 --- diff --git a/ChangeLog b/ChangeLog index 16ec4595..c934f35c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -103,8 +103,9 @@ Changes in current version: o Fix use of freed memory in event_reinit; pointed out by Peter Postma o constify struct timeval * where possible o make event_get_supported_methods obey environment variables + o support for edge-triggered events on epoll and kqueue backends: patch from Valery Kholodkov + - Changes in 1.4.0: o allow \r or \n individually to separate HTTP headers instead of the standard "\r\n"; from Charles Kerr. o demote most http warnings to debug messages diff --git a/epoll.c b/epoll.c index 423d9898..0b718cc8 100644 --- a/epoll.c +++ b/epoll.c @@ -241,9 +241,9 @@ epoll_dispatch(struct event_base *base, void *arg, struct timeval *tv) continue; if (evread != NULL) - event_active(evread, EV_READ, 1); + event_active(evread, EV_READ | (evread->ev_events & EV_ET), 1); if (evwrite != NULL) - event_active(evwrite, EV_WRITE, 1); + event_active(evwrite, EV_WRITE | (evwrite->ev_events & EV_ET), 1); } return (0); @@ -283,6 +283,8 @@ epoll_add(void *arg, struct event *ev) events |= EPOLLIN; if (ev->ev_events & EV_WRITE) events |= EPOLLOUT; + if(ev->ev_events & EV_ET) + events |= EPOLLET; epev.data.ptr = evep; epev.events = events; diff --git a/include/event2/event.h b/include/event2/event.h index 5702b939..4cd4608d 100644 --- a/include/event2/event.h +++ b/include/event2/event.h @@ -258,12 +258,16 @@ void evperiodic_assign(struct event *ev, struct event_base *base, const struct timeval *tv, void (*cb)(int, short, void *), void *arg); /* Flags to pass to event_set(), event_new(), event_assign(), - * event_pending()... */ + * event_pending(), and anything else with an argument of the form + * "short events" */ #define EV_TIMEOUT 0x01 #define EV_READ 0x02 #define EV_WRITE 0x04 #define EV_SIGNAL 0x08 -#define EV_PERSIST 0x10 /* Persistant event */ +/** Persistent event: won't get removed automatically when activated. */ +#define EV_PERSIST 0x10 +/** Select edge-triggered behavior, if supported by the backend. */ +#define EV_ET 0x20 /** Define a timer event. @@ -321,6 +325,11 @@ void evperiodic_assign(struct event *ev, struct event_base *base, EV_READ, or EV_WRITE. The additional flag EV_PERSIST makes an event_add() persistent until event_del() has been called. + For read and write events, edge-triggered behavior can be requested + with the EV_ET flag. Not all backends support edge-triggered + behavior. When an edge-triggered event is activated, the EV_ET flag + is added to its events argument. + @param ev an event struct to be modified @param fd the file descriptor to be monitored @param event desired events to monitor; can be EV_READ and/or EV_WRITE diff --git a/kqueue.c b/kqueue.c index b213be02..38278938 100644 --- a/kqueue.c +++ b/kqueue.c @@ -272,7 +272,7 @@ kq_dispatch(struct event_base *base, void *arg, struct timeval *tv) if (!(ev->ev_events & EV_PERSIST)) ev->ev_flags &= ~EVLIST_X_KQINKERNEL; - event_active(ev, which, + event_active(ev, which | (ev->ev_events & EV_ET), ev->ev_events & EV_SIGNAL ? events[i].data : 1); } @@ -322,6 +322,8 @@ kq_add(void *arg, struct event *ev) kev.flags = EV_ADD; if (!(ev->ev_events & EV_PERSIST)) kev.flags |= EV_ONESHOT; + if (ev->ev_events & EV_ET) + kev.flags |= EV_CLEAR; kev.udata = PTR_TO_UDATA(ev); if (kq_insert(kqop, &kev) == -1) @@ -337,6 +339,8 @@ kq_add(void *arg, struct event *ev) kev.flags = EV_ADD; if (!(ev->ev_events & EV_PERSIST)) kev.flags |= EV_ONESHOT; + if (ev->ev_events & EV_ET) + kev.flags |= EV_CLEAR; kev.udata = PTR_TO_UDATA(ev); if (kq_insert(kqop, &kev) == -1) diff --git a/test/Makefile.am b/test/Makefile.am index 2e3b7767..4f89eece 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -17,7 +17,7 @@ test_weof_LDADD = ../libevent_core.la test_time_SOURCES = test-time.c test_time_LDADD = ../libevent_core.la regress_SOURCES = regress.c regress.h regress_http.c regress_dns.c \ - regress_rpc.c regress.gen.c regress.gen.h + regress_rpc.c regress.gen.c regress.gen.h regress_et.c if PTHREAD_REGRESS regress_SOURCES += regress_pthread.c endif diff --git a/test/regress.c b/test/regress.c index ca83e879..a6ca9b4d 100644 --- a/test/regress.c +++ b/test/regress.c @@ -2185,7 +2185,7 @@ main (int argc, char **argv) test_evbuffer_iterative(); test_evbuffer_readln(); test_evbuffer_find(); - + test_bufferevent(); test_bufferevent_watermarks(); test_bufferevent_filters(); @@ -2201,7 +2201,7 @@ main (int argc, char **argv) #if defined(HAVE_LIBZ) regress_zlib(); #endif - + http_suite(); rpc_suite(); @@ -2224,6 +2224,8 @@ main (int argc, char **argv) test_simpletimeout(); + test_edgetriggered(); + #ifndef WIN32 test_simplesignal(); test_immediatesignal(); diff --git a/test/regress.h b/test/regress.h index 5ac6dff9..cb92c9ea 100644 --- a/test/regress.h +++ b/test/regress.h @@ -39,7 +39,9 @@ void rpc_suite(void); void dns_suite(void); void regress_pthread(void); -void regress_zlib(void); +void regress_zlib(void); + +void test_edgetriggered(void); #ifdef __cplusplus }