Source-Changes-HG archive

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

[src/trunk]: src/sys softint: implement softint_schedule_cpu() to trigger sof...



details:   https://anonhg.NetBSD.org/src/rev/920012d48e0a
branches:  trunk
changeset: 329467:920012d48e0a
user:      rmind <rmind%NetBSD.org@localhost>
date:      Sun May 25 15:42:01 2014 +0000

description:
softint: implement softint_schedule_cpu() to trigger software interrupts
on the remote CPUs and add SOFTINT_RCPU flag to indicate whether this is
going to be used; implemented using asynchronous IPIs.

diffstat:

 sys/kern/kern_softint.c |  66 ++++++++++++++++++++++++++++++++++++++++--------
 sys/sys/intr.h          |   4 ++-
 2 files changed, 58 insertions(+), 12 deletions(-)

diffs (171 lines):

diff -r 044d797bc731 -r 920012d48e0a sys/kern/kern_softint.c
--- a/sys/kern/kern_softint.c   Sun May 25 15:34:19 2014 +0000
+++ b/sys/kern/kern_softint.c   Sun May 25 15:42:01 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_softint.c,v 1.40 2013/09/07 03:34:59 matt Exp $   */
+/*     $NetBSD: kern_softint.c,v 1.41 2014/05/25 15:42:01 rmind Exp $  */
 
 /*-
  * Copyright (c) 2007, 2008 The NetBSD Foundation, Inc.
@@ -167,20 +167,15 @@
  *     execution as a normal LWP (kthread) and gains VM context.  Only
  *     when it has completed and is ready to fire again will it
  *     interrupt other threads.
- *
- * Future directions
- *
- *     Provide a cheap way to direct software interrupts to remote
- *     CPUs.  Provide a way to enqueue work items into the handler
- *     record, removing additional spl calls (see subr_workqueue.c). 
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_softint.c,v 1.40 2013/09/07 03:34:59 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_softint.c,v 1.41 2014/05/25 15:42:01 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/proc.h>
 #include <sys/intr.h>
+#include <sys/ipi.h>
 #include <sys/mutex.h>
 #include <sys/kthread.h>
 #include <sys/evcnt.h>
@@ -211,6 +206,7 @@
        void                    *sh_arg;
        softint_t               *sh_isr;
        u_int                   sh_flags;
+       u_int                   sh_ipi_id;
 } softhand_t;
 
 typedef struct softcpu {
@@ -338,6 +334,8 @@
        softcpu_t *sc;
        softhand_t *sh;
        u_int level, index;
+       u_int ipi_id = 0;
+       void *sih;
 
        level = (flags & SOFTINT_LVLMASK);
        KASSERT(level < SOFTINT_COUNT);
@@ -357,6 +355,14 @@
                    "increase softint_bytes\n");
                return NULL;
        }
+       sih = (void *)((uint8_t *)&sc->sc_hand[index] - (uint8_t *)sc);
+
+       if (flags & SOFTINT_RCPU) {
+               if ((ipi_id = ipi_register(softint_schedule, sih)) == 0) {
+                       mutex_exit(&softint_lock);
+                       return NULL;
+               }
+       }
 
        /* Set up the handler on each CPU. */
        if (ncpu < 2) {
@@ -367,6 +373,7 @@
                sh->sh_func = func;
                sh->sh_arg = arg;
                sh->sh_flags = flags;
+               sh->sh_ipi_id = ipi_id;
        } else for (CPU_INFO_FOREACH(cii, ci)) {
                sc = ci->ci_data.cpu_softcpu;
                sh = &sc->sc_hand[index];
@@ -374,11 +381,11 @@
                sh->sh_func = func;
                sh->sh_arg = arg;
                sh->sh_flags = flags;
+               sh->sh_ipi_id = ipi_id;
        }
-
        mutex_exit(&softint_lock);
 
-       return (void *)((uint8_t *)&sc->sc_hand[index] - (uint8_t *)sc);
+       return sih;
 }
 
 /*
@@ -407,6 +414,16 @@
            offset, softint_bytes);
 
        /*
+        * Unregister an 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);
+       if (sh->sh_ipi_id) {
+               ipi_unregister(sh->sh_ipi_id);
+       }
+
+       /*
         * 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
@@ -490,6 +507,33 @@
 }
 
 /*
+ * softint_schedule_cpu:
+ *
+ *     Trigger a software interrupt on a target CPU.  This invokes
+ *     softint_schedule() for the local CPU or send an IPI to invoke
+ *     this routine on the remote CPU.  Preemption must be disabled.
+ */
+void
+softint_schedule_cpu(void *arg, struct cpu_info *ci)
+{
+       KASSERT(kpreempt_disabled());
+
+       if (curcpu() != ci) {
+               const softcpu_t *sc = ci->ci_data.cpu_softcpu;
+               const uintptr_t offset = (uintptr_t)arg;
+               const softhand_t *sh;
+
+               sh = (const softhand_t *)((const uint8_t *)sc + offset);
+               KASSERT((sh->sh_flags & SOFTINT_RCPU) != 0);
+               ipi_trigger(sh->sh_ipi_id, ci);
+               return;
+       }
+
+       /* Just a local CPU. */
+       softint_schedule(arg);
+}
+
+/*
  * softint_execute:
  *
  *     Invoke handlers for the specified soft interrupt.
@@ -548,7 +592,7 @@
                KASSERTMSG(curcpu()->ci_mtx_count == 0,
                    "%s: ci_mtx_count (%d) != 0, sh_func %p\n",
                    __func__, curcpu()->ci_mtx_count, sh->sh_func);
-       
+
                (void)splhigh();
                KASSERT((sh->sh_flags & SOFTINT_ACTIVE) != 0);
                sh->sh_flags ^= SOFTINT_ACTIVE;
diff -r 044d797bc731 -r 920012d48e0a sys/sys/intr.h
--- a/sys/sys/intr.h    Sun May 25 15:34:19 2014 +0000
+++ b/sys/sys/intr.h    Sun May 25 15:42:01 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: intr.h,v 1.16 2013/08/25 03:08:56 matt Exp $   */
+/*     $NetBSD: intr.h,v 1.17 2014/05/25 15:42:01 rmind Exp $  */
 
 /*-
  * Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -42,6 +42,7 @@
 void   *softint_establish(u_int, void (*)(void *), void *);
 void   softint_disestablish(void *);
 void   softint_schedule(void *);
+void   softint_schedule_cpu(void *, struct cpu_info *);
 
 /* MI hooks. */
 void   softint_init(struct cpu_info *);
@@ -62,6 +63,7 @@
 #define        SOFTINT_SERIAL  0x0002
 #define        SOFTINT_NET     0x0003
 #define        SOFTINT_MPSAFE  0x0100
+#define        SOFTINT_RCPU    0x0200
 
 /* Implementation private flags. */
 #define        SOFTINT_PENDING 0x1000



Home | Main Index | Thread Index | Old Index