1 /* Copyright (c) 2015 Google Inc
2 * Davide Libenzi <dlibenzi@google.com>
3 * See LICENSE for details.
5 * The per CPU utility macros allow file local declaration of per CPU variables.
6 * When a struct my_struct needs to have a per CPU instance, one would declare
9 * static DEFINE_PERCPU(struct my_struct, my_data);
11 * The per CPU data can then be accessed with either of those forms:
13 * struct my_struct *ptr = PERCPU_VARPTR(my_data);
14 * PERCPU_VAR(my_data).field = 17;
16 * When the per CPU data has complex initialization, it is possible to register
17 * functions which will be called immediately after the per CPU data is created:
19 * DEFINE_PERCPU_INIT(my_init);
21 * Then the my_init() function would just:
23 * static void my_init(void)
25 * for (int i = 0; i < num_cores; i++) {
26 * struct my_struct *ptr = _PERCPU_VARPTR(my_data, i);
28 * // Initialize ptr data
35 #include <sys/types.h>
36 #include <arch/topology.h>
37 #include <ros/common.h>
39 #define PERCPU_SECTION __percpu
40 #define PERCPU_SECTION_STR STRINGIFY(PERCPU_SECTION)
42 #define PASTE_THEM(x, y) x ## y
43 #define PASTE(x, y) PASTE_THEM(x, y)
45 #define PERCPU_VARNAME(var) PASTE(__percpu_, var)
47 #define PERCPU_START_VAR PASTE(__start_, PERCPU_SECTION)
48 #define PERCPU_STOP_VAR PASTE(__stop_, PERCPU_SECTION)
50 #define PERCPU_SIZE (PERCPU_STOP_VAR - PERCPU_START_VAR)
51 #define PERCPU_OFFSET(var) ((char *) &(var) - PERCPU_START_VAR)
53 #define __PERCPU_VARPTR(var, cpu) \
56 if (likely(percpu_base)) \
57 __cv = (typeof(var) *) (percpu_base + cpu * PERCPU_SIZE + \
58 PERCPU_OFFSET(var)); \
63 #define _PERCPU_VARPTR(var, cpu) __PERCPU_VARPTR(PERCPU_VARNAME(var), cpu)
64 #define PERCPU_VARPTR(var) __PERCPU_VARPTR(PERCPU_VARNAME(var), core_id())
66 #define _PERCPU_VAR(var, cpu) (*__PERCPU_VARPTR(PERCPU_VARNAME(var), cpu))
67 #define PERCPU_VAR(var) (*__PERCPU_VARPTR(PERCPU_VARNAME(var), core_id()))
69 #define DEFINE_PERCPU(type, var) \
70 type PERCPU_VARNAME(var) __attribute__ ((section (PERCPU_SECTION_STR)))
71 #define DECLARE_PERCPU(type, var) \
72 extern type PERCPU_VARNAME(var) \
73 __attribute__ ((section (PERCPU_SECTION_STR)))
75 #define PERCPU_INIT_SECTION __percpu_init
76 #define PERCPU_INIT_SECTION_STR STRINGIFY(PERCPU_INIT_SECTION)
78 #define PERCPU_INIT_START_VAR PASTE(__start_, PERCPU_INIT_SECTION)
79 #define PERCPU_INIT_STOP_VAR PASTE(__stop_, PERCPU_INIT_SECTION)
81 #define DEFINE_PERCPU_INIT(func) \
82 static void func(void); \
83 void (* const PERCPU_VARNAME(func))(void) \
84 __attribute__ ((section (PERCPU_INIT_SECTION_STR))) = (func)
86 extern char __attribute__((weak)) PERCPU_START_VAR[];
87 extern char __attribute__((weak)) PERCPU_STOP_VAR[];
88 extern char *percpu_base;
90 void percpu_init(void);