Skip to content

Commit be97544

Browse files
committed
srcu: Document __srcu_read_{,un}lock_fast() implicit RCU readers
This commit documents the implicit RCU readers that are implied by the this_cpu_inc() and atomic_long_inc() operations in __srcu_read_lock_fast() and __srcu_read_unlock_fast(). While in the area, fix the documentation of the memory pairing of atomic_long_inc() in __srcu_read_lock_fast(). [ paulmck: Apply Joel Fernandes feedback. ] Signed-off-by: Paul E. McKenney <paulmck@kernel.org> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Cc: <bpf@vger.kernel.org>
1 parent cacadb6 commit be97544

1 file changed

Lines changed: 27 additions & 15 deletions

File tree

include/linux/srcutree.h

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -232,9 +232,27 @@ static inline struct srcu_ctr __percpu *__srcu_ctr_to_ptr(struct srcu_struct *ss
232232
* srcu_read_unlock_fast().
233233
*
234234
* Note that both this_cpu_inc() and atomic_long_inc() are RCU read-side
235-
* critical sections either because they disables interrupts, because they
236-
* are a single instruction, or because they are a read-modify-write atomic
237-
* operation, depending on the whims of the architecture.
235+
* critical sections either because they disables interrupts, because
236+
* they are a single instruction, or because they are read-modify-write
237+
* atomic operations, depending on the whims of the architecture.
238+
* This matters because the SRCU-fast grace-period mechanism uses either
239+
* synchronize_rcu() or synchronize_rcu_expedited(), that is, RCU,
240+
* *not* SRCU, in order to eliminate the need for the read-side smp_mb()
241+
* invocations that are used by srcu_read_lock() and srcu_read_unlock().
242+
* The __srcu_read_unlock_fast() function also relies on this same RCU
243+
* (again, *not* SRCU) trick to eliminate the need for smp_mb().
244+
*
245+
* The key point behind this RCU trick is that if any part of a given
246+
* RCU reader precedes the beginning of a given RCU grace period, then
247+
* the entirety of that RCU reader and everything preceding it happens
248+
* before the end of that same RCU grace period. Similarly, if any part
249+
* of a given RCU reader follows the end of a given RCU grace period,
250+
* then the entirety of that RCU reader and everything following it
251+
* happens after the beginning of that same RCU grace period. Therefore,
252+
* the operations labeled Y in __srcu_read_lock_fast() and those labeled Z
253+
* in __srcu_read_unlock_fast() are ordered against the corresponding SRCU
254+
* read-side critical section from the viewpoint of the SRCU grace period.
255+
* This is all the ordering that is required, hence no calls to smp_mb().
238256
*
239257
* This means that __srcu_read_lock_fast() is not all that fast
240258
* on architectures that support NMIs but do not supply NMI-safe
@@ -245,9 +263,9 @@ static inline struct srcu_ctr __percpu notrace *__srcu_read_lock_fast(struct src
245263
struct srcu_ctr __percpu *scp = READ_ONCE(ssp->srcu_ctrp);
246264

247265
if (!IS_ENABLED(CONFIG_NEED_SRCU_NMI_SAFE))
248-
this_cpu_inc(scp->srcu_locks.counter); /* Y */
266+
this_cpu_inc(scp->srcu_locks.counter); // Y, and implicit RCU reader.
249267
else
250-
atomic_long_inc(raw_cpu_ptr(&scp->srcu_locks)); /* Z */
268+
atomic_long_inc(raw_cpu_ptr(&scp->srcu_locks)); // Y, and implicit RCU reader.
251269
barrier(); /* Avoid leaking the critical section. */
252270
return scp;
253271
}
@@ -258,23 +276,17 @@ static inline struct srcu_ctr __percpu notrace *__srcu_read_lock_fast(struct src
258276
* different CPU than that which was incremented by the corresponding
259277
* srcu_read_lock_fast(), but it must be within the same task.
260278
*
261-
* Note that both this_cpu_inc() and atomic_long_inc() are RCU read-side
262-
* critical sections either because they disables interrupts, because they
263-
* are a single instruction, or because they are a read-modify-write atomic
264-
* operation, depending on the whims of the architecture.
265-
*
266-
* This means that __srcu_read_unlock_fast() is not all that fast
267-
* on architectures that support NMIs but do not supply NMI-safe
268-
* implementations of this_cpu_inc().
279+
* Please see the __srcu_read_lock_fast() function's header comment for
280+
* information on implicit RCU readers and NMI safety.
269281
*/
270282
static inline void notrace
271283
__srcu_read_unlock_fast(struct srcu_struct *ssp, struct srcu_ctr __percpu *scp)
272284
{
273285
barrier(); /* Avoid leaking the critical section. */
274286
if (!IS_ENABLED(CONFIG_NEED_SRCU_NMI_SAFE))
275-
this_cpu_inc(scp->srcu_unlocks.counter); /* Z */
287+
this_cpu_inc(scp->srcu_unlocks.counter); // Z, and implicit RCU reader.
276288
else
277-
atomic_long_inc(raw_cpu_ptr(&scp->srcu_unlocks)); /* Z */
289+
atomic_long_inc(raw_cpu_ptr(&scp->srcu_unlocks)); // Z, and implicit RCU reader.
278290
}
279291

280292
void __srcu_check_read_flavor(struct srcu_struct *ssp, int read_flavor);

0 commit comments

Comments
 (0)