Commit a3fbf860 authored by Paul E. McKenney's avatar Paul E. McKenney
Browse files

doc: Clarify rcu_assign_pointer() and rcu_dereference() ordering



This commit expands on the ordering properties of rcu_assign_pointer()
and rcu_dereference(), outlining their constraints on CPUs and compilers.

Reported-by: default avatarRao Shoaib <rao.shoaib@oracle.com>
Signed-off-by: default avatarPaul E. McKenney <paulmck@kernel.org>
parent 293d9013
Loading
Loading
Loading
Loading
+19 −11
Original line number Diff line number Diff line
@@ -250,21 +250,25 @@ rcu_assign_pointer()
^^^^^^^^^^^^^^^^^^^^
	void rcu_assign_pointer(p, typeof(p) v);

	Yes, rcu_assign_pointer() **is** implemented as a macro, though it
	would be cool to be able to declare a function in this manner.
	(Compiler experts will no doubt disagree.)
	Yes, rcu_assign_pointer() **is** implemented as a macro, though
	it would be cool to be able to declare a function in this manner.
	(And there has been some discussion of adding overloaded functions
	to the C language, so who knows?)

	The updater uses this spatial macro to assign a new value to an
	RCU-protected pointer, in order to safely communicate the change
	in value from the updater to the reader.  This is a spatial (as
	opposed to temporal) macro.  It does not evaluate to an rvalue,
	but it does execute any memory-barrier instructions required
	for a given CPU architecture.  Its ordering properties are that
	of a store-release operation.

	Perhaps just as important, it serves to document (1) which
	pointers are protected by RCU and (2) the point at which a
	given structure becomes accessible to other CPUs.  That said,
	but it does provide any compiler directives and memory-barrier
	instructions required for a given compile or CPU architecture.
	Its ordering properties are that of a store-release operation,
	that is, any prior loads and stores required to initialize the
	structure are ordered before the store that publishes the pointer
	to that structure.

	Perhaps just as important, rcu_assign_pointer() serves to document
	(1) which pointers are protected by RCU and (2) the point at which
	a given structure becomes accessible to other CPUs.  That said,
	rcu_assign_pointer() is most frequently used indirectly, via
	the _rcu list-manipulation primitives such as list_add_rcu().

@@ -283,7 +287,11 @@ rcu_dereference()
	executes any needed memory-barrier instructions for a given
	CPU architecture.  Currently, only Alpha needs memory barriers
	within rcu_dereference() -- on other CPUs, it compiles to a
	volatile load.
	volatile load.	However, no mainstream C compilers respect
	address dependencies, so rcu_dereference() uses volatile casts,
	which, in combination with the coding guidelines listed in
	rcu_dereference.rst, prevent current compilers from breaking
	these dependencies.

	Common coding practice uses rcu_dereference() to copy an
	RCU-protected pointer to a local variable, then dereferences