diff options
| author | Kyle Evans <kevans@FreeBSD.org> | 2026-04-01 22:30:48 +0000 |
|---|---|---|
| committer | Kyle Evans <kevans@FreeBSD.org> | 2026-04-01 22:30:48 +0000 |
| commit | ff1050d2a366bd288a6ebbf63f98003272513f92 (patch) | |
| tree | 5415ba285cfb7cb0ca8b0a5675d7d8e7d5da2c44 | |
| parent | 14d0baf2e89202cec3f9cb03a573372ccbc568b2 (diff) | |
kqueue: simplify knote_fdclose()
The influx logic in knote_fdclose() is a little misguided, the resulting
wakeup() call should always be redundant: knote_drop_detached() will
always issue a wakeup before it returns, so anything waiting on *that*
knote that had entered fluxwait should have been woken up then. This is
the obvious divergence from the other influx/wakeup pattern in the
implementation, which will kn_influx-- and then issue the wakeup after
it has processed all of the knotes it can make progress on.
While we're here, the kq_knlist cannot shrink, so we can avoid that
condition in the loop and avoid potentially excessive wakeups from
fluxwait on kqueues that we didn't touch.
Reviewed by: kib, markj
Differential Revision: https://reviews.freebsd.org/D56210
| -rw-r--r-- | sys/kern/kern_event.c | 22 |
1 files changed, 12 insertions, 10 deletions
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index 6af53cf6cd91..485123989319 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -2836,7 +2836,6 @@ knote_fdclose(struct thread *td, int fd) struct filedesc *fdp = td->td_proc->p_fd; struct kqueue *kq; struct knote *kn; - int influx; FILEDESC_XLOCK_ASSERT(fdp); @@ -2846,22 +2845,25 @@ knote_fdclose(struct thread *td, int fd) */ TAILQ_FOREACH(kq, &fdp->fd_kqlist, kq_list) { KQ_LOCK(kq); + if (kq->kq_knlistsize <= fd || + SLIST_EMPTY(&kq->kq_knlist[fd])) { + KQ_UNLOCK(kq); + continue; + } -again: - influx = 0; - while (kq->kq_knlistsize > fd && - (kn = SLIST_FIRST(&kq->kq_knlist[fd])) != NULL) { + while ((kn = SLIST_FIRST(&kq->kq_knlist[fd])) != NULL) { if (kn_in_flux(kn)) { - /* someone else might be waiting on our knote */ - if (influx) - wakeup(kq); + /* + * Wait for this knote to stabilize, it could be + * the case that it's in the process of being + * dropped anyways. + */ kq->kq_state |= KQ_FLUXWAIT; msleep(kq, &kq->kq_lock, PSOCK, "kqflxwt", 0); - goto again; + continue; } kn_enter_flux(kn); KQ_UNLOCK(kq); - influx = 1; knote_drop(kn, td); KQ_LOCK(kq); } |
