Source-Changes-HG archive

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

[src/trunk]: src/sys/kern - Rename kqueue_misc_lock -> kqueue_timer_lock, sin...



details:   https://anonhg.NetBSD.org/src/rev/8092f88377af
branches:  trunk
changeset: 987461:8092f88377af
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Sun Sep 26 23:34:46 2021 +0000

description:
- Rename kqueue_misc_lock -> kqueue_timer_lock, since EVFILT_TIMER is
  now its only user.  Also initialize it as IPL_SOFTCLOCK; there is no
  practical difference in how it operates (it is still an adaptive lock),
  but this serves as a visual reminder that we are interlocking against
  a callout.
- Add some comments that describe why we don't need to hold kqueue_timer_lock
  when detaching an EVFILT_TIMER due to guarantees made by callout_halt().
- Mark timer_filtops as MPSAFE.

diffstat:

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

diffs (112 lines):

diff -r ca0245277278 -r 8092f88377af sys/kern/kern_event.c
--- a/sys/kern/kern_event.c     Sun Sep 26 21:32:58 2021 +0000
+++ b/sys/kern/kern_event.c     Sun Sep 26 23:34:46 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_event.c,v 1.124 2021/09/26 21:29:38 thorpej Exp $ */
+/*     $NetBSD: kern_event.c,v 1.125 2021/09/26 23:34:46 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.124 2021/09/26 21:29:38 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_event.c,v 1.125 2021/09/26 23:34:46 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -154,7 +154,7 @@
 };
 
 static const struct filterops timer_filtops = {
-       .f_flags = 0,
+       .f_flags = FILTEROP_MPSAFE,
        .f_attach = filt_timerattach,
        .f_detach = filt_timerdetach,
        .f_event = filt_timer,
@@ -222,7 +222,7 @@
  *
  *     kqueue_filter_lock
  *     -> kn_kq->kq_fdp->fd_lock
- *     -> object lock (e.g., device driver lock, kqueue_misc_lock, &c.)
+ *     -> object lock (e.g., device driver lock, &c.)
  *     -> kn_kq->kq_lock
  *
  * Locking rules:
@@ -236,7 +236,7 @@
  *                                     acquires/releases object lock inside.
  */
 static krwlock_t       kqueue_filter_lock;     /* lock on filter lists */
-static kmutex_t                kqueue_misc_lock;       /* miscellaneous */
+static kmutex_t                kqueue_timer_lock;      /* for EVFILT_TIMER */
 
 static int
 filter_attach(struct knote *kn)
@@ -333,7 +333,7 @@
 {
 
        rw_init(&kqueue_filter_lock);
-       mutex_init(&kqueue_misc_lock, MUTEX_DEFAULT, IPL_NONE);
+       mutex_init(&kqueue_timer_lock, MUTEX_DEFAULT, IPL_SOFTCLOCK);
 
        kqueue_listener = kauth_listen_scope(KAUTH_SCOPE_PROCESS,
            kqueue_listener_cb, NULL);
@@ -735,7 +735,7 @@
        struct knote *kn = knx;
        int tticks;
 
-       mutex_enter(&kqueue_misc_lock);
+       mutex_enter(&kqueue_timer_lock);
        kn->kn_data++;
        knote_activate(kn);
        if ((kn->kn_flags & EV_ONESHOT) == 0) {
@@ -744,7 +744,7 @@
                        tticks = 1;
                callout_schedule((callout_t *)kn->kn_hook, tticks);
        }
-       mutex_exit(&kqueue_misc_lock);
+       mutex_exit(&kqueue_timer_lock);
 }
 
 /*
@@ -790,13 +790,27 @@
        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.
+        */
+
        mutex_spin_enter(&kq->kq_lock);
        /* prevent rescheduling when we expire */
        kn->kn_flags |= EV_ONESHOT;
        mutex_spin_exit(&kq->kq_lock);
 
        calloutp = (callout_t *)kn->kn_hook;
+
+       /*
+        * Attempt to stop the callout.  This will block if it's
+        * already running.
+        */
        callout_halt(calloutp, NULL);
+
        callout_destroy(calloutp);
        kmem_free(calloutp, sizeof(*calloutp));
        atomic_dec_uint(&kq_ncallouts);
@@ -807,9 +821,9 @@
 {
        int rv;
 
-       mutex_enter(&kqueue_misc_lock);
+       mutex_enter(&kqueue_timer_lock);
        rv = (kn->kn_data != 0);
-       mutex_exit(&kqueue_misc_lock);
+       mutex_exit(&kqueue_timer_lock);
 
        return rv;
 }



Home | Main Index | Thread Index | Old Index