signal support for kqueue; support of EV_PERSIST flag to event_set

svn:r18
This commit is contained in:
Niels Provos 2002-04-10 02:10:47 +00:00
parent b855bc5500
commit d10f85dbce
5 changed files with 76 additions and 13 deletions

View File

@ -143,6 +143,7 @@ event_process_active(void)
ev = TAILQ_FIRST(&activequeue)) { ev = TAILQ_FIRST(&activequeue)) {
event_queue_remove(ev, EVLIST_ACTIVE); event_queue_remove(ev, EVLIST_ACTIVE);
while (ev->ev_ncalls--)
(*ev->ev_callback)(ev->ev_fd, ev->ev_res, ev->ev_arg); (*ev->ev_callback)(ev->ev_fd, ev->ev_res, ev->ev_arg);
} }
} }
@ -324,9 +325,10 @@ event_del(struct event *ev)
} }
void void
event_active(struct event *ev, int res) event_active(struct event *ev, int res, short ncalls)
{ {
ev->ev_res = res; ev->ev_res = res;
ev->ev_ncalls = ncalls;
event_queue_insert(ev, EVLIST_ACTIVE); event_queue_insert(ev, EVLIST_ACTIVE);
} }
@ -389,7 +391,7 @@ timeout_process(void)
LOG_DBG((LOG_MISC, 60, "timeout_process: call %p", LOG_DBG((LOG_MISC, 60, "timeout_process: call %p",
ev->ev_callback)); ev->ev_callback));
event_active(ev, EV_TIMEOUT); event_active(ev, EV_TIMEOUT, 1);
} }
} }

11
event.h
View File

@ -47,6 +47,7 @@ extern "C" {
#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 */
/* Fix so that ppl dont have to run with <sys/queue.h> */ /* Fix so that ppl dont have to run with <sys/queue.h> */
#ifndef TAILQ_ENTRY #ifndef TAILQ_ENTRY
@ -76,6 +77,7 @@ struct event {
int ev_fd; int ev_fd;
short ev_events; short ev_events;
short ev_ncalls;
struct timeval ev_timeout; struct timeval ev_timeout;
@ -128,10 +130,17 @@ void timeout_process(void);
#define timeout_pending(ev, tv) event_pending(ev, EV_TIMEOUT, tv) #define timeout_pending(ev, tv) event_pending(ev, EV_TIMEOUT, tv)
#define timeout_initialized(ev) ((ev)->ev_flags & EVLIST_INIT) #define timeout_initialized(ev) ((ev)->ev_flags & EVLIST_INIT)
#define signal_add(ev, tv) event_add(ev, tv)
#define signal_set(ev, x, cb, arg) \
event_set(ev, x, EV_SIGNAL|EV_PERSIST, cb, arg)
#define signal_del(ev) event_del(ev)
#define signal_pending(ev, tv) event_pending(ev, EV_SIGNAL, tv)
#define signal_initialized(ev) ((ev)->ev_flags & EVLIST_INIT)
void event_set(struct event *, int, short, void (*)(int, short, void *), void *); void event_set(struct event *, int, short, void (*)(int, short, void *), void *);
int event_add(struct event *, struct timeval *); int event_add(struct event *, struct timeval *);
int event_del(struct event *); int event_del(struct event *);
void event_active(struct event *, int); void event_active(struct event *, int, short);
int event_pending(struct event *, short, struct timeval *); int event_pending(struct event *, short, struct timeval *);

View File

@ -33,6 +33,7 @@
#include <sys/time.h> #include <sys/time.h>
#include <sys/queue.h> #include <sys/queue.h>
#include <sys/event.h> #include <sys/event.h>
#include <signal.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
@ -215,12 +216,17 @@ kq_dispatch(void *arg, struct timeval *tv)
which |= EV_READ; which |= EV_READ;
} else if (events[i].filter == EVFILT_WRITE) { } else if (events[i].filter == EVFILT_WRITE) {
which |= EV_WRITE; which |= EV_WRITE;
} else if (events[i].filter == EVFILT_SIGNAL) {
which |= EV_SIGNAL;
} }
if (which) { if (which) {
if (!(ev->ev_events & EV_PERSIST)) {
ev->ev_flags &= ~EVLIST_X_KQINKERNEL; ev->ev_flags &= ~EVLIST_X_KQINKERNEL;
event_del(ev); event_del(ev);
event_active(ev, which); }
event_active(ev, which,
ev->ev_events & EV_SIGNAL ? events[i].data : 1);
} }
} }
@ -234,6 +240,27 @@ kq_add(void *arg, struct event *ev)
struct kqop *kqop = arg; struct kqop *kqop = arg;
struct kevent kev; struct kevent kev;
if (ev->ev_events & EV_SIGNAL) {
int nsignal = EVENT_SIGNAL(ev);
memset(&kev, 0, sizeof(kev));
kev.ident = nsignal;
kev.filter = EVFILT_SIGNAL;
kev.flags = EV_ADD;
if (!(ev->ev_events & EV_PERSIST))
kev.filter |= EV_ONESHOT;
kev.udata = ev;
if (kq_insert(kqop, &kev) == -1)
return (-1);
if (signal(nsignal, SIG_IGN) == SIG_ERR)
return (-1);
ev->ev_flags |= EVLIST_X_KQINKERNEL;
return (0);
}
if (ev->ev_events & EV_READ) { if (ev->ev_events & EV_READ) {
memset(&kev, 0, sizeof(kev)); memset(&kev, 0, sizeof(kev));
kev.ident = ev->ev_fd; kev.ident = ev->ev_fd;
@ -272,6 +299,24 @@ kq_del(void *arg, struct event *ev)
if (!(ev->ev_flags & EVLIST_X_KQINKERNEL)) if (!(ev->ev_flags & EVLIST_X_KQINKERNEL))
return (0); return (0);
if (ev->ev_events & EV_SIGNAL) {
int nsignal = EVENT_SIGNAL(ev);
memset(&kev, 0, sizeof(kev));
kev.ident = signal;
kev.filter = EVFILT_SIGNAL;
kev.flags = EV_DELETE;
if (kq_insert(kqop, &kev) == -1)
return (-1);
if (signal(nsignal, SIG_DFL) == SIG_ERR)
return (-1);
ev->ev_flags &= ~EVLIST_X_KQINKERNEL;
return (0);
}
if (ev->ev_events & EV_READ) { if (ev->ev_events & EV_READ) {
memset(&kev, 0, sizeof(kev)); memset(&kev, 0, sizeof(kev));
kev.ident = ev->ev_fd; kev.ident = ev->ev_fd;

View File

@ -41,7 +41,8 @@ main (int argc, char **argv)
event_init(); event_init();
/* Initalize one event */ /* Initalize one event */
event_set(&signal_int, SIGINT, EV_SIGNAL, signal_cb, &signal_int); event_set(&signal_int, SIGINT, EV_SIGNAL|EV_PERSIST, signal_cb,
&signal_int);
event_add(&signal_int, NULL); event_add(&signal_int, NULL);

View File

@ -56,7 +56,7 @@ extern struct event_list signalqueue;
#define howmany(x, y) (((x)+((y)-1))/(y)) #define howmany(x, y) (((x)+((y)-1))/(y))
#endif #endif
int evsigcaught[NSIG]; short evsigcaught[NSIG];
struct selectop { struct selectop {
int event_fds; /* Highest fd in fd set */ int event_fds; /* Highest fd in fd set */
@ -192,8 +192,9 @@ select_dispatch(void *arg, struct timeval *tv)
res &= ev->ev_events; res &= ev->ev_events;
if (res) { if (res) {
if (!(ev->ev_events & EV_PERSIST))
event_del(ev); event_del(ev);
event_active(ev, res); event_active(ev, res, 1);
} else if (ev->ev_fd > maxfd) } else if (ev->ev_fd > maxfd)
maxfd = ev->ev_fd; maxfd = ev->ev_fd;
} }
@ -291,10 +292,15 @@ void
signal_process(void) signal_process(void)
{ {
struct event *ev; struct event *ev;
short ncalls;
TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) { TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) {
if (evsigcaught[EVENT_SIGNAL(ev)]) ncalls = evsigcaught[EVENT_SIGNAL(ev)];
event_active(ev, EV_SIGNAL); if (ncalls) {
if (!(ev->ev_events & EV_PERSIST))
event_del(ev);
event_active(ev, EV_SIGNAL, ncalls);
}
} }
memset(evsigcaught, 0, sizeof(evsigcaught)); memset(evsigcaught, 0, sizeof(evsigcaught));