summaryrefslogtreecommitdiffstats
path: root/sys/sys/event.h
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2014-04-05 14:09:16 +0000
committerkib <kib@FreeBSD.org>2014-04-05 14:09:16 +0000
commite965005b685fc6937753e4eceeaa74cdff56ee0c (patch)
tree972e4dfe819e13e02e9e7730f613d2d675c5073d /sys/sys/event.h
parentdd28e6bbc0ebb901c5b00356af4645a9bc9c7b3b (diff)
downloadFreeBSD-src-e965005b685fc6937753e4eceeaa74cdff56ee0c.zip
FreeBSD-src-e965005b685fc6937753e4eceeaa74cdff56ee0c.tar.gz
When KN_INFLUX is set on the knote due to kqueue_register() or
kqueue_scan() unlocking the kqueue to call f_event, knote() or knote_fork() should not skip the knote. The knote is not going to disappear during the influx time, and the mutual exclusion between scan and knote() is ensured by both code pathes taking knlist lock. The race appears since knlist lock is before kq lock, so KN_INFLUX must be set, kq lock must be dropped and only then knlist lock can be taken. The window between kq unlock and knlist lock causes lost events. Add a flag KN_SCAN to indicate that KN_INFLUX is set in a manner safe for the knote(), and check for it to ignore KN_INFLUX in the knote*() as needed. Also, in knote(), remove the lockless check for the KN_INFLUX flag, which could also result in the lost notification. Reported and tested by: Kohji Okuno <okuno.kohji@jp.panasonic.com> Discussed with: jmg Sponsored by: The FreeBSD Foundation MFC after: 1 week
Diffstat (limited to 'sys/sys/event.h')
-rw-r--r--sys/sys/event.h1
1 files changed, 1 insertions, 0 deletions
diff --git a/sys/sys/event.h b/sys/sys/event.h
index bad8c9e..3b765c0 100644
--- a/sys/sys/event.h
+++ b/sys/sys/event.h
@@ -207,6 +207,7 @@ struct knote {
#define KN_MARKER 0x20 /* ignore this knote */
#define KN_KQUEUE 0x40 /* this knote belongs to a kq */
#define KN_HASKQLOCK 0x80 /* for _inevent */
+#define KN_SCAN 0x100 /* flux set in kqueue_scan() */
int kn_sfflags; /* saved filter flags */
intptr_t kn_sdata; /* saved data field */
union {
OpenPOWER on IntegriCloud