• Christoph Lameter's avatar
    this_cpu: Introduce this_cpu_ptr() and generic this_cpu_* operations · 7340a0b1
    Christoph Lameter authored
    This patch introduces two things: First this_cpu_ptr and then per cpu
    atomic operations.
    
    this_cpu_ptr
    ------------
    
    A common operation when dealing with cpu data is to get the instance of the
    cpu data associated with the currently executing processor. This can be
    optimized by
    
    this_cpu_ptr(xx) = per_cpu_ptr(xx, smp_processor_id).
    
    The problem with per_cpu_ptr(x, smp_processor_id) is that it requires
    an array lookup to find the offset for the cpu. Processors typically
    have the offset for the current cpu area in some kind of (arch dependent)
    efficiently accessible register or memory location.
    
    We can use that instead of doing the array lookup to speed up the
    determination of the address of the percpu variable. This is particularly
    significant because these lookups occur in performance critical paths
    of the core kernel. this_cpu_ptr() can avoid memory accesses and
    
    this_cpu_ptr comes in two flavors. The preemption context matters since we
    are referring the the currently executing processor. In many cases we must
    insure that the processor does not change while a code segment is executed.
    
    __this_cpu_ptr 	-> Do not check for preemption context
    this_cpu_ptr	-> Check preemption context
    
    The parameter to these operations is a per cpu pointer. This can be the
    address of a statically defined per cpu variable (&per_cpu_var(xxx)) or
    the address of a per cpu variable allocated with the per cpu allocator.
    
    per cpu atomic operations: this_cpu_*(var, val)
    -----------------------------------------------
    this_cpu_* operations (like this_cpu_add(struct->y, value) operate on
    abitrary scalars that are members of structures allocated with the new
    per cpu allocator. They can also operate on static per_cpu variables
    if they are passed to per_cpu_var() (See patch to use this_cpu_*
    operations for vm statistics).
    
    These operations are guaranteed to be atomic vs preemption when modifying
    the scalar. The calculation of the per cpu offset is also guaranteed to
    be atomic at the same time. This means that a this_cpu_* operation can be
    safely used to modify a per cpu variable in a context where interrupts are
    enabled and preemption is allowed. Many architectures can perform such
    a per cpu atomic operation with a single instruction.
    
    Note that the atomicity here is different from regular atomic operations.
    Atomicity is only guaranteed for data accessed from the currently executing
    processor. Modifications from other processors are still possible. There
    must be other guarantees that the per cpu data is not modified from another
    processor when using these instruction. The per cpu atomicity is created
    by the fact that the processor either executes and instruction or not.
    Embedded in the instruction is the relocation of the per cpu address to
    the are reserved for the current processor and the RMW action. Therefore
    interrupts or preemption cannot occur in the mids of this processing.
    
    Generic fallback functions are used if an arch does not define optimized
    this_cpu operations. The functions come also come in the two flavors used
    for this_cpu_ptr().
    
    The firstparameter is a scalar that is a member of a structure allocated
    through allocpercpu or a per cpu variable (use per_cpu_var(xxx)). The
    operations are similar to what percpu_add() and friends do.
    
    this_cpu_read(scalar)
    this_cpu_write(scalar, value)
    this_cpu_add(scale, value)
    this_cpu_sub(scalar, value)
    this_cpu_inc(scalar)
    this_cpu_dec(scalar)
    this_cpu_and(scalar, value)
    this_cpu_or(scalar, value)
    this_cpu_xor(scalar, value)
    
    Arch code can override the generic functions and provide optimized atomic
    per cpu operations. These atomic operations must provide both the relocation
    (x86 does it through a segment override) and the operation on the data in a
    single instruction. Otherwise preempt needs to be disabled and there is no
    gain from providing arch implementations.
    
    A third variant is provided prefixed by irqsafe_. These variants are safe
    against hardware interrupts on the *same* processor (all per cpu atomic
    primitives are *always* *only* providing safety for code running on the
    *same* processor!). The increment needs to be implemented by the hardware
    in such a way that it is a single RMW instruction that is either processed
    before or after an interrupt.
    
    cc: David Howells <dhowells@redhat.com>
    cc: Ingo Molnar <mingo@elte.hu>
    cc: Rusty Russell <rusty@rustcorp.com.au>
    cc: Eric Dumazet <dada1@cosmosbay.com>
    Signed-off-by: default avatarChristoph Lameter <cl@linux-foundation.org>
    Signed-off-by: default avatarTejun Heo <tj@kernel.org>
    7340a0b1
percpu.h 2.86 KB