15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*	$OpenBSD: kqueue.c,v 1.5 2002/07/10 14:41:31 art Exp $	*/
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * All rights reserved.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Redistribution and use in source and binary forms, with or without
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * modification, are permitted provided that the following conditions
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * are met:
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1. Redistributions of source code must retain the above copyright
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *    notice, this list of conditions and the following disclaimer.
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *    notice, this list of conditions and the following disclaimer in the
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *    documentation and/or other materials provided with the distribution.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 3. The name of the author may not be used to endorse or promote products
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *    derived from this software without specific prior written permission.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_CONFIG_H
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "config.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _GNU_SOURCE 1
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h>
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_SYS_TIME_H
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/time.h>
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/_libevent_time.h>
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/queue.h>
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/event.h>
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <signal.h>
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h>
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h>
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h>
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h>
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <assert.h>
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_INTTYPES_H
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <inttypes.h>
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Some platforms apparently define the udata field of struct kevent as
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * intptr_t, whereas others define it as void*.  There doesn't seem to be an
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * easy way to tell them apart via autoconf, so we need to use OS macros. */
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(HAVE_INTTYPES_H) && !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__darwin__) && !defined(__APPLE__)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PTR_TO_UDATA(x)	((intptr_t)(x))
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PTR_TO_UDATA(x)	(x)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "event.h"
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "event-internal.h"
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "log.h"
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define EVLIST_X_KQINKERNEL	0x1000
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NEVENT		64
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct kqop {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct kevent *changes;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	int nchanges;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct kevent *events;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct event_list evsigevents[NSIG];
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	int nevents;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	int kq;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	pid_t pid;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void *kq_init	(struct event_base *);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int kq_add	(void *, struct event *);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int kq_del	(void *, struct event *);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int kq_dispatch	(struct event_base *, void *, struct timeval *);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int kq_insert	(struct kqop *, struct kevent *);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void kq_dealloc (struct event_base *, void *);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const struct eventop kqops = {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	"kqueue",
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	kq_init,
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	kq_add,
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	kq_del,
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	kq_dispatch,
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	kq_dealloc,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	1 /* need reinit */
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void *
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)kq_init(struct event_base *base)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	int i, kq;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct kqop *kqueueop;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Disable kqueue when this environment variable is set */
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (evutil_getenv("EVENT_NOKQUEUE"))
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return (NULL);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (!(kqueueop = calloc(1, sizeof(struct kqop))))
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return (NULL);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Initalize the kernel queue */
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((kq = kqueue()) == -1) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		event_warn("kqueue");
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		free (kqueueop);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return (NULL);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	kqueueop->kq = kq;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	kqueueop->pid = getpid();
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Initalize fields */
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	kqueueop->changes = malloc(NEVENT * sizeof(struct kevent));
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (kqueueop->changes == NULL) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		free (kqueueop);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return (NULL);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	kqueueop->events = malloc(NEVENT * sizeof(struct kevent));
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (kqueueop->events == NULL) {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		free (kqueueop->changes);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		free (kqueueop);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return (NULL);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	kqueueop->nevents = NEVENT;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* we need to keep track of multiple events per signal */
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (i = 0; i < NSIG; ++i) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		TAILQ_INIT(&kqueueop->evsigevents[i]);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Check for Mac OS X kqueue bug. */
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	kqueueop->changes[0].ident = -1;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	kqueueop->changes[0].filter = EVFILT_READ;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	kqueueop->changes[0].flags = EV_ADD;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/*
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * If kqueue works, then kevent will succeed, and it will
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * stick an error in events[0].  If kqueue is broken, then
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * kevent will fail.
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 */
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (kevent(kq,
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		kqueueop->changes, 1, kqueueop->events, NEVENT, NULL) != 1 ||
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    kqueueop->events[0].ident != -1 ||
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    kqueueop->events[0].flags != EV_ERROR) {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		event_warn("%s: detected broken kqueue; not using.", __func__);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		free(kqueueop->changes);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		free(kqueueop->events);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		free(kqueueop);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		close(kq);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return (NULL);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return (kqueueop);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)kq_insert(struct kqop *kqop, struct kevent *kev)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	int nevents = kqop->nevents;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (kqop->nchanges == nevents) {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		struct kevent *newchange;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		struct kevent *newresult;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		nevents *= 2;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		newchange = realloc(kqop->changes,
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    nevents * sizeof(struct kevent));
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (newchange == NULL) {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			event_warn("%s: malloc", __func__);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			return (-1);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		kqop->changes = newchange;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		newresult = realloc(kqop->events,
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    nevents * sizeof(struct kevent));
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		/*
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 * If we fail, we don't have to worry about freeing,
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 * the next realloc will pick it up.
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 */
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (newresult == NULL) {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			event_warn("%s: malloc", __func__);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			return (-1);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		kqop->events = newresult;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		kqop->nevents = nevents;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	memcpy(&kqop->changes[kqop->nchanges++], kev, sizeof(struct kevent));
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	event_debug(("%s: fd %d %s%s",
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		__func__, (int)kev->ident,
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		kev->filter == EVFILT_READ ? "EVFILT_READ" : "EVFILT_WRITE",
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		kev->flags == EV_DELETE ? " (del)" : ""));
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return (0);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)kq_sighandler(int sig)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Do nothing here */
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)kq_dispatch(struct event_base *base, void *arg, struct timeval *tv)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct kqop *kqop = arg;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct kevent *changes = kqop->changes;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct kevent *events = kqop->events;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct event *ev;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct timespec ts, *ts_p = NULL;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	int i, res;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (tv != NULL) {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		TIMEVAL_TO_TIMESPEC(tv, &ts);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ts_p = &ts;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	res = kevent(kqop->kq, changes, kqop->nchanges,
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    events, kqop->nevents, ts_p);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	kqop->nchanges = 0;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (res == -1) {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (errno != EINTR) {
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        event_warn("kevent");
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			return (-1);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return (0);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	event_debug(("%s: kevent reports %d", __func__, res));
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (i = 0; i < res; i++) {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		int which = 0;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (events[i].flags & EV_ERROR) {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			/*
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 * Error messages that can happen, when a delete fails.
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 *   EBADF happens when the file discriptor has been
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 *   closed,
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 *   ENOENT when the file discriptor was closed and
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 *   then reopened.
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 *   EINVAL for some reasons not understood; EINVAL
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 *   should not be returned ever; but FreeBSD does :-\
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 * An error is also indicated when a callback deletes
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 * an event we are still processing.  In that case
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 * the data field is set to ENOENT.
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 */
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			if (events[i].data == EBADF ||
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    events[i].data == EINVAL ||
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    events[i].data == ENOENT)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				continue;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			errno = events[i].data;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			return (-1);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (events[i].filter == EVFILT_READ) {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			which |= EV_READ;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		} else if (events[i].filter == EVFILT_WRITE) {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			which |= EV_WRITE;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		} else if (events[i].filter == EVFILT_SIGNAL) {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			which |= EV_SIGNAL;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (!which)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			continue;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (events[i].filter == EVFILT_SIGNAL) {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			struct event_list *head =
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    (struct event_list *)events[i].udata;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			TAILQ_FOREACH(ev, head, ev_signal_next) {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				event_active(ev, which, events[i].data);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			}
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		} else {
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			ev = (struct event *)events[i].udata;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			if (!(ev->ev_events & EV_PERSIST))
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				ev->ev_flags &= ~EVLIST_X_KQINKERNEL;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			event_active(ev, which, 1);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return (0);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)kq_add(void *arg, struct event *ev)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct kqop *kqop = arg;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct kevent kev;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ev->ev_events & EV_SIGNAL) {
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		int nsignal = EVENT_SIGNAL(ev);
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		assert(nsignal >= 0 && nsignal < NSIG);
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (TAILQ_EMPTY(&kqop->evsigevents[nsignal])) {
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			struct timespec timeout = { 0, 0 };
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			memset(&kev, 0, sizeof(kev));
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			kev.ident = nsignal;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			kev.filter = EVFILT_SIGNAL;
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			kev.flags = EV_ADD;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			kev.udata = PTR_TO_UDATA(&kqop->evsigevents[nsignal]);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			/* Be ready for the signal if it is sent any
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 * time between now and the next call to
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 * kq_dispatch. */
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			if (kevent(kqop->kq, &kev, 1, NULL, 0, &timeout) == -1)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				return (-1);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			if (_evsignal_set_handler(ev->ev_base, nsignal,
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				kq_sighandler) == -1)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				return (-1);
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		TAILQ_INSERT_TAIL(&kqop->evsigevents[nsignal], ev,
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    ev_signal_next);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ev->ev_flags |= EVLIST_X_KQINKERNEL;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return (0);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ev->ev_events & EV_READ) {
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 		memset(&kev, 0, sizeof(kev));
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		kev.ident = ev->ev_fd;
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		kev.filter = EVFILT_READ;
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef NOTE_EOF
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		/* Make it behave like select() and poll() */
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		kev.fflags = NOTE_EOF;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		kev.flags = EV_ADD;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (!(ev->ev_events & EV_PERSIST))
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			kev.flags |= EV_ONESHOT;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		kev.udata = PTR_TO_UDATA(ev);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (kq_insert(kqop, &kev) == -1)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			return (-1);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ev->ev_flags |= EVLIST_X_KQINKERNEL;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ev->ev_events & EV_WRITE) {
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 		memset(&kev, 0, sizeof(kev));
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		kev.ident = ev->ev_fd;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		kev.filter = EVFILT_WRITE;
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		kev.flags = EV_ADD;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (!(ev->ev_events & EV_PERSIST))
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			kev.flags |= EV_ONESHOT;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		kev.udata = PTR_TO_UDATA(ev);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (kq_insert(kqop, &kev) == -1)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			return (-1);
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ev->ev_flags |= EVLIST_X_KQINKERNEL;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return (0);
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)kq_del(void *arg, struct event *ev)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct kqop *kqop = arg;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct kevent kev;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (!(ev->ev_flags & EVLIST_X_KQINKERNEL))
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return (0);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ev->ev_events & EV_SIGNAL) {
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		int nsignal = EVENT_SIGNAL(ev);
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		struct timespec timeout = { 0, 0 };
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		assert(nsignal >= 0 && nsignal < NSIG);
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		TAILQ_REMOVE(&kqop->evsigevents[nsignal], ev, ev_signal_next);
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (TAILQ_EMPTY(&kqop->evsigevents[nsignal])) {
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			memset(&kev, 0, sizeof(kev));
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			kev.ident = nsignal;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			kev.filter = EVFILT_SIGNAL;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			kev.flags = EV_DELETE;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			/* Because we insert signal events
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 * immediately, we need to delete them
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 * immediately, too */
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			if (kevent(kqop->kq, &kev, 1, NULL, 0, &timeout) == -1)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				return (-1);
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			if (_evsignal_restore_handler(ev->ev_base,
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				nsignal) == -1)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				return (-1);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ev->ev_flags &= ~EVLIST_X_KQINKERNEL;
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return (0);
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ev->ev_events & EV_READ) {
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 		memset(&kev, 0, sizeof(kev));
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		kev.ident = ev->ev_fd;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		kev.filter = EVFILT_READ;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		kev.flags = EV_DELETE;
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (kq_insert(kqop, &kev) == -1)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			return (-1);
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ev->ev_flags &= ~EVLIST_X_KQINKERNEL;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ev->ev_events & EV_WRITE) {
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 		memset(&kev, 0, sizeof(kev));
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		kev.ident = ev->ev_fd;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		kev.filter = EVFILT_WRITE;
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		kev.flags = EV_DELETE;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (kq_insert(kqop, &kev) == -1)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			return (-1);
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ev->ev_flags &= ~EVLIST_X_KQINKERNEL;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return (0);
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)kq_dealloc(struct event_base *base, void *arg)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct kqop *kqop = arg;
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (kqop->changes)
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		free(kqop->changes);
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (kqop->events)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		free(kqop->events);
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (kqop->kq >= 0 && kqop->pid == getpid())
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		close(kqop->kq);
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	memset(kqop, 0, sizeof(struct kqop));
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	free(kqop);
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
451