To prevent an infinite loop, threads looking for events inside
kqueue_scan(), insert a `marker' in the list. Such markers are
not accounted and they are removed from the list as soon as the
thread is finished or goes to sleep.
Diff below is a small cleanup to keep the accounting of events in
sync with the number of events on the list. This is a noop for the
moment, but it's small & easy part to review of my upcoming diff.
ok?
Index: kern/kern_event.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_event.c,v
retrieving revision 1.79
diff -u -p -r1.79 kern_event.c
--- kern/kern_event.c 31 May 2017 14:52:05 -0000 1.79
+++ kern/kern_event.c 9 Oct 2017 09:57:54 -0000
@@ -760,22 +760,24 @@ start:
TAILQ_INSERT_TAIL(&kq->kq_head, &marker, kn_tqe);
while (count) {
kn = TAILQ_FIRST(&kq->kq_head);
- TAILQ_REMOVE(&kq->kq_head, kn, kn_tqe);
if (kn == &marker) {
+ TAILQ_REMOVE(&kq->kq_head, kn, kn_tqe);
splx(s);
if (count == maxevents)
goto retry;
goto done;
}
+
+ TAILQ_REMOVE(&kq->kq_head, kn, kn_tqe);
+ kq->kq_count--;
+
if (kn->kn_status & KN_DISABLED) {
kn->kn_status &= ~KN_QUEUED;
- kq->kq_count--;
continue;
}
if ((kn->kn_flags & EV_ONESHOT) == 0 &&
kn->kn_fop->f_event(kn, 0) == 0) {
kn->kn_status &= ~(KN_QUEUED | KN_ACTIVE);
- kq->kq_count--;
continue;
}
*kevp = kn->kn_kevent;
@@ -783,7 +785,6 @@ start:
nkev++;
if (kn->kn_flags & EV_ONESHOT) {
kn->kn_status &= ~KN_QUEUED;
- kq->kq_count--;
splx(s);
kn->kn_fop->f_detach(kn);
knote_drop(kn, p, p->p_fd);
@@ -796,9 +797,9 @@ start:
if (kn->kn_flags & EV_DISPATCH)
kn->kn_status |= KN_DISABLED;
kn->kn_status &= ~(KN_QUEUED | KN_ACTIVE);
- kq->kq_count--;
} else {
TAILQ_INSERT_TAIL(&kq->kq_head, kn, kn_tqe);
+ kq->kq_count++;
}
count--;
if (nkev == KQ_NEVENTS) {