How to ensure the uniqueness of global characters and limit their volume in C?

The following is a trick used in the Linux kernel for pricing. As noted in the commentary, he can achieve these two goals:

Area 1.enforce.

2. Provide uniqueness, even static.

This is how magic plays (for simplicity, I'm inferior to some MACROs):

/*
 * __pcpu_scope_* dummy variable is used to enforce scope.  It
 * receives the static modifier when it used in front of
 * DEFINE_PER_CPU() and will trigger build failure if
 * DECLARE_PER_CPU() is used for the same variable.
 *
 * __pcpu_unique_* dummy variable is used to enforce symbol uniqueness
 * such that hidden weak symbol collision, which will cause unrelated
 * variables to share the same address, can be detected during build.
 */
 #define DECLARE_PER_CPU_SECTION(type, name, sec)                        \
 extern __attribute__((section(".discard"), unused))                     \
               char __pcpu_scope_##name;                                 \
 extern __attribute__((section(sec))) __typeof__(type) name

 #define DEFINE_PER_CPU_SECTION(type, name, sec)                         \
 __attribute__((section(".discard"), unused)) char __pcpu_scope_##name;  \
 extern __attribute__((section(".discard"), unused))                     \
             char __pcpu_unique_##name;                                  \
 __attribute__((section(".discard"), unused)) char __pcpu_unique_##name; \
 __attribute__((section(sec)))  __attribute__((weak))                    \
              __typeof__(type) name

My questions

  • For goal number 1. How can this ensure compliance with the scope? Does it work like this:

    When DECLARE * and DEFINE * exist in the same translation system , it turns the variable in question into an internal connection, and thus any additional DECLARE * for the same variable will cause the assembly to fail (because they do not agree with the binding)

    But if so, then

    • -? C99 6.9.2.2 ( ) , ?
    • "- -mutiple-declarations-are-OK" ?
  • β„– 2 __pcpu_unique _ ## (, - , - ), , trcik, __pcpu_scope _ ##, ?

FYI, : http://lxr.linux.no/linux+v3.9/include/linux/percpu-defs.h#L61

+5
1

, . . ARM vmlinux.lds.S, vmlinux.lds.h percpu.h; . ".discard" , ; .

PER_CPU, PER_CPU_FIRST, PER_CPU_SHARED_ALIGNED .. .

.

 #define DECLARE_PER_CPU_SECTION(type, name, sec)                        \
 extern __attribute__((section(".discard"), unused))                     \
               char __pcpu_scope_##name;                                 \
 extern __attribute__((section(PER_CPU_BASE_SECTION sec))) __typeof__(type) name

sec ; note PER_CPU_BASE_SECTION .

, ... , . If, .... ,

static DEFINE_PER_CPU_PAGE_ALIGNED(... /* Cause error with DECLARE */
DEFINE_PER_CPU(unsigned int, irq_count) = -1; /* Fine with DECLARE */

, GNU (, , ), , , kbuild.

, ,

 * s390 and alpha modules require percpu variables to be defined as
 * weak to force the compiler to generate GOT based external
 * references for them.  This is necessary because percpu sections
 * will be located outside of the usually addressable area.
 * This definition puts the following two extra restrictions when
 * defining percpu variables.
 *
 * 1. The symbol must be globally unique, even the static ones.
 * 2. Static percpu variables cannot be defined inside a function.
 *
 * Archs which need weak percpu definitions should define
 * ARCH_NEEDS_WEAK_PER_CPU in asm/percpu.h when necessary.

.. __attribute__((weak)) , . #else, weak .

, ,

β„–1. ?

,

DECLARE_PER_CPU_PAGE_ALIGNED(int,foobar);
static DEFINE_PER_CPU_PAGE_ALIGNED(int,foobar);

β„–2,... __pcpu_unique_##name, ?

weak . __pcpu_unique_##name weak, , weak .

. Gcc , .

+4

All Articles