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