Module Name:    src
Committed By:   riastradh
Date:           Thu Feb 23 14:57:29 UTC 2023

Modified Files:
        src/sys/kern: kern_lock.c kern_mutex.c

Log Message:
KERNEL_LOCK(9): Minor tweaks to ci->ci_biglock_wanted access.

1. Use atomic_load_relaxed to read ci->ci_biglock_wanted from another
   CPU, for clarity and to avoid the appearance of data races in thread
   sanitizers.  (Reading ci->ci_biglock_wanted on the local CPU need
   not be atomic because no other CPU can be writing to it.)

2. Use atomic_store_relaxed to update ci->ci_biglock_wanted when we
   start to spin, to avoid the appearance of data races.

3. Add comments to explain what's going on and cross-reference the
   specific matching membars in mutex_vector_enter.

related to PR kern/57240


To generate a diff of this commit:
cvs rdiff -u -r1.182 -r1.183 src/sys/kern/kern_lock.c
cvs rdiff -u -r1.102 -r1.103 src/sys/kern/kern_mutex.c

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/kern_lock.c
diff -u src/sys/kern/kern_lock.c:1.182 src/sys/kern/kern_lock.c:1.183
--- src/sys/kern/kern_lock.c:1.182	Fri Jan 27 09:28:41 2023
+++ src/sys/kern/kern_lock.c	Thu Feb 23 14:57:29 2023
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_lock.c,v 1.182 2023/01/27 09:28:41 ozaki-r Exp $	*/
+/*	$NetBSD: kern_lock.c,v 1.183 2023/02/23 14:57:29 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2002, 2006, 2007, 2008, 2009, 2020 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_lock.c,v 1.182 2023/01/27 09:28:41 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_lock.c,v 1.183 2023/02/23 14:57:29 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_lockdebug.h"
@@ -235,10 +235,18 @@ _kernel_lock(int nlocks)
 	 * is required to ensure that the result of any mutex_exit()
 	 * by the current LWP becomes visible on the bus before the set
 	 * of ci->ci_biglock_wanted becomes visible.
+	 *
+	 * This membar_producer matches the membar_consumer in
+	 * mutex_vector_enter.
+	 *
+	 * That way, if l has just released a mutex, mutex_vector_enter
+	 * can't see this store ci->ci_biglock_wanted := l until it
+	 * will also see the mutex_exit store mtx->mtx_owner := 0 which
+	 * clears the has-waiters bit.
 	 */
 	membar_producer();
 	owant = ci->ci_biglock_wanted;
-	ci->ci_biglock_wanted = l;
+	atomic_store_relaxed(&ci->ci_biglock_wanted, l);
 #if defined(DIAGNOSTIC) && !defined(LOCKDEBUG)
 	l->l_ld_wanted = __builtin_return_address(0);
 #endif
@@ -286,22 +294,20 @@ _kernel_lock(int nlocks)
 
 	/*
 	 * Now that we have kernel_lock, reset ci_biglock_wanted.  This
-	 * store must be unbuffered (immediately visible on the bus) in
-	 * order for non-interlocked mutex release to work correctly.
-	 * It must be visible before a mutex_exit() can execute on this
-	 * processor.
+	 * store must be visible on other CPUs before a mutex_exit() on
+	 * this CPU can test the has-waiters bit.
+	 *
+	 * This membar_enter matches the membar_enter in
+	 * mutex_vector_enter.  (Yes, not membar_exit -- the legacy
+	 * naming is confusing, but store-before-load usually pairs
+	 * with store-before-load, in the extremely rare cases where it
+	 * is used at all.)
 	 *
-	 * Note: only where CAS is available in hardware will this be
-	 * an unbuffered write, but non-interlocked release cannot be
-	 * done on CPUs without CAS in hardware.
+	 * That way, mutex_vector_enter can't see this store
+	 * ci->ci_biglock_wanted := owant until it has set the
+	 * has-waiters bit.
 	 */
 	(void)atomic_swap_ptr(&ci->ci_biglock_wanted, owant);
-
-	/*
-	 * Issue a memory barrier as we have acquired a lock.  This also
-	 * prevents stores from a following mutex_exit() being reordered
-	 * to occur before our store to ci_biglock_wanted above.
-	 */
 #ifndef __HAVE_ATOMIC_AS_MEMBAR
 	membar_enter();
 #endif

Index: src/sys/kern/kern_mutex.c
diff -u src/sys/kern/kern_mutex.c:1.102 src/sys/kern/kern_mutex.c:1.103
--- src/sys/kern/kern_mutex.c:1.102	Fri Jan 27 09:28:41 2023
+++ src/sys/kern/kern_mutex.c	Thu Feb 23 14:57:29 2023
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_mutex.c,v 1.102 2023/01/27 09:28:41 ozaki-r Exp $	*/
+/*	$NetBSD: kern_mutex.c,v 1.103 2023/02/23 14:57:29 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2002, 2006, 2007, 2008, 2019 The NetBSD Foundation, Inc.
@@ -40,7 +40,7 @@
 #define	__MUTEX_PRIVATE
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_mutex.c,v 1.102 2023/01/27 09:28:41 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_mutex.c,v 1.103 2023/02/23 14:57:29 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/atomic.h>
@@ -427,7 +427,7 @@ mutex_oncpu(uintptr_t owner)
 
 	if (ci && ci->ci_curlwp == l) {
 		/* Target is running; do we need to block? */
-		return (ci->ci_biglock_wanted != l);
+		return (atomic_load_relaxed(&ci->ci_biglock_wanted) != l);
 	}
 
 	/* Not running.  It may be safe to block now. */

Reply via email to