Module Name: src
Committed By: thorpej
Date: Sun Sep 26 03:12:50 UTC 2021
Modified Files:
src/sys/kern: kern_event.c
src/sys/sys: event.h
Log Message:
- Define a new filterops flag FILTEROP_MPSAFE, which states that the
kqueue filter does not require the KERNEL_LOCK to be held.
- Add wrappers around the calls into the filterops that take care of
the locking requirements.
No functional change, since no filterops yet define FILTEROP_MPSAFE.
To generate a diff of this commit:
cvs rdiff -u -r1.121 -r1.122 src/sys/kern/kern_event.c
cvs rdiff -u -r1.41 -r1.42 src/sys/sys/event.h
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.121 src/sys/kern/kern_event.c:1.122
--- src/sys/kern/kern_event.c:1.121 Sun Sep 26 01:16:10 2021
+++ src/sys/kern/kern_event.c Sun Sep 26 03:12:50 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_event.c,v 1.121 2021/09/26 01:16:10 thorpej Exp $ */
+/* $NetBSD: kern_event.c,v 1.122 2021/09/26 03:12:50 thorpej 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.121 2021/09/26 01:16:10 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_event.c,v 1.122 2021/09/26 03:12:50 thorpej Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -143,6 +143,12 @@ static const struct filterops proc_filto
.f_event = filt_proc,
};
+/*
+ * file_filtops is not marked MPSAFE because it's going to call
+ * fileops::fo_kqfilter(), which might not be. That function,
+ * however, will override the knote's filterops, and thus will
+ * inherit the MPSAFE-ness of the back-end at that time.
+ */
static const struct filterops file_filtops = {
.f_flags = FILTEROP_ISFD,
.f_attach = filt_fileattach,
@@ -241,6 +247,69 @@ static size_t user_kfiltersz; /* size
static krwlock_t kqueue_filter_lock; /* lock on filter lists */
static kmutex_t kqueue_misc_lock; /* miscellaneous */
+static int
+filter_attach(struct knote *kn)
+{
+ int rv;
+
+ KASSERT(kn->kn_fop != NULL);
+ KASSERT(kn->kn_fop->f_attach != NULL);
+
+ /*
+ * N.B. that kn->kn_fop may change as the result of calling
+ * f_attach().
+ */
+ if (kn->kn_fop->f_flags & FILTEROP_MPSAFE) {
+ rv = kn->kn_fop->f_attach(kn);
+ } else {
+ KERNEL_LOCK(1, NULL);
+ rv = kn->kn_fop->f_attach(kn);
+ KERNEL_UNLOCK_ONE(NULL);
+ }
+
+ return rv;
+}
+
+static void
+filter_detach(struct knote *kn)
+{
+ KASSERT(kn->kn_fop != NULL);
+ KASSERT(kn->kn_fop->f_detach != NULL);
+
+ if (kn->kn_fop->f_flags & FILTEROP_MPSAFE) {
+ kn->kn_fop->f_detach(kn);
+ } else {
+ KERNEL_LOCK(1, NULL);
+ kn->kn_fop->f_detach(kn);
+ KERNEL_UNLOCK_ONE(NULL);
+ }
+}
+
+static int
+filter_event(struct knote *kn, long hint)
+{
+ int rv;
+
+ KASSERT(kn->kn_fop != NULL);
+ KASSERT(kn->kn_fop->f_event != NULL);
+
+ if (kn->kn_fop->f_flags & FILTEROP_MPSAFE) {
+ rv = kn->kn_fop->f_event(kn, hint);
+ } else {
+ KERNEL_LOCK(1, NULL);
+ rv = kn->kn_fop->f_event(kn, hint);
+ KERNEL_UNLOCK_ONE(NULL);
+ }
+
+ return rv;
+}
+
+static void
+filter_touch(struct knote *kn, struct kevent *kev, long type)
+{
+ kn->kn_fop->f_touch(kn, kev, type);
+}
+
static kauth_listener_t kqueue_listener;
static int
@@ -1233,9 +1302,11 @@ kqueue_register(struct kqueue *kq, struc
}
SLIST_INSERT_HEAD(list, kn, kn_link);
- KERNEL_LOCK(1, NULL); /* XXXSMP */
- error = (*kfilter->filtops->f_attach)(kn);
- KERNEL_UNLOCK_ONE(NULL); /* XXXSMP */
+ /*
+ * N.B. kn->kn_fop may change as the result
+ * of filter_attach()!
+ */
+ error = filter_attach(kn);
if (error != 0) {
#ifdef DEBUG
struct proc *p = curlwp->l_proc;
@@ -1277,7 +1348,7 @@ kqueue_register(struct kqueue *kq, struc
if (!(kn->kn_fop->f_flags & FILTEROP_ISFD) &&
kn->kn_fop->f_touch != NULL) {
mutex_spin_enter(&kq->kq_lock);
- (*kn->kn_fop->f_touch)(kn, kev, EVENT_REGISTER);
+ filter_touch(kn, kev, EVENT_REGISTER);
mutex_spin_exit(&kq->kq_lock);
} else {
kn->kn_sfflags = kev->fflags;
@@ -1291,11 +1362,7 @@ kqueue_register(struct kqueue *kq, struc
* broken and does not return an error.
*/
done_ev_add:
- KASSERT(kn->kn_fop != NULL);
- KASSERT(kn->kn_fop->f_event != NULL);
- KERNEL_LOCK(1, NULL); /* XXXSMP */
- rv = (*kn->kn_fop->f_event)(kn, 0);
- KERNEL_UNLOCK_ONE(NULL); /* XXXSMP */
+ rv = filter_event(kn, 0);
if (rv)
knote_activate(kn);
@@ -1507,12 +1574,8 @@ relock:
}
if ((kn->kn_flags & EV_ONESHOT) == 0) {
mutex_spin_exit(&kq->kq_lock);
- KASSERT(kn->kn_fop != NULL);
- KASSERT(kn->kn_fop->f_event != NULL);
- KERNEL_LOCK(1, NULL); /* XXXSMP */
KASSERT(mutex_owned(&fdp->fd_lock));
- rv = (*kn->kn_fop->f_event)(kn, 0);
- KERNEL_UNLOCK_ONE(NULL); /* XXXSMP */
+ rv = filter_event(kn, 0);
mutex_spin_enter(&kq->kq_lock);
/* Re-poll if note was re-enqueued. */
if ((kn->kn_status & KN_QUEUED) != 0) {
@@ -1538,7 +1601,7 @@ relock:
kn->kn_fop->f_touch != NULL);
/* XXXAD should be got from f_event if !oneshot. */
if (touch) {
- (*kn->kn_fop->f_touch)(kn, kevp, EVENT_PROCESS);
+ filter_touch(kn, kevp, EVENT_PROCESS);
} else {
*kevp = kn->kn_kevent;
}
@@ -1872,10 +1935,7 @@ knote_detach(struct knote *kn, filedesc_
KASSERT(kn->kn_fop != NULL);
/* Remove from monitored object. */
if (dofop) {
- KASSERT(kn->kn_fop->f_detach != NULL);
- KERNEL_LOCK(1, NULL); /* XXXSMP */
- (*kn->kn_fop->f_detach)(kn);
- KERNEL_UNLOCK_ONE(NULL); /* XXXSMP */
+ filter_detach(kn);
}
/* Remove from descriptor table. */
Index: src/sys/sys/event.h
diff -u src/sys/sys/event.h:1.41 src/sys/sys/event.h:1.42
--- src/sys/sys/event.h:1.41 Sun Sep 26 01:16:10 2021
+++ src/sys/sys/event.h Sun Sep 26 03:12:50 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: event.h,v 1.41 2021/09/26 01:16:10 thorpej Exp $ */
+/* $NetBSD: event.h,v 1.42 2021/09/26 03:12:50 thorpej Exp $ */
/*-
* Copyright (c) 1999,2000,2001 Jonathan Lemon <[email protected]>
@@ -221,6 +221,7 @@ struct filterops {
/* filterops flags */
#define FILTEROP_ISFD __BIT(0) /* ident == file descriptor */
+#define FILTEROP_MPSAFE __BIT(1) /* does not require KERNEL_LOCK */
/*
* Field locking: