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
This commit is contained in:
Kyle Evans
2026-04-01 17:30:48 -05:00
parent 14d0baf2e8
commit ff1050d2a3
+12 -10
View File
@@ -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);
}