Source-Changes-HG archive

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

[src/trunk]: src/sys/kern - Don't use a separate kqueue_timer_lock; just prot...



details:   https://anonhg.NetBSD.org/src/rev/571047d2eadd
branches:  trunk
changeset: 989940:571047d2eadd
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Thu Oct 21 00:54:15 2021 +0000

description:
- Don't use a separate kqueue_timer_lock; just protect those knotes
  with the kq->kq_lock.
- Re-factor the guts of knote_activate() into knote_activate_locked(),
  and use it in a few places to avoid a few unlock-the-immediately-lock
  cycles.
- Define a FILT_TIMER_NOSCHED macro, rather than hard-coding (uintptr_t)-1
  in a bunch of difference place.

NFC.

diffstat:

 sys/kern/kern_event.c |  70 ++++++++++++++++++++++++++------------------------
 1 files changed, 36 insertions(+), 34 deletions(-)

diffs (196 lines):

diff -r cd978844bd26 -r 571047d2eadd sys/kern/kern_event.c
--- a/sys/kern/kern_event.c     Thu Oct 21 00:09:28 2021 +0000
+++ b/sys/kern/kern_event.c     Thu Oct 21 00:54:15 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_event.c,v 1.132 2021/10/13 04:57:19 thorpej Exp $ */
+/*     $NetBSD: kern_event.c,v 1.133 2021/10/21 00:54:15 thorpej Exp $ */
 
 /*-
  * Copyright (c) 2008, 2009, 2021 The NetBSD Foundation, Inc.
@@ -63,7 +63,7 @@
 #endif /* _KERNEL_OPT */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_event.c,v 1.132 2021/10/13 04:57:19 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_event.c,v 1.133 2021/10/21 00:54:15 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -101,6 +101,7 @@
 static void    knote_detach(struct knote *, filedesc_t *fdp, bool);
 static void    knote_enqueue(struct knote *);
 static void    knote_activate(struct knote *);
+static void    knote_activate_locked(struct knote *);
 
 static void    filt_kqdetach(struct knote *);
 static int     filt_kqueue(struct knote *, long hint);
@@ -273,7 +274,6 @@
  * KM_SLEEP is not).
  */
 static krwlock_t       kqueue_filter_lock;     /* lock on filter lists */
-static kmutex_t                kqueue_timer_lock;      /* for EVFILT_TIMER */
 
 #define        KQ_FLUX_WAIT(kq)        (void)cv_wait(&kq->kq_cv, &kq->kq_lock)
 #define        KQ_FLUX_WAKEUP(kq)      cv_broadcast(&kq->kq_cv)
@@ -514,7 +514,6 @@
 {
 
        rw_init(&kqueue_filter_lock);
-       mutex_init(&kqueue_timer_lock, MUTEX_DEFAULT, IPL_SOFTCLOCK);
 
        kqueue_listener = kauth_listen_scope(KAUTH_SCOPE_PROCESS,
            kqueue_listener_cb, NULL);
@@ -877,10 +876,10 @@
                kq = kn->kn_kq;
                mutex_spin_enter(&kq->kq_lock);
                fflags = (kn->kn_fflags |= (kn->kn_sfflags & NOTE_EXEC));
+               if (fflags) {
+                       knote_activate_locked(kn);
+               }
                mutex_spin_exit(&kq->kq_lock);
-               if (fflags) {
-                       knote_activate(kn);
-               }
        }
 
        mutex_exit(p->p_lock);
@@ -1095,10 +1094,10 @@
                        KASSERT(mutex_owned(&kq->kq_lock));
                }
                fflags = kn->kn_fflags;
+               if (fflags) {
+                       knote_activate_locked(kn);
+               }
                mutex_spin_exit(&kq->kq_lock);
-               if (fflags) {
-                       knote_activate(kn);
-               }
        }
 
        mutex_exit(p1->p_lock);
@@ -1141,31 +1140,34 @@
                        kn->kn_status |= KN_DETACHED;
                        SLIST_REMOVE_HEAD(&p->p_klist, kn_selnext);
                }
-               mutex_spin_exit(&kq->kq_lock);
 
                /*
                 * Always activate the knote for NOTE_EXIT regardless
                 * of whether or not the listener cares about it.
                 * This matches historical behavior.
                 */
-               knote_activate(kn);
+               knote_activate_locked(kn);
+               mutex_spin_exit(&kq->kq_lock);
        }
 }
 
+#define        FILT_TIMER_NOSCHED      ((uintptr_t)-1)
+
 static void
 filt_timerexpire(void *knx)
 {
        struct knote *kn = knx;
+       struct kqueue *kq = kn->kn_kq;
 
-       mutex_enter(&kqueue_timer_lock);
+       mutex_spin_enter(&kq->kq_lock);
        kn->kn_data++;
-       knote_activate(kn);
-       if (kn->kn_sdata != (uintptr_t)-1) {
+       knote_activate_locked(kn);
+       if (kn->kn_sdata != FILT_TIMER_NOSCHED) {
                KASSERT(kn->kn_sdata > 0 && kn->kn_sdata <= INT_MAX);
                callout_schedule((callout_t *)kn->kn_hook,
                    (int)kn->kn_sdata);
        }
-       mutex_exit(&kqueue_timer_lock);
+       mutex_spin_exit(&kq->kq_lock);
 }
 
 static int
@@ -1245,9 +1247,9 @@
        if ((kn->kn_flags & EV_ONESHOT) != 0 ||
            (kn->kn_sfflags & NOTE_ABSTIME) != 0) {
                /* Timer does not repeat. */
-               kn->kn_sdata = (uintptr_t)-1;
+               kn->kn_sdata = FILT_TIMER_NOSCHED;
        } else {
-               KASSERT((uintptr_t)tticks != (uintptr_t)-1);
+               KASSERT((uintptr_t)tticks != FILT_TIMER_NOSCHED);
                kn->kn_sdata = tticks;
        }
 
@@ -1275,17 +1277,9 @@
        callout_t *calloutp;
        struct kqueue *kq = kn->kn_kq;
 
-       /*
-        * We don't need to hold the kqueue_timer_lock here; even
-        * if filt_timerexpire() misses our setting of EV_ONESHOT,
-        * we are guaranteed that the callout will no longer be
-        * scheduled even if we attempted to halt it after it already
-        * started running, even if it rescheduled itself.
-        */
-
+       /* prevent rescheduling when we expire */
        mutex_spin_enter(&kq->kq_lock);
-       /* prevent rescheduling when we expire */
-       kn->kn_flags |= EV_ONESHOT;
+       kn->kn_sdata = FILT_TIMER_NOSCHED;
        mutex_spin_exit(&kq->kq_lock);
 
        calloutp = (callout_t *)kn->kn_hook;
@@ -1304,11 +1298,12 @@
 static int
 filt_timer(struct knote *kn, long hint)
 {
+       struct kqueue *kq = kn->kn_kq;
        int rv;
 
-       mutex_enter(&kqueue_timer_lock);
+       mutex_spin_enter(&kq->kq_lock);
        rv = (kn->kn_data != 0);
-       mutex_exit(&kqueue_timer_lock);
+       mutex_spin_exit(&kq->kq_lock);
 
        return rv;
 }
@@ -2613,7 +2608,7 @@
  * Queue new event for knote.
  */
 static void
-knote_activate(struct knote *kn)
+knote_activate_locked(struct knote *kn)
 {
        struct kqueue *kq;
 
@@ -2621,10 +2616,9 @@
 
        kq = kn->kn_kq;
 
-       mutex_spin_enter(&kq->kq_lock);
        if (__predict_false(kn->kn_status & KN_WILLDETACH)) {
                /* Don't bother enqueueing a dying knote. */
-               goto out;
+               return;
        }
        kn->kn_status |= KN_ACTIVE;
        if ((kn->kn_status & (KN_QUEUED | KN_DISABLED)) == 0) {
@@ -2637,7 +2631,15 @@
                cv_broadcast(&kq->kq_cv);
                selnotify(&kq->kq_sel, 0, NOTE_SUBMIT);
        }
- out:
+}
+
+static void
+knote_activate(struct knote *kn)
+{
+       struct kqueue *kq = kn->kn_kq;
+
+       mutex_spin_enter(&kq->kq_lock);
+       knote_activate_locked(kn);
        mutex_spin_exit(&kq->kq_lock);
 }
 



Home | Main Index | Thread Index | Old Index