Most of the this_cpu_*() operations may be used in preemptible code, but not this_cpu_ptr(), and for good reasons. Therefore, better explain the reasons and call out raw_cpu_ptr() as an alternative in certain very special cases. Signed-off-by: Paul E. McKenney <paulmck@xxxxxxxxxx> Cc: Jonathan Corbet <corbet@xxxxxxx> Cc: Peter Zijlstra <peterz@xxxxxxxxxxxxx> Cc: Mark Rutland <mark.rutland@xxxxxxx> Cc: Boqun Feng <boqun.feng@xxxxxxxxx> Cc: <linux-doc@xxxxxxxxxxxxxxx> --- Documentation/core-api/this_cpu_ops.rst | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/Documentation/core-api/this_cpu_ops.rst b/Documentation/core-api/this_cpu_ops.rst index 91acbcf30e9bd..11e3e48731553 100644 --- a/Documentation/core-api/this_cpu_ops.rst +++ b/Documentation/core-api/this_cpu_ops.rst @@ -138,12 +138,22 @@ get_cpu/put_cpu sequence requires. No processor number is available. Instead, the offset of the local per cpu area is simply added to the per cpu offset. -Note that this operation is usually used in a code segment when -preemption has been disabled. The pointer is then used to -access local per cpu data in a critical section. When preemption -is re-enabled this pointer is usually no longer useful since it may -no longer point to per cpu data of the current processor. - +Note that this operation can only be used in code segments where +smp_processor_id() may be used, for example, where preemption has been +disabled. The pointer is then used to access local per cpu data in a +critical section. When preemption is re-enabled this pointer is usually +no longer useful since it may no longer point to per cpu data of the +current processor. + +The special cases where it makes sense do obtain a per-CPU pointer in +preemptible code are addressed by raw_cpu_ptr(), but please note that such +use cases need to handle cases where two different CPUs are accessing +the same per cpu variable, which might well be that of a third CPU. +These use cases are typically performance optimizations. For example, +SRCU implements a pair of counters as a pair of per-CPU variables, +and rcu_read_lock_nmisafe() uses raw_cpu_ptr() to get a pointer to some +CPU's counter, and uses atomic_inc_long() to handle migration between +the raw_cpu_ptr() and the atomic_inc_long(). Per cpu variables and offsets ----------------------------- -- 2.40.1