]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
rcu: Mark accesses to ->rcu_read_lock_nesting
authorPaul E. McKenney <paulmck@kernel.org>
Thu, 20 May 2021 20:35:50 +0000 (13:35 -0700)
committerPaul E. McKenney <paulmck@kernel.org>
Tue, 25 May 2021 00:19:08 +0000 (17:19 -0700)
KCSAN flags accesses to ->rcu_read_lock_nesting as data races, but
in the past, the overhead of marked accesses was excessive.  However,
that was long ago, and much has changed since then, both in terms of
hardware and of compilers.  Here is data taken on an eight-core laptop
using Intel(R) Core(TM) i9-10885H CPU @ 2.40GHz with a kernel built
using gcc version 9.3.0, with all data in nanoseconds.

Unmarked accesses (status quo), measured by three refscale runs:

Minimum reader duration:  3.286  2.851  3.395
Median reader duration:   3.698  3.531  3.4695
Maximum reader duration:  4.481  5.215  5.157

Marked accesses, also measured by three refscale runs:

Minimum reader duration:  3.501  3.677  3.580
Median reader duration:   4.053  3.723  3.895
Maximum reader duration:  7.307  4.999  5.511

This focused microbenhmark shows only sub-nanosecond differences which
unlikely to be visible at the system level.  This commit therefore marks
data-racing accesses to ->rcu_read_lock_nesting.

Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
include/linux/rcupdate.h
kernel/rcu/tree_plugin.h

index d9680b798b211381d95fc7d10cf41cde731969e9..cfeb43bfc719e37d5056802657c134873b8405ad 100644 (file)
@@ -53,7 +53,7 @@ void __rcu_read_unlock(void);
  * nesting depth, but makes sense only if CONFIG_PREEMPT_RCU -- in other
  * types of kernel builds, the rcu_read_lock() nesting depth is unknowable.
  */
-#define rcu_preempt_depth() (current->rcu_read_lock_nesting)
+#define rcu_preempt_depth() READ_ONCE(current->rcu_read_lock_nesting)
 
 #else /* #ifdef CONFIG_PREEMPT_RCU */
 
index aec5075c60b307d56d14f2d465ec9bc2ae67d475..27b74352cccf08940c860421e19f7825e4aa884e 100644 (file)
@@ -372,17 +372,20 @@ static int rcu_preempt_blocked_readers_cgp(struct rcu_node *rnp)
 
 static void rcu_preempt_read_enter(void)
 {
-       current->rcu_read_lock_nesting++;
+       WRITE_ONCE(current->rcu_read_lock_nesting, READ_ONCE(current->rcu_read_lock_nesting) + 1);
 }
 
 static int rcu_preempt_read_exit(void)
 {
-       return --current->rcu_read_lock_nesting;
+       int ret = READ_ONCE(current->rcu_read_lock_nesting) - 1;
+
+       WRITE_ONCE(current->rcu_read_lock_nesting, ret);
+       return ret;
 }
 
 static void rcu_preempt_depth_set(int val)
 {
-       current->rcu_read_lock_nesting = val;
+       WRITE_ONCE(current->rcu_read_lock_nesting, val);
 }
 
 /*