git: c6dd40f2d35d - main - kqueue: slightly clarify the flow in knlist_cleardel()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 09 Apr 2026 02:37:34 UTC
The branch main has been updated by kevans:
URL: https://cgit.FreeBSD.org/src/commit/?id=c6dd40f2d35d596ca60a5d87616c3e4a0fd4f676
commit c6dd40f2d35d596ca60a5d87616c3e4a0fd4f676
Author: Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2026-04-09 02:37:00 +0000
Commit: Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2026-04-09 02:37:11 +0000
kqueue: slightly clarify the flow in knlist_cleardel()
This is purely a cosmetic change to make it a little easier on the eyes,
rather than jumping back to the else branch up top. Re-flow it to use
another loop on the outside and just inline the re-lock before we repeat
after awaking from fluxwait.
The !killkn path should maybe issue a wakeup if there's a thread in
KQ_SLEEP so that userland can observe the EOF, but this isn't a
practical problem today: pretty much every case of knlist_clear is tied
to a file descriptor and called in the close(2) path. As a consequence,
potentially affected knotes are almost always destroyed before we even
get to knlist_clear().
Reviewed by: kib, markj
Differential Revision: https://reviews.freebsd.org/D56226
---
sys/kern/kern_event.c | 50 +++++++++++++++++++++++++++++---------------------
1 file changed, 29 insertions(+), 21 deletions(-)
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index 1deb7a705c56..01731ca46b6b 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -2792,31 +2792,39 @@ knlist_cleardel(struct knlist *knl, struct thread *td, int islocked, int killkn)
KNL_ASSERT_LOCKED(knl);
else {
KNL_ASSERT_UNLOCKED(knl);
-again: /* need to reacquire lock since we have dropped it */
knl->kl_lock(knl->kl_lockarg);
}
- SLIST_FOREACH_SAFE(kn, &knl->kl_list, kn_selnext, kn2) {
- kq = kn->kn_kq;
- KQ_LOCK(kq);
- if (kn_in_flux(kn)) {
- KQ_UNLOCK(kq);
- continue;
- }
- knlist_remove_kq(knl, kn, 1, 1);
- if (killkn) {
- kn_enter_flux(kn);
- KQ_UNLOCK(kq);
- knote_drop_detached(kn, td);
- } else {
- /* Make sure cleared knotes disappear soon */
- kn->kn_flags |= EV_EOF | EV_ONESHOT;
- KQ_UNLOCK(kq);
+ for (;;) {
+ /*
+ * Each pass removes as many knotes as we can before dropping
+ * into FLUXWAIT. Active knotes are simply detached and either
+ * freed or converted to one-shot, as the attached subject is
+ * essentially disappearing.
+ */
+ SLIST_FOREACH_SAFE(kn, &knl->kl_list, kn_selnext, kn2) {
+ kq = kn->kn_kq;
+ KQ_LOCK(kq);
+ if (kn_in_flux(kn)) {
+ KQ_UNLOCK(kq);
+ continue;
+ }
+ knlist_remove_kq(knl, kn, 1, 1);
+ if (killkn) {
+ kn_enter_flux(kn);
+ KQ_UNLOCK(kq);
+ knote_drop_detached(kn, td);
+ } else {
+ /* Make sure cleared knotes disappear soon */
+ kn->kn_flags |= EV_EOF | EV_ONESHOT;
+ KQ_UNLOCK(kq);
+ }
+ kq = NULL;
}
- kq = NULL;
- }
- if (!SLIST_EMPTY(&knl->kl_list)) {
+ if (SLIST_EMPTY(&knl->kl_list))
+ break;
+
/* there are still in flux knotes remaining */
kn = SLIST_FIRST(&knl->kl_list);
kq = kn->kn_kq;
@@ -2826,7 +2834,7 @@ again: /* need to reacquire lock since we have dropped it */
kq->kq_state |= KQ_FLUXWAIT;
msleep(kq, &kq->kq_lock, PSOCK | PDROP, "kqkclr", 0);
kq = NULL;
- goto again;
+ knl->kl_lock(knl->kl_lockarg);
}
if (islocked)