Module Name: src
Committed By: thorpej
Date: Sat Apr 6 02:59:05 UTC 2019
Modified Files:
src/sys/kern: subr_ipi.c
src/sys/sys: ipi.h
Log Message:
Add an ipi_trigger_broadcast() call, like ipi_trigger_multi() but to the
full set of attached CPUs, with an optional "skip_self" argument to skip
the calling CPU. Add a "skip_self" to the ipi_broadcast() call for
symmetry.
(Kernel version bump coming in a subsequent commit.)
To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/sys/kern/subr_ipi.c
cvs rdiff -u -r1.3 -r1.4 src/sys/sys/ipi.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/kern/subr_ipi.c
diff -u src/sys/kern/subr_ipi.c:1.3 src/sys/kern/subr_ipi.c:1.4
--- src/sys/kern/subr_ipi.c:1.3 Sun Jan 18 23:16:35 2015
+++ src/sys/kern/subr_ipi.c Sat Apr 6 02:59:05 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: subr_ipi.c,v 1.3 2015/01/18 23:16:35 rmind Exp $ */
+/* $NetBSD: subr_ipi.c,v 1.4 2019/04/06 02:59:05 thorpej Exp $ */
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_ipi.c,v 1.3 2015/01/18 23:16:35 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_ipi.c,v 1.4 2019/04/06 02:59:05 thorpej Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -162,38 +162,53 @@ ipi_unregister(u_int ipi_id)
/* Ensure that there are no IPIs in flight. */
kpreempt_disable();
- ipi_broadcast(&ipimsg);
+ ipi_broadcast(&ipimsg, false);
ipi_wait(&ipimsg);
kpreempt_enable();
mutex_exit(&ipi_mngmt_lock);
}
/*
- * ipi_trigger: asynchronously send an IPI to the specified CPU.
+ * ipi_mark_pending: internal routine to mark an IPI pending on the
+ * specified CPU (which might be curcpu()).
*/
-void
-ipi_trigger(u_int ipi_id, struct cpu_info *ci)
+static bool
+ipi_mark_pending(u_int ipi_id, struct cpu_info *ci)
{
const u_int i = ipi_id >> IPI_BITW_SHIFT;
const uint32_t bitm = 1U << (ipi_id & IPI_BITW_MASK);
KASSERT(ipi_id < IPI_MAXREG);
KASSERT(kpreempt_disabled());
- KASSERT(curcpu() != ci);
/* Mark as pending and send an IPI. */
if (membar_consumer(), (ci->ci_ipipend[i] & bitm) == 0) {
atomic_or_32(&ci->ci_ipipend[i], bitm);
- cpu_ipi(ci);
+ return true;
}
+ return false;
}
/*
- * ipi_trigger_multi: same as ipi_trigger() but sends to the multiple
- * CPUs given the target CPU set.
+ * ipi_trigger: asynchronously send an IPI to the specified CPU.
*/
void
-ipi_trigger_multi(u_int ipi_id, const kcpuset_t *target)
+ipi_trigger(u_int ipi_id, struct cpu_info *ci)
+{
+
+ KASSERT(curcpu() != ci);
+ if (ipi_mark_pending(ipi_id, ci)) {
+ cpu_ipi(ci);
+ }
+}
+
+/*
+ * ipi_trigger_multi_internal: the guts of ipi_trigger_multi() and
+ * ipi_trigger_broadcast().
+ */
+static void
+ipi_trigger_multi_internal(u_int ipi_id, const kcpuset_t *target,
+ bool skip_self)
{
const cpuid_t selfid = cpu_index(curcpu());
CPU_INFO_ITERATOR cii;
@@ -210,7 +225,8 @@ ipi_trigger_multi(u_int ipi_id, const kc
}
ipi_trigger(ipi_id, ci);
}
- if (kcpuset_isset(target, selfid)) {
+ if (!skip_self && kcpuset_isset(target, selfid)) {
+ ipi_mark_pending(ipi_id, curcpu());
int s = splhigh();
ipi_cpu_handler();
splx(s);
@@ -218,6 +234,26 @@ ipi_trigger_multi(u_int ipi_id, const kc
}
/*
+ * ipi_trigger_multi: same as ipi_trigger() but sends to the multiple
+ * CPUs given the target CPU set.
+ */
+void
+ipi_trigger_multi(u_int ipi_id, const kcpuset_t *target)
+{
+ ipi_trigger_multi_internal(ipi_id, target, false);
+}
+
+/*
+ * ipi_trigger_broadcast: same as ipi_trigger_multi() to kcpuset_attached,
+ * optionally skipping the sending CPU.
+ */
+void
+ipi_trigger_broadcast(u_int ipi_id, bool skip_self)
+{
+ ipi_trigger_multi_internal(ipi_id, kcpuset_attached, skip_self);
+}
+
+/*
* put_msg: insert message into the mailbox.
*/
static inline void
@@ -365,7 +401,7 @@ ipi_multicast(ipi_msg_t *msg, const kcpu
* => The caller must ipi_wait() on the message for completion.
*/
void
-ipi_broadcast(ipi_msg_t *msg)
+ipi_broadcast(ipi_msg_t *msg, bool skip_self)
{
const struct cpu_info * const self = curcpu();
CPU_INFO_ITERATOR cii;
@@ -389,8 +425,10 @@ ipi_broadcast(ipi_msg_t *msg)
ipi_trigger(IPI_SYNCH_ID, ci);
}
- /* Finally, execute locally. */
- msg->func(msg->arg);
+ if (!skip_self) {
+ /* Finally, execute locally. */
+ msg->func(msg->arg);
+ }
}
/*
Index: src/sys/sys/ipi.h
diff -u src/sys/sys/ipi.h:1.3 src/sys/sys/ipi.h:1.4
--- src/sys/sys/ipi.h:1.3 Sun Jan 18 23:16:35 2015
+++ src/sys/sys/ipi.h Sat Apr 6 02:59:05 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ipi.h,v 1.3 2015/01/18 23:16:35 rmind Exp $ */
+/* $NetBSD: ipi.h,v 1.4 2019/04/06 02:59:05 thorpej Exp $ */
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -68,11 +68,12 @@ u_int ipi_register(ipi_func_t, void *);
void ipi_unregister(u_int);
void ipi_trigger(u_int, struct cpu_info *);
void ipi_trigger_multi(u_int, const kcpuset_t *);
+void ipi_trigger_broadcast(u_int, bool);
/* Public interface: synchronous IPIs. */
void ipi_unicast(ipi_msg_t *, struct cpu_info *);
void ipi_multicast(ipi_msg_t *, const kcpuset_t *);
-void ipi_broadcast(ipi_msg_t *);
+void ipi_broadcast(ipi_msg_t *, bool);
void ipi_wait(ipi_msg_t *);
#endif