1/*	$NetBSD$	*/
2/*
3 * Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 *    derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28#ifdef HAVE_CONFIG_H
29#include "config.h"
30#endif
31
32#ifdef WIN32
33#define WIN32_LEAN_AND_MEAN
34#include <windows.h>
35#undef WIN32_LEAN_AND_MEAN
36#endif
37#include <sys/types.h>
38#ifdef HAVE_SYS_TIME_H
39#include <sys/time.h>
40#else
41#include <sys/_time.h>
42#endif
43#include <sys/queue.h>
44#include <stdio.h>
45#include <stdlib.h>
46#ifndef WIN32
47#include <unistd.h>
48#endif
49#include <errno.h>
50#include <signal.h>
51#include <string.h>
52#include <assert.h>
53#include <time.h>
54
55#include "event.h"
56#include "event-internal.h"
57#include "evutil.h"
58#include "log.h"
59
60#ifdef HAVE_EVENT_PORTS
61extern const struct eventop evportops;
62#endif
63#ifdef HAVE_SELECT
64extern const struct eventop selectops;
65#endif
66#ifdef HAVE_POLL
67extern const struct eventop pollops;
68#endif
69#ifdef HAVE_EPOLL
70extern const struct eventop epollops;
71#endif
72#ifdef HAVE_WORKING_KQUEUE
73extern const struct eventop kqops;
74#endif
75#ifdef HAVE_DEVPOLL
76extern const struct eventop devpollops;
77#endif
78#ifdef WIN32
79extern const struct eventop win32ops;
80#endif
81
82/* In order of preference */
83static const struct eventop *eventops[] = {
84#ifdef HAVE_EVENT_PORTS
85	&evportops,
86#endif
87#ifdef HAVE_WORKING_KQUEUE
88	&kqops,
89#endif
90#ifdef HAVE_EPOLL
91	&epollops,
92#endif
93#ifdef HAVE_DEVPOLL
94	&devpollops,
95#endif
96#ifdef HAVE_POLL
97	&pollops,
98#endif
99#ifdef HAVE_SELECT
100	&selectops,
101#endif
102#ifdef WIN32
103	&win32ops,
104#endif
105	NULL
106};
107
108/* Global state */
109struct event_base *current_base = NULL;
110extern struct event_base *evsignal_base;
111static int use_monotonic;
112
113/* Handle signals - This is a deprecated interface */
114int (*event_sigcb)(void);		/* Signal callback when gotsig is set */
115volatile sig_atomic_t event_gotsig;	/* Set in signal handler */
116
117/* Prototypes */
118static void	event_queue_insert(struct event_base *, struct event *, int);
119static void	event_queue_remove(struct event_base *, struct event *, int);
120static int	event_haveevents(struct event_base *);
121
122static void	event_process_active(struct event_base *);
123
124static int	timeout_next(struct event_base *, struct timeval **);
125static void	timeout_process(struct event_base *);
126static void	timeout_correct(struct event_base *, struct timeval *);
127
128static void
129detect_monotonic(void)
130{
131#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
132	struct timespec	ts;
133
134	if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
135		use_monotonic = 1;
136#endif
137}
138
139static int
140gettime(struct event_base *base, struct timeval *tp)
141{
142	if (base->tv_cache.tv_sec) {
143		*tp = base->tv_cache;
144		return (0);
145	}
146
147#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
148	if (use_monotonic) {
149		struct timespec	ts;
150
151		if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
152			return (-1);
153
154		tp->tv_sec = ts.tv_sec;
155		tp->tv_usec = ts.tv_nsec / 1000;
156		return (0);
157	}
158#endif
159
160	return (evutil_gettimeofday(tp, NULL));
161}
162
163struct event_base *
164event_init(void)
165{
166	struct event_base *base = event_base_new();
167
168	if (base != NULL)
169		current_base = base;
170
171	return (base);
172}
173
174struct event_base *
175event_base_new(void)
176{
177	int i;
178	struct event_base *base;
179
180	if ((base = calloc(1, sizeof(struct event_base))) == NULL)
181		event_err(1, "%s: calloc", __func__);
182
183	event_sigcb = NULL;
184	event_gotsig = 0;
185
186	detect_monotonic();
187	gettime(base, &base->event_tv);
188
189	min_heap_ctor(&base->timeheap);
190	TAILQ_INIT(&base->eventqueue);
191	base->sig.ev_signal_pair[0] = -1;
192	base->sig.ev_signal_pair[1] = -1;
193
194	base->evbase = NULL;
195	for (i = 0; eventops[i] && !base->evbase; i++) {
196		base->evsel = eventops[i];
197
198		base->evbase = base->evsel->init(base);
199	}
200
201	if (base->evbase == NULL)
202		event_errx(1, "%s: no event mechanism available", __func__);
203
204	if (getenv("EVENT_SHOW_METHOD"))
205		event_msgx("libevent using: %s\n",
206			   base->evsel->name);
207
208	/* allocate a single active event queue */
209	event_base_priority_init(base, 1);
210
211	return (base);
212}
213
214void
215event_base_free(struct event_base *base)
216{
217	int i, n_deleted=0;
218	struct event *ev;
219
220	if (base == NULL && current_base)
221		base = current_base;
222	if (base == current_base)
223		current_base = NULL;
224
225	/* XXX(niels) - check for internal events first */
226	assert(base);
227	/* Delete all non-internal events. */
228	for (ev = TAILQ_FIRST(&base->eventqueue); ev; ) {
229		struct event *next = TAILQ_NEXT(ev, ev_next);
230		if (!(ev->ev_flags & EVLIST_INTERNAL)) {
231			event_del(ev);
232			++n_deleted;
233		}
234		ev = next;
235	}
236	while ((ev = min_heap_top(&base->timeheap)) != NULL) {
237		event_del(ev);
238		++n_deleted;
239	}
240
241	for (i = 0; i < base->nactivequeues; ++i) {
242		for (ev = TAILQ_FIRST(base->activequeues[i]); ev; ) {
243			struct event *next = TAILQ_NEXT(ev, ev_active_next);
244			if (!(ev->ev_flags & EVLIST_INTERNAL)) {
245				event_del(ev);
246				++n_deleted;
247			}
248			ev = next;
249		}
250	}
251
252	if (n_deleted)
253		event_debug(("%s: %d events were still set in base",
254			__func__, n_deleted));
255
256	if (base->evsel->dealloc != NULL)
257		base->evsel->dealloc(base, base->evbase);
258
259	for (i = 0; i < base->nactivequeues; ++i)
260		assert(TAILQ_EMPTY(base->activequeues[i]));
261
262	assert(min_heap_empty(&base->timeheap));
263	min_heap_dtor(&base->timeheap);
264
265	for (i = 0; i < base->nactivequeues; ++i)
266		free(base->activequeues[i]);
267	free(base->activequeues);
268
269	assert(TAILQ_EMPTY(&base->eventqueue));
270
271	free(base);
272}
273
274/* reinitialized the event base after a fork */
275int
276event_reinit(struct event_base *base)
277{
278	const struct eventop *evsel = base->evsel;
279	void *evbase = base->evbase;
280	int res = 0;
281	struct event *ev;
282
283	/* check if this event mechanism requires reinit */
284	if (!evsel->need_reinit)
285		return (0);
286
287	/* prevent internal delete */
288	if (base->sig.ev_signal_added) {
289		/* we cannot call event_del here because the base has
290		 * not been reinitialized yet. */
291		event_queue_remove(base, &base->sig.ev_signal,
292		    EVLIST_INSERTED);
293		if (base->sig.ev_signal.ev_flags & EVLIST_ACTIVE)
294			event_queue_remove(base, &base->sig.ev_signal,
295			    EVLIST_ACTIVE);
296		base->sig.ev_signal_added = 0;
297	}
298
299	if (base->evsel->dealloc != NULL)
300		base->evsel->dealloc(base, base->evbase);
301	evbase = base->evbase = evsel->init(base);
302	if (base->evbase == NULL)
303		event_errx(1, "%s: could not reinitialize event mechanism",
304		    __func__);
305
306	TAILQ_FOREACH(ev, &base->eventqueue, ev_next) {
307		if (evsel->add(evbase, ev) == -1)
308			res = -1;
309	}
310
311	return (res);
312}
313
314int
315event_priority_init(int npriorities)
316{
317  return event_base_priority_init(current_base, npriorities);
318}
319
320int
321event_base_priority_init(struct event_base *base, int npriorities)
322{
323	int i;
324
325	if (base->event_count_active)
326		return (-1);
327
328	if (base->nactivequeues && npriorities != base->nactivequeues) {
329		for (i = 0; i < base->nactivequeues; ++i) {
330			free(base->activequeues[i]);
331		}
332		free(base->activequeues);
333	}
334
335	/* Allocate our priority queues */
336	base->nactivequeues = npriorities;
337	base->activequeues = (struct event_list **)calloc(base->nactivequeues,
338	    npriorities * sizeof(struct event_list *));
339	if (base->activequeues == NULL)
340		event_err(1, "%s: calloc", __func__);
341
342	for (i = 0; i < base->nactivequeues; ++i) {
343		base->activequeues[i] = malloc(sizeof(struct event_list));
344		if (base->activequeues[i] == NULL)
345			event_err(1, "%s: malloc", __func__);
346		TAILQ_INIT(base->activequeues[i]);
347	}
348
349	return (0);
350}
351
352int
353event_haveevents(struct event_base *base)
354{
355	return (base->event_count > 0);
356}
357
358/*
359 * Active events are stored in priority queues.  Lower priorities are always
360 * process before higher priorities.  Low priority events can starve high
361 * priority ones.
362 */
363
364static void
365event_process_active(struct event_base *base)
366{
367	struct event *ev;
368	struct event_list *activeq = NULL;
369	int i;
370	short ncalls;
371
372	for (i = 0; i < base->nactivequeues; ++i) {
373		if (TAILQ_FIRST(base->activequeues[i]) != NULL) {
374			activeq = base->activequeues[i];
375			break;
376		}
377	}
378
379	assert(activeq != NULL);
380
381	for (ev = TAILQ_FIRST(activeq); ev; ev = TAILQ_FIRST(activeq)) {
382		if (ev->ev_events & EV_PERSIST)
383			event_queue_remove(base, ev, EVLIST_ACTIVE);
384		else
385			event_del(ev);
386
387		/* Allows deletes to work */
388		ncalls = ev->ev_ncalls;
389		ev->ev_pncalls = &ncalls;
390		while (ncalls) {
391			ncalls--;
392			ev->ev_ncalls = ncalls;
393			(*ev->ev_callback)((int)ev->ev_fd, ev->ev_res, ev->ev_arg);
394			if (event_gotsig || base->event_break)
395				return;
396		}
397	}
398}
399
400/*
401 * Wait continously for events.  We exit only if no events are left.
402 */
403
404int
405event_dispatch(void)
406{
407	return (event_loop(0));
408}
409
410int
411event_base_dispatch(struct event_base *event_base)
412{
413  return (event_base_loop(event_base, 0));
414}
415
416const char *
417event_base_get_method(struct event_base *base)
418{
419	assert(base);
420	return (base->evsel->name);
421}
422
423static void
424event_loopexit_cb(int fd, short what, void *arg)
425{
426	struct event_base *base = arg;
427	base->event_gotterm = 1;
428}
429
430/* not thread safe */
431int
432event_loopexit(const struct timeval *tv)
433{
434	return (event_once(-1, EV_TIMEOUT, event_loopexit_cb,
435		    current_base, tv));
436}
437
438int
439event_base_loopexit(struct event_base *event_base, const struct timeval *tv)
440{
441	return (event_base_once(event_base, -1, EV_TIMEOUT, event_loopexit_cb,
442		    event_base, tv));
443}
444
445/* not thread safe */
446int
447event_loopbreak(void)
448{
449	return (event_base_loopbreak(current_base));
450}
451
452int
453event_base_loopbreak(struct event_base *event_base)
454{
455	if (event_base == NULL)
456		return (-1);
457
458	event_base->event_break = 1;
459	return (0);
460}
461
462
463
464/* not thread safe */
465
466int
467event_loop(int flags)
468{
469	return event_base_loop(current_base, flags);
470}
471
472int
473event_base_loop(struct event_base *base, int flags)
474{
475	const struct eventop *evsel = base->evsel;
476	void *evbase = base->evbase;
477	struct timeval tv;
478	struct timeval *tv_p;
479	int res, done;
480
481	/* clear time cache */
482	base->tv_cache.tv_sec = 0;
483
484	if (base->sig.ev_signal_added)
485		evsignal_base = base;
486	done = 0;
487	while (!done) {
488		/* Terminate the loop if we have been asked to */
489		if (base->event_gotterm) {
490			base->event_gotterm = 0;
491			break;
492		}
493
494		if (base->event_break) {
495			base->event_break = 0;
496			break;
497		}
498
499		/* You cannot use this interface for multi-threaded apps */
500		while (event_gotsig) {
501			event_gotsig = 0;
502			if (event_sigcb) {
503				res = (*event_sigcb)();
504				if (res == -1) {
505					errno = EINTR;
506					return (-1);
507				}
508			}
509		}
510
511		timeout_correct(base, &tv);
512
513		tv_p = &tv;
514		if (!base->event_count_active && !(flags & EVLOOP_NONBLOCK)) {
515			timeout_next(base, &tv_p);
516		} else {
517			/*
518			 * if we have active events, we just poll new events
519			 * without waiting.
520			 */
521			evutil_timerclear(&tv);
522		}
523
524		/* If we have no events, we just exit */
525		if (!event_haveevents(base)) {
526			event_debug(("%s: no events registered.", __func__));
527			return (1);
528		}
529
530		/* update last old time */
531		gettime(base, &base->event_tv);
532
533		/* clear time cache */
534		base->tv_cache.tv_sec = 0;
535
536		res = evsel->dispatch(base, evbase, tv_p);
537
538		if (res == -1)
539			return (-1);
540		gettime(base, &base->tv_cache);
541
542		timeout_process(base);
543
544		if (base->event_count_active) {
545			event_process_active(base);
546			if (!base->event_count_active && (flags & EVLOOP_ONCE))
547				done = 1;
548		} else if (flags & EVLOOP_NONBLOCK)
549			done = 1;
550	}
551
552	/* clear time cache */
553	base->tv_cache.tv_sec = 0;
554
555	event_debug(("%s: asked to terminate loop.", __func__));
556	return (0);
557}
558
559/* Sets up an event for processing once */
560
561struct event_once {
562	struct event ev;
563
564	void (*cb)(int, short, void *);
565	void *arg;
566};
567
568/* One-time callback, it deletes itself */
569
570static void
571event_once_cb(int fd, short events, void *arg)
572{
573	struct event_once *eonce = arg;
574
575	(*eonce->cb)(fd, events, eonce->arg);
576	free(eonce);
577}
578
579/* not threadsafe, event scheduled once. */
580int
581event_once(int fd, short events,
582    void (*callback)(int, short, void *), void *arg, const struct timeval *tv)
583{
584	return event_base_once(current_base, fd, events, callback, arg, tv);
585}
586
587/* Schedules an event once */
588int
589event_base_once(struct event_base *base, int fd, short events,
590    void (*callback)(int, short, void *), void *arg, const struct timeval *tv)
591{
592	struct event_once *eonce;
593	struct timeval etv;
594	int res;
595
596	/* We cannot support signals that just fire once */
597	if (events & EV_SIGNAL)
598		return (-1);
599
600	if ((eonce = calloc(1, sizeof(struct event_once))) == NULL)
601		return (-1);
602
603	eonce->cb = callback;
604	eonce->arg = arg;
605
606	if (events == EV_TIMEOUT) {
607		if (tv == NULL) {
608			evutil_timerclear(&etv);
609			tv = &etv;
610		}
611
612		evtimer_set(&eonce->ev, event_once_cb, eonce);
613	} else if (events & (EV_READ|EV_WRITE)) {
614		events &= EV_READ|EV_WRITE;
615
616		event_set(&eonce->ev, fd, events, event_once_cb, eonce);
617	} else {
618		/* Bad event combination */
619		free(eonce);
620		return (-1);
621	}
622
623	res = event_base_set(base, &eonce->ev);
624	if (res == 0)
625		res = event_add(&eonce->ev, tv);
626	if (res != 0) {
627		free(eonce);
628		return (res);
629	}
630
631	return (0);
632}
633
634void
635event_set(struct event *ev, int fd, short events,
636	  void (*callback)(int, short, void *), void *arg)
637{
638	/* Take the current base - caller needs to set the real base later */
639	ev->ev_base = current_base;
640
641	ev->ev_callback = callback;
642	ev->ev_arg = arg;
643	ev->ev_fd = fd;
644	ev->ev_events = events;
645	ev->ev_res = 0;
646	ev->ev_flags = EVLIST_INIT;
647	ev->ev_ncalls = 0;
648	ev->ev_pncalls = NULL;
649
650	min_heap_elem_init(ev);
651
652	/* by default, we put new events into the middle priority */
653	if(current_base)
654		ev->ev_pri = current_base->nactivequeues/2;
655}
656
657int
658event_base_set(struct event_base *base, struct event *ev)
659{
660	/* Only innocent events may be assigned to a different base */
661	if (ev->ev_flags != EVLIST_INIT)
662		return (-1);
663
664	ev->ev_base = base;
665	ev->ev_pri = base->nactivequeues/2;
666
667	return (0);
668}
669
670/*
671 * Set's the priority of an event - if an event is already scheduled
672 * changing the priority is going to fail.
673 */
674
675int
676event_priority_set(struct event *ev, int pri)
677{
678	if (ev->ev_flags & EVLIST_ACTIVE)
679		return (-1);
680	if (pri < 0 || pri >= ev->ev_base->nactivequeues)
681		return (-1);
682
683	ev->ev_pri = pri;
684
685	return (0);
686}
687
688/*
689 * Checks if a specific event is pending or scheduled.
690 */
691
692int
693event_pending(struct event *ev, short event, struct timeval *tv)
694{
695	struct timeval	now, res;
696	int flags = 0;
697
698	if (ev->ev_flags & EVLIST_INSERTED)
699		flags |= (ev->ev_events & (EV_READ|EV_WRITE|EV_SIGNAL));
700	if (ev->ev_flags & EVLIST_ACTIVE)
701		flags |= ev->ev_res;
702	if (ev->ev_flags & EVLIST_TIMEOUT)
703		flags |= EV_TIMEOUT;
704
705	event &= (EV_TIMEOUT|EV_READ|EV_WRITE|EV_SIGNAL);
706
707	/* See if there is a timeout that we should report */
708	if (tv != NULL && (flags & event & EV_TIMEOUT)) {
709		gettime(ev->ev_base, &now);
710		evutil_timersub(&ev->ev_timeout, &now, &res);
711		/* correctly remap to real time */
712		evutil_gettimeofday(&now, NULL);
713		evutil_timeradd(&now, &res, tv);
714	}
715
716	return (flags & event);
717}
718
719int
720event_add(struct event *ev, const struct timeval *tv)
721{
722	struct event_base *base = ev->ev_base;
723	const struct eventop *evsel = base->evsel;
724	void *evbase = base->evbase;
725	int res = 0;
726
727	event_debug((
728		 "event_add: event: %p, %s%s%scall %p",
729		 ev,
730		 ev->ev_events & EV_READ ? "EV_READ " : " ",
731		 ev->ev_events & EV_WRITE ? "EV_WRITE " : " ",
732		 tv ? "EV_TIMEOUT " : " ",
733		 ev->ev_callback));
734
735	assert(!(ev->ev_flags & ~EVLIST_ALL));
736
737	/*
738	 * prepare for timeout insertion further below, if we get a
739	 * failure on any step, we should not change any state.
740	 */
741	if (tv != NULL && !(ev->ev_flags & EVLIST_TIMEOUT)) {
742		if (min_heap_reserve(&base->timeheap,
743			1 + min_heap_size(&base->timeheap)) == -1)
744			return (-1);  /* ENOMEM == errno */
745	}
746
747	if ((ev->ev_events & (EV_READ|EV_WRITE|EV_SIGNAL)) &&
748	    !(ev->ev_flags & (EVLIST_INSERTED|EVLIST_ACTIVE))) {
749		res = evsel->add(evbase, ev);
750		if (res != -1)
751			event_queue_insert(base, ev, EVLIST_INSERTED);
752	}
753
754	/*
755	 * we should change the timout state only if the previous event
756	 * addition succeeded.
757	 */
758	if (res != -1 && tv != NULL) {
759		struct timeval now;
760
761		/*
762		 * we already reserved memory above for the case where we
763		 * are not replacing an exisiting timeout.
764		 */
765		if (ev->ev_flags & EVLIST_TIMEOUT)
766			event_queue_remove(base, ev, EVLIST_TIMEOUT);
767
768		/* Check if it is active due to a timeout.  Rescheduling
769		 * this timeout before the callback can be executed
770		 * removes it from the active list. */
771		if ((ev->ev_flags & EVLIST_ACTIVE) &&
772		    (ev->ev_res & EV_TIMEOUT)) {
773			/* See if we are just active executing this
774			 * event in a loop
775			 */
776			if (ev->ev_ncalls && ev->ev_pncalls) {
777				/* Abort loop */
778				*ev->ev_pncalls = 0;
779			}
780
781			event_queue_remove(base, ev, EVLIST_ACTIVE);
782		}
783
784		gettime(base, &now);
785		evutil_timeradd(&now, tv, &ev->ev_timeout);
786
787		event_debug((
788			 "event_add: timeout in %ld seconds, call %p",
789			 tv->tv_sec, ev->ev_callback));
790
791		event_queue_insert(base, ev, EVLIST_TIMEOUT);
792	}
793
794	return (res);
795}
796
797int
798event_del(struct event *ev)
799{
800	struct event_base *base;
801	const struct eventop *evsel;
802	void *evbase;
803
804	event_debug(("event_del: %p, callback %p",
805		 ev, ev->ev_callback));
806
807	/* An event without a base has not been added */
808	if (ev->ev_base == NULL)
809		return (-1);
810
811	base = ev->ev_base;
812	evsel = base->evsel;
813	evbase = base->evbase;
814
815	assert(!(ev->ev_flags & ~EVLIST_ALL));
816
817	/* See if we are just active executing this event in a loop */
818	if (ev->ev_ncalls && ev->ev_pncalls) {
819		/* Abort loop */
820		*ev->ev_pncalls = 0;
821	}
822
823	if (ev->ev_flags & EVLIST_TIMEOUT)
824		event_queue_remove(base, ev, EVLIST_TIMEOUT);
825
826	if (ev->ev_flags & EVLIST_ACTIVE)
827		event_queue_remove(base, ev, EVLIST_ACTIVE);
828
829	if (ev->ev_flags & EVLIST_INSERTED) {
830		event_queue_remove(base, ev, EVLIST_INSERTED);
831		return (evsel->del(evbase, ev));
832	}
833
834	return (0);
835}
836
837void
838event_active(struct event *ev, int res, short ncalls)
839{
840	/* We get different kinds of events, add them together */
841	if (ev->ev_flags & EVLIST_ACTIVE) {
842		ev->ev_res |= res;
843		return;
844	}
845
846	ev->ev_res = res;
847	ev->ev_ncalls = ncalls;
848	ev->ev_pncalls = NULL;
849	event_queue_insert(ev->ev_base, ev, EVLIST_ACTIVE);
850}
851
852static int
853timeout_next(struct event_base *base, struct timeval **tv_p)
854{
855	struct timeval now;
856	struct event *ev;
857	struct timeval *tv = *tv_p;
858
859	if ((ev = min_heap_top(&base->timeheap)) == NULL) {
860		/* if no time-based events are active wait for I/O */
861		*tv_p = NULL;
862		return (0);
863	}
864
865	if (gettime(base, &now) == -1)
866		return (-1);
867
868	if (evutil_timercmp(&ev->ev_timeout, &now, <=)) {
869		evutil_timerclear(tv);
870		return (0);
871	}
872
873	evutil_timersub(&ev->ev_timeout, &now, tv);
874
875	assert(tv->tv_sec >= 0);
876	assert(tv->tv_usec >= 0);
877
878	event_debug(("timeout_next: in %ld seconds", tv->tv_sec));
879	return (0);
880}
881
882/*
883 * Determines if the time is running backwards by comparing the current
884 * time against the last time we checked.  Not needed when using clock
885 * monotonic.
886 */
887
888static void
889timeout_correct(struct event_base *base, struct timeval *tv)
890{
891	struct event **pev;
892	unsigned int size;
893	struct timeval off;
894
895	if (use_monotonic)
896		return;
897
898	/* Check if time is running backwards */
899	gettime(base, tv);
900	if (evutil_timercmp(tv, &base->event_tv, >=)) {
901		base->event_tv = *tv;
902		return;
903	}
904
905	event_debug(("%s: time is running backwards, corrected",
906		    __func__));
907	evutil_timersub(&base->event_tv, tv, &off);
908
909	/*
910	 * We can modify the key element of the node without destroying
911	 * the key, beause we apply it to all in the right order.
912	 */
913	pev = base->timeheap.p;
914	size = base->timeheap.n;
915	for (; size-- > 0; ++pev) {
916		struct timeval *ev_tv = &(**pev).ev_timeout;
917		evutil_timersub(ev_tv, &off, ev_tv);
918	}
919	/* Now remember what the new time turned out to be. */
920	base->event_tv = *tv;
921}
922
923void
924timeout_process(struct event_base *base)
925{
926	struct timeval now;
927	struct event *ev;
928
929	if (min_heap_empty(&base->timeheap))
930		return;
931
932	gettime(base, &now);
933
934	while ((ev = min_heap_top(&base->timeheap))) {
935		if (evutil_timercmp(&ev->ev_timeout, &now, >))
936			break;
937
938		/* delete this event from the I/O queues */
939		event_del(ev);
940
941		event_debug(("timeout_process: call %p",
942			 ev->ev_callback));
943		event_active(ev, EV_TIMEOUT, 1);
944	}
945}
946
947void
948event_queue_remove(struct event_base *base, struct event *ev, int queue)
949{
950	if (!(ev->ev_flags & queue))
951		event_errx(1, "%s: %p(fd %d) not on queue %x", __func__,
952			   ev, ev->ev_fd, queue);
953
954	if (~ev->ev_flags & EVLIST_INTERNAL)
955		base->event_count--;
956
957	ev->ev_flags &= ~queue;
958	switch (queue) {
959	case EVLIST_INSERTED:
960		TAILQ_REMOVE(&base->eventqueue, ev, ev_next);
961		break;
962	case EVLIST_ACTIVE:
963		base->event_count_active--;
964		TAILQ_REMOVE(base->activequeues[ev->ev_pri],
965		    ev, ev_active_next);
966		break;
967	case EVLIST_TIMEOUT:
968		min_heap_erase(&base->timeheap, ev);
969		break;
970	default:
971		event_errx(1, "%s: unknown queue %x", __func__, queue);
972	}
973}
974
975void
976event_queue_insert(struct event_base *base, struct event *ev, int queue)
977{
978	if (ev->ev_flags & queue) {
979		/* Double insertion is possible for active events */
980		if (queue & EVLIST_ACTIVE)
981			return;
982
983		event_errx(1, "%s: %p(fd %d) already on queue %x", __func__,
984			   ev, ev->ev_fd, queue);
985	}
986
987	if (~ev->ev_flags & EVLIST_INTERNAL)
988		base->event_count++;
989
990	ev->ev_flags |= queue;
991	switch (queue) {
992	case EVLIST_INSERTED:
993		TAILQ_INSERT_TAIL(&base->eventqueue, ev, ev_next);
994		break;
995	case EVLIST_ACTIVE:
996		base->event_count_active++;
997		TAILQ_INSERT_TAIL(base->activequeues[ev->ev_pri],
998		    ev,ev_active_next);
999		break;
1000	case EVLIST_TIMEOUT: {
1001		min_heap_push(&base->timeheap, ev);
1002		break;
1003	}
1004	default:
1005		event_errx(1, "%s: unknown queue %x", __func__, queue);
1006	}
1007}
1008
1009/* Functions for debugging */
1010
1011const char *
1012event_get_version(void)
1013{
1014	return (VERSION);
1015}
1016
1017/*
1018 * No thread-safe interface needed - the information should be the same
1019 * for all threads.
1020 */
1021
1022const char *
1023event_get_method(void)
1024{
1025	return (current_base->evsel->name);
1026}
1027