• Mark Rutland's avatar
    locking/atomic: scripts: restructure fallback ifdeffery · 9257959a
    Mark Rutland authored
    Currently the various ordering variants of an atomic operation are
    defined in groups of full/acquire/release/relaxed ordering variants with
    some shared ifdeffery and several potential definitions of each ordering
    variant in different branches of the shared ifdeffery.
    
    As an ordering variant can have several potential definitions down
    different branches of the shared ifdeffery, it can be painful for a
    human to find a relevant definition, and we don't have a good location
    to place anything common to all definitions of an ordering variant (e.g.
    kerneldoc).
    
    Historically the grouping of full/acquire/release/relaxed ordering
    variants was necessary as we filled in the missing atomics in the same
    namespace as the architecture used. It would be easy to accidentally
    define one ordering fallback in terms of another ordering fallback with
    redundant barriers, and avoiding that would otherwise require a lot of
    baroque ifdeffery.
    
    With recent changes we no longer need to fill in the missing atomics in
    the arch_atomic*_<op>() namespace, and only need to fill in the
    raw_atomic*_<op>() namespace. Due to this, there's no risk of a
    namespace collision, and we can define each raw_atomic*_<op> ordering
    variant with its own ifdeffery checking for the arch_atomic*_<op>
    ordering variants.
    
    Restructure the fallbacks in this way, with each ordering variant having
    its own ifdeffery of the form:
    
    | #if defined(arch_atomic_fetch_andnot_acquire)
    | #define raw_atomic_fetch_andnot_acquire arch_atomic_fetch_andnot_acquire
    | #elif defined(arch_atomic_fetch_andnot_relaxed)
    | static __always_inline int
    | raw_atomic_fetch_andnot_acquire(int i, atomic_t *v)
    | {
    | 	int ret = arch_atomic_fetch_andnot_relaxed(i, v);
    | 	__atomic_acquire_fence();
    | 	return ret;
    | }
    | #elif defined(arch_atomic_fetch_andnot)
    | #define raw_atomic_fetch_andnot_acquire arch_atomic_fetch_andnot
    | #else
    | static __always_inline int
    | raw_atomic_fetch_andnot_acquire(int i, atomic_t *v)
    | {
    | 	return raw_atomic_fetch_and_acquire(~i, v);
    | }
    | #endif
    
    Note that where there's no relevant arch_atomic*_<op>() ordering
    variant, we'll define the operation in terms of a distinct
    raw_atomic*_<otherop>(), as this itself might have been filled in with a
    fallback.
    
    As we now generate the raw_atomic*_<op>() implementations directly, we
    no longer need the trivial wrappers, so they are removed.
    
    This makes the ifdeffery easier to follow, and will allow for further
    improvements in subsequent patches.
    
    There should be no functional change as a result of this patch.
    Signed-off-by: default avatarMark Rutland <mark.rutland@arm.com>
    Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
    Reviewed-by: default avatarKees Cook <keescook@chromium.org>
    Link: https://lore.kernel.org/r/20230605070124.3741859-21-mark.rutland@arm.com
    9257959a
gen-atomics.sh 626 Bytes