summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_event.c
diff options
context:
space:
mode:
authorgreen <green@FreeBSD.org>2004-08-16 03:08:38 +0000
committergreen <green@FreeBSD.org>2004-08-16 03:08:38 +0000
commit99deda206a35ed06d1d8fef339557383b8220880 (patch)
treef59fe8ca20d4db814db121e19b7f2cb95780ea42 /sys/kern/kern_event.c
parent382c9ac35742bd991cb011d96e824555a1aed06e (diff)
downloadFreeBSD-src-99deda206a35ed06d1d8fef339557383b8220880.zip
FreeBSD-src-99deda206a35ed06d1d8fef339557383b8220880.tar.gz
Allocate the marker, when scanning a kqueue, from the "heap" instead of the
stack. When swapped out, a process's kernel stack would be unavailable, and we could get a page fault when scanning the same kqueue. PR: kern/61849
Diffstat (limited to 'sys/kern/kern_event.c')
-rw-r--r--sys/kern/kern_event.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index d7949a7..978513a 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -1050,7 +1050,7 @@ kqueue_scan(struct kqueue *kq, int maxevents, struct kevent *ulistp,
{
struct kevent *kevp;
struct timeval atv, rtv, ttv;
- struct knote *kn, marker;
+ struct knote *kn, *marker;
int count, timeout, nkev, error;
int haskqglobal;
@@ -1058,7 +1058,6 @@ kqueue_scan(struct kqueue *kq, int maxevents, struct kevent *ulistp,
nkev = 0;
error = 0;
haskqglobal = 0;
- marker.kn_status = KN_MARKER;
if (maxevents == 0)
goto done_nl;
@@ -1081,6 +1080,12 @@ kqueue_scan(struct kqueue *kq, int maxevents, struct kevent *ulistp,
atv.tv_usec = 0;
timeout = 0;
}
+ marker = knote_alloc(1);
+ if (marker == NULL) {
+ error = ENOMEM;
+ goto done_nl;
+ }
+ marker->kn_status = KN_MARKER;
KQ_LOCK(kq);
goto start;
@@ -1115,12 +1120,12 @@ start:
goto done;
}
- TAILQ_INSERT_TAIL(&kq->kq_head, &marker, kn_tqe);
+ TAILQ_INSERT_TAIL(&kq->kq_head, marker, kn_tqe);
while (count) {
KQ_OWNED(kq);
kn = TAILQ_FIRST(&kq->kq_head);
- if ((kn->kn_status == KN_MARKER && kn != &marker) ||
+ if ((kn->kn_status == KN_MARKER && kn != marker) ||
(kn->kn_status & KN_INFLUX) == KN_INFLUX) {
kq->kq_state |= KQ_FLUXWAIT;
error = msleep(kq, &kq->kq_lock, PSOCK,
@@ -1134,7 +1139,7 @@ start:
kq->kq_count--;
continue;
}
- if (kn == &marker) {
+ if (kn == marker) {
KQ_FLUX_WAKEUP(kq);
if (count == maxevents)
goto retry;
@@ -1200,11 +1205,12 @@ start:
break;
}
}
- TAILQ_REMOVE(&kq->kq_head, &marker, kn_tqe);
+ TAILQ_REMOVE(&kq->kq_head, marker, kn_tqe);
done:
KQ_OWNED(kq);
KQ_UNLOCK_FLUX(kq);
KQ_GLOBAL_UNLOCK(&kq_global, haskqglobal);
+ knote_free(marker);
done_nl:
KQ_NOTOWNED(kq);
if (nkev != 0)
OpenPOWER on IntegriCloud