Search code examples
clinux-kernelcompilationmacros

Why does the kernel use macro definitions that expand to the same before and after?


I found that some macro definitions in the kernel code expand to the same before and after. Why go through the trouble of defining this macro?

For example, in /arch/arm64/include/asm/atomic.h :

#define arch_atomic_add_return_relaxed      arch_atomic_add_return_relaxed
#define arch_atomic_add_return_acquire      arch_atomic_add_return_acquire
#define arch_atomic_add_return_release      arch_atomic_add_return_release
#define arch_atomic_add_return              arch_atomic_add_return

Solution

  • A macro that expands to itself has no effect if used in normal code, but it counts as a defined macro for #ifdef, #ifndef, and #if defined.

    This is useful when you want to define some identifier not as a macro, but you also want to be able to conditionally compile code based on whether or not that identifier has been defined. That's what seems to be going on in your example; arch/arm64/include/asm/atomic.h pairs the macro definitions that you quoted with (macros that expand to) concrete definitions as inline functions:

    #define ATOMIC_FETCH_OP(name, op)                                       \
    static __always_inline int arch_##op##name(int i, atomic_t *v)          \
    {                                                                       \
            return __lse_ll_sc_body(op##name, i, v);                        \
    }
    
    #define ATOMIC_FETCH_OPS(op)                                            \
            ATOMIC_FETCH_OP(_relaxed, op)                                   \
            ATOMIC_FETCH_OP(_acquire, op)                                   \
            ATOMIC_FETCH_OP(_release, op)                                   \
            ATOMIC_FETCH_OP(        , op)
    
    ATOMIC_FETCH_OPS(atomic_add_return)
    
    #define arch_atomic_add_return_relaxed          arch_atomic_add_return_relaxed
    #define arch_atomic_add_return_acquire          arch_atomic_add_return_acquire
    #define arch_atomic_add_return_release          arch_atomic_add_return_release
    #define arch_atomic_add_return                  arch_atomic_add_return
    

    After preprocessing the definition of arch_atomic_add_return will be something like

    static inline __attribute__((always_inline))
    int arch_atomic_add_return(int i, atomic_t *v)
    {
        return __lse_ll_sc_body(atomic_add_return, i, v);
    }
    

    Meanwhile, over in include/linux/atomic-arch-fallback.h there is a conditional definition of arch_atomic_add_return:

    #ifndef arch_atomic_add_return
    static __always_inline int
    arch_atomic_add_return(int i, atomic_t *v)
    {
        int ret;
        __atomic_pre_full_fence();
        ret = arch_atomic_add_return_relaxed(i, v);
        __atomic_post_full_fence();
        return ret;
    }
    #define arch_atomic_add_return arch_atomic_add_return
    #endif
    

    Thus, the point of the #define in arch/arm64/include/asm/atomic.h is to tell include/linux/atomic-arch-fallback.h "don't define arch_atomic_add_return, I already did that".