Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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
like image 357
Frontier_Setter Avatar asked Dec 31 '25 21:12

Frontier_Setter


2 Answers

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".

like image 56
zwol Avatar answered Jan 02 '26 14:01

zwol


If you search for one of them, you will see that in include/linux/atomic-arch-fallback.h there are #ifndef checks to use fallback function definitions when the macro is not defined:

#ifndef arch_atomic_add_return_relaxed
#define arch_atomic_add_return_acquire arch_atomic_add_return
#define arch_atomic_add_return_release arch_atomic_add_return
#define arch_atomic_add_return_relaxed arch_atomic_add_return
#else /* arch_atomic_add_return_relaxed */

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

#ifndef arch_atomic_add_return_release
static __always_inline int
arch_atomic_add_return_release(int i, atomic_t *v)
{
    __atomic_release_fence();
    return arch_atomic_add_return_relaxed(i, v);
}
#define arch_atomic_add_return_release arch_atomic_add_return_release
#endif

#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

#endif /* arch_atomic_add_return_relaxed */
like image 34
ouuan Avatar answered Jan 02 '26 13:01

ouuan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!