Source-Changes-HG archive

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

[src/trunk]: src/sys/kern KERNEL_LOCK(9): Minor tweaks to ci->ci_biglock_want...



details:   https://anonhg.NetBSD.org/src/rev/893a09c791ac
branches:  trunk
changeset: 373676:893a09c791ac
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Thu Feb 23 14:57:29 2023 +0000

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

diffstat:

 sys/kern/kern_lock.c  |  38 ++++++++++++++++++++++----------------
 sys/kern/kern_mutex.c |   6 +++---
 2 files changed, 25 insertions(+), 19 deletions(-)

diffs (99 lines):

diff -r ae30c377602d -r 893a09c791ac sys/kern/kern_lock.c
--- a/sys/kern/kern_lock.c      Thu Feb 23 14:57:08 2023 +0000
+++ b/sys/kern/kern_lock.c      Thu Feb 23 14:57:29 2023 +0000
@@ -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 @@
         * 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 @@
 
        /*
         * 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.
         *
-        * 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.
+        * 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.)
+        *
+        * 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
diff -r ae30c377602d -r 893a09c791ac sys/kern/kern_mutex.c
--- a/sys/kern/kern_mutex.c     Thu Feb 23 14:57:08 2023 +0000
+++ b/sys/kern/kern_mutex.c     Thu Feb 23 14:57:29 2023 +0000
@@ -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 @@
 
        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. */



Home | Main Index | Thread Index | Old Index