Module Name:    src
Committed By:   snj
Date:           Mon Feb 19 18:33:38 UTC 2018

Modified Files:
        src/share/man/man9 [netbsd-8]: xcall.9
        src/sys/kern [netbsd-8]: subr_psref.c subr_xcall.c
        src/sys/sys [netbsd-8]: xcall.h

Log Message:
Pull up following revision(s) (requested by ozaki-r in ticket #556):
        sys/sys/xcall.h: 1.6
        share/man/man9/xcall.9: 1.11-1.12
        sys/kern/subr_xcall.c: 1.21-1.25
Refer softint(9)
--
Support arbitrary softint IPLs in high priority xcall
The high priority xcall supported only a softint of IPL_SOFTSERIAL. It meant
that it didn't work for xcall callbacks depending on lower IPLs than
IPL_SOFTSERIAL.
The change makes xcall have multiple softints of IPLs and allow users to specify
arbitrary IPLs. Users can specify an IPL by XC_HIGHPRI_IPL passed to the 1st
argument of xc_broadcast or xc_unicast.
Note that xcall still serves requests one by one (i.e., doesn't run them
concurrently) even if requests have different IPLs.
Proposed on tech-kern@
--
Use high priority xcall with a softint of an IPL the same as psref class's one
This mitigates undesired delay of psref_target_destroy under load such as heavy
netowrk traffic that loads softint.
--
Try to fix the build: avoid duplicate case labels when IPL_SOFT* are
all the same.
--
Fix build of kernels that some (or all) IPL_SOFT* share a value (e.g., mips)
--
Avoid allocating unused softints that share a value of IPL between another
Sort XC_IPL_* in order of priority (NFC)


To generate a diff of this commit:
cvs rdiff -u -r1.10 -r1.10.18.1 src/share/man/man9/xcall.9
cvs rdiff -u -r1.7.2.2 -r1.7.2.3 src/sys/kern/subr_psref.c
cvs rdiff -u -r1.19 -r1.19.8.1 src/sys/kern/subr_xcall.c
cvs rdiff -u -r1.5 -r1.5.30.1 src/sys/sys/xcall.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/share/man/man9/xcall.9
diff -u src/share/man/man9/xcall.9:1.10 src/share/man/man9/xcall.9:1.10.18.1
--- src/share/man/man9/xcall.9:1.10	Tue Nov 26 20:48:25 2013
+++ src/share/man/man9/xcall.9	Mon Feb 19 18:33:38 2018
@@ -1,4 +1,4 @@
-.\"     $NetBSD: xcall.9,v 1.10 2013/11/26 20:48:25 rmind Exp $
+.\"     $NetBSD: xcall.9,v 1.10.18.1 2018/02/19 18:33:38 snj Exp $
 .\"
 .\" Copyright (c) 2010 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -27,7 +27,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd November 26, 2013
+.Dd February 1, 2018
 .Dt XCALL 9
 .Os
 .Sh NAME
@@ -87,7 +87,6 @@ also provides a mechanism for making
 .Dq "high priority"
 cross calls.
 The function to be executed runs on the remote CPU within a
-.Dv IPL_SOFTSERIAL
 software interrupt context, possibly interrupting other lower-priority
 code running on the CPU.
 .Sh NOTES
@@ -112,7 +111,18 @@ on for the cross-call to complete.
 .Fa flags
 should be
 .Dv XC_HIGHPRI
+or
+.Fo XC_HIGHPRI_IPL
+.Fa ipl
+.Fc
 for a "high priority" call, and 0 for a "low priority" call.
+.Dv XC_HIGHPRI
+uses an
+.Dv IPL_SOFTSERIAL
+software interrupt while
+.Fn XC_HIGHPRI_IPL
+uses a software interrupt with an IPL specified by
+.Fa ipl .
 .Fn xc_broadcast
 should not be called from interrupt context.
 .It Fn xc_unicast "flags" "func" "arg1" "arg2" "ci"
@@ -144,7 +154,8 @@ interface is implemented within the file
 .\" .Sh EXAMPLES
 .Sh SEE ALSO
 .Xr kpreempt 9 ,
-.Xr percpu 9
+.Xr percpu 9 ,
+.Xr softint 9
 .Sh HISTORY
 The
 .Nm

Index: src/sys/kern/subr_psref.c
diff -u src/sys/kern/subr_psref.c:1.7.2.2 src/sys/kern/subr_psref.c:1.7.2.3
--- src/sys/kern/subr_psref.c:1.7.2.2	Mon Jan 22 12:30:20 2018
+++ src/sys/kern/subr_psref.c	Mon Feb 19 18:33:38 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: subr_psref.c,v 1.7.2.2 2018/01/22 12:30:20 martin Exp $	*/
+/*	$NetBSD: subr_psref.c,v 1.7.2.3 2018/02/19 18:33:38 snj Exp $	*/
 
 /*-
  * Copyright (c) 2016 The NetBSD Foundation, Inc.
@@ -64,7 +64,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_psref.c,v 1.7.2.2 2018/01/22 12:30:20 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_psref.c,v 1.7.2.3 2018/02/19 18:33:38 snj Exp $");
 
 #include <sys/types.h>
 #include <sys/condvar.h>
@@ -94,6 +94,7 @@ struct psref_class {
 	kcondvar_t		prc_cv;
 	struct percpu		*prc_percpu; /* struct psref_cpu */
 	ipl_cookie_t		prc_iplcookie;
+	unsigned int		prc_xc_flags;
 };
 
 /*
@@ -124,6 +125,7 @@ psref_class_create(const char *name, int
 	mutex_init(&class->prc_lock, MUTEX_DEFAULT, ipl);
 	cv_init(&class->prc_cv, name);
 	class->prc_iplcookie = makeiplcookie(ipl);
+	class->prc_xc_flags = XC_HIGHPRI_IPL(ipl);
 
 	return class;
 }
@@ -434,7 +436,8 @@ psreffed_p(struct psref_target *target, 
 		 * Ask all CPUs to say whether they hold a psref to the
 		 * target.
 		 */
-		xc_wait(xc_broadcast(0, &psreffed_p_xc, &P, NULL));
+		xc_wait(xc_broadcast(class->prc_xc_flags, &psreffed_p_xc, &P,
+		                     NULL));
 	} else
 		psreffed_p_xc(&P, NULL);
 

Index: src/sys/kern/subr_xcall.c
diff -u src/sys/kern/subr_xcall.c:1.19 src/sys/kern/subr_xcall.c:1.19.8.1
--- src/sys/kern/subr_xcall.c:1.19	Mon Nov 21 00:54:21 2016
+++ src/sys/kern/subr_xcall.c	Mon Feb 19 18:33:38 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: subr_xcall.c,v 1.19 2016/11/21 00:54:21 ozaki-r Exp $	*/
+/*	$NetBSD: subr_xcall.c,v 1.19.8.1 2018/02/19 18:33:38 snj Exp $	*/
 
 /*-
  * Copyright (c) 2007-2010 The NetBSD Foundation, Inc.
@@ -74,7 +74,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_xcall.c,v 1.19 2016/11/21 00:54:21 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_xcall.c,v 1.19.8.1 2018/02/19 18:33:38 snj Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -98,6 +98,7 @@ typedef struct {
 	void *		xc_arg2;
 	uint64_t	xc_headp;
 	uint64_t	xc_donep;
+	unsigned int	xc_ipl;
 } xc_state_t;
 
 /* Bit indicating high (1) or low (0) priority. */
@@ -108,7 +109,7 @@ static xc_state_t	xc_low_pri	__cacheline
 
 /* High priority xcall structures. */
 static xc_state_t	xc_high_pri	__cacheline_aligned;
-static void *		xc_sih		__cacheline_aligned;
+static void *		xc_sihs[4]	__cacheline_aligned;
 
 /* Event counters. */
 static struct evcnt	xc_unicast_ev	__cacheline_aligned;
@@ -117,9 +118,24 @@ static struct evcnt	xc_broadcast_ev	__ca
 static void		xc_init(void);
 static void		xc_thread(void *);
 
-static inline uint64_t	xc_highpri(xcfunc_t, void *, void *, struct cpu_info *);
+static inline uint64_t	xc_highpri(xcfunc_t, void *, void *, struct cpu_info *,
+			    unsigned int);
 static inline uint64_t	xc_lowpri(xcfunc_t, void *, void *, struct cpu_info *);
 
+/* The internal form of IPL */
+#define XC_IPL_MASK		0xff00
+/*
+ * Assign 0 to XC_IPL_SOFTSERIAL to treat IPL_SOFTSERIAL as the default value
+ * (just XC_HIGHPRI).
+ */
+#define XC_IPL_SOFTSERIAL	0
+#define XC_IPL_SOFTNET		1
+#define XC_IPL_SOFTBIO		2
+#define XC_IPL_SOFTCLOCK	3
+#define XC_IPL_MAX		XC_IPL_SOFTCLOCK
+
+CTASSERT(XC_IPL_MAX <= __arraycount(xc_sihs));
+
 /*
  * xc_init:
  *
@@ -137,9 +153,31 @@ xc_init(void)
 	memset(xchi, 0, sizeof(xc_state_t));
 	mutex_init(&xchi->xc_lock, MUTEX_DEFAULT, IPL_SOFTSERIAL);
 	cv_init(&xchi->xc_busy, "xchicv");
-	xc_sih = softint_establish(SOFTINT_SERIAL | SOFTINT_MPSAFE,
-	    xc__highpri_intr, NULL);
-	KASSERT(xc_sih != NULL);
+
+	/* Set up a softint for each IPL_SOFT*. */
+#define SETUP_SOFTINT(xipl, sipl) do {					\
+		xc_sihs[(xipl)] = softint_establish( (sipl) | SOFTINT_MPSAFE,\
+		    xc__highpri_intr, NULL);				\
+		KASSERT(xc_sihs[(xipl)] != NULL);			\
+	} while (0)
+
+	SETUP_SOFTINT(XC_IPL_SOFTSERIAL, SOFTINT_SERIAL);
+	/*
+	 * If a IPL_SOFTXXX have the same value of the previous, we don't use
+	 * the IPL (see xc_encode_ipl).  So we don't need to allocate a softint
+	 * for it.
+	 */
+#if IPL_SOFTNET != IPL_SOFTSERIAL
+	SETUP_SOFTINT(XC_IPL_SOFTNET, SOFTINT_NET);
+#endif
+#if IPL_SOFTBIO != IPL_SOFTNET
+	SETUP_SOFTINT(XC_IPL_SOFTBIO, SOFTINT_BIO);
+#endif
+#if IPL_SOFTCLOCK != IPL_SOFTBIO
+	SETUP_SOFTINT(XC_IPL_SOFTCLOCK, SOFTINT_CLOCK);
+#endif
+
+#undef SETUP_SOFTINT
 
 	evcnt_attach_dynamic(&xc_unicast_ev, EVCNT_TYPE_MISC, NULL,
 	   "crosscall", "unicast");
@@ -148,6 +186,45 @@ xc_init(void)
 }
 
 /*
+ * Encode an IPL to a form that can be embedded into flags of xc_broadcast
+ * or xc_unicast.
+ */
+unsigned int
+xc_encode_ipl(int ipl)
+{
+
+	switch (ipl) {
+	case IPL_SOFTSERIAL:
+		return __SHIFTIN(XC_IPL_SOFTSERIAL, XC_IPL_MASK);
+	/* IPL_SOFT* can be the same value (e.g., on sparc or mips). */
+#if IPL_SOFTNET != IPL_SOFTSERIAL
+	case IPL_SOFTNET:
+		return __SHIFTIN(XC_IPL_SOFTNET, XC_IPL_MASK);
+#endif
+#if IPL_SOFTBIO != IPL_SOFTNET
+	case IPL_SOFTBIO:
+		return __SHIFTIN(XC_IPL_SOFTBIO, XC_IPL_MASK);
+#endif
+#if IPL_SOFTCLOCK != IPL_SOFTBIO
+	case IPL_SOFTCLOCK:
+		return __SHIFTIN(XC_IPL_SOFTCLOCK, XC_IPL_MASK);
+#endif
+	}
+
+	panic("Invalid IPL: %d", ipl);
+}
+
+/*
+ * Extract an XC_IPL from flags of xc_broadcast or xc_unicast.
+ */
+static inline unsigned int
+xc_extract_ipl(unsigned int flags)
+{
+
+	return __SHIFTOUT(flags, XC_IPL_MASK);
+}
+
+/*
  * xc_init_cpu:
  *
  *	Initialize the cross-call subsystem.  Called once for each CPU
@@ -176,13 +253,14 @@ xc_init_cpu(struct cpu_info *ci)
  *	Trigger a call on all CPUs in the system.
  */
 uint64_t
-xc_broadcast(u_int flags, xcfunc_t func, void *arg1, void *arg2)
+xc_broadcast(unsigned int flags, xcfunc_t func, void *arg1, void *arg2)
 {
 
 	KASSERT(!cpu_intr_p() && !cpu_softintr_p());
 
 	if ((flags & XC_HIGHPRI) != 0) {
-		return xc_highpri(func, arg1, arg2, NULL);
+		int ipl = xc_extract_ipl(flags);
+		return xc_highpri(func, arg1, arg2, NULL, ipl);
 	} else {
 		return xc_lowpri(func, arg1, arg2, NULL);
 	}
@@ -194,7 +272,7 @@ xc_broadcast(u_int flags, xcfunc_t func,
  *	Trigger a call on one CPU.
  */
 uint64_t
-xc_unicast(u_int flags, xcfunc_t func, void *arg1, void *arg2,
+xc_unicast(unsigned int flags, xcfunc_t func, void *arg1, void *arg2,
 	   struct cpu_info *ci)
 {
 
@@ -202,7 +280,8 @@ xc_unicast(u_int flags, xcfunc_t func, v
 	KASSERT(!cpu_intr_p() && !cpu_softintr_p());
 
 	if ((flags & XC_HIGHPRI) != 0) {
-		return xc_highpri(func, arg1, arg2, ci);
+		int ipl = xc_extract_ipl(flags);
+		return xc_highpri(func, arg1, arg2, ci, ipl);
 	} else {
 		return xc_lowpri(func, arg1, arg2, ci);
 	}
@@ -329,8 +408,13 @@ xc_thread(void *cookie)
 void
 xc_ipi_handler(void)
 {
+	xc_state_t *xc = & xc_high_pri;
+
+	KASSERT(xc->xc_ipl < __arraycount(xc_sihs));
+	KASSERT(xc_sihs[xc->xc_ipl] != NULL);
+
 	/* Executes xc__highpri_intr() via software interrupt. */
-	softint_schedule(xc_sih);
+	softint_schedule(xc_sihs[xc->xc_ipl]);
 }
 
 /*
@@ -375,7 +459,8 @@ xc__highpri_intr(void *dummy)
  *	Trigger a high priority call on one or more CPUs.
  */
 static inline uint64_t
-xc_highpri(xcfunc_t func, void *arg1, void *arg2, struct cpu_info *ci)
+xc_highpri(xcfunc_t func, void *arg1, void *arg2, struct cpu_info *ci,
+    unsigned int ipl)
 {
 	xc_state_t *xc = &xc_high_pri;
 	uint64_t where;
@@ -388,6 +473,7 @@ xc_highpri(xcfunc_t func, void *arg1, vo
 	xc->xc_arg1 = arg1;
 	xc->xc_arg2 = arg2;
 	xc->xc_headp += (ci ? 1 : ncpu);
+	xc->xc_ipl = ipl;
 	where = xc->xc_headp;
 	mutex_exit(&xc->xc_lock);
 

Index: src/sys/sys/xcall.h
diff -u src/sys/sys/xcall.h:1.5 src/sys/sys/xcall.h:1.5.30.1
--- src/sys/sys/xcall.h:1.5	Tue Feb 19 09:04:53 2013
+++ src/sys/sys/xcall.h	Mon Feb 19 18:33:38 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: xcall.h,v 1.5 2013/02/19 09:04:53 martin Exp $	*/
+/*	$NetBSD: xcall.h,v 1.5.30.1 2018/02/19 18:33:38 snj Exp $	*/
 
 /*-
  * Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -33,7 +33,8 @@
 #define	_SYS_XCALL_H_
 
 #ifdef _KERNEL
-#define	XC_HIGHPRI	0x01	/* high priority */
+#define XC_HIGHPRI		0x01	/* high priority */
+#define XC_HIGHPRI_IPL(ipl)	(XC_HIGHPRI | xc_encode_ipl(ipl))
 
 typedef void (*xcfunc_t)(void *, void *);
 
@@ -49,6 +50,8 @@ uint64_t	xc_broadcast(u_int, xcfunc_t, v
 uint64_t	xc_unicast(u_int, xcfunc_t, void *, void *, struct cpu_info *);
 void		xc_wait(uint64_t);
 
+unsigned int	xc_encode_ipl(int);
+
 #endif	/* _KERNEL */
 
 #endif	/* _SYS_XCALL_H_ */

Reply via email to