diff options
author | Stanislav Sedov <stas@FreeBSD.org> | 2009-06-28 21:49:43 +0000 |
---|---|---|
committer | Stanislav Sedov <stas@FreeBSD.org> | 2009-06-28 21:49:43 +0000 |
commit | fe1d3f15f6b68135ca25a5c67caf135cd137e435 (patch) | |
tree | 022e59bcdde11f99bd112a6b3f3fb767e6be937c /sys/kern/kern_event.c | |
parent | f551adb0a94b0e9a6221b4c26b2e29e18321fc8c (diff) | |
download | src-fe1d3f15f6b68135ca25a5c67caf135cd137e435.tar.gz src-fe1d3f15f6b68135ca25a5c67caf135cd137e435.zip |
- Turn the third (islocked) argument of the knote call into flags parameter.
Introduce the new flag KNF_NOKQLOCK to allow event callers to be called
without KQ_LOCK mtx held.
- Modify VFS knote calls to always use KNF_NOKQLOCK flag. This is required
for ZFS as its getattr implementation may sleep.
Approved by: re (rwatson)
Reviewed by: kib
MFC after: 2 weeks
Notes
Notes:
svn path=/head/; revision=195148
Diffstat (limited to 'sys/kern/kern_event.c')
-rw-r--r-- | sys/kern/kern_event.c | 24 |
1 files changed, 18 insertions, 6 deletions
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index 17157418654a..6603d110c23f 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -1606,17 +1606,18 @@ kqueue_wakeup(struct kqueue *kq) * first. */ void -knote(struct knlist *list, long hint, int islocked) +knote(struct knlist *list, long hint, int lockflags) { struct kqueue *kq; struct knote *kn; + int error; if (list == NULL) return; - KNL_ASSERT_LOCK(list, islocked); + KNL_ASSERT_LOCK(list, lockflags & KNF_LISTLOCKED); - if (!islocked) + if ((lockflags & KNF_LISTLOCKED) == 0) list->kl_lock(list->kl_lockarg); /* @@ -1631,17 +1632,28 @@ knote(struct knlist *list, long hint, int islocked) kq = kn->kn_kq; if ((kn->kn_status & KN_INFLUX) != KN_INFLUX) { KQ_LOCK(kq); - if ((kn->kn_status & KN_INFLUX) != KN_INFLUX) { + if ((kn->kn_status & KN_INFLUX) == KN_INFLUX) { + KQ_UNLOCK(kq); + } else if ((lockflags & KNF_NOKQLOCK) != 0) { + kn->kn_status |= KN_INFLUX; + KQ_UNLOCK(kq); + error = kn->kn_fop->f_event(kn, hint); + KQ_LOCK(kq); + kn->kn_status &= ~KN_INFLUX; + if (error) + KNOTE_ACTIVATE(kn, 1); + KQ_UNLOCK_FLUX(kq); + } else { kn->kn_status |= KN_HASKQLOCK; if (kn->kn_fop->f_event(kn, hint)) KNOTE_ACTIVATE(kn, 1); kn->kn_status &= ~KN_HASKQLOCK; + KQ_UNLOCK(kq); } - KQ_UNLOCK(kq); } kq = NULL; } - if (!islocked) + if ((lockflags & KNF_LISTLOCKED) == 0) list->kl_unlock(list->kl_lockarg); } |