Source-Changes-HG archive

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

[src/trunk]: src/sys softint_disestablish(): use a high priority xcall to det...



details:   https://anonhg.NetBSD.org/src/rev/ff8ca01a30f3
branches:  trunk
changeset: 932908:ff8ca01a30f3
user:      ad <ad%NetBSD.org@localhost>
date:      Sun May 17 14:11:30 2020 +0000

description:
softint_disestablish(): use a high priority xcall to determine that the
handler is no longer running.

diffstat:

 sys/kern/kern_softint.c |  79 +++++++++++++++++-------------------------------
 sys/sys/intr.h          |   5 +-
 2 files changed, 31 insertions(+), 53 deletions(-)

diffs (227 lines):

diff -r 82c0bdcf16a9 -r ff8ca01a30f3 sys/kern/kern_softint.c
--- a/sys/kern/kern_softint.c   Sun May 17 13:49:37 2020 +0000
+++ b/sys/kern/kern_softint.c   Sun May 17 14:11:30 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_softint.c,v 1.65 2020/04/30 20:54:27 skrll Exp $  */
+/*     $NetBSD: kern_softint.c,v 1.66 2020/05/17 14:11:30 ad Exp $     */
 
 /*-
  * Copyright (c) 2007, 2008, 2019, 2020 The NetBSD Foundation, Inc.
@@ -170,7 +170,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_softint.c,v 1.65 2020/04/30 20:54:27 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_softint.c,v 1.66 2020/05/17 14:11:30 ad Exp $");
 
 #include <sys/param.h>
 #include <sys/proc.h>
@@ -197,6 +197,7 @@
        struct evcnt            si_evcnt;
        struct evcnt            si_evcnt_block;
        volatile int            si_active;
+       int                     si_ipl;
        char                    si_name[8];
        char                    si_name_block[8+6];
 } softint_t;
@@ -230,7 +231,8 @@
  *     Initialize a single interrupt level for a single CPU.
  */
 static void
-softint_init_isr(softcpu_t *sc, const char *desc, pri_t pri, u_int level)
+softint_init_isr(softcpu_t *sc, const char *desc, pri_t pri, u_int level,
+    int ipl)
 {
        struct cpu_info *ci;
        softint_t *si;
@@ -257,6 +259,7 @@
        evcnt_attach_dynamic(&si->si_evcnt_block, EVCNT_TYPE_MISC, NULL,
           "softint", si->si_name_block);
 
+       si->si_ipl = ipl;
        si->si_lwp->l_private = si;
        softint_init_md(si->si_lwp, level, &si->si_machdep);
 }
@@ -292,10 +295,14 @@
        ci->ci_data.cpu_softints = 0;
        sc->sc_cpu = ci;
 
-       softint_init_isr(sc, "net", PRI_SOFTNET, SOFTINT_NET);
-       softint_init_isr(sc, "bio", PRI_SOFTBIO, SOFTINT_BIO);
-       softint_init_isr(sc, "clk", PRI_SOFTCLOCK, SOFTINT_CLOCK);
-       softint_init_isr(sc, "ser", PRI_SOFTSERIAL, SOFTINT_SERIAL);
+       softint_init_isr(sc, "net", PRI_SOFTNET, SOFTINT_NET,
+           IPL_SOFTNET);
+       softint_init_isr(sc, "bio", PRI_SOFTBIO, SOFTINT_BIO,
+           IPL_SOFTBIO);
+       softint_init_isr(sc, "clk", PRI_SOFTCLOCK, SOFTINT_CLOCK,
+           IPL_SOFTCLOCK);
+       softint_init_isr(sc, "ser", PRI_SOFTSERIAL, SOFTINT_SERIAL,
+           IPL_SOFTSERIAL);
 
        if (first != ci) {
                mutex_enter(&softint_lock);
@@ -407,15 +414,14 @@
        softcpu_t *sc;
        softhand_t *sh;
        uintptr_t offset;
-       u_int flags;
 
        offset = (uintptr_t)arg;
        KASSERTMSG(offset != 0 && offset < softint_bytes, "%"PRIuPTR" %u",
            offset, softint_bytes);
 
        /*
-        * Unregister an IPI handler if there is any.  Note: there is
-        * no need to disable preemption here - ID is stable.
+        * Unregister IPI handler if there is any.  Note: there is no need
+        * to disable preemption here - ID is stable.
         */
        sc = curcpu()->ci_data.cpu_softcpu;
        sh = (softhand_t *)((uint8_t *)sc + offset);
@@ -424,32 +430,11 @@
        }
 
        /*
-        * Run a cross call so we see up to date values of sh_flags from
-        * all CPUs.  Once softint_disestablish() is called, the caller
-        * commits to not trigger the interrupt and set SOFTINT_ACTIVE on
-        * it again.  So, we are only looking for handler records with
-        * SOFTINT_ACTIVE already set.
+        * Run a dummy softint at the same level on all CPUs and wait for
+        * completion, to make sure this softint is no longer running
+        * anywhere.
         */
-       if (__predict_true(mp_online)) {
-               xc_barrier(0);
-       }
-
-       for (;;) {
-               /* Collect flag values from each CPU. */
-               flags = 0;
-               for (CPU_INFO_FOREACH(cii, ci)) {
-                       sc = ci->ci_data.cpu_softcpu;
-                       sh = (softhand_t *)((uint8_t *)sc + offset);
-                       KASSERT(sh->sh_func != NULL);
-                       flags |= sh->sh_flags;
-               }
-               /* Inactive on all CPUs? */
-               if ((flags & SOFTINT_ACTIVE) == 0) {
-                       break;
-               }
-               /* Oops, still active.  Wait for it to clear. */
-               (void)kpause("softdis", false, 1, NULL);
-       }
+       xc_barrier(XC_HIGHPRI_IPL(sh->sh_isr->si_ipl));
 
        /* Clear the handler on each CPU. */
        mutex_enter(&softint_lock);
@@ -547,8 +532,9 @@
  *     to the level specified, but returns back at splhigh.
  */
 static inline void
-softint_execute(softint_t *si, lwp_t *l, int s)
+softint_execute(lwp_t *l, int s)
 {
+       softint_t *si = l->l_private;
        softhand_t *sh;
 
        KASSERT(si->si_lwp == curlwp);
@@ -571,8 +557,7 @@
                sh = SIMPLEQ_FIRST(&si->si_q);
                SIMPLEQ_REMOVE_HEAD(&si->si_q, sh_q);
                KASSERT((sh->sh_flags & SOFTINT_PENDING) != 0);
-               KASSERT((sh->sh_flags & SOFTINT_ACTIVE) == 0);
-               sh->sh_flags ^= (SOFTINT_PENDING | SOFTINT_ACTIVE);
+               sh->sh_flags ^= SOFTINT_PENDING;
                splx(s);
 
                /* Run the handler. */
@@ -593,8 +578,6 @@
                    __func__, l->l_psrefs, sh->sh_func);
 
                (void)splhigh();
-               KASSERT((sh->sh_flags & SOFTINT_ACTIVE) != 0);
-               sh->sh_flags ^= SOFTINT_ACTIVE;
        }
 
        PSREF_DEBUG_BARRIER();
@@ -717,7 +700,7 @@
                /* Clear pending status and run it. */
                s = splhigh();
                l->l_cpu->ci_data.cpu_softints &= ~si->si_machdep;
-               softint_execute(si, l, s);
+               softint_execute(l, s);
                splx(s);
 
                /* Interrupts allowed to run again before switching. */
@@ -786,7 +769,6 @@
 softint_dispatch(lwp_t *pinned, int s)
 {
        struct bintime now;
-       softint_t *si;
        u_int timing;
        lwp_t *l;
 
@@ -808,9 +790,6 @@
        }
 #endif
 
-       l = curlwp;
-       si = l->l_private;
-
        /*
         * Note the interrupted LWP, and mark the current LWP as running
         * before proceeding.  Although this must as a rule be done with
@@ -818,6 +797,7 @@
         * modify the interrupt LWP's state.
         */
        timing = softint_timing;
+       l = curlwp;
        l->l_switchto = pinned;
        l->l_stat = LSONPROC;
 
@@ -831,7 +811,7 @@
                l->l_pflag |= LP_TIMEINTR;
        }
        l->l_pflag |= LP_RUNNING;
-       softint_execute(si, l, s);
+       softint_execute(l, s);
        if (timing) {
                binuptime(&now);
                updatertime(l, &now);
@@ -840,10 +820,9 @@
 
        /*
         * If we blocked while handling the interrupt, the pinned LWP is
-        * gone, so find another LWP to run.  It will select a new LWP to
-        * run.  softint_dispatch() won't be reentered until the priority
-        * is finally dropped to IPL_NONE on entry to the LWP chosen by
-        * mi_switch().
+        * gone and we are now running as a kthread, so find another LWP to
+        * run.  softint_dispatch() won't be reentered until the priority is
+        * finally dropped to IPL_NONE on entry to the next LWP on this CPU.
         */
        l->l_stat = LSIDL;
        if (l->l_switchto == NULL) {
diff -r 82c0bdcf16a9 -r ff8ca01a30f3 sys/sys/intr.h
--- a/sys/sys/intr.h    Sun May 17 13:49:37 2020 +0000
+++ b/sys/sys/intr.h    Sun May 17 14:11:30 2020 +0000
@@ -1,7 +1,7 @@
-/*     $NetBSD: intr.h,v 1.20 2020/03/26 20:19:06 ad Exp $     */
+/*     $NetBSD: intr.h,v 1.21 2020/05/17 14:11:30 ad Exp $     */
 
 /*-
- * Copyright (c) 2007 The NetBSD Foundation, Inc.
+ * Copyright (c) 2007, 2020 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
@@ -69,7 +69,6 @@
 
 /* Implementation private flags. */
 #define        SOFTINT_PENDING 0x1000
-#define        SOFTINT_ACTIVE  0x2000
 
 #define        SOFTINT_COUNT   0x0004
 #define        SOFTINT_LVLMASK 0x00ff



Home | Main Index | Thread Index | Old Index