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);