xref: /freebsd/contrib/ntp/sntp/libevent/kqueue.c (revision f5f40dd63bc7acbb5312b26ac1ea1103c12352a6)
12b15cb3dSCy Schubert /*	$OpenBSD: kqueue.c,v 1.5 2002/07/10 14:41:31 art Exp $	*/
22b15cb3dSCy Schubert 
32b15cb3dSCy Schubert /*
42b15cb3dSCy Schubert  * Copyright 2000-2007 Niels Provos <provos@citi.umich.edu>
52b15cb3dSCy Schubert  * Copyright 2007-2012 Niels Provos and Nick Mathewson
62b15cb3dSCy Schubert  *
72b15cb3dSCy Schubert  * Redistribution and use in source and binary forms, with or without
82b15cb3dSCy Schubert  * modification, are permitted provided that the following conditions
92b15cb3dSCy Schubert  * are met:
102b15cb3dSCy Schubert  * 1. Redistributions of source code must retain the above copyright
112b15cb3dSCy Schubert  *    notice, this list of conditions and the following disclaimer.
122b15cb3dSCy Schubert  * 2. Redistributions in binary form must reproduce the above copyright
132b15cb3dSCy Schubert  *    notice, this list of conditions and the following disclaimer in the
142b15cb3dSCy Schubert  *    documentation and/or other materials provided with the distribution.
152b15cb3dSCy Schubert  * 3. The name of the author may not be used to endorse or promote products
162b15cb3dSCy Schubert  *    derived from this software without specific prior written permission.
172b15cb3dSCy Schubert  *
182b15cb3dSCy Schubert  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
192b15cb3dSCy Schubert  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
202b15cb3dSCy Schubert  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
212b15cb3dSCy Schubert  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
222b15cb3dSCy Schubert  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
232b15cb3dSCy Schubert  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
242b15cb3dSCy Schubert  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
252b15cb3dSCy Schubert  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
262b15cb3dSCy Schubert  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
272b15cb3dSCy Schubert  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
282b15cb3dSCy Schubert  */
292b15cb3dSCy Schubert #include "event2/event-config.h"
302b15cb3dSCy Schubert #include "evconfig-private.h"
312b15cb3dSCy Schubert 
322b15cb3dSCy Schubert #ifdef EVENT__HAVE_KQUEUE
332b15cb3dSCy Schubert 
342b15cb3dSCy Schubert #include <sys/types.h>
352b15cb3dSCy Schubert #ifdef EVENT__HAVE_SYS_TIME_H
362b15cb3dSCy Schubert #include <sys/time.h>
372b15cb3dSCy Schubert #endif
382b15cb3dSCy Schubert #include <sys/queue.h>
392b15cb3dSCy Schubert #include <sys/event.h>
40a466cc55SCy Schubert #include <limits.h>
412b15cb3dSCy Schubert #include <signal.h>
422b15cb3dSCy Schubert #include <stdio.h>
432b15cb3dSCy Schubert #include <stdlib.h>
442b15cb3dSCy Schubert #include <string.h>
452b15cb3dSCy Schubert #include <unistd.h>
462b15cb3dSCy Schubert #include <errno.h>
472b15cb3dSCy Schubert #ifdef EVENT__HAVE_INTTYPES_H
482b15cb3dSCy Schubert #include <inttypes.h>
492b15cb3dSCy Schubert #endif
502b15cb3dSCy Schubert 
512b15cb3dSCy Schubert /* Some platforms apparently define the udata field of struct kevent as
522b15cb3dSCy Schubert  * intptr_t, whereas others define it as void*.  There doesn't seem to be an
532b15cb3dSCy Schubert  * easy way to tell them apart via autoconf, so we need to use OS macros. */
54a466cc55SCy Schubert #if defined(__NetBSD__)
55a466cc55SCy Schubert #define PTR_TO_UDATA(x) ((typeof(((struct kevent *)0)->udata))(x))
56a466cc55SCy Schubert #define INT_TO_UDATA(x) ((typeof(((struct kevent *)0)->udata))(intptr_t)(x))
57a466cc55SCy Schubert #elif defined(EVENT__HAVE_INTTYPES_H) && !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__darwin__) && !defined(__APPLE__) && !defined(__CloudABI__)
582b15cb3dSCy Schubert #define PTR_TO_UDATA(x)	((intptr_t)(x))
592b15cb3dSCy Schubert #define INT_TO_UDATA(x) ((intptr_t)(x))
602b15cb3dSCy Schubert #else
612b15cb3dSCy Schubert #define PTR_TO_UDATA(x)	(x)
622b15cb3dSCy Schubert #define INT_TO_UDATA(x) ((void*)(x))
632b15cb3dSCy Schubert #endif
642b15cb3dSCy Schubert 
652b15cb3dSCy Schubert #include "event-internal.h"
662b15cb3dSCy Schubert #include "log-internal.h"
672b15cb3dSCy Schubert #include "evmap-internal.h"
682b15cb3dSCy Schubert #include "event2/thread.h"
69a466cc55SCy Schubert #include "event2/util.h"
702b15cb3dSCy Schubert #include "evthread-internal.h"
712b15cb3dSCy Schubert #include "changelist-internal.h"
722b15cb3dSCy Schubert 
732b15cb3dSCy Schubert #include "kqueue-internal.h"
742b15cb3dSCy Schubert 
752b15cb3dSCy Schubert #define NEVENT		64
762b15cb3dSCy Schubert 
772b15cb3dSCy Schubert struct kqop {
782b15cb3dSCy Schubert 	struct kevent *changes;
792b15cb3dSCy Schubert 	int changes_size;
802b15cb3dSCy Schubert 
812b15cb3dSCy Schubert 	struct kevent *events;
822b15cb3dSCy Schubert 	int events_size;
832b15cb3dSCy Schubert 	int kq;
842b15cb3dSCy Schubert 	int notify_event_added;
852b15cb3dSCy Schubert 	pid_t pid;
862b15cb3dSCy Schubert };
872b15cb3dSCy Schubert 
882b15cb3dSCy Schubert static void kqop_free(struct kqop *kqop);
892b15cb3dSCy Schubert 
902b15cb3dSCy Schubert static void *kq_init(struct event_base *);
912b15cb3dSCy Schubert static int kq_sig_add(struct event_base *, int, short, short, void *);
922b15cb3dSCy Schubert static int kq_sig_del(struct event_base *, int, short, short, void *);
932b15cb3dSCy Schubert static int kq_dispatch(struct event_base *, struct timeval *);
942b15cb3dSCy Schubert static void kq_dealloc(struct event_base *);
952b15cb3dSCy Schubert 
962b15cb3dSCy Schubert const struct eventop kqops = {
972b15cb3dSCy Schubert 	"kqueue",
982b15cb3dSCy Schubert 	kq_init,
992b15cb3dSCy Schubert 	event_changelist_add_,
1002b15cb3dSCy Schubert 	event_changelist_del_,
1012b15cb3dSCy Schubert 	kq_dispatch,
1022b15cb3dSCy Schubert 	kq_dealloc,
1032b15cb3dSCy Schubert 	1 /* need reinit */,
1042b15cb3dSCy Schubert     EV_FEATURE_ET|EV_FEATURE_O1|EV_FEATURE_FDS,
1052b15cb3dSCy Schubert 	EVENT_CHANGELIST_FDINFO_SIZE
1062b15cb3dSCy Schubert };
1072b15cb3dSCy Schubert 
1082b15cb3dSCy Schubert static const struct eventop kqsigops = {
1092b15cb3dSCy Schubert 	"kqueue_signal",
1102b15cb3dSCy Schubert 	NULL,
1112b15cb3dSCy Schubert 	kq_sig_add,
1122b15cb3dSCy Schubert 	kq_sig_del,
1132b15cb3dSCy Schubert 	NULL,
1142b15cb3dSCy Schubert 	NULL,
1152b15cb3dSCy Schubert 	1 /* need reinit */,
1162b15cb3dSCy Schubert 	0,
1172b15cb3dSCy Schubert 	0
1182b15cb3dSCy Schubert };
1192b15cb3dSCy Schubert 
1202b15cb3dSCy Schubert static void *
1212b15cb3dSCy Schubert kq_init(struct event_base *base)
1222b15cb3dSCy Schubert {
1232b15cb3dSCy Schubert 	int kq = -1;
1242b15cb3dSCy Schubert 	struct kqop *kqueueop = NULL;
1252b15cb3dSCy Schubert 
1262b15cb3dSCy Schubert 	if (!(kqueueop = mm_calloc(1, sizeof(struct kqop))))
1272b15cb3dSCy Schubert 		return (NULL);
1282b15cb3dSCy Schubert 
1292b15cb3dSCy Schubert /* Initialize the kernel queue */
1302b15cb3dSCy Schubert 
1312b15cb3dSCy Schubert 	if ((kq = kqueue()) == -1) {
1322b15cb3dSCy Schubert 		event_warn("kqueue");
1332b15cb3dSCy Schubert 		goto err;
1342b15cb3dSCy Schubert 	}
1352b15cb3dSCy Schubert 
1362b15cb3dSCy Schubert 	kqueueop->kq = kq;
1372b15cb3dSCy Schubert 
1382b15cb3dSCy Schubert 	kqueueop->pid = getpid();
1392b15cb3dSCy Schubert 
1402b15cb3dSCy Schubert 	/* Initialize fields */
1412b15cb3dSCy Schubert 	kqueueop->changes = mm_calloc(NEVENT, sizeof(struct kevent));
1422b15cb3dSCy Schubert 	if (kqueueop->changes == NULL)
1432b15cb3dSCy Schubert 		goto err;
1442b15cb3dSCy Schubert 	kqueueop->events = mm_calloc(NEVENT, sizeof(struct kevent));
1452b15cb3dSCy Schubert 	if (kqueueop->events == NULL)
1462b15cb3dSCy Schubert 		goto err;
1472b15cb3dSCy Schubert 	kqueueop->events_size = kqueueop->changes_size = NEVENT;
1482b15cb3dSCy Schubert 
1492b15cb3dSCy Schubert 	/* Check for Mac OS X kqueue bug. */
1502b15cb3dSCy Schubert 	memset(&kqueueop->changes[0], 0, sizeof kqueueop->changes[0]);
1512b15cb3dSCy Schubert 	kqueueop->changes[0].ident = -1;
1522b15cb3dSCy Schubert 	kqueueop->changes[0].filter = EVFILT_READ;
1532b15cb3dSCy Schubert 	kqueueop->changes[0].flags = EV_ADD;
1542b15cb3dSCy Schubert 	/*
1552b15cb3dSCy Schubert 	 * If kqueue works, then kevent will succeed, and it will
1562b15cb3dSCy Schubert 	 * stick an error in events[0].  If kqueue is broken, then
1572b15cb3dSCy Schubert 	 * kevent will fail.
1582b15cb3dSCy Schubert 	 */
1592b15cb3dSCy Schubert 	if (kevent(kq,
1602b15cb3dSCy Schubert 		kqueueop->changes, 1, kqueueop->events, NEVENT, NULL) != 1 ||
1612b15cb3dSCy Schubert 	    (int)kqueueop->events[0].ident != -1 ||
162a466cc55SCy Schubert 	    !(kqueueop->events[0].flags & EV_ERROR)) {
1632b15cb3dSCy Schubert 		event_warn("%s: detected broken kqueue; not using.", __func__);
1642b15cb3dSCy Schubert 		goto err;
1652b15cb3dSCy Schubert 	}
1662b15cb3dSCy Schubert 
1672b15cb3dSCy Schubert 	base->evsigsel = &kqsigops;
1682b15cb3dSCy Schubert 
1692b15cb3dSCy Schubert 	return (kqueueop);
1702b15cb3dSCy Schubert err:
1712b15cb3dSCy Schubert 	if (kqueueop)
1722b15cb3dSCy Schubert 		kqop_free(kqueueop);
1732b15cb3dSCy Schubert 
1742b15cb3dSCy Schubert 	return (NULL);
1752b15cb3dSCy Schubert }
1762b15cb3dSCy Schubert 
1772b15cb3dSCy Schubert #define ADD_UDATA 0x30303
1782b15cb3dSCy Schubert 
1792b15cb3dSCy Schubert static void
1802b15cb3dSCy Schubert kq_setup_kevent(struct kevent *out, evutil_socket_t fd, int filter, short change)
1812b15cb3dSCy Schubert {
1822b15cb3dSCy Schubert 	memset(out, 0, sizeof(struct kevent));
1832b15cb3dSCy Schubert 	out->ident = fd;
1842b15cb3dSCy Schubert 	out->filter = filter;
1852b15cb3dSCy Schubert 
1862b15cb3dSCy Schubert 	if (change & EV_CHANGE_ADD) {
1872b15cb3dSCy Schubert 		out->flags = EV_ADD;
1882b15cb3dSCy Schubert 		/* We set a magic number here so that we can tell 'add'
1892b15cb3dSCy Schubert 		 * errors from 'del' errors. */
1902b15cb3dSCy Schubert 		out->udata = INT_TO_UDATA(ADD_UDATA);
1912b15cb3dSCy Schubert 		if (change & EV_ET)
1922b15cb3dSCy Schubert 			out->flags |= EV_CLEAR;
1932b15cb3dSCy Schubert #ifdef NOTE_EOF
1942b15cb3dSCy Schubert 		/* Make it behave like select() and poll() */
1952b15cb3dSCy Schubert 		if (filter == EVFILT_READ)
1962b15cb3dSCy Schubert 			out->fflags = NOTE_EOF;
1972b15cb3dSCy Schubert #endif
1982b15cb3dSCy Schubert 	} else {
1992b15cb3dSCy Schubert 		EVUTIL_ASSERT(change & EV_CHANGE_DEL);
2002b15cb3dSCy Schubert 		out->flags = EV_DELETE;
2012b15cb3dSCy Schubert 	}
2022b15cb3dSCy Schubert }
2032b15cb3dSCy Schubert 
2042b15cb3dSCy Schubert static int
2052b15cb3dSCy Schubert kq_build_changes_list(const struct event_changelist *changelist,
2062b15cb3dSCy Schubert     struct kqop *kqop)
2072b15cb3dSCy Schubert {
2082b15cb3dSCy Schubert 	int i;
2092b15cb3dSCy Schubert 	int n_changes = 0;
2102b15cb3dSCy Schubert 
2112b15cb3dSCy Schubert 	for (i = 0; i < changelist->n_changes; ++i) {
2122b15cb3dSCy Schubert 		struct event_change *in_ch = &changelist->changes[i];
2132b15cb3dSCy Schubert 		struct kevent *out_ch;
2142b15cb3dSCy Schubert 		if (n_changes >= kqop->changes_size - 1) {
215a466cc55SCy Schubert 			int newsize;
2162b15cb3dSCy Schubert 			struct kevent *newchanges;
2172b15cb3dSCy Schubert 
218a466cc55SCy Schubert 			if (kqop->changes_size > INT_MAX / 2 ||
219a466cc55SCy Schubert 			    (size_t)kqop->changes_size * 2 > EV_SIZE_MAX /
220a466cc55SCy Schubert 			    sizeof(struct kevent)) {
221a466cc55SCy Schubert 				event_warnx("%s: int overflow", __func__);
222a466cc55SCy Schubert 				return (-1);
223a466cc55SCy Schubert 			}
224a466cc55SCy Schubert 
225a466cc55SCy Schubert 			newsize = kqop->changes_size * 2;
2262b15cb3dSCy Schubert 			newchanges = mm_realloc(kqop->changes,
2272b15cb3dSCy Schubert 			    newsize * sizeof(struct kevent));
2282b15cb3dSCy Schubert 			if (newchanges == NULL) {
2292b15cb3dSCy Schubert 				event_warn("%s: realloc", __func__);
2302b15cb3dSCy Schubert 				return (-1);
2312b15cb3dSCy Schubert 			}
2322b15cb3dSCy Schubert 			kqop->changes = newchanges;
2332b15cb3dSCy Schubert 			kqop->changes_size = newsize;
2342b15cb3dSCy Schubert 		}
2352b15cb3dSCy Schubert 		if (in_ch->read_change) {
2362b15cb3dSCy Schubert 			out_ch = &kqop->changes[n_changes++];
2372b15cb3dSCy Schubert 			kq_setup_kevent(out_ch, in_ch->fd, EVFILT_READ,
2382b15cb3dSCy Schubert 			    in_ch->read_change);
2392b15cb3dSCy Schubert 		}
2402b15cb3dSCy Schubert 		if (in_ch->write_change) {
2412b15cb3dSCy Schubert 			out_ch = &kqop->changes[n_changes++];
2422b15cb3dSCy Schubert 			kq_setup_kevent(out_ch, in_ch->fd, EVFILT_WRITE,
2432b15cb3dSCy Schubert 			    in_ch->write_change);
2442b15cb3dSCy Schubert 		}
2452b15cb3dSCy Schubert 	}
2462b15cb3dSCy Schubert 	return n_changes;
2472b15cb3dSCy Schubert }
2482b15cb3dSCy Schubert 
2492b15cb3dSCy Schubert static int
2502b15cb3dSCy Schubert kq_grow_events(struct kqop *kqop, size_t new_size)
2512b15cb3dSCy Schubert {
2522b15cb3dSCy Schubert 	struct kevent *newresult;
2532b15cb3dSCy Schubert 
2542b15cb3dSCy Schubert 	newresult = mm_realloc(kqop->events,
2552b15cb3dSCy Schubert 	    new_size * sizeof(struct kevent));
2562b15cb3dSCy Schubert 
2572b15cb3dSCy Schubert 	if (newresult) {
2582b15cb3dSCy Schubert 		kqop->events = newresult;
2592b15cb3dSCy Schubert 		kqop->events_size = new_size;
2602b15cb3dSCy Schubert 		return 0;
2612b15cb3dSCy Schubert 	} else {
2622b15cb3dSCy Schubert 		return -1;
2632b15cb3dSCy Schubert 	}
2642b15cb3dSCy Schubert }
2652b15cb3dSCy Schubert 
2662b15cb3dSCy Schubert static int
2672b15cb3dSCy Schubert kq_dispatch(struct event_base *base, struct timeval *tv)
2682b15cb3dSCy Schubert {
2692b15cb3dSCy Schubert 	struct kqop *kqop = base->evbase;
2702b15cb3dSCy Schubert 	struct kevent *events = kqop->events;
2712b15cb3dSCy Schubert 	struct kevent *changes;
2722b15cb3dSCy Schubert 	struct timespec ts, *ts_p = NULL;
2732b15cb3dSCy Schubert 	int i, n_changes, res;
2742b15cb3dSCy Schubert 
2752b15cb3dSCy Schubert 	if (tv != NULL) {
276a466cc55SCy Schubert 		ts.tv_sec = tv->tv_sec;
277a466cc55SCy Schubert 		ts.tv_nsec = tv->tv_usec * 1000;
2782b15cb3dSCy Schubert 		ts_p = &ts;
2792b15cb3dSCy Schubert 	}
2802b15cb3dSCy Schubert 
2812b15cb3dSCy Schubert 	/* Build "changes" from "base->changes" */
2822b15cb3dSCy Schubert 	EVUTIL_ASSERT(kqop->changes);
2832b15cb3dSCy Schubert 	n_changes = kq_build_changes_list(&base->changelist, kqop);
2842b15cb3dSCy Schubert 	if (n_changes < 0)
2852b15cb3dSCy Schubert 		return -1;
2862b15cb3dSCy Schubert 
2872b15cb3dSCy Schubert 	event_changelist_remove_all_(&base->changelist, base);
2882b15cb3dSCy Schubert 
2892b15cb3dSCy Schubert 	/* steal the changes array in case some broken code tries to call
2902b15cb3dSCy Schubert 	 * dispatch twice at once. */
2912b15cb3dSCy Schubert 	changes = kqop->changes;
2922b15cb3dSCy Schubert 	kqop->changes = NULL;
2932b15cb3dSCy Schubert 
2942b15cb3dSCy Schubert 	/* Make sure that 'events' is at least as long as the list of changes:
2952b15cb3dSCy Schubert 	 * otherwise errors in the changes can get reported as a -1 return
2962b15cb3dSCy Schubert 	 * value from kevent() rather than as EV_ERROR events in the events
2972b15cb3dSCy Schubert 	 * array.
2982b15cb3dSCy Schubert 	 *
2992b15cb3dSCy Schubert 	 * (We could instead handle -1 return values from kevent() by
3002b15cb3dSCy Schubert 	 * retrying with a smaller changes array or a larger events array,
3012b15cb3dSCy Schubert 	 * but this approach seems less risky for now.)
3022b15cb3dSCy Schubert 	 */
3032b15cb3dSCy Schubert 	if (kqop->events_size < n_changes) {
3042b15cb3dSCy Schubert 		int new_size = kqop->events_size;
3052b15cb3dSCy Schubert 		do {
3062b15cb3dSCy Schubert 			new_size *= 2;
3072b15cb3dSCy Schubert 		} while (new_size < n_changes);
3082b15cb3dSCy Schubert 
3092b15cb3dSCy Schubert 		kq_grow_events(kqop, new_size);
3102b15cb3dSCy Schubert 		events = kqop->events;
3112b15cb3dSCy Schubert 	}
3122b15cb3dSCy Schubert 
3132b15cb3dSCy Schubert 	EVBASE_RELEASE_LOCK(base, th_base_lock);
3142b15cb3dSCy Schubert 
3152b15cb3dSCy Schubert 	res = kevent(kqop->kq, changes, n_changes,
3162b15cb3dSCy Schubert 	    events, kqop->events_size, ts_p);
3172b15cb3dSCy Schubert 
3182b15cb3dSCy Schubert 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
3192b15cb3dSCy Schubert 
3202b15cb3dSCy Schubert 	EVUTIL_ASSERT(kqop->changes == NULL);
3212b15cb3dSCy Schubert 	kqop->changes = changes;
3222b15cb3dSCy Schubert 
3232b15cb3dSCy Schubert 	if (res == -1) {
3242b15cb3dSCy Schubert 		if (errno != EINTR) {
3252b15cb3dSCy Schubert 			event_warn("kevent");
3262b15cb3dSCy Schubert 			return (-1);
3272b15cb3dSCy Schubert 		}
3282b15cb3dSCy Schubert 
3292b15cb3dSCy Schubert 		return (0);
3302b15cb3dSCy Schubert 	}
3312b15cb3dSCy Schubert 
3322b15cb3dSCy Schubert 	event_debug(("%s: kevent reports %d", __func__, res));
3332b15cb3dSCy Schubert 
3342b15cb3dSCy Schubert 	for (i = 0; i < res; i++) {
3352b15cb3dSCy Schubert 		int which = 0;
3362b15cb3dSCy Schubert 
3372b15cb3dSCy Schubert 		if (events[i].flags & EV_ERROR) {
3382b15cb3dSCy Schubert 			switch (events[i].data) {
3392b15cb3dSCy Schubert 
3402b15cb3dSCy Schubert 			/* Can occur on delete if we are not currently
3412b15cb3dSCy Schubert 			 * watching any events on this fd.  That can
3422b15cb3dSCy Schubert 			 * happen when the fd was closed and another
3432b15cb3dSCy Schubert 			 * file was opened with that fd. */
3442b15cb3dSCy Schubert 			case ENOENT:
3452b15cb3dSCy Schubert 			/* Can occur for reasons not fully understood
3462b15cb3dSCy Schubert 			 * on FreeBSD. */
3472b15cb3dSCy Schubert 			case EINVAL:
3482b15cb3dSCy Schubert 				continue;
349*f5f40dd6SCy Schubert #if defined(__FreeBSD__) && defined(ENOTCAPABLE)
350a25439b6SCy Schubert 			/*
351a25439b6SCy Schubert 			 * This currently occurs if an FD is closed
352a25439b6SCy Schubert 			 * before the EV_DELETE makes it out via kevent().
353a25439b6SCy Schubert 			 * The FreeBSD capabilities code sees the blank
354a25439b6SCy Schubert 			 * capability set and rejects the request to
355a25439b6SCy Schubert 			 * modify an event.
356a25439b6SCy Schubert 			 *
357a25439b6SCy Schubert 			 * To be strictly correct - when an FD is closed,
358a25439b6SCy Schubert 			 * all the registered events are also removed.
359a25439b6SCy Schubert 			 * Queuing EV_DELETE to a closed FD is wrong.
360a25439b6SCy Schubert 			 * The event(s) should just be deleted from
361a25439b6SCy Schubert 			 * the pending changelist.
362a25439b6SCy Schubert 			 */
363a25439b6SCy Schubert 			case ENOTCAPABLE:
364a25439b6SCy Schubert 				continue;
365a25439b6SCy Schubert #endif
3662b15cb3dSCy Schubert 
3672b15cb3dSCy Schubert 			/* Can occur on a delete if the fd is closed. */
3682b15cb3dSCy Schubert 			case EBADF:
3692b15cb3dSCy Schubert 				/* XXXX On NetBSD, we can also get EBADF if we
3702b15cb3dSCy Schubert 				 * try to add the write side of a pipe, but
3712b15cb3dSCy Schubert 				 * the read side has already been closed.
3722b15cb3dSCy Schubert 				 * Other BSDs call this situation 'EPIPE'. It
3732b15cb3dSCy Schubert 				 * would be good if we had a way to report
3742b15cb3dSCy Schubert 				 * this situation. */
3752b15cb3dSCy Schubert 				continue;
3762b15cb3dSCy Schubert 			/* These two can occur on an add if the fd was one side
3772b15cb3dSCy Schubert 			 * of a pipe, and the other side was closed. */
3782b15cb3dSCy Schubert 			case EPERM:
3792b15cb3dSCy Schubert 			case EPIPE:
3802b15cb3dSCy Schubert 				/* Report read events, if we're listening for
3812b15cb3dSCy Schubert 				 * them, so that the user can learn about any
3822b15cb3dSCy Schubert 				 * add errors.  (If the operation was a
3832b15cb3dSCy Schubert 				 * delete, then udata should be cleared.) */
3842b15cb3dSCy Schubert 				if (events[i].udata) {
3852b15cb3dSCy Schubert 					/* The operation was an add:
3862b15cb3dSCy Schubert 					 * report the error as a read. */
3872b15cb3dSCy Schubert 					which |= EV_READ;
3882b15cb3dSCy Schubert 					break;
3892b15cb3dSCy Schubert 				} else {
3902b15cb3dSCy Schubert 					/* The operation was a del:
3912b15cb3dSCy Schubert 					 * report nothing. */
3922b15cb3dSCy Schubert 					continue;
3932b15cb3dSCy Schubert 				}
3942b15cb3dSCy Schubert 
3952b15cb3dSCy Schubert 			/* Other errors shouldn't occur. */
3962b15cb3dSCy Schubert 			default:
3972b15cb3dSCy Schubert 				errno = events[i].data;
3982b15cb3dSCy Schubert 				return (-1);
3992b15cb3dSCy Schubert 			}
4002b15cb3dSCy Schubert 		} else if (events[i].filter == EVFILT_READ) {
4012b15cb3dSCy Schubert 			which |= EV_READ;
4022b15cb3dSCy Schubert 		} else if (events[i].filter == EVFILT_WRITE) {
4032b15cb3dSCy Schubert 			which |= EV_WRITE;
4042b15cb3dSCy Schubert 		} else if (events[i].filter == EVFILT_SIGNAL) {
4052b15cb3dSCy Schubert 			which |= EV_SIGNAL;
4062b15cb3dSCy Schubert #ifdef EVFILT_USER
4072b15cb3dSCy Schubert 		} else if (events[i].filter == EVFILT_USER) {
4082b15cb3dSCy Schubert 			base->is_notify_pending = 0;
4092b15cb3dSCy Schubert #endif
4102b15cb3dSCy Schubert 		}
4112b15cb3dSCy Schubert 
4122b15cb3dSCy Schubert 		if (!which)
4132b15cb3dSCy Schubert 			continue;
4142b15cb3dSCy Schubert 
4152b15cb3dSCy Schubert 		if (events[i].filter == EVFILT_SIGNAL) {
4162b15cb3dSCy Schubert 			evmap_signal_active_(base, events[i].ident, 1);
4172b15cb3dSCy Schubert 		} else {
4182b15cb3dSCy Schubert 			evmap_io_active_(base, events[i].ident, which | EV_ET);
4192b15cb3dSCy Schubert 		}
4202b15cb3dSCy Schubert 	}
4212b15cb3dSCy Schubert 
4222b15cb3dSCy Schubert 	if (res == kqop->events_size) {
4232b15cb3dSCy Schubert 		/* We used all the events space that we have. Maybe we should
4242b15cb3dSCy Schubert 		   make it bigger. */
4252b15cb3dSCy Schubert 		kq_grow_events(kqop, kqop->events_size * 2);
4262b15cb3dSCy Schubert 	}
4272b15cb3dSCy Schubert 
4282b15cb3dSCy Schubert 	return (0);
4292b15cb3dSCy Schubert }
4302b15cb3dSCy Schubert 
4312b15cb3dSCy Schubert static void
4322b15cb3dSCy Schubert kqop_free(struct kqop *kqop)
4332b15cb3dSCy Schubert {
4342b15cb3dSCy Schubert 	if (kqop->changes)
4352b15cb3dSCy Schubert 		mm_free(kqop->changes);
4362b15cb3dSCy Schubert 	if (kqop->events)
4372b15cb3dSCy Schubert 		mm_free(kqop->events);
4382b15cb3dSCy Schubert 	if (kqop->kq >= 0 && kqop->pid == getpid())
4392b15cb3dSCy Schubert 		close(kqop->kq);
4402b15cb3dSCy Schubert 	memset(kqop, 0, sizeof(struct kqop));
4412b15cb3dSCy Schubert 	mm_free(kqop);
4422b15cb3dSCy Schubert }
4432b15cb3dSCy Schubert 
4442b15cb3dSCy Schubert static void
4452b15cb3dSCy Schubert kq_dealloc(struct event_base *base)
4462b15cb3dSCy Schubert {
4472b15cb3dSCy Schubert 	struct kqop *kqop = base->evbase;
4482b15cb3dSCy Schubert 	evsig_dealloc_(base);
4492b15cb3dSCy Schubert 	kqop_free(kqop);
4502b15cb3dSCy Schubert }
4512b15cb3dSCy Schubert 
4522b15cb3dSCy Schubert /* signal handling */
4532b15cb3dSCy Schubert static int
4542b15cb3dSCy Schubert kq_sig_add(struct event_base *base, int nsignal, short old, short events, void *p)
4552b15cb3dSCy Schubert {
4562b15cb3dSCy Schubert 	struct kqop *kqop = base->evbase;
4572b15cb3dSCy Schubert 	struct kevent kev;
4582b15cb3dSCy Schubert 	struct timespec timeout = { 0, 0 };
4592b15cb3dSCy Schubert 	(void)p;
4602b15cb3dSCy Schubert 
4612b15cb3dSCy Schubert 	EVUTIL_ASSERT(nsignal >= 0 && nsignal < NSIG);
4622b15cb3dSCy Schubert 
4632b15cb3dSCy Schubert 	memset(&kev, 0, sizeof(kev));
4642b15cb3dSCy Schubert 	kev.ident = nsignal;
4652b15cb3dSCy Schubert 	kev.filter = EVFILT_SIGNAL;
4662b15cb3dSCy Schubert 	kev.flags = EV_ADD;
4672b15cb3dSCy Schubert 
4682b15cb3dSCy Schubert 	/* Be ready for the signal if it is sent any
4692b15cb3dSCy Schubert 	 * time between now and the next call to
4702b15cb3dSCy Schubert 	 * kq_dispatch. */
4712b15cb3dSCy Schubert 	if (kevent(kqop->kq, &kev, 1, NULL, 0, &timeout) == -1)
4722b15cb3dSCy Schubert 		return (-1);
4732b15cb3dSCy Schubert 
4742b15cb3dSCy Schubert         /* We can set the handler for most signals to SIG_IGN and
4752b15cb3dSCy Schubert          * still have them reported to us in the queue.  However,
4762b15cb3dSCy Schubert          * if the handler for SIGCHLD is SIG_IGN, the system reaps
4772b15cb3dSCy Schubert          * zombie processes for us, and we don't get any notification.
4782b15cb3dSCy Schubert          * This appears to be the only signal with this quirk. */
4792b15cb3dSCy Schubert 	if (evsig_set_handler_(base, nsignal,
4802b15cb3dSCy Schubert                                nsignal == SIGCHLD ? SIG_DFL : SIG_IGN) == -1)
4812b15cb3dSCy Schubert 		return (-1);
4822b15cb3dSCy Schubert 
4832b15cb3dSCy Schubert 	return (0);
4842b15cb3dSCy Schubert }
4852b15cb3dSCy Schubert 
4862b15cb3dSCy Schubert static int
4872b15cb3dSCy Schubert kq_sig_del(struct event_base *base, int nsignal, short old, short events, void *p)
4882b15cb3dSCy Schubert {
4892b15cb3dSCy Schubert 	struct kqop *kqop = base->evbase;
4902b15cb3dSCy Schubert 	struct kevent kev;
4912b15cb3dSCy Schubert 
4922b15cb3dSCy Schubert 	struct timespec timeout = { 0, 0 };
4932b15cb3dSCy Schubert 	(void)p;
4942b15cb3dSCy Schubert 
4952b15cb3dSCy Schubert 	EVUTIL_ASSERT(nsignal >= 0 && nsignal < NSIG);
4962b15cb3dSCy Schubert 
4972b15cb3dSCy Schubert 	memset(&kev, 0, sizeof(kev));
4982b15cb3dSCy Schubert 	kev.ident = nsignal;
4992b15cb3dSCy Schubert 	kev.filter = EVFILT_SIGNAL;
5002b15cb3dSCy Schubert 	kev.flags = EV_DELETE;
5012b15cb3dSCy Schubert 
5022b15cb3dSCy Schubert 	/* Because we insert signal events
5032b15cb3dSCy Schubert 	 * immediately, we need to delete them
5042b15cb3dSCy Schubert 	 * immediately, too */
5052b15cb3dSCy Schubert 	if (kevent(kqop->kq, &kev, 1, NULL, 0, &timeout) == -1)
5062b15cb3dSCy Schubert 		return (-1);
5072b15cb3dSCy Schubert 
5082b15cb3dSCy Schubert 	if (evsig_restore_handler_(base, nsignal) == -1)
5092b15cb3dSCy Schubert 		return (-1);
5102b15cb3dSCy Schubert 
5112b15cb3dSCy Schubert 	return (0);
5122b15cb3dSCy Schubert }
5132b15cb3dSCy Schubert 
5142b15cb3dSCy Schubert 
5152b15cb3dSCy Schubert /* OSX 10.6 and FreeBSD 8.1 add support for EVFILT_USER, which we can use
5162b15cb3dSCy Schubert  * to wake up the event loop from another thread. */
5172b15cb3dSCy Schubert 
5182b15cb3dSCy Schubert /* Magic number we use for our filter ID. */
5192b15cb3dSCy Schubert #define NOTIFY_IDENT 42
5202b15cb3dSCy Schubert 
5212b15cb3dSCy Schubert int
5222b15cb3dSCy Schubert event_kq_add_notify_event_(struct event_base *base)
5232b15cb3dSCy Schubert {
5242b15cb3dSCy Schubert 	struct kqop *kqop = base->evbase;
5252b15cb3dSCy Schubert #if defined(EVFILT_USER) && defined(NOTE_TRIGGER)
5262b15cb3dSCy Schubert 	struct kevent kev;
5272b15cb3dSCy Schubert 	struct timespec timeout = { 0, 0 };
5282b15cb3dSCy Schubert #endif
5292b15cb3dSCy Schubert 
5302b15cb3dSCy Schubert 	if (kqop->notify_event_added)
5312b15cb3dSCy Schubert 		return 0;
5322b15cb3dSCy Schubert 
5332b15cb3dSCy Schubert #if defined(EVFILT_USER) && defined(NOTE_TRIGGER)
5342b15cb3dSCy Schubert 	memset(&kev, 0, sizeof(kev));
5352b15cb3dSCy Schubert 	kev.ident = NOTIFY_IDENT;
5362b15cb3dSCy Schubert 	kev.filter = EVFILT_USER;
5372b15cb3dSCy Schubert 	kev.flags = EV_ADD | EV_CLEAR;
5382b15cb3dSCy Schubert 
5392b15cb3dSCy Schubert 	if (kevent(kqop->kq, &kev, 1, NULL, 0, &timeout) == -1) {
5402b15cb3dSCy Schubert 		event_warn("kevent: adding EVFILT_USER event");
5412b15cb3dSCy Schubert 		return -1;
5422b15cb3dSCy Schubert 	}
5432b15cb3dSCy Schubert 
5442b15cb3dSCy Schubert 	kqop->notify_event_added = 1;
5452b15cb3dSCy Schubert 
5462b15cb3dSCy Schubert 	return 0;
5472b15cb3dSCy Schubert #else
5482b15cb3dSCy Schubert 	return -1;
5492b15cb3dSCy Schubert #endif
5502b15cb3dSCy Schubert }
5512b15cb3dSCy Schubert 
5522b15cb3dSCy Schubert int
5532b15cb3dSCy Schubert event_kq_notify_base_(struct event_base *base)
5542b15cb3dSCy Schubert {
5552b15cb3dSCy Schubert 	struct kqop *kqop = base->evbase;
5562b15cb3dSCy Schubert #if defined(EVFILT_USER) && defined(NOTE_TRIGGER)
5572b15cb3dSCy Schubert 	struct kevent kev;
5582b15cb3dSCy Schubert 	struct timespec timeout = { 0, 0 };
5592b15cb3dSCy Schubert #endif
5602b15cb3dSCy Schubert 	if (! kqop->notify_event_added)
5612b15cb3dSCy Schubert 		return -1;
5622b15cb3dSCy Schubert 
5632b15cb3dSCy Schubert #if defined(EVFILT_USER) && defined(NOTE_TRIGGER)
5642b15cb3dSCy Schubert 	memset(&kev, 0, sizeof(kev));
5652b15cb3dSCy Schubert 	kev.ident = NOTIFY_IDENT;
5662b15cb3dSCy Schubert 	kev.filter = EVFILT_USER;
5672b15cb3dSCy Schubert 	kev.fflags = NOTE_TRIGGER;
5682b15cb3dSCy Schubert 
5692b15cb3dSCy Schubert 	if (kevent(kqop->kq, &kev, 1, NULL, 0, &timeout) == -1) {
5702b15cb3dSCy Schubert 		event_warn("kevent: triggering EVFILT_USER event");
5712b15cb3dSCy Schubert 		return -1;
5722b15cb3dSCy Schubert 	}
5732b15cb3dSCy Schubert 
5742b15cb3dSCy Schubert 	return 0;
5752b15cb3dSCy Schubert #else
5762b15cb3dSCy Schubert 	return -1;
5772b15cb3dSCy Schubert #endif
5782b15cb3dSCy Schubert }
5792b15cb3dSCy Schubert 
5802b15cb3dSCy Schubert #endif /* EVENT__HAVE_KQUEUE */
581