From 81aaded24099f3685918bea8bbfc0fa5d60ab781 Mon Sep 17 00:00:00 2001 From: riastradh Date: Sat, 8 Jul 2023 13:59:05 +0000 Subject: curcpu_stable(9): New function for asserting curcpu() is stable. --- share/man/man9/curproc.9 | 33 +++++++++++++++++++++++++-------- sys/kern/kern_heartbeat.c | 14 ++------------ sys/kern/subr_cpu.c | 32 ++++++++++++++++++++++++++++++-- sys/sys/cpu.h | 3 ++- 4 files changed, 59 insertions(+), 23 deletions(-) diff --git a/share/man/man9/curproc.9 b/share/man/man9/curproc.9 index 3e77ffc5c85..282af8d1fbb 100644 --- a/share/man/man9/curproc.9 +++ b/share/man/man9/curproc.9 @@ -1,4 +1,4 @@ -.\" $NetBSD: curproc.9,v 1.6 2022/09/22 14:02:24 riastradh Exp $ +.\" $NetBSD: curproc.9,v 1.7 2023/07/08 13:59:05 riastradh Exp $ .\" .\" Copyright (c) 2002 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -27,24 +27,25 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd July 1, 2010 +.Dd July 8, 2023 .Dt CURPROC 9 .Os .Sh NAME -.Nm curproc , .Nm curcpu , -.Nm curlwp -.Nd current process, processor, and -.Tn LWP +.Nm curlwp , +.Nm curproc +.Nd current processor, thread, and process .Sh SYNOPSIS .In sys/proc.h .Ft struct cpu_info * .Fn curcpu "void" .Vt struct proc *curproc ; .Vt struct lwp *curlwp ; +.In sys/cpu.h +.Ft bool +.Fn curcpu_stable "void" .Sh DESCRIPTION -The following macros retrieve -the current CPU, process, and thread +The following retrieve the current CPU, process, and thread .Pq lightweight process, or Tn LWP , respectively: .Bl -tag -width Dv @@ -62,6 +63,17 @@ by disabling preemption .Pq Xr kpreempt_disable 9 , or by binding the thread to its CPU .Pq Xr curlwp_bind 9 . +.Pp +The function +.Fn curcpu_stable +can be used in assertions +.Pq Xr KASSERT 9 +to verify that +.Fn curcpu +is stable in the current context. +.Fn curcpu_stable +MUST NOT be used to make dynamic decisions about whether to query +.Fn curcpu . .It Dv curproc Yields a pointer to the .Vt "struct proc" @@ -102,6 +114,11 @@ but it may be overridden by .Pa machine/cpu.h , and must be overridden on architectures supporting multiprocessing and kernel preemption. +.Pp +The +.Fn curcpu_stable +function is defined in +.Pa kern/subr_cpu.c . .Sh SEE ALSO .Xr cpu_number 9 , .Xr proc_find 9 diff --git a/sys/kern/kern_heartbeat.c b/sys/kern/kern_heartbeat.c index 3b7631aba6f..7bb4811b7f5 100644 --- a/sys/kern/kern_heartbeat.c +++ b/sys/kern/kern_heartbeat.c @@ -1,4 +1,4 @@ -/* $NetBSD: kern_heartbeat.c,v 1.2 2023/07/07 17:05:13 riastradh Exp $ */ +/* $NetBSD: kern_heartbeat.c,v 1.3 2023/07/08 13:59:05 riastradh Exp $ */ /*- * Copyright (c) 2023 The NetBSD Foundation, Inc. @@ -78,7 +78,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: kern_heartbeat.c,v 1.2 2023/07/07 17:05:13 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_heartbeat.c,v 1.3 2023/07/08 13:59:05 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_ddb.h" @@ -104,16 +104,6 @@ __KERNEL_RCSID(0, "$NetBSD: kern_heartbeat.c,v 1.2 2023/07/07 17:05:13 riastradh #include #endif -static inline bool -curcpu_stable(void) -{ - - return kpreempt_disabled() || - (curlwp->l_pflag & LP_BOUND) || - cpu_intr_p() || - cpu_softintr_p(); -} - /* * Global state. * diff --git a/sys/kern/subr_cpu.c b/sys/kern/subr_cpu.c index 523de709c92..f8a4b6f5b0f 100644 --- a/sys/kern/subr_cpu.c +++ b/sys/kern/subr_cpu.c @@ -1,4 +1,4 @@ -/* $NetBSD: subr_cpu.c,v 1.18 2022/01/24 09:42:14 andvar Exp $ */ +/* $NetBSD: subr_cpu.c,v 1.19 2023/07/08 13:59:05 riastradh Exp $ */ /*- * Copyright (c) 2007, 2008, 2009, 2010, 2012, 2019, 2020 @@ -61,7 +61,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: subr_cpu.c,v 1.18 2022/01/24 09:42:14 andvar Exp $"); +__KERNEL_RCSID(0, "$NetBSD: subr_cpu.c,v 1.19 2023/07/08 13:59:05 riastradh Exp $"); #include #include @@ -137,6 +137,34 @@ cpu_softintr_p(void) return (curlwp->l_pflag & LP_INTR) != 0; } +bool +curcpu_stable(void) +{ + struct lwp *const l = curlwp; + const int pflag = l->l_pflag; + const int nopreempt = l->l_nopreempt; + + /* + * - Softints (LP_INTR) never migrate between CPUs. + * - Bound lwps (LP_BOUND), either kthreads created bound to + * a CPU or any lwps bound with curlwp_bind, never migrate. + * - If kpreemption is disabled, the lwp can't migrate. + * - If we're in interrupt context, preemption is blocked. + * + * We combine the LP_INTR, LP_BOUND, and l_nopreempt test into + * a single predicted-true branch so this is cheap to assert in + * most contexts where it will be used, then fall back to + * calling the full kpreempt_disabled() and cpu_intr_p() as + * subroutines. + * + * XXX Is cpu_intr_p redundant with kpreempt_disabled? + */ + return __predict_true(((pflag & (LP_INTR|LP_BOUND)) | nopreempt) + != 0) || + kpreempt_disabled() || + cpu_intr_p(); +} + /* * Collect CPU topology information as each CPU is attached. This can be * called early during boot, so we need to be careful what we do. diff --git a/sys/sys/cpu.h b/sys/sys/cpu.h index ca266fc33cd..54b9f478ae2 100644 --- a/sys/sys/cpu.h +++ b/sys/sys/cpu.h @@ -1,4 +1,4 @@ -/* $NetBSD: cpu.h,v 1.51 2020/06/15 18:04:42 ad Exp $ */ +/* $NetBSD: cpu.h,v 1.52 2023/07/08 13:59:05 riastradh Exp $ */ /*- * Copyright (c) 2007 YAMAMOTO Takashi, @@ -84,6 +84,7 @@ int cpu_setstate(struct cpu_info *, bool); int cpu_setintr(struct cpu_info *, bool); bool cpu_intr_p(void); bool cpu_softintr_p(void); +bool curcpu_stable(void); bool cpu_kpreempt_enter(uintptr_t, int); void cpu_kpreempt_exit(uintptr_t); bool cpu_kpreempt_disabled(void); -- cgit