Module Name: src
Committed By: jdolecek
Date: Mon Jan 25 19:57:05 UTC 2021
Modified Files:
src/sys/kern: kern_event.c
Log Message:
put back clearing of KN_QUEUED and check for re-queue - as rev. 1.53 notes,
it's necessary for correct function
fixes PR kern/55946, thanks to Paul Goyette for testing
part of PR kern/50094 fix
To generate a diff of this commit:
cvs rdiff -u -r1.114 -r1.115 src/sys/kern/kern_event.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/kern/kern_event.c
diff -u src/sys/kern/kern_event.c:1.114 src/sys/kern/kern_event.c:1.115
--- src/sys/kern/kern_event.c:1.114 Sun Jan 24 11:31:47 2021
+++ src/sys/kern/kern_event.c Mon Jan 25 19:57:05 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_event.c,v 1.114 2021/01/24 11:31:47 jdolecek Exp $ */
+/* $NetBSD: kern_event.c,v 1.115 2021/01/25 19:57:05 jdolecek Exp $ */
/*-
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -59,7 +59,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_event.c,v 1.114 2021/01/24 11:31:47 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_event.c,v 1.115 2021/01/25 19:57:05 jdolecek Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -1487,11 +1487,12 @@ relock:
KASSERT((kn->kn_status & KN_BUSY) == 0);
kq_check(kq);
+ kn->kn_status &= ~KN_QUEUED;
kn->kn_status |= KN_BUSY;
kq_check(kq);
if (kn->kn_status & KN_DISABLED) {
+ kn->kn_status &= ~KN_BUSY;
kq->kq_count--;
- kn->kn_status &= ~(KN_QUEUED|KN_BUSY);
/* don't want disabled events */
continue;
}
@@ -1504,12 +1505,20 @@ relock:
rv = (*kn->kn_fop->f_event)(kn, 0);
KERNEL_UNLOCK_ONE(NULL); /* XXXSMP */
mutex_spin_enter(&kq->kq_lock);
+ /* Re-poll if note was re-enqueued. */
+ if ((kn->kn_status & KN_QUEUED) != 0) {
+ kn->kn_status &= ~KN_BUSY;
+ /* Re-enqueue raised kq_count, lower it again */
+ kq->kq_count--;
+ influx = 1;
+ continue;
+ }
if (rv == 0) {
/*
* non-ONESHOT event that hasn't
* triggered again, so de-queue.
*/
- kn->kn_status &= ~(KN_QUEUED|KN_ACTIVE|KN_BUSY);
+ kn->kn_status &= ~(KN_ACTIVE|KN_BUSY);
kq->kq_count--;
influx = 1;
continue;
@@ -1533,7 +1542,7 @@ relock:
influx = 1;
if (kn->kn_flags & EV_ONESHOT) {
/* delete ONESHOT events after retrieval */
- kn->kn_status &= ~(KN_QUEUED|KN_BUSY);
+ kn->kn_status &= ~KN_BUSY;
kq->kq_count--;
mutex_spin_exit(&kq->kq_lock);
knote_detach(kn, fdp, true);
@@ -1551,15 +1560,16 @@ relock:
kn->kn_data = 0;
kn->kn_fflags = 0;
}
- kn->kn_status &= ~(KN_QUEUED|KN_ACTIVE|KN_BUSY);
+ kn->kn_status &= ~(KN_ACTIVE|KN_BUSY);
kq->kq_count--;
} else if (kn->kn_flags & EV_DISPATCH) {
kn->kn_status |= KN_DISABLED;
- kn->kn_status &= ~(KN_QUEUED|KN_ACTIVE|KN_BUSY);
+ kn->kn_status &= ~(KN_ACTIVE|KN_BUSY);
kq->kq_count--;
} else {
/* add event back on list */
kq_check(kq);
+ kn->kn_status |= KN_QUEUED;
kn->kn_status &= ~KN_BUSY;
TAILQ_INSERT_TAIL(&kq->kq_head, kn, kn_tqe);
kq_check(kq);