@@ -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 */
270282static 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
280292void __srcu_check_read_flavor (struct srcu_struct * ssp , int read_flavor );
0 commit comments