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
This commit is contained in:
Nick Mathewson 2008-05-30 16:56:34 +00:00
parent 9ca7a3a3d6
commit 39400e68b6
7 changed files with 30 additions and 10 deletions

View File

@ -103,8 +103,9 @@ Changes in current version:
o Fix use of freed memory in event_reinit; pointed out by Peter Postma o Fix use of freed memory in event_reinit; pointed out by Peter Postma
o constify struct timeval * where possible o constify struct timeval * where possible
o make event_get_supported_methods obey environment variables 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: 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 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 o demote most http warnings to debug messages

View File

@ -241,9 +241,9 @@ epoll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
continue; continue;
if (evread != NULL) if (evread != NULL)
event_active(evread, EV_READ, 1); event_active(evread, EV_READ | (evread->ev_events & EV_ET), 1);
if (evwrite != NULL) if (evwrite != NULL)
event_active(evwrite, EV_WRITE, 1); event_active(evwrite, EV_WRITE | (evwrite->ev_events & EV_ET), 1);
} }
return (0); return (0);
@ -283,6 +283,8 @@ epoll_add(void *arg, struct event *ev)
events |= EPOLLIN; events |= EPOLLIN;
if (ev->ev_events & EV_WRITE) if (ev->ev_events & EV_WRITE)
events |= EPOLLOUT; events |= EPOLLOUT;
if(ev->ev_events & EV_ET)
events |= EPOLLET;
epev.data.ptr = evep; epev.data.ptr = evep;
epev.events = events; epev.events = events;

View File

@ -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); const struct timeval *tv, void (*cb)(int, short, void *), void *arg);
/* Flags to pass to event_set(), event_new(), event_assign(), /* 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_TIMEOUT 0x01
#define EV_READ 0x02 #define EV_READ 0x02
#define EV_WRITE 0x04 #define EV_WRITE 0x04
#define EV_SIGNAL 0x08 #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. 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() EV_READ, or EV_WRITE. The additional flag EV_PERSIST makes an event_add()
persistent until event_del() has been called. 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 ev an event struct to be modified
@param fd the file descriptor to be monitored @param fd the file descriptor to be monitored
@param event desired events to monitor; can be EV_READ and/or EV_WRITE @param event desired events to monitor; can be EV_READ and/or EV_WRITE

View File

@ -272,7 +272,7 @@ kq_dispatch(struct event_base *base, void *arg, struct timeval *tv)
if (!(ev->ev_events & EV_PERSIST)) if (!(ev->ev_events & EV_PERSIST))
ev->ev_flags &= ~EVLIST_X_KQINKERNEL; 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); ev->ev_events & EV_SIGNAL ? events[i].data : 1);
} }
@ -322,6 +322,8 @@ kq_add(void *arg, struct event *ev)
kev.flags = EV_ADD; kev.flags = EV_ADD;
if (!(ev->ev_events & EV_PERSIST)) if (!(ev->ev_events & EV_PERSIST))
kev.flags |= EV_ONESHOT; kev.flags |= EV_ONESHOT;
if (ev->ev_events & EV_ET)
kev.flags |= EV_CLEAR;
kev.udata = PTR_TO_UDATA(ev); kev.udata = PTR_TO_UDATA(ev);
if (kq_insert(kqop, &kev) == -1) if (kq_insert(kqop, &kev) == -1)
@ -337,6 +339,8 @@ kq_add(void *arg, struct event *ev)
kev.flags = EV_ADD; kev.flags = EV_ADD;
if (!(ev->ev_events & EV_PERSIST)) if (!(ev->ev_events & EV_PERSIST))
kev.flags |= EV_ONESHOT; kev.flags |= EV_ONESHOT;
if (ev->ev_events & EV_ET)
kev.flags |= EV_CLEAR;
kev.udata = PTR_TO_UDATA(ev); kev.udata = PTR_TO_UDATA(ev);
if (kq_insert(kqop, &kev) == -1) if (kq_insert(kqop, &kev) == -1)

View File

@ -17,7 +17,7 @@ test_weof_LDADD = ../libevent_core.la
test_time_SOURCES = test-time.c test_time_SOURCES = test-time.c
test_time_LDADD = ../libevent_core.la test_time_LDADD = ../libevent_core.la
regress_SOURCES = regress.c regress.h regress_http.c regress_dns.c \ 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 if PTHREAD_REGRESS
regress_SOURCES += regress_pthread.c regress_SOURCES += regress_pthread.c
endif endif

View File

@ -2185,7 +2185,7 @@ main (int argc, char **argv)
test_evbuffer_iterative(); test_evbuffer_iterative();
test_evbuffer_readln(); test_evbuffer_readln();
test_evbuffer_find(); test_evbuffer_find();
test_bufferevent(); test_bufferevent();
test_bufferevent_watermarks(); test_bufferevent_watermarks();
test_bufferevent_filters(); test_bufferevent_filters();
@ -2201,7 +2201,7 @@ main (int argc, char **argv)
#if defined(HAVE_LIBZ) #if defined(HAVE_LIBZ)
regress_zlib(); regress_zlib();
#endif #endif
http_suite(); http_suite();
rpc_suite(); rpc_suite();
@ -2224,6 +2224,8 @@ main (int argc, char **argv)
test_simpletimeout(); test_simpletimeout();
test_edgetriggered();
#ifndef WIN32 #ifndef WIN32
test_simplesignal(); test_simplesignal();
test_immediatesignal(); test_immediatesignal();

View File

@ -39,7 +39,9 @@ void rpc_suite(void);
void dns_suite(void); void dns_suite(void);
void regress_pthread(void); void regress_pthread(void);
void regress_zlib(void); void regress_zlib(void);
void test_edgetriggered(void);
#ifdef __cplusplus #ifdef __cplusplus
} }