32 #define WIN32_LEAN_AND_MEAN 
   34 #undef WIN32_LEAN_AND_MEAN 
   36 #include <sys/types.h> 
   37 #ifdef HAVE_SYS_TIME_H 
   40 #include <sys/_time.h> 
   42 #include <sys/queue.h> 
   55 #include "event-internal.h" 
   59 #ifdef HAVE_EVENT_PORTS 
   60 extern const struct eventop evportops;
 
   63 extern const struct eventop selectops;
 
   66 extern const struct eventop pollops;
 
   69 extern const struct eventop epollops;
 
   71 #ifdef HAVE_WORKING_KQUEUE 
   72 extern const struct eventop kqops;
 
   75 extern const struct eventop devpollops;
 
   78 extern const struct eventop win32ops;
 
   82 static const struct eventop *eventops[] = {
 
   83 #ifdef HAVE_EVENT_PORTS 
   86 #ifdef HAVE_WORKING_KQUEUE 
  110 static int use_monotonic;
 
  113 int (*event_sigcb)(void);               
 
  114 volatile sig_atomic_t event_gotsig;     
 
  117 static void     event_queue_insert(
struct event_base *, 
struct event *, 
int);
 
  118 static void     event_queue_remove(
struct event_base *, 
struct event *, 
int);
 
  119 static int      event_haveevents(
struct event_base *);
 
  121 static void     event_process_active(
struct event_base *);
 
  124 static void     timeout_process(
struct event_base *);
 
  128 detect_monotonic(
void)
 
  130 #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) 
  133         if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
 
  141         if (base->tv_cache.tv_sec) {
 
  142                 *tp = base->tv_cache;
 
  146 #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) 
  150                 if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
 
  153                 tp->tv_sec = ts.tv_sec;
 
  154                 tp->tv_usec = ts.tv_nsec / 1000;
 
  159         return (evutil_gettimeofday(tp, NULL));
 
  179         if ((base = calloc(1, 
sizeof(
struct event_base))) == NULL)
 
  180                 event_err(1, 
"%s: calloc", __func__);
 
  186         gettime(base, &base->event_tv);
 
  188         min_heap_ctor(&base->timeheap);
 
  189         TAILQ_INIT(&base->eventqueue);
 
  190         base->sig.ev_signal_pair[0] = -1;
 
  191         base->sig.ev_signal_pair[1] = -1;
 
  194         for (i = 0; eventops[
i] && !base->evbase; i++) {
 
  195                 base->evsel = eventops[
i];
 
  197                 base->evbase = base->evsel->init(base);
 
  200         if (base->evbase == NULL)
 
  201                 event_errx(1, 
"%s: no event mechanism available", __func__);
 
  203         if (getenv(
"EVENT_SHOW_METHOD")) 
 
  204                 event_msgx(
"libevent using: %s\n",
 
  208         event_base_priority_init(base, 1);
 
  219         if (base == NULL && current_base)
 
  221         if (base == current_base)
 
  227         for (ev = TAILQ_FIRST(&base->eventqueue); ev; ) {
 
  228                 struct event *next = TAILQ_NEXT(ev, ev_next);
 
  229                 if (!(ev->ev_flags & EVLIST_INTERNAL)) {
 
  235         while ((ev = min_heap_top(&base->timeheap)) != NULL) {
 
  240         for (i = 0; i < base->nactivequeues; ++
i) {
 
  241                 for (ev = TAILQ_FIRST(base->activequeues[i]); ev; ) {
 
  242                         struct event *next = TAILQ_NEXT(ev, ev_active_next);
 
  243                         if (!(ev->ev_flags & EVLIST_INTERNAL)) {
 
  252                 event_debug((
"%s: %d events were still set in base",
 
  253                         __func__, n_deleted));
 
  255         if (base->evsel->dealloc != NULL)
 
  256                 base->evsel->dealloc(base, base->evbase);
 
  258         for (i = 0; i < base->nactivequeues; ++
i)
 
  259                 assert(TAILQ_EMPTY(base->activequeues[i]));
 
  261         assert(min_heap_empty(&base->timeheap));
 
  262         min_heap_dtor(&base->timeheap);
 
  264         for (i = 0; i < base->nactivequeues; ++
i)
 
  265                 free(base->activequeues[i]);
 
  266         free(base->activequeues);
 
  268         assert(TAILQ_EMPTY(&base->eventqueue));
 
  277         const struct eventop *evsel = base->evsel;
 
  278         void *evbase = base->evbase;
 
  283         if (!evsel->need_reinit)
 
  287         if (base->sig.ev_signal_added) {
 
  290                 event_queue_remove(base, &base->sig.ev_signal,
 
  292                 if (base->sig.ev_signal.ev_flags & EVLIST_ACTIVE)
 
  293                         event_queue_remove(base, &base->sig.ev_signal,
 
  295                 base->sig.ev_signal_added = 0;
 
  298         if (base->evsel->dealloc != NULL)
 
  299                 base->evsel->dealloc(base, base->evbase);
 
  300         evbase = base->evbase = evsel->init(base);
 
  301         if (base->evbase == NULL)
 
  302                 event_errx(1, 
"%s: could not reinitialize event mechanism",
 
  305         TAILQ_FOREACH(ev, &base->eventqueue, ev_next) {
 
  306                 if (evsel->add(evbase, ev) == -1)
 
  314 event_priority_init(
int npriorities)
 
  316   return event_base_priority_init(current_base, npriorities);
 
  320 event_base_priority_init(
struct event_base *base, 
int npriorities)
 
  324         if (base->event_count_active)
 
  327         if (base->nactivequeues && npriorities != base->nactivequeues) {
 
  328                 for (i = 0; i < base->nactivequeues; ++
i) {
 
  329                         free(base->activequeues[i]);
 
  331                 free(base->activequeues);
 
  335         base->nactivequeues = npriorities;
 
  336         base->activequeues = (
struct event_list **)calloc(base->nactivequeues,
 
  337             npriorities * 
sizeof(
struct event_list *));
 
  338         if (base->activequeues == NULL)
 
  339                 event_err(1, 
"%s: calloc", __func__);
 
  341         for (i = 0; i < base->nactivequeues; ++
i) {
 
  342                 base->activequeues[
i] = malloc(
sizeof(
struct event_list));
 
  343                 if (base->activequeues[i] == NULL)
 
  344                         event_err(1, 
"%s: malloc", __func__);
 
  345                 TAILQ_INIT(base->activequeues[i]);
 
  354         return (base->event_count > 0);
 
  367         struct event_list *activeq = NULL;
 
  371         for (i = 0; i < base->nactivequeues; ++
i) {
 
  372                 if (TAILQ_FIRST(base->activequeues[i]) != NULL) {
 
  373                         activeq = base->activequeues[
i];
 
  378         assert(activeq != NULL);
 
  380         for (ev = TAILQ_FIRST(activeq); ev; ev = TAILQ_FIRST(activeq)) {
 
  381                 if (ev->ev_events & EV_PERSIST)
 
  382                         event_queue_remove(base, ev, EVLIST_ACTIVE);
 
  387                 ncalls = ev->ev_ncalls;
 
  388                 ev->ev_pncalls = &ncalls;
 
  391                         ev->ev_ncalls = ncalls;
 
  392                         (*ev->ev_callback)((
int)ev->ev_fd, ev->ev_res, ev->ev_arg);
 
  393                         if (event_gotsig || base->event_break)
 
  406         return (event_loop(0));
 
  412   return (event_base_loop(event_base, 0));
 
  419         return (base->evsel->name);
 
  423 event_loopexit_cb(
int fd, 
short what, 
void *arg)
 
  426         base->event_gotterm = 1;
 
  433         return (
event_once(-1, EV_TIMEOUT, event_loopexit_cb,
 
  440         return (event_base_once(event_base, -1, EV_TIMEOUT, event_loopexit_cb,
 
  446 event_loopbreak(
void)
 
  448         return (event_base_loopbreak(current_base));
 
  454         if (event_base == NULL)
 
  457         event_base->event_break = 1;
 
  468         return event_base_loop(current_base, flags);
 
  474         const struct eventop *evsel = base->evsel;
 
  475         void *evbase = base->evbase;
 
  481         base->tv_cache.tv_sec = 0;
 
  483         if (base->sig.ev_signal_added)
 
  484                 evsignal_base = base;
 
  488                 if (base->event_gotterm) {
 
  489                         base->event_gotterm = 0;
 
  493                 if (base->event_break) {
 
  494                         base->event_break = 0;
 
  499                 while (event_gotsig) {
 
  502                                 res = (*event_sigcb)();
 
  510                 timeout_correct(base, &tv);
 
  514                         timeout_next(base, &tv_p);
 
  520                         evutil_timerclear(&tv);
 
  524                 if (!event_haveevents(base)) {
 
  525                         event_debug((
"%s: no events registered.", __func__));
 
  530                 gettime(base, &base->event_tv);
 
  533                 base->tv_cache.tv_sec = 0;
 
  535                 res = evsel->dispatch(base, evbase, tv_p);
 
  539                 gettime(base, &base->tv_cache);
 
  541                 timeout_process(base);
 
  543                 if (base->event_count_active) {
 
  544                         event_process_active(base);
 
  545                         if (!base->event_count_active && (flags & 
EVLOOP_ONCE))
 
  547                 } 
else if (flags & EVLOOP_NONBLOCK)
 
  552         base->tv_cache.tv_sec = 0;
 
  554         event_debug((
"%s: asked to terminate loop.", __func__));
 
  563         void (*cb)(int, short, 
void *);
 
  570 event_once_cb(
int fd, 
short events, 
void *arg)
 
  574         (*eonce->cb)(fd, events, eonce->arg);
 
  581     void (*callback)(
int, 
short, 
void *), 
void *arg, 
const struct timeval *tv)
 
  583         return event_base_once(current_base, fd, events, callback, arg, tv);
 
  588 event_base_once(
struct event_base *base, 
int fd, 
short events,
 
  589     void (*callback)(
int, 
short, 
void *), 
void *arg, 
const struct timeval *tv)
 
  596         if (events & EV_SIGNAL)
 
  599         if ((eonce = calloc(1, 
sizeof(
struct event_once))) == NULL)
 
  602         eonce->cb = callback;
 
  605         if (events == EV_TIMEOUT) {
 
  607                         evutil_timerclear(&etv);
 
  612         } 
else if (events & (EV_READ|EV_WRITE)) {
 
  613                 events &= EV_READ|EV_WRITE;
 
  615                 event_set(&eonce->ev, fd, events, event_once_cb, eonce);
 
  622         res = event_base_set(base, &eonce->ev);
 
  624                 res = event_add(&eonce->ev, tv);
 
  634 event_set(
struct event *ev, 
int fd, 
short events,
 
  635           void (*callback)(
int, 
short, 
void *), 
void *arg)
 
  638         ev->ev_base = current_base;
 
  640         ev->ev_callback = callback;
 
  643         ev->ev_events = events;
 
  645         ev->ev_flags = EVLIST_INIT;
 
  647         ev->ev_pncalls = NULL;
 
  649         min_heap_elem_init(ev);
 
  653                 ev->ev_pri = current_base->nactivequeues/2;
 
  660         if (ev->ev_flags != EVLIST_INIT)
 
  664         ev->ev_pri = base->nactivequeues/2;
 
  675 event_priority_set(
struct event *ev, 
int pri)
 
  677         if (ev->ev_flags & EVLIST_ACTIVE)
 
  679         if (pri < 0 || pri >= ev->ev_base->nactivequeues)
 
  697         if (ev->ev_flags & EVLIST_INSERTED)
 
  698                 flags |= (ev->ev_events & (EV_READ|EV_WRITE|EV_SIGNAL));
 
  699         if (ev->ev_flags & EVLIST_ACTIVE)
 
  701         if (ev->ev_flags & EVLIST_TIMEOUT)
 
  704         event &= (EV_TIMEOUT|EV_READ|EV_WRITE|EV_SIGNAL);
 
  707         if (tv != NULL && (flags & event & EV_TIMEOUT)) {
 
  708                 gettime(ev->ev_base, &now);
 
  709                 evutil_timersub(&ev->ev_timeout, &now, &res);
 
  711                 evutil_gettimeofday(&now, NULL);
 
  712                 evutil_timeradd(&now, &res, tv);
 
  715         return (flags & event);
 
  722         const struct eventop *evsel = base->evsel;
 
  723         void *evbase = base->evbase;
 
  727                  "event_add: event: %p, %s%s%scall %p",
 
  729                  ev->ev_events & EV_READ ? 
"EV_READ " : 
" ",
 
  730                  ev->ev_events & EV_WRITE ? 
"EV_WRITE " : 
" ",
 
  731                  tv ? 
"EV_TIMEOUT " : 
" ",
 
  734         assert(!(ev->ev_flags & ~EVLIST_ALL));
 
  740         if (tv != NULL && !(ev->ev_flags & EVLIST_TIMEOUT)) {
 
  741                 if (min_heap_reserve(&base->timeheap,
 
  742                         1 + min_heap_size(&base->timeheap)) == -1)
 
  746         if ((ev->ev_events & (EV_READ|EV_WRITE|EV_SIGNAL)) &&
 
  747             !(ev->ev_flags & (EVLIST_INSERTED|EVLIST_ACTIVE))) {
 
  748                 res = evsel->add(evbase, ev);
 
  750                         event_queue_insert(base, ev, EVLIST_INSERTED);
 
  757         if (res != -1 && tv != NULL) {
 
  764                 if (ev->ev_flags & EVLIST_TIMEOUT)
 
  765                         event_queue_remove(base, ev, EVLIST_TIMEOUT);
 
  770                 if ((ev->ev_flags & EVLIST_ACTIVE) &&
 
  771                     (ev->ev_res & EV_TIMEOUT)) {
 
  775                         if (ev->ev_ncalls && ev->ev_pncalls) {
 
  780                         event_queue_remove(base, ev, EVLIST_ACTIVE);
 
  784                 evutil_timeradd(&now, tv, &ev->ev_timeout);
 
  787                          "event_add: timeout in %ld seconds, call %p",
 
  788                          tv->tv_sec, ev->ev_callback));
 
  790                 event_queue_insert(base, ev, EVLIST_TIMEOUT);
 
  803         event_debug((
"event_del: %p, callback %p",
 
  804                  ev, ev->ev_callback));
 
  807         if (ev->ev_base == NULL)
 
  812         evbase = base->evbase;
 
  814         assert(!(ev->ev_flags & ~EVLIST_ALL));
 
  817         if (ev->ev_ncalls && ev->ev_pncalls) {
 
  822         if (ev->ev_flags & EVLIST_TIMEOUT)
 
  823                 event_queue_remove(base, ev, EVLIST_TIMEOUT);
 
  825         if (ev->ev_flags & EVLIST_ACTIVE)
 
  826                 event_queue_remove(base, ev, EVLIST_ACTIVE);
 
  828         if (ev->ev_flags & EVLIST_INSERTED) {
 
  829                 event_queue_remove(base, ev, EVLIST_INSERTED);
 
  830                 return (evsel->del(evbase, ev));
 
  837 event_active(
struct event *ev, 
int res, 
short ncalls)
 
  840         if (ev->ev_flags & EVLIST_ACTIVE) {
 
  846         ev->ev_ncalls = ncalls;
 
  847         ev->ev_pncalls = NULL;
 
  848         event_queue_insert(ev->ev_base, ev, EVLIST_ACTIVE);
 
  858         if ((ev = min_heap_top(&base->timeheap)) == NULL) {
 
  864         if (gettime(base, &now) == -1)
 
  867         if (evutil_timercmp(&ev->ev_timeout, &now, <=)) {
 
  868                 evutil_timerclear(tv);
 
  872         evutil_timersub(&ev->ev_timeout, &now, tv);
 
  874         assert(tv->tv_sec >= 0);
 
  875         assert(tv->tv_usec >= 0);
 
  877         event_debug((
"timeout_next: in %ld seconds", tv->tv_sec));
 
  899         if (evutil_timercmp(tv, &base->event_tv, >=)) {
 
  900                 base->event_tv = *tv;
 
  904         event_debug((
"%s: time is running backwards, corrected",
 
  906         evutil_timersub(&base->event_tv, tv, &off);
 
  912         pev = base->timeheap.p;
 
  913         size = base->timeheap.n;
 
  914         for (; size-- > 0; ++pev) {
 
  915                 struct timeval *ev_tv = &(**pev).ev_timeout;
 
  916                 evutil_timersub(ev_tv, &off, ev_tv);
 
  919         base->event_tv = *tv;
 
  928         if (min_heap_empty(&base->timeheap))
 
  933         while ((ev = min_heap_top(&base->timeheap))) {
 
  934                 if (evutil_timercmp(&ev->ev_timeout, &now, >))
 
  940                 event_debug((
"timeout_process: call %p",
 
  942                 event_active(ev, EV_TIMEOUT, 1);
 
  947 event_queue_remove(
struct event_base *base, 
struct event *ev, 
int queue)
 
  949         if (!(ev->ev_flags & queue))
 
  950                 event_errx(1, 
"%s: %p(fd %d) not on queue %x", __func__,
 
  951                            ev, ev->ev_fd, queue);
 
  953         if (~ev->ev_flags & EVLIST_INTERNAL)
 
  956         ev->ev_flags &= ~queue;
 
  958         case EVLIST_INSERTED:
 
  959                 TAILQ_REMOVE(&base->eventqueue, ev, ev_next);
 
  962                 base->event_count_active--;
 
  963                 TAILQ_REMOVE(base->activequeues[ev->ev_pri],
 
  967                 min_heap_erase(&base->timeheap, ev);
 
  970                 event_errx(1, 
"%s: unknown queue %x", __func__, queue);
 
  975 event_queue_insert(
struct event_base *base, 
struct event *ev, 
int queue)
 
  977         if (ev->ev_flags & queue) {
 
  979                 if (queue & EVLIST_ACTIVE)
 
  982                 event_errx(1, 
"%s: %p(fd %d) already on queue %x", __func__,
 
  983                            ev, ev->ev_fd, queue);
 
  986         if (~ev->ev_flags & EVLIST_INTERNAL)
 
  989         ev->ev_flags |= queue;
 
  991         case EVLIST_INSERTED:
 
  992                 TAILQ_INSERT_TAIL(&base->eventqueue, ev, ev_next);
 
  995                 base->event_count_active++;
 
  996                 TAILQ_INSERT_TAIL(base->activequeues[ev->ev_pri],
 
  999         case EVLIST_TIMEOUT: {
 
 1000                 min_heap_push(&base->timeheap, ev);
 
 1004                 event_errx(1, 
"%s: unknown queue %x", __func__, queue);
 
 1011 event_get_version(
void)
 
 1022 event_get_method(
void)
 
 1024         return (current_base->evsel->name);