diff options
author | Markus Friedl <markus@cvs.openbsd.org> | 2003-09-23 08:52:05 +0000 |
---|---|---|
committer | Markus Friedl <markus@cvs.openbsd.org> | 2003-09-23 08:52:05 +0000 |
commit | fa5ac32cbd68bc040f3e6787e9958e5d885f23aa (patch) | |
tree | a9d332d019bf8aa66591c350c5a0ecb556a7254f /lib | |
parent | 8f6601634e34584d51395d0e65d5bab7701b158c (diff) |
add support for poll(2); ok deraadt
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libevent/Makefile | 5 | ||||
-rw-r--r-- | lib/libevent/event.3 | 11 | ||||
-rw-r--r-- | lib/libevent/poll.c | 240 |
3 files changed, 250 insertions, 6 deletions
diff --git a/lib/libevent/Makefile b/lib/libevent/Makefile index ec9498e4e76..33cc7c32c15 100644 --- a/lib/libevent/Makefile +++ b/lib/libevent/Makefile @@ -1,7 +1,7 @@ -# $OpenBSD: Makefile,v 1.6 2003/07/10 07:48:41 markus Exp $ +# $OpenBSD: Makefile,v 1.7 2003/09/23 08:52:04 markus Exp $ LIB= event -SRCS= event.c select.c signal.c kqueue.c +SRCS= event.c select.c poll.c signal.c kqueue.c HDRS= event.h MAN= event.3 MLINKS= event.3 event_init.3 event.3 event_dispatch.3 event.3 event_loop.3 \ @@ -15,6 +15,7 @@ MLINKS= event.3 event_init.3 event.3 event_dispatch.3 event.3 event_loop.3 \ CFLAGS+= -I${.CURDIR} \ -DHAVE_WORKING_KQUEUE \ -DHAVE_SELECT \ + -DHAVE_POLL \ -DHAVE_SYS_TIME_H \ NOPIC= diff --git a/lib/libevent/event.3 b/lib/libevent/event.3 index d31ee7ac516..3db118f1e09 100644 --- a/lib/libevent/event.3 +++ b/lib/libevent/event.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: event.3,v 1.9 2003/07/09 10:54:38 markus Exp $ +.\" $OpenBSD: event.3,v 1.10 2003/09/23 08:52:04 markus Exp $ .\" .\" Copyright (c) 2000 Artur Grabowski <art@openbsd.org> .\" All rights reserved. @@ -278,11 +278,13 @@ adds .Va EV_PERSIST . .Pp It is possible to disable support for -.Va kqueue +.Xr kqueue 2 , +.Xr poll 2 , or -.Va select +.Xr select 2 by setting the environment variable -.Va EVENT_NOKQUEUE +.Va EVENT_NOKQUEUE , +.Va EVENT_NOPOLL , or .Va EVENT_NOSELECT . By setting the environment variable @@ -300,6 +302,7 @@ Otherwise, -1 is returned and the global variable errno is set to indicate the error. .Sh SEE ALSO .Xr kqueue 2 , +.Xr poll 2 , .Xr select 2 , .Xr timeout 9 .Sh HISTORY diff --git a/lib/libevent/poll.c b/lib/libevent/poll.c new file mode 100644 index 00000000000..727c4dfa25a --- /dev/null +++ b/lib/libevent/poll.c @@ -0,0 +1,240 @@ +/* $OpenBSD: poll.c,v 1.1 2003/09/23 08:52:04 markus Exp $ */ + +/* + * Copyright 2000-2003 Niels Provos <provos@citi.umich.edu> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <sys/types.h> +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#else +#include <sys/_time.h> +#endif +#include <sys/queue.h> +#include <poll.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <err.h> + +#ifdef USE_LOG +#include "log.h" +#else +#define LOG_DBG(x) +#define log_error(x) perror(x) +#endif + +#include "event.h" +#include "evsignal.h" + +extern struct event_list eventqueue; + +extern volatile sig_atomic_t evsignal_caught; + +struct pollop { + int event_count; /* Highest number alloc */ + struct pollfd *event_set; + struct event **event_back; + sigset_t evsigmask; +} pop; + +void *poll_init (void); +int poll_add (void *, struct event *); +int poll_del (void *, struct event *); +int poll_recalc (void *, int); +int poll_dispatch (void *, struct timeval *); + +struct eventop pollops = { + "poll", + poll_init, + poll_add, + poll_del, + poll_recalc, + poll_dispatch +}; + +void * +poll_init(void) +{ + /* Disable kqueue when this environment variable is set */ + if (!issetugid() && getenv("EVENT_NOPOLL")) + return (NULL); + + memset(&pop, 0, sizeof(pop)); + + evsignal_init(&pop.evsigmask); + + return (&pop); +} + +/* + * Called with the highest fd that we know about. If it is 0, completely + * recalculate everything. + */ + +int +poll_recalc(void *arg, int max) +{ + struct pollop *pop = arg; + + return (evsignal_recalc(&pop->evsigmask)); +} + +int +poll_dispatch(void *arg, struct timeval *tv) +{ + int res, i, count, sec, nfds; + struct event *ev; + struct pollop *pop = arg; + + count = pop->event_count; + nfds = 0; + TAILQ_FOREACH(ev, &eventqueue, ev_next) { + if (nfds + 1 >= count) { + if (count < 32) + count = 32; + else + count *= 2; + + /* We need more file descriptors */ + pop->event_set = realloc(pop->event_set, + count * sizeof(struct pollfd)); + if (pop->event_set == NULL) { + log_error("realloc"); + return (-1); + } + pop->event_back = realloc(pop->event_back, + count * sizeof(struct event *)); + if (pop->event_back == NULL) { + log_error("realloc"); + return (-1); + } + pop->event_count = count; + } + if (ev->ev_events & EV_WRITE) { + struct pollfd *pfd = &pop->event_set[nfds]; + pfd->fd = ev->ev_fd; + pfd->events = POLLOUT; + pfd->revents = 0; + + pop->event_back[nfds] = ev; + + nfds++; + } + if (ev->ev_events & EV_READ) { + struct pollfd *pfd = &pop->event_set[nfds]; + + pfd->fd = ev->ev_fd; + pfd->events = POLLIN; + pfd->revents = 0; + + pop->event_back[nfds] = ev; + + nfds++; + } + } + + if (evsignal_deliver(&pop->evsigmask) == -1) + return (-1); + + sec = tv->tv_sec * 1000 + tv->tv_usec / 1000; + res = poll(pop->event_set, nfds, sec); + + if (evsignal_recalc(&pop->evsigmask) == -1) + return (-1); + + if (res == -1) { + if (errno != EINTR) { + log_error("poll"); + return (-1); + } + + evsignal_process(); + return (0); + } else if (evsignal_caught) + evsignal_process(); + + LOG_DBG((LOG_MISC, 80, "%s: poll reports %d", __func__, res)); + + if (res == 0) + return (0); + + for (i = 0; i < nfds; i++) { + res = 0; + if (pop->event_set[i].revents & POLLIN) + res = EV_READ; + else if (pop->event_set[i].revents & POLLOUT) + res = EV_WRITE; + if (res == 0) + continue; + + ev = pop->event_back[i]; + res &= ev->ev_events; + + if (res) { + if (!(ev->ev_events & EV_PERSIST)) + event_del(ev); + event_active(ev, res, 1); + } + } + + return (0); +} + +int +poll_add(void *arg, struct event *ev) +{ + struct pollop *pop = arg; + + if (ev->ev_events & EV_SIGNAL) + return (evsignal_add(&pop->evsigmask, ev)); + + return (0); +} + +/* + * Nothing to be done here. + */ + +int +poll_del(void *arg, struct event *ev) +{ + struct pollop *pop = arg; + + if (!(ev->ev_events & EV_SIGNAL)) + return (0); + + return (evsignal_del(&pop->evsigmask, ev)); +} |