From 5cdca6d7950e9fa01c4c1dfc32e1bfb63aaefee1 Mon Sep 17 00:00:00 2001 From: Ben Woolley Date: Thu, 3 Dec 2015 23:58:21 -0800 Subject: [PATCH] Bring in EV_RECEIPT (revision 197243) and EV_DISPATCH (revision 197242) from FreeBSD. --- lib/libc/sys/kqueue.2 | 14 ++++++++++++++ sys/kern/kern_event.c | 13 +++++++++---- sys/sys/event.h | 2 ++ 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/lib/libc/sys/kqueue.2 b/lib/libc/sys/kqueue.2 index 80e0401..fcf6025 100644 --- a/lib/libc/sys/kqueue.2 +++ b/lib/libc/sys/kqueue.2 @@ -177,10 +177,24 @@ Disable the event so .Fn kevent will not return it. The filter itself is not disabled. +.It EV_DISPATCH +Disable the event source immediately after delivery of an event. +See +.Dv EV_DISABLE +above. .It Dv EV_DELETE Removes the event from the kqueue. Events which are attached to file descriptors are automatically deleted on the last close of the descriptor. +.It EV_RECEIPT +This flag is useful for making bulk changes to a kqueue without draining +any pending events. +When passed as input, it forces +.Dv EV_ERROR +to always be returned. +When a filter is successfully added the +.Va data +field will be zero. .It Dv EV_ONESHOT Causes the event to return only the first occurrence of the filter being triggered. diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index 34f4249..08983a3 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -745,7 +745,7 @@ kern_kevent(struct kqueue *kq, int nevents, int *res, void *uap, * to post the error (see sys_poll()), then we * ignore it too. */ - if (error) { + if (error || (kevp->flags & EV_RECEIPT)) { kevp->flags = EV_ERROR; kevp->data = error; lres = *res; @@ -1273,9 +1273,14 @@ kqueue_scan(struct kqueue *kq, struct kevent *kevp, int count, kn->kn_status &= ~KN_QUEUED; kn->kn_status |= KN_DELETING | KN_REPROCESS; } else { - if (kn->kn_flags & EV_CLEAR) { - kn->kn_data = 0; - kn->kn_fflags = 0; + if (kn->kn_flags & (EV_CLEAR | EV_DISPATCH)) { + if (kn->kn_flags & EV_CLEAR) { + kn->kn_data = 0; + kn->kn_fflags = 0; + } + if (kn->kn_flags & EV_DISPATCH) { + kn->kn_status |= KN_DISABLED; + } kn->kn_status &= ~(KN_QUEUED | KN_ACTIVE); } else { diff --git a/sys/sys/event.h b/sys/sys/event.h index 1710c20..c3c9508 100644 --- a/sys/sys/event.h +++ b/sys/sys/event.h @@ -82,6 +82,8 @@ struct kevent { /* flags */ #define EV_ONESHOT 0x0010 /* only report one occurrence */ #define EV_CLEAR 0x0020 /* clear event state after reporting */ +#define EV_RECEIPT 0x0040 /* force EV_ERROR on success, data=0 */ +#define EV_DISPATCH 0x0080 /* disable event after reporting */ #define EV_SYSFLAGS 0xF000 /* reserved by system */ #define EV_FLAG1 0x2000 /* filter-specific flag */ -- 2.6.3