summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorchristos <christos@NetBSD.org>2015-12-08 14:52:06 +0000
committerchristos <christos@NetBSD.org>2015-12-08 14:52:06 +0000
commit0babdab098f352ba9ffbe89fd69c937dddcd505e (patch)
tree5eab054fe7645087af192e7e31370214ccbb632e /sys
parent25acac336c2d5233c7a80b53db4bcf7b9723e3e8 (diff)
PR/50506: Tobias Nygren: kqueue(2) lacks EV_DISPATCH/EV_RECEIPT support
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/kern_event.c13
-rw-r--r--sys/sys/event.h4
2 files changed, 12 insertions, 5 deletions
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index 603fdfaf55e..c265f77d3f5 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_event.c,v 1.83 2015/03/02 19:24:53 christos Exp $ */
+/* $NetBSD: kern_event.c,v 1.84 2015/12/08 14:52:06 christos Exp $ */
/*-
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -58,7 +58,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_event.c,v 1.83 2015/03/02 19:24:53 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_event.c,v 1.84 2015/12/08 14:52:06 christos Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -867,7 +867,7 @@ kevent1(register_t *retval, int fd,
kevp->flags &= ~EV_SYSFLAGS;
/* register each knote */
error = kqueue_register(kq, kevp);
- if (error) {
+ if (error || (kevp->flags & EV_RECEIPT)) {
if (nevents != 0) {
kevp->flags = EV_ERROR;
kevp->data = error;
@@ -1229,6 +1229,7 @@ kqueue_scan(file_t *fp, size_t maxevents, struct kevent *ulistp,
}
if ((kn->kn_flags & EV_ONESHOT) == 0) {
mutex_spin_exit(&kq->kq_lock);
+ KASSERT(kn->kn_fop->f_event != NULL);
KERNEL_LOCK(1, NULL); /* XXXSMP */
rv = (*kn->kn_fop->f_event)(kn, 0);
KERNEL_UNLOCK_ONE(NULL); /* XXXSMP */
@@ -1258,7 +1259,10 @@ kqueue_scan(file_t *fp, size_t maxevents, struct kevent *ulistp,
/* clear state after retrieval */
kn->kn_data = 0;
kn->kn_fflags = 0;
- kn->kn_status &= ~KN_ACTIVE;
+ kn->kn_status &= ~(KN_QUEUED|KN_ACTIVE);
+ } else if (kn->kn_flags & EV_DISPATCH) {
+ kn->kn_status |= KN_DISABLED;
+ kn->kn_status &= ~(KN_QUEUED|KN_ACTIVE);
} else {
/* add event back on list */
kq_check(kq);
@@ -1510,6 +1514,7 @@ knote(struct klist *list, long hint)
struct knote *kn, *tmpkn;
SLIST_FOREACH_SAFE(kn, list, kn_selnext, tmpkn) {
+ KASSERT(kn->kn_fop->f_event != NULL);
if ((*kn->kn_fop->f_event)(kn, hint))
knote_activate(kn);
}
diff --git a/sys/sys/event.h b/sys/sys/event.h
index b1040f81c15..0387ec5ae4b 100644
--- a/sys/sys/event.h
+++ b/sys/sys/event.h
@@ -1,4 +1,4 @@
-/* $NetBSD: event.h,v 1.24 2015/01/14 22:21:00 christos Exp $ */
+/* $NetBSD: event.h,v 1.25 2015/12/08 14:52:06 christos Exp $ */
/*-
* Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org>
@@ -74,6 +74,8 @@ struct kevent {
/* flags */
#define EV_ONESHOT 0x0010U /* only report one occurrence */
#define EV_CLEAR 0x0020U /* clear event state after reporting */
+#define EV_RECEIPT 0x0040U /* force EV_ERROR on success, data=0 */
+#define EV_DISPATCH 0x0080U /* disable event after reporting */
#define EV_SYSFLAGS 0xF000U /* reserved by system */
#define EV_FLAG1 0x2000U /* filter-specific flag */