1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index 65ff246..7beb332 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -1121,11 +1121,27 @@ void
 knote(struct klist *list, long hint)
 {
        struct knote *kn;
+       short wakeone[EVFILT_SYSCOUNT];
+       short wake_filter;
+
+       memset(&wakeone, 0, sizeof(wakeone));

        lwkt_gettoken(&kq_token);
-       SLIST_FOREACH(kn, list, kn_next)
-               if (filter_event(kn, hint))
-                       KNOTE_ACTIVATE(kn);
+       SLIST_FOREACH(kn, list, kn_next) {
+               /*
+                * Activate the knote, but only once for a given
+                * filter type when EV_WAKEONE is set.
+                */
+               wake_filter = kn->kn_filter + EVFILT_SYSCOUNT;
+               if (wakeone[wake_filter] == 0 ||
+                   !(kn->kn_flags & EV_WAKEONE)) {
+                       if (filter_event(kn, hint)) {
+                               KNOTE_ACTIVATE(kn);
+                               if (kn->kn_flags & EV_WAKEONE)
+                                       wakeone[wake_filter] = 1;
+                       }
+               }
+       }
        lwkt_reltoken(&kq_token);
 }

diff --git a/sys/sys/event.h b/sys/sys/event.h
index f0d20b7..cf76cfb 100644
--- a/sys/sys/event.h
+++ b/sys/sys/event.h
@@ -81,6 +81,7 @@ struct kevent {
 /* flags */
 #define EV_ONESHOT     0x0010          /* only report one occurrence */
 #define EV_CLEAR       0x0020          /* clear event state after reporting */
+#define EV_WAKEONE     0x0040          /* only wake a single WAKEONE listener */

 #define EV_SYSFLAGS    0xF000          /* reserved by system */
 #define EV_FLAG1       0x2000          /* filter-specific flag */