Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys - Define a new filterops flag FILTEROP_MPSAFE, which sta...



details:   https://anonhg.NetBSD.org/src/rev/23ee4531f851
branches:  trunk
changeset: 1023777:23ee4531f851
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Sun Sep 26 03:12:50 2021 +0000

description:
- 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.

diffstat:

 sys/kern/kern_event.c |  102 +++++++++++++++++++++++++++++++++++++++----------
 sys/sys/event.h       |    3 +-
 2 files changed, 83 insertions(+), 22 deletions(-)

diffs (190 lines):

diff -r a3b44f38b442 -r 23ee4531f851 sys/kern/kern_event.c
--- a/sys/kern/kern_event.c     Sun Sep 26 01:28:43 2021 +0000
+++ b/sys/kern/kern_event.c     Sun Sep 26 03:12:50 2021 +0000
@@ -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 @@
        .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 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 @@
                        }
                        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 @@
        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 @@
         * 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 @@
                }
                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 @@
                                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 @@
        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. */
diff -r a3b44f38b442 -r 23ee4531f851 sys/sys/event.h
--- a/sys/sys/event.h   Sun Sep 26 01:28:43 2021 +0000
+++ b/sys/sys/event.h   Sun Sep 26 03:12:50 2021 +0000
@@ -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 <jlemon%FreeBSD.org@localhost>
@@ -221,6 +221,7 @@
 
 /* filterops flags */
 #define        FILTEROP_ISFD   __BIT(0)        /* ident == file descriptor */
+#define        FILTEROP_MPSAFE __BIT(1)        /* does not require KERNEL_LOCK */
 
 /*
  * Field locking:



Home | Main Index | Thread Index | Old Index