Source-Changes-HG archive

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

[src/trunk]: src/sys Add an ipi_trigger_broadcast() call, like ipi_trigger_mu...



details:   https://anonhg.NetBSD.org/src/rev/bec080af7dbe
branches:  trunk
changeset: 455552:bec080af7dbe
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Sat Apr 06 02:59:05 2019 +0000

description:
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.)

diffstat:

 sys/kern/subr_ipi.c |  76 +++++++++++++++++++++++++++++++++++++++-------------
 sys/sys/ipi.h       |   5 ++-
 2 files changed, 60 insertions(+), 21 deletions(-)

diffs (167 lines):

diff -r e5839723c9b6 -r bec080af7dbe sys/kern/subr_ipi.c
--- a/sys/kern/subr_ipi.c       Sat Apr 06 00:35:25 2019 +0000
+++ b/sys/kern/subr_ipi.c       Sat Apr 06 02:59:05 2019 +0000
@@ -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 @@
 
        /* 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_mark_pending: internal routine to mark an IPI pending on the
+ * specified CPU (which might be curcpu()).
+ */
+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());
+
+       /* Mark as pending and send an IPI. */
+       if (membar_consumer(), (ci->ci_ipipend[i] & bitm) == 0) {
+               atomic_or_32(&ci->ci_ipipend[i], bitm);
+               return true;
+       }
+       return false;
+}
+
+/*
  * ipi_trigger: asynchronously send an IPI to the specified CPU.
  */
 void
 ipi_trigger(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);
+       if (ipi_mark_pending(ipi_id, ci)) {
                cpu_ipi(ci);
        }
 }
 
 /*
- * ipi_trigger_multi: same as ipi_trigger() but sends to the multiple
- * CPUs given the target CPU set.
+ * ipi_trigger_multi_internal: the guts of ipi_trigger_multi() and
+ * ipi_trigger_broadcast().
  */
-void
-ipi_trigger_multi(u_int ipi_id, const kcpuset_t *target)
+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(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: 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 @@
  * => 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_trigger(IPI_SYNCH_ID, ci);
        }
 
-       /* Finally, execute locally. */
-       msg->func(msg->arg);
+       if (!skip_self) {
+               /* Finally, execute locally. */
+               msg->func(msg->arg);
+       }
 }
 
 /*
diff -r e5839723c9b6 -r bec080af7dbe sys/sys/ipi.h
--- a/sys/sys/ipi.h     Sat Apr 06 00:35:25 2019 +0000
+++ b/sys/sys/ipi.h     Sat Apr 06 02:59:05 2019 +0000
@@ -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 @@
 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



Home | Main Index | Thread Index | Old Index