diff options
-rw-r--r-- | sys/kern/kern_event.c | 25 | ||||
-rw-r--r-- | sys/sys/eventvar.h | 5 |
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 |