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