diff options
author | Konstantin Belousov <kib@FreeBSD.org> | 2008-05-10 11:37:05 +0000 |
---|---|---|
committer | Konstantin Belousov <kib@FreeBSD.org> | 2008-05-10 11:37:05 +0000 |
commit | e15864efd81eb2c3b7e44a36874fe0ddbe2d9638 (patch) | |
tree | b0a19b1d462442a84e999ac884cce5589c1c0243 /sys/kern/kern_event.c | |
parent | 2e711e4d0da6b15bfcf2b1dc83234b560ae1102f (diff) | |
download | src-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.c | 11 |
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; |