]> granicus.if.org Git - libevent/commitdiff
make libevent thread-safe; first cut
authorNiels Provos <provos@gmail.com>
Thu, 25 Nov 2004 09:50:18 +0000 (09:50 +0000)
committerNiels Provos <provos@gmail.com>
Thu, 25 Nov 2004 09:50:18 +0000 (09:50 +0000)
svn:r122

devpoll.c
epoll.c
event-internal.h [new file with mode: 0644]
event.c
event.h
kqueue.c
poll.c
rtsig.c
select.c
test/regress.c

index 183db85d9e97238eaf05cd651da1067d43522b99..3532d59ab095485c8f2f2cfcd8fdc2e0c368f71a 100644 (file)
--- a/devpoll.c
+++ b/devpoll.c
@@ -57,8 +57,6 @@
 #include "event.h"
 #include "evsignal.h"
 
-extern struct event_list eventqueue;
-
 extern volatile sig_atomic_t evsignal_caught;
 
 /* due to limitations in the devpoll interface, we need to keep track of
@@ -81,8 +79,8 @@ struct devpollop {
 void *devpoll_init     (void);
 int devpoll_add        (void *, struct event *);
 int devpoll_del        (void *, struct event *);
-int devpoll_recalc     (void *, int);
-int devpoll_dispatch   (void *, struct timeval *);
+int devpoll_recalc     (struct event_base *, void *, int);
+int devpoll_dispatch   (struct event_base *, void *, struct timeval *);
 
 struct eventop devpollops = {
        "devpoll",
@@ -139,7 +137,7 @@ devpoll_init(void)
 }
 
 int
-devpoll_recalc(void *arg, int max)
+devpoll_recalc(struct event_base *base, void *arg, int max)
 {
        struct devpollop *devpollop = arg;
 
@@ -166,7 +164,7 @@ devpoll_recalc(void *arg, int max)
 }
 
 int
-devpoll_dispatch(void *arg, struct timeval *tv)
+devpoll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
 {
        struct devpollop *devpollop = arg;
        struct pollfd *events = devpollop->events;
@@ -257,7 +255,7 @@ devpoll_add(void *arg, struct event *ev)
        fd = ev->ev_fd;
        if (fd >= devpollop->nfds) {
                /* Extent the file descriptor array as necessary */
-               if (devpoll_recalc(devpollop, fd) == -1)
+               if (devpoll_recalc(ev->ev_base, devpollop, fd) == -1)
                        return (-1);
        }
        evdp = &devpollop->fds[fd];
diff --git a/epoll.c b/epoll.c
index 9924d0fb6841f130709caa6aa985d7da51eabfdf..2ffc2335fff2dd9d2cfeb2c5bed43ee655e02ef5 100644 (file)
--- a/epoll.c
+++ b/epoll.c
@@ -59,8 +59,6 @@
 #include "event.h"
 #include "evsignal.h"
 
-extern struct event_list eventqueue;
-
 extern volatile sig_atomic_t evsignal_caught;
 
 /* due to limitations in the epoll interface, we need to keep track of
@@ -83,8 +81,8 @@ struct epollop {
 void *epoll_init       (void);
 int epoll_add  (void *, struct event *);
 int epoll_del  (void *, struct event *);
-int epoll_recalc       (void *, int);
-int epoll_dispatch     (void *, struct timeval *);
+int epoll_recalc       (struct event_base *, void *, int);
+int epoll_dispatch     (struct event_base *, void *, struct timeval *);
 
 struct eventop epollops = {
        "epoll",
@@ -152,7 +150,7 @@ epoll_init(void)
 }
 
 int
-epoll_recalc(void *arg, int max)
+epoll_recalc(struct event_base *base, void *arg, int max)
 {
        struct epollop *epollop = arg;
 
@@ -179,7 +177,7 @@ epoll_recalc(void *arg, int max)
 }
 
 int
-epoll_dispatch(void *arg, struct timeval *tv)
+epoll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
 {
        struct epollop *epollop = arg;
        struct epoll_event *events = epollop->events;
@@ -263,7 +261,7 @@ epoll_add(void *arg, struct event *ev)
        fd = ev->ev_fd;
        if (fd >= epollop->nfds) {
                /* Extent the file descriptor array as necessary */
-               if (epoll_recalc(epollop, fd) == -1)
+               if (epoll_recalc(ev->ev_base, epollop, fd) == -1)
                        return (-1);
        }
        evep = &epollop->fds[fd];
diff --git a/event-internal.h b/event-internal.h
new file mode 100644 (file)
index 0000000..4f36595
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2000-2004 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. 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.
+ */
+#ifndef _EVENT_INTERNAL_H_
+#define _EVENT_INTERNAL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct event_base {
+       const struct eventop *evsel;
+       void *evbase;
+       int event_count;                /* counts number of total events */
+       int event_count_active; /* counts number of active events */
+
+       /* Handle signals - This is a deprecated interface */
+       int (*event_sigcb)(void);       /* Signal callback when gotsig is set */
+       int event_gotsig;               /* Set in signal handler */
+       int event_gotterm;              /* Set to terminate loop */
+
+       /* active event management */
+       struct event_list **activequeues;
+       int nactivequeues;
+
+       struct event_list eventqueue;
+       struct timeval event_tv;
+
+       RB_HEAD(event_tree, event) timetree;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _EVENT_INTERNAL_H_ */
diff --git a/event.c b/event.c
index c62574e30aac41df947e089e13d45239f5552682..cc5b1640ef9f606ddb63adbe14131d9e30d658bb 100644 (file)
--- a/event.c
+++ b/event.c
@@ -60,6 +60,7 @@
 #endif
 
 #include "event.h"
+#include "event-internal.h"
 
 #ifdef HAVE_SELECT
 extern const struct eventop selectops;
@@ -110,33 +111,20 @@ const struct eventop *eventops[] = {
 };
 
 /* Global state */
+struct event_list signalqueue;
 
-const struct eventop *evsel;
-void *evbase;
-static int event_count;                        /* counts number of total events */
-static int event_count_active;         /* counts number of active events */
-
-/* Handle signals - This is a deprecated interface */
-int (*event_sigcb)(void);      /* Signal callback when gotsig is set */
-int event_gotsig;              /* Set in signal handler */
-int event_gotterm;             /* Set to terminate loop */
+struct event_base *current_base = NULL;
 
 /* Prototypes */
-void           event_queue_insert(struct event *, int);
-void           event_queue_remove(struct event *, int);
-int            event_haveevents(void);
+static void    event_queue_insert(struct event_base *, struct event *, int);
+static void    event_queue_remove(struct event_base *, struct event *, int);
+static int     event_haveevents(struct event_base *);
 
-static void    event_process_active(void);
+static void    event_process_active(struct event_base *);
 
-static RB_HEAD(event_tree, event) timetree;
-
-/* active event management */
-static struct event_list **activequeues;
-static int nactivequeues;
-
-struct event_list signalqueue;
-struct event_list eventqueue;
-static struct timeval event_tv;
+static int     timeout_next(struct event_base *, struct timeval *);
+static void    timeout_process(struct event_base *);
+static void    timeout_correct(struct event_base *, struct timeval *);
 
 static int
 compare(struct event *a, struct event *b)
@@ -157,77 +145,83 @@ RB_PROTOTYPE(event_tree, event, ev_timeout_node, compare);
 RB_GENERATE(event_tree, event, ev_timeout_node, compare);
 
 
-void
+void *
 event_init(void)
 {
        int i;
 
-       event_sigcb = NULL;
-       event_gotsig = 0;
-       gettimeofday(&event_tv, NULL);
+       if ((current_base = calloc(1, sizeof(struct event_base))) == NULL)
+               err(1, "%s: calloc");
+
+       current_base->event_sigcb = NULL;
+       current_base->event_gotsig = 0;
+       gettimeofday(&current_base->event_tv, NULL);
        
 #if defined(USE_LOG) && defined(USE_DEBUG)
        log_to(stderr);
        log_debug_cmd(LOG_MISC, 80);
 #endif
 
-       RB_INIT(&timetree);
-       TAILQ_INIT(&eventqueue);
+       RB_INIT(&current_base->timetree);
+       TAILQ_INIT(&current_base->eventqueue);
        TAILQ_INIT(&signalqueue);
        
-       evbase = NULL;
-       for (i = 0; eventops[i] && !evbase; i++) {
-               evsel = eventops[i];
+       current_base->evbase = NULL;
+       for (i = 0; eventops[i] && !current_base->evbase; i++) {
+               current_base->evsel = eventops[i];
 
-               evbase = evsel->init();
+               current_base->evbase = current_base->evsel->init();
        }
 
-       if (evbase == NULL)
+       if (current_base->evbase == NULL)
                errx(1, "%s: no event mechanism available", __func__);
 
        if (getenv("EVENT_SHOW_METHOD")) 
-               fprintf(stderr, "libevent using: %s\n", evsel->name); 
+               fprintf(stderr, "libevent using: %s\n",
+                   current_base->evsel->name); 
 
        /* allocate a single active event queue */
-       event_priority_init(1);
+       event_priority_init(current_base, 1);
+
+       return (current_base);
 }
 
 int
-event_priority_init(int npriorities)
+event_priority_init(struct event_base *base, int npriorities)
 {
        int i;
 
-       if (event_count_active)
+       if (base->event_count_active)
                return (-1);
 
-       if (nactivequeues && npriorities != nactivequeues) {
-               for (i = 0; i < nactivequeues; ++i) {
-                       free(activequeues[i]);
+       if (base->nactivequeues && npriorities != base->nactivequeues) {
+               for (i = 0; i < base->nactivequeues; ++i) {
+                       free(base->activequeues[i]);
                }
-               free(activequeues);
+               free(base->activequeues);
        }
 
        /* Allocate our priority queues */
-       nactivequeues = npriorities;
-       activequeues = (struct event_list **)calloc(nactivequeues,
+       base->nactivequeues = npriorities;
+       base->activequeues = (struct event_list **)calloc(base->nactivequeues,
            npriorities * sizeof(struct event_list *));
-       if (activequeues == NULL)
+       if (base->activequeues == NULL)
                err(1, "%s: calloc", __func__);
 
-       for (i = 0; i < nactivequeues; ++i) {
-               activequeues[i] = malloc(sizeof(struct event_list));
-               if (activequeues[i] == NULL)
+       for (i = 0; i < base->nactivequeues; ++i) {
+               base->activequeues[i] = malloc(sizeof(struct event_list));
+               if (base->activequeues[i] == NULL)
                        err(1, "%s: malloc", __func__);
-               TAILQ_INIT(activequeues[i]);
+               TAILQ_INIT(base->activequeues[i]);
        }
 
        return (0);
 }
 
 int
-event_haveevents(void)
+event_haveevents(struct event_base *base)
 {
-       return (event_count > 0);
+       return (base->event_count > 0);
 }
 
 /*
@@ -237,25 +231,25 @@ event_haveevents(void)
  */
 
 static void
-event_process_active(void)
+event_process_active(struct event_base *base)
 {
        struct event *ev;
        struct event_list *activeq = NULL;
        int i;
        short ncalls;
 
-       if (!event_count_active)
+       if (!base->event_count_active)
                return;
 
-       for (i = 0; i < nactivequeues; ++i) {
-               if (TAILQ_FIRST(activequeues[i]) != NULL) {
-                       activeq = activequeues[i];
+       for (i = 0; i < base->nactivequeues; ++i) {
+               if (TAILQ_FIRST(base->activequeues[i]) != NULL) {
+                       activeq = base->activequeues[i];
                        break;
                }
        }
 
        for (ev = TAILQ_FIRST(activeq); ev; ev = TAILQ_FIRST(activeq)) {
-               event_queue_remove(ev, EVLIST_ACTIVE);
+               event_queue_remove(base, ev, EVLIST_ACTIVE);
                
                /* Allows deletes to work */
                ncalls = ev->ev_ncalls;
@@ -281,37 +275,51 @@ event_dispatch(void)
 static void
 event_loopexit_cb(int fd, short what, void *arg)
 {
-       event_gotterm = 1;
+       struct event_base *base = arg;
+       base->event_gotterm = 1;
 }
 
+/* not thread safe */
+
 int
 event_loopexit(struct timeval *tv)
 {
-       return (event_once(-1, EV_TIMEOUT, event_loopexit_cb, NULL, tv));
+       return (event_once(-1, EV_TIMEOUT, event_loopexit_cb,
+                   current_base, tv));
 }
 
+/* not thread safe */
+
 int
 event_loop(int flags)
 {
+       return event_loop_base(current_base, flags);
+}
+
+int
+event_loop_base(struct event_base *base, int flags)
+{
+       const struct eventop *evsel = base->evsel;
+       void *evbase = base->evbase;
        struct timeval tv;
        int res, done;
 
        /* Calculate the initial events that we are waiting for */
-       if (evsel->recalc(evbase, 0) == -1)
+       if (evsel->recalc(base, evbase, 0) == -1)
                return (-1);
 
        done = 0;
        while (!done) {
                /* Terminate the loop if we have been asked to */
-               if (event_gotterm) {
-                       event_gotterm = 0;
+               if (base->event_gotterm) {
+                       base->event_gotterm = 0;
                        break;
                }
 
-               while (event_gotsig) {
-                       event_gotsig = 0;
-                       if (event_sigcb) {
-                               res = (*event_sigcb)();
+               while (base->event_gotsig) {
+                       base->event_gotsig = 0;
+                       if (base->event_sigcb) {
+                               res = (*base->event_sigcb)();
                                if (res == -1) {
                                        errno = EINTR;
                                        return (-1);
@@ -321,41 +329,41 @@ event_loop(int flags)
 
                /* Check if time is running backwards */
                gettimeofday(&tv, NULL);
-               if (timercmp(&tv, &event_tv, <)) {
+               if (timercmp(&tv, &base->event_tv, <)) {
                        struct timeval off;
                        LOG_DBG((LOG_MISC, 10,
                                    "%s: time is running backwards, corrected",
                                    __func__));
 
-                       timersub(&event_tv, &tv, &off);
-                       timeout_correct(&off);
+                       timersub(&base->event_tv, &tv, &off);
+                       timeout_correct(base, &off);
                }
-               event_tv = tv;
+               base->event_tv = tv;
 
-               if (!event_count_active && !(flags & EVLOOP_NONBLOCK))
-                       timeout_next(&tv);
+               if (!base->event_count_active && !(flags & EVLOOP_NONBLOCK))
+                       timeout_next(base, &tv);
                else
                        timerclear(&tv);
                
                /* If we have no events, we just exit */
-               if (!event_haveevents())
+               if (!event_haveevents(base))
                        return (1);
 
-               res = evsel->dispatch(evbase, &tv);
+               res = evsel->dispatch(base, evbase, &tv);
 
                if (res == -1)
                        return (-1);
 
-               timeout_process();
+               timeout_process(base);
 
-               if (event_count_active) {
-                       event_process_active();
-                       if (!event_count_active && (flags & EVLOOP_ONCE))
+               if (base->event_count_active) {
+                       event_process_active(base);
+                       if (!base->event_count_active && (flags & EVLOOP_ONCE))
                                done = 1;
                } else if (flags & EVLOOP_NONBLOCK)
                        done = 1;
 
-               if (evsel->recalc(evbase, 0) == -1)
+               if (evsel->recalc(base, evbase, 0) == -1)
                        return (-1);
        }
 
@@ -426,6 +434,9 @@ void
 event_set(struct event *ev, int fd, short events,
          void (*callback)(int, short, void *), void *arg)
 {
+       /* Take the current base - caller needs to set the real base later */
+       ev->ev_base = current_base;
+
        ev->ev_callback = callback;
        ev->ev_arg = arg;
 #ifdef WIN32
@@ -440,7 +451,20 @@ event_set(struct event *ev, int fd, short events,
        ev->ev_pncalls = NULL;
 
        /* by default, we put new events into the middle priority */
-       ev->ev_pri = nactivequeues/2;
+       ev->ev_pri = current_base->nactivequeues/2;
+}
+
+int
+event_base_set(struct event_base *base, struct event *ev)
+{
+       /* Only innocent events may be assigned to a different base */
+       if (ev->ev_flags != EVLIST_INIT)
+               return (-1);
+
+       ev->ev_base = base;
+       ev->ev_pri = current_base->nactivequeues/2;
+
+       return (0);
 }
 
 /*
@@ -453,7 +477,7 @@ event_priority_set(struct event *ev, int pri)
 {
        if (ev->ev_flags & EVLIST_ACTIVE)
                return (-1);
-       if (pri < 0 || pri >= nactivequeues)
+       if (pri < 0 || pri >= ev->ev_base->nactivequeues)
                return (-1);
 
        ev->ev_pri = pri;
@@ -491,6 +515,10 @@ event_pending(struct event *ev, short event, struct timeval *tv)
 int
 event_add(struct event *ev, struct timeval *tv)
 {
+       struct event_base *base = ev->ev_base;
+       const struct eventop *evsel = base->evsel;
+       void *evbase = base->evbase;
+
        LOG_DBG((LOG_MISC, 55,
                 "event_add: event: %p, %s%s%scall %p",
                 ev,
@@ -505,7 +533,7 @@ event_add(struct event *ev, struct timeval *tv)
                struct timeval now;
 
                if (ev->ev_flags & EVLIST_TIMEOUT)
-                       event_queue_remove(ev, EVLIST_TIMEOUT);
+                       event_queue_remove(base, ev, EVLIST_TIMEOUT);
 
                /* Check if it is active due to a timeout.  Rescheduling
                 * this timeout before the callback can be executed
@@ -520,7 +548,7 @@ event_add(struct event *ev, struct timeval *tv)
                                *ev->ev_pncalls = 0;
                        }
                        
-                       event_queue_remove(ev, EVLIST_ACTIVE);
+                       event_queue_remove(base, ev, EVLIST_ACTIVE);
                }
 
                gettimeofday(&now, NULL);
@@ -530,17 +558,17 @@ event_add(struct event *ev, struct timeval *tv)
                         "event_add: timeout in %d seconds, call %p",
                         tv->tv_sec, ev->ev_callback));
 
-               event_queue_insert(ev, EVLIST_TIMEOUT);
+               event_queue_insert(base, ev, EVLIST_TIMEOUT);
        }
 
        if ((ev->ev_events & (EV_READ|EV_WRITE)) &&
            !(ev->ev_flags & (EVLIST_INSERTED|EVLIST_ACTIVE))) {
-               event_queue_insert(ev, EVLIST_INSERTED);
+               event_queue_insert(base, ev, EVLIST_INSERTED);
 
                return (evsel->add(evbase, ev));
        } else if ((ev->ev_events & EV_SIGNAL) &&
            !(ev->ev_flags & EVLIST_SIGNAL)) {
-               event_queue_insert(ev, EVLIST_SIGNAL);
+               event_queue_insert(base, ev, EVLIST_SIGNAL);
 
                return (evsel->add(evbase, ev));
        }
@@ -551,6 +579,10 @@ event_add(struct event *ev, struct timeval *tv)
 int
 event_del(struct event *ev)
 {
+       struct event_base *base = ev->ev_base;
+       const struct eventop *evsel = base->evsel;
+       void *evbase = base->evbase;
+
        LOG_DBG((LOG_MISC, 80, "event_del: %p, callback %p",
                 ev, ev->ev_callback));
 
@@ -563,16 +595,16 @@ event_del(struct event *ev)
        }
 
        if (ev->ev_flags & EVLIST_TIMEOUT)
-               event_queue_remove(ev, EVLIST_TIMEOUT);
+               event_queue_remove(base, ev, EVLIST_TIMEOUT);
 
        if (ev->ev_flags & EVLIST_ACTIVE)
-               event_queue_remove(ev, EVLIST_ACTIVE);
+               event_queue_remove(base, ev, EVLIST_ACTIVE);
 
        if (ev->ev_flags & EVLIST_INSERTED) {
-               event_queue_remove(ev, EVLIST_INSERTED);
+               event_queue_remove(base, ev, EVLIST_INSERTED);
                return (evsel->del(evbase, ev));
        } else if (ev->ev_flags & EVLIST_SIGNAL) {
-               event_queue_remove(ev, EVLIST_SIGNAL);
+               event_queue_remove(base, ev, EVLIST_SIGNAL);
                return (evsel->del(evbase, ev));
        }
 
@@ -591,18 +623,18 @@ event_active(struct event *ev, int res, short ncalls)
        ev->ev_res = res;
        ev->ev_ncalls = ncalls;
        ev->ev_pncalls = NULL;
-       event_queue_insert(ev, EVLIST_ACTIVE);
+       event_queue_insert(ev->ev_base, ev, EVLIST_ACTIVE);
 }
 
 int
-timeout_next(struct timeval *tv)
+timeout_next(struct event_base *base, struct timeval *tv)
 {
        struct timeval dflt = TIMEOUT_DEFAULT;
 
        struct timeval now;
        struct event *ev;
 
-       if ((ev = RB_MIN(event_tree, &timetree)) == NULL) {
+       if ((ev = RB_MIN(event_tree, &base->timetree)) == NULL) {
                *tv = dflt;
                return (0);
        }
@@ -624,8 +656,8 @@ timeout_next(struct timeval *tv)
        return (0);
 }
 
-void
-timeout_correct(struct timeval *off)
+static void
+timeout_correct(struct event_base *base, struct timeval *off)
 {
        struct event *ev;
 
@@ -633,24 +665,24 @@ timeout_correct(struct timeval *off)
         * We can modify the key element of the node without destroying
         * the key, beause we apply it to all in the right order.
         */
-       RB_FOREACH(ev, event_tree, &timetree)
+       RB_FOREACH(ev, event_tree, &base->timetree)
                timersub(&ev->ev_timeout, off, &ev->ev_timeout);
 }
 
 void
-timeout_process(void)
+timeout_process(struct event_base *base)
 {
        struct timeval now;
        struct event *ev, *next;
 
        gettimeofday(&now, NULL);
 
-       for (ev = RB_MIN(event_tree, &timetree); ev; ev = next) {
+       for (ev = RB_MIN(event_tree, &base->timetree); ev; ev = next) {
                if (timercmp(&ev->ev_timeout, &now, >))
                        break;
-               next = RB_NEXT(event_tree, &timetree, ev);
+               next = RB_NEXT(event_tree, &base->timetree, ev);
 
-               event_queue_remove(ev, EVLIST_TIMEOUT);
+               event_queue_remove(base, ev, EVLIST_TIMEOUT);
 
                /* delete this event from the I/O queues */
                event_del(ev);
@@ -662,7 +694,7 @@ timeout_process(void)
 }
 
 void
-event_queue_remove(struct event *ev, int queue)
+event_queue_remove(struct event_base *base, struct event *ev, int queue)
 {
        int docount = 1;
 
@@ -674,23 +706,24 @@ event_queue_remove(struct event *ev, int queue)
                docount = 0;
 
        if (docount)
-               event_count--;
+               base->event_count--;
 
        ev->ev_flags &= ~queue;
        switch (queue) {
        case EVLIST_ACTIVE:
                if (docount)
-                       event_count_active--;
-               TAILQ_REMOVE(activequeues[ev->ev_pri], ev, ev_active_next);
+                       base->event_count_active--;
+               TAILQ_REMOVE(base->activequeues[ev->ev_pri],
+                   ev, ev_active_next);
                break;
        case EVLIST_SIGNAL:
                TAILQ_REMOVE(&signalqueue, ev, ev_signal_next);
                break;
        case EVLIST_TIMEOUT:
-               RB_REMOVE(event_tree, &timetree, ev);
+               RB_REMOVE(event_tree, &base->timetree, ev);
                break;
        case EVLIST_INSERTED:
-               TAILQ_REMOVE(&eventqueue, ev, ev_next);
+               TAILQ_REMOVE(&base->eventqueue, ev, ev_next);
                break;
        default:
                errx(1, "%s: unknown queue %x", __func__, queue);
@@ -698,7 +731,7 @@ event_queue_remove(struct event *ev, int queue)
 }
 
 void
-event_queue_insert(struct event *ev, int queue)
+event_queue_insert(struct event_base *base, struct event *ev, int queue)
 {
        int docount = 1;
 
@@ -715,25 +748,26 @@ event_queue_insert(struct event *ev, int queue)
                docount = 0;
 
        if (docount)
-               event_count++;
+               base->event_count++;
 
        ev->ev_flags |= queue;
        switch (queue) {
        case EVLIST_ACTIVE:
                if (docount)
-                       event_count_active++;
-               TAILQ_INSERT_TAIL(activequeues[ev->ev_pri], ev,ev_active_next);
+                       base->event_count_active++;
+               TAILQ_INSERT_TAIL(base->activequeues[ev->ev_pri],
+                   ev,ev_active_next);
                break;
        case EVLIST_SIGNAL:
                TAILQ_INSERT_TAIL(&signalqueue, ev, ev_signal_next);
                break;
        case EVLIST_TIMEOUT: {
-               struct event *tmp = RB_INSERT(event_tree, &timetree, ev);
+               struct event *tmp = RB_INSERT(event_tree, &base->timetree, ev);
                assert(tmp == NULL);
                break;
        }
        case EVLIST_INSERTED:
-               TAILQ_INSERT_TAIL(&eventqueue, ev, ev_next);
+               TAILQ_INSERT_TAIL(&base->eventqueue, ev, ev_next);
                break;
        default:
                errx(1, "%s: unknown queue %x", __func__, queue);
diff --git a/event.h b/event.h
index 83230bf71f26fdd648975f9aac6d61718ef96839..bb4019de39f3affbb005d7715ec62cc0fe2ff981 100644 (file)
--- a/event.h
+++ b/event.h
@@ -71,12 +71,14 @@ struct {                                                            \
 }
 #endif /* !RB_ENTRY */
 
+struct event_base;
 struct event {
        TAILQ_ENTRY (event) ev_next;
        TAILQ_ENTRY (event) ev_active_next;
        TAILQ_ENTRY (event) ev_signal_next;
        RB_ENTRY (event) ev_timeout_node;
 
+       struct event_base *ev_base;
 #ifdef WIN32
        HANDLE ev_fd;
        OVERLAPPED overlap;
@@ -117,24 +119,21 @@ struct eventop {
        void *(*init)(void);
        int (*add)(void *, struct event *);
        int (*del)(void *, struct event *);
-       int (*recalc)(void *, int);
-       int (*dispatch)(void *, struct timeval *);
+       int (*recalc)(struct event_base *, void *, int);
+       int (*dispatch)(struct event_base *, void *, struct timeval *);
 };
 
 #define TIMEOUT_DEFAULT        {5, 0}
 
-void event_init(void);
+void *event_init(void);
 int event_dispatch(void);
 
 #define EVLOOP_ONCE    0x01
 #define EVLOOP_NONBLOCK        0x02
 int event_loop(int);
+int event_loop_base(struct event_base *, int);
 int event_loopexit(struct timeval *);  /* Causes the loop to exit */
 
-int timeout_next(struct timeval *);
-void timeout_correct(struct timeval *);
-void timeout_process(void);
-
 #define evtimer_add(ev, tv)            event_add(ev, tv)
 #define evtimer_set(ev, cb, arg)       event_set(ev, -1, 0, cb, arg)
 #define evtimer_del(ev)                        event_del(ev)
@@ -171,7 +170,7 @@ int event_pending(struct event *, short, struct timeval *);
 
 /* These functions deal with event priorities */
 
-int    event_priority_init(int);
+int    event_priority_init(struct event_base *, int);
 int    event_priority_set(struct event *, int);
 
 /* These functions deal with buffering input and output */
index a17e69bbd8de9c1d5e5d30a9dc923daa513d5e57..68d6cb03937d9c58990fdfdc03a9e3edccd3f2a7 100644 (file)
--- a/kqueue.c
+++ b/kqueue.c
 
 #include "event.h"
 
-extern struct event_list timequeue;
-extern struct event_list eventqueue;
-extern struct event_list addqueue;
-
 #define EVLIST_X_KQINKERNEL    0x1000
 
 #define NEVENT         64
@@ -83,8 +79,8 @@ struct kqop {
 void *kq_init  (void);
 int kq_add     (void *, struct event *);
 int kq_del     (void *, struct event *);
-int kq_recalc  (void *, int);
-int kq_dispatch        (void *, struct timeval *);
+int kq_recalc  (struct event_base *, void *, int);
+int kq_dispatch        (struct event_base *, void *, struct timeval *);
 int kq_insert  (struct kqop *, struct kevent *);
 
 const struct eventop kqops = {
@@ -131,7 +127,7 @@ kq_init(void)
 }
 
 int
-kq_recalc(void *arg, int max)
+kq_recalc(struct event_base *base, void *arg, int max)
 {
        return (0);
 }
@@ -188,7 +184,7 @@ kq_sighandler(int sig)
 }
 
 int
-kq_dispatch(void *arg, struct timeval *tv)
+kq_dispatch(struct event_base *base, void *arg, struct timeval *tv)
 {
        struct kqop *kqop = arg;
        struct kevent *changes = kqop->changes;
diff --git a/poll.c b/poll.c
index bba594d4ca4d2dd6f3d0b3857d408621c9010156..ec2366d8f0b57a8236d28d380811e9baaf31098a 100644 (file)
--- a/poll.c
+++ b/poll.c
@@ -37,6 +37,7 @@
 #include <sys/_time.h>
 #endif
 #include <sys/queue.h>
+#include <sys/tree.h>
 #include <poll.h>
 #include <signal.h>
 #include <stdio.h>
 #endif
 
 #include "event.h"
+#include "event-internal.h"
 #include "evsignal.h"
 
-extern struct event_list eventqueue;
-
 extern volatile sig_atomic_t evsignal_caught;
 
 struct pollop {
@@ -70,8 +70,8 @@ struct pollop {
 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 *);
+int poll_recalc                (struct event_base *, void *, int);
+int poll_dispatch      (struct event_base *, void *, struct timeval *);
 
 struct eventop pollops = {
        "poll",
@@ -102,7 +102,7 @@ poll_init(void)
  */
 
 int
-poll_recalc(void *arg, int max)
+poll_recalc(struct event_base *base, void *arg, int max)
 {
        struct pollop *pop = arg;
 
@@ -110,7 +110,7 @@ poll_recalc(void *arg, int max)
 }
 
 int
-poll_dispatch(void *arg, struct timeval *tv)
+poll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
 {
        int res, i, count, sec, nfds;
        struct event *ev;
@@ -118,7 +118,7 @@ poll_dispatch(void *arg, struct timeval *tv)
 
        count = pop->event_count;
        nfds = 0;
-       TAILQ_FOREACH(ev, &eventqueue, ev_next) {
+       TAILQ_FOREACH(ev, &base->eventqueue, ev_next) {
                if (nfds + 1 >= count) {
                        if (count < 32)
                                count = 32;
diff --git a/rtsig.c b/rtsig.c
index 59d1ceaad351549b91e8488a160e7b15d7e91afc..54e5cdf6830b1f184bb97bf9b6f554af5b2c1178 100644 (file)
--- a/rtsig.c
+++ b/rtsig.c
@@ -28,7 +28,6 @@
 #define EVLIST_X_NORT  0x1000  /* Skip RT signals (internal) */
 
 #include "event.h"
-extern struct event_list eventqueue;
 extern struct event_list signalqueue;
 
 struct rtsigop {
@@ -122,8 +121,8 @@ activate(struct event *ev, int flags)
 void *rtsig_init(void);
 int rtsig_add(void *, struct event *);
 int rtsig_del(void *, struct event *);
-int rtsig_recalc(void *, int);
-int rtsig_dispatch(void *, struct timeval *);
+int rtsig_recalc(struct event_base *, void *, int);
+int rtsig_dispatch(struct event_base *, void *, struct timeval *);
 
 struct eventop rtsigops = {
     "rtsig",
@@ -251,13 +250,13 @@ rtsig_del(void *arg, struct event *ev)
 }
 
 int
-rtsig_recalc(void *arg, int max)
+rtsig_recalc(struct event_base *base, void *arg, int max)
 {
     return (0);
 }
 
 int
-rtsig_dispatch(void *arg, struct timeval *tv)
+rtsig_dispatch(struct event_base *base, void *arg, struct timeval *tv)
 {
        struct rtsigop *op = (struct rtsigop *) arg;
        struct timespec ts;
@@ -311,7 +310,7 @@ rtsig_dispatch(void *arg, struct timeval *tv)
                                return (-1);
                        }
 
-                       TAILQ_FOREACH(ev, &eventqueue, ev_next)
+                       TAILQ_FOREACH(ev, &base->eventqueue, ev_next)
                            if (!(ev->ev_flags & EVLIST_X_NORT))
                                    poll_add(op, ev);
 
@@ -339,8 +338,8 @@ rtsig_dispatch(void *arg, struct timeval *tv)
                                }
                        }
 
-                       for (ev = TAILQ_FIRST(&eventqueue);
-                           flags && ev != TAILQ_END(&eventqueue);
+                       for (ev = TAILQ_FIRST(&base->eventqueue);
+                           flags && ev != TAILQ_END(&base->eventqueue);
                            ev = TAILQ_NEXT(ev, ev_next)) {
                                if (ev->ev_fd == info.si_fd) {
                                        if (flags & ev->ev_events) {
index 2a1c6f330984838b9ddebb104d0ded2170d3ef22..865f24279b0a05b315dda49e3015fc583c5dff55 100644 (file)
--- a/select.c
+++ b/select.c
@@ -37,6 +37,7 @@
 #include <sys/_time.h>
 #endif
 #include <sys/queue.h>
+#include <sys/tree.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #endif
 
 #include "event.h"
+#include "event-internal.h"
 #include "evsignal.h"
 
-extern struct event_list eventqueue;
-
 #ifndef howmany
 #define        howmany(x, y)   (((x)+((y)-1))/(y))
 #endif
@@ -74,8 +74,8 @@ struct selectop {
 void *select_init      (void);
 int select_add         (void *, struct event *);
 int select_del         (void *, struct event *);
-int select_recalc      (void *, int);
-int select_dispatch    (void *, struct timeval *);
+int select_recalc      (struct event_base *, void *, int);
+int select_dispatch    (struct event_base *, void *, struct timeval *);
 
 const struct eventop selectops = {
        "select",
@@ -106,7 +106,7 @@ select_init(void)
  */
 
 int
-select_recalc(void *arg, int max)
+select_recalc(struct event_base *base, void *arg, int max)
 {
        struct selectop *sop = arg;
        fd_set *readset, *writeset;
@@ -117,7 +117,7 @@ select_recalc(void *arg, int max)
                sop->event_fds = max;
 
        if (!sop->event_fds) {
-               TAILQ_FOREACH(ev, &eventqueue, ev_next)
+               TAILQ_FOREACH(ev, &base->eventqueue, ev_next)
                        if (ev->ev_fd > sop->event_fds)
                                sop->event_fds = ev->ev_fd;
        }
@@ -149,7 +149,7 @@ select_recalc(void *arg, int max)
 }
 
 int
-select_dispatch(void *arg, struct timeval *tv)
+select_dispatch(struct event_base *base, void *arg, struct timeval *tv)
 {
        int maxfd, res;
        struct event *ev, *next;
@@ -158,7 +158,7 @@ select_dispatch(void *arg, struct timeval *tv)
        memset(sop->event_readset, 0, sop->event_fdsz);
        memset(sop->event_writeset, 0, sop->event_fdsz);
 
-       TAILQ_FOREACH(ev, &eventqueue, ev_next) {
+       TAILQ_FOREACH(ev, &base->eventqueue, ev_next) {
                if (ev->ev_events & EV_WRITE)
                        FD_SET(ev->ev_fd, sop->event_writeset);
                if (ev->ev_events & EV_READ)
@@ -188,7 +188,7 @@ select_dispatch(void *arg, struct timeval *tv)
        LOG_DBG((LOG_MISC, 80, "%s: select reports %d", __func__, res));
 
        maxfd = 0;
-       for (ev = TAILQ_FIRST(&eventqueue); ev != NULL; ev = next) {
+       for (ev = TAILQ_FIRST(&base->eventqueue); ev != NULL; ev = next) {
                next = TAILQ_NEXT(ev, ev_next);
 
                res = 0;
index 20ef0b40d68751ef7ca35262a89b338242e67c08..f12b9231e6f47ef98e8bf73d9b5d745adb13ae6c 100644 (file)
@@ -63,6 +63,7 @@ static int roff;
 static int usepersist;
 static struct timeval tset;
 static struct timeval tcalled;
+static struct event_base *event_base;
 
 #define TEST1  "this is a test"
 #define SECONDS        1
@@ -561,7 +562,7 @@ test_priorities(int npriorities)
        snprintf(buf, sizeof(buf), "Priorities %d: ", npriorities);
        setup_test(buf);
 
-       event_priority_init(npriorities);
+       event_priority_init(event_base, npriorities);
 
        memset(&one, 0, sizeof(one));
        memset(&two, 0, sizeof(two));
@@ -621,7 +622,7 @@ main (int argc, char **argv)
        setvbuf(stdout, NULL, _IONBF, 0);
 
        /* Initalize the event library */
-       event_init();
+       event_base = event_init();
 
        test1();