Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

doc: Update rcu_dereference.rst

This commit updates rcu_dereference.rst to reflect RCU additions and
changes over the past few years

Signed-off-by: Paul E. McKenney <paulmck@kernel.org>

+16 -5
+16 -5
Documentation/RCU/rcu_dereference.rst
··· 19 19 can reload the value, and won't your code have fun with two 20 20 different values for a single pointer! Without rcu_dereference(), 21 21 DEC Alpha can load a pointer, dereference that pointer, and 22 - return data preceding initialization that preceded the store of 23 - the pointer. 22 + return data preceding initialization that preceded the store 23 + of the pointer. (As noted later, in recent kernels READ_ONCE() 24 + also prevents DEC Alpha from playing these tricks.) 24 25 25 26 In addition, the volatile cast in rcu_dereference() prevents the 26 27 compiler from deducing the resulting pointer value. Please see ··· 35 34 takes on the role of the lockless_dereference() primitive that 36 35 was removed in v4.15. 37 36 38 - - You are only permitted to use rcu_dereference on pointer values. 37 + - You are only permitted to use rcu_dereference() on pointer values. 39 38 The compiler simply knows too much about integral values to 40 39 trust it to carry dependencies through integer operations. 41 40 There are a very few exceptions, namely that you can temporarily ··· 241 240 struct foo *q; 242 241 int r1, r2; 243 242 243 + rcu_read_lock(); 244 244 p = rcu_dereference(gp2); 245 245 if (p == NULL) 246 246 return; ··· 250 248 if (p == q) { 251 249 /* The compiler decides that q->c is same as p->c. */ 252 250 r2 = p->c; /* Could get 44 on weakly order system. */ 251 + } else { 252 + r2 = p->c - r1; /* Unconditional access to p->c. */ 253 253 } 254 + rcu_read_unlock(); 254 255 do_something_with(r1, r2); 255 256 } 256 257 ··· 302 297 struct foo *q; 303 298 int r1, r2; 304 299 300 + rcu_read_lock(); 305 301 p = rcu_dereference(gp2); 306 302 if (p == NULL) 307 303 return; ··· 312 306 if (p == q) { 313 307 /* The compiler decides that q->c is same as p->c. */ 314 308 r2 = p->c; /* Locking guarantees r2 == 144. */ 309 + } else { 310 + spin_lock(&q->lock); 311 + r2 = q->c - r1; 312 + spin_unlock(&q->lock); 315 313 } 314 + rcu_read_unlock(); 316 315 spin_unlock(&p->lock); 317 316 do_something_with(r1, r2); 318 317 } ··· 375 364 compiler to make the return values independent of the load from "gp", 376 365 in turn destroying the ordering between this load and the loads of the 377 366 return values. This can result in "p->b" returning pre-initialization 378 - garbage values. 367 + garbage values on weakly ordered systems. 379 368 380 369 In short, rcu_dereference() is *not* optional when you are going to 381 370 dereference the resulting pointer. ··· 441 430 SPARSE CHECKING OF RCU-PROTECTED POINTERS 442 431 ----------------------------------------- 443 432 444 - The sparse static-analysis tool checks for direct access to RCU-protected 433 + The sparse static-analysis tool checks for non-RCU access to RCU-protected 445 434 pointers, which can result in "interesting" bugs due to compiler 446 435 optimizations involving invented loads and perhaps also load tearing. 447 436 For example, suppose someone mistakenly does something like this::