aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/kern_event.c
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2008-05-10 11:37:05 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2008-05-10 11:37:05 +0000
commite15864efd81eb2c3b7e44a36874fe0ddbe2d9638 (patch)
treeb0a19b1d462442a84e999ac884cce5589c1c0243 /sys/kern/kern_event.c
parent2e711e4d0da6b15bfcf2b1dc83234b560ae1102f (diff)
downloadsrc-e15864efd81eb2c3b7e44a36874fe0ddbe2d9638.tar.gz
src-e15864efd81eb2c3b7e44a36874fe0ddbe2d9638.zip
Kqueue_scan() may sleep when encountered the influx knotes. On the other
hand, it may cause other threads to sleep since kqueue_scan() may mark some knotes as infux. This could lead to the deadlock. Before kqueue_scan() sleeps, wakeup the threads that are waiting for the influx knotes produced by this thread. Tested by: pho (previous version) Reviewed by: jmg MFC after: 2 weeks
Notes
Notes: svn path=/head/; revision=178914
Diffstat (limited to 'sys/kern/kern_event.c')
-rw-r--r--sys/kern/kern_event.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index ffd18d416120..b031fa00a76a 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -1134,7 +1134,7 @@ kqueue_scan(struct kqueue *kq, int maxevents, struct kevent_copyops *k_ops,
struct kevent *kevp;
struct timeval atv, rtv, ttv;
struct knote *kn, *marker;
- int count, timeout, nkev, error;
+ int count, timeout, nkev, error, influx;
int haskqglobal;
count = maxevents;
@@ -1204,6 +1204,7 @@ start:
}
TAILQ_INSERT_TAIL(&kq->kq_head, marker, kn_tqe);
+ influx = 0;
while (count) {
KQ_OWNED(kq);
kn = TAILQ_FIRST(&kq->kq_head);
@@ -1211,6 +1212,11 @@ start:
if ((kn->kn_status == KN_MARKER && kn != marker) ||
(kn->kn_status & KN_INFLUX) == KN_INFLUX) {
kq->kq_state |= KQ_FLUXWAIT;
+ if (influx) {
+ influx = 0;
+ KQ_FLUX_WAKEUP(kq);
+ }
+
error = msleep(kq, &kq->kq_lock, PSOCK,
"kqflxwt", 0);
continue;
@@ -1259,6 +1265,7 @@ start:
~(KN_QUEUED | KN_ACTIVE | KN_INFLUX);
kq->kq_count--;
KN_LIST_UNLOCK(kn);
+ influx = 1;
continue;
}
*kevp = kn->kn_kevent;
@@ -1274,6 +1281,7 @@ start:
kn->kn_status &= ~(KN_INFLUX);
KN_LIST_UNLOCK(kn);
+ influx = 1;
}
/* we are returning a copy to the user */
@@ -1282,6 +1290,7 @@ start:
count--;
if (nkev == KQ_NEVENTS) {
+ influx = 0;
KQ_UNLOCK_FLUX(kq);
error = k_ops->k_copyout(k_ops->arg, keva, nkev);
nkev = 0;