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

Reply via email to