summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/kern/kern_event.c25
-rw-r--r--sys/sys/eventvar.h5
2 files changed, 26 insertions, 4 deletions
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index 8c42b479251..e2ae0fb95d8 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_event.c,v 1.123 2020/02/09 14:09:08 visa Exp $ */
+/* $OpenBSD: kern_event.c,v 1.124 2020/02/14 16:50:25 visa Exp $ */
/*-
* Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org>
@@ -72,6 +72,7 @@ void kqueue_wakeup(struct kqueue *kq);
static void kqueue_expand_hash(struct kqueue *kq);
static void kqueue_expand_list(struct kqueue *kq, int fd);
+static void kqueue_task(void *);
const struct fileops kqueueops = {
.fo_read = kqueue_read,
@@ -498,6 +499,7 @@ sys_kqueue(struct proc *p, void *v, register_t *retval)
kq->kq_refs = 1;
kq->kq_fdp = fdp;
TAILQ_INIT(&kq->kq_head);
+ task_set(&kq->kq_task, kqueue_task, kq);
fdplock(fdp);
error = falloc(p, &fp, &fd);
@@ -1061,6 +1063,10 @@ kqueue_close(struct file *fp, struct proc *p)
kq->kq_state |= KQ_DYING;
kqueue_wakeup(kq);
+
+ KASSERT(SLIST_EMPTY(&kq->kq_sel.si_note));
+ task_del(systq, &kq->kq_task);
+
KQRELE(kq);
KERNEL_UNLOCK();
@@ -1068,6 +1074,15 @@ kqueue_close(struct file *fp, struct proc *p)
return (0);
}
+static void
+kqueue_task(void *arg)
+{
+ struct kqueue *kq = arg;
+
+ KNOTE(&kq->kq_sel.si_note, 0);
+ KQRELE(kq);
+}
+
void
kqueue_wakeup(struct kqueue *kq)
{
@@ -1079,8 +1094,12 @@ kqueue_wakeup(struct kqueue *kq)
if (kq->kq_state & KQ_SEL) {
kq->kq_state &= ~KQ_SEL;
selwakeup(&kq->kq_sel);
- } else
- KNOTE(&kq->kq_sel.si_note, 0);
+ } else if (!SLIST_EMPTY(&kq->kq_sel.si_note)) {
+ /* Defer activation to avoid recursion. */
+ KQREF(kq);
+ if (!task_add(systq, &kq->kq_task))
+ KQRELE(kq);
+ }
}
static void
diff --git a/sys/sys/eventvar.h b/sys/sys/eventvar.h
index 9f70e317216..c288d49adbb 100644
--- a/sys/sys/eventvar.h
+++ b/sys/sys/eventvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: eventvar.h,v 1.7 2020/01/10 15:49:37 visa Exp $ */
+/* $OpenBSD: eventvar.h,v 1.8 2020/02/14 16:50:25 visa Exp $ */
/*-
* Copyright (c) 1999,2000 Jonathan Lemon <jlemon@FreeBSD.org>
@@ -31,6 +31,8 @@
#ifndef _SYS_EVENTVAR_H_
#define _SYS_EVENTVAR_H_
+#include <sys/task.h>
+
#define KQ_NEVENTS 8 /* minimize copy{in,out} calls */
#define KQEXTENT 256 /* linear growth by this amount */
@@ -51,6 +53,7 @@ struct kqueue {
struct klist *kq_knlist; /* list of attached knotes */
u_long kq_knhashmask; /* size of knhash */
struct klist *kq_knhash; /* hash table for attached knotes */
+ struct task kq_task; /* deferring of activation */
int kq_state;
#define KQ_SEL 0x01