ktest: Add minor fixes for kernel tests
[akaros.git] / kern / include / percpu.h
1 /* Copyright (c) 2015 Google Inc
2  * Davide Libenzi <dlibenzi@google.com>
3  * See LICENSE for details.
4  *
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
7  * something like:
8  *
9  *   static DEFINE_PERCPU(struct my_struct, my_data);
10  *
11  * The per CPU data can then be accessed with either of those forms:
12  *
13  *   struct my_struct *ptr = PERCPU_VARPTR(my_data);
14  *   PERCPU_VAR(my_data).field = 17;
15  *
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:
18  *
19  *   DEFINE_PERCPU_INIT(my_init);
20  *
21  * Then the my_init() function would just:
22  *
23  *   static void my_init(void)
24  *   {
25  *       for (int i = 0; i < num_cores; i++) {
26  *           struct my_struct *ptr = _PERCPU_VARPTR(my_data, i);
27  *
28  *           // Initialize ptr data
29  *       }
30  *   }
31  */
32
33 #pragma once
34
35 #include <sys/types.h>
36 #include <arch/topology.h>
37 #include <ros/common.h>
38
39 #define PERCPU_SECTION __percpu
40 #define PERCPU_SECTION_STR STRINGIFY(PERCPU_SECTION)
41
42 #define PERCPU_VARNAME(var) PASTE(__percpu_, var)
43
44 #define PERCPU_START_VAR PASTE(__start_, PERCPU_SECTION)
45 #define PERCPU_STOP_VAR PASTE(__stop_, PERCPU_SECTION)
46
47 #define PERCPU_SIZE (PERCPU_STOP_VAR - PERCPU_START_VAR)
48 #define PERCPU_OFFSET(var) ((char *) &(var) - PERCPU_START_VAR)
49
50 #define __PERCPU_VARPTR(var, cpu)                                                                               \
51         ({                                                                                                                                      \
52                 typeof(var) *__cv;                                                                                              \
53                 if (likely(percpu_base))                                                                                \
54                         __cv = (typeof(var) *) (percpu_base + cpu * PERCPU_SIZE +       \
55                                                     PERCPU_OFFSET(var));                                \
56                 else                                                                                                                    \
57                         __cv = &var;                                                                                            \
58                 __cv;                                                                                                                   \
59         })
60 #define _PERCPU_VARPTR(var, cpu) __PERCPU_VARPTR(PERCPU_VARNAME(var), cpu)
61 #define PERCPU_VARPTR(var) __PERCPU_VARPTR(PERCPU_VARNAME(var), core_id())
62
63 #define _PERCPU_VAR(var, cpu) (*__PERCPU_VARPTR(PERCPU_VARNAME(var), cpu))
64 #define PERCPU_VAR(var) (*__PERCPU_VARPTR(PERCPU_VARNAME(var), core_id()))
65
66 #define DEFINE_PERCPU(type, var)                                                \
67         __typeof__(type) PERCPU_VARNAME(var) __attribute__ ((section (PERCPU_SECTION_STR)))
68 #define DECLARE_PERCPU(type, var)                                                               \
69         extern __typeof__(type) PERCPU_VARNAME(var)                                     \
70                 __attribute__ ((section (PERCPU_SECTION_STR)))
71
72 #define PERCPU_INIT_SECTION __percpu_init
73 #define PERCPU_INIT_SECTION_STR STRINGIFY(PERCPU_INIT_SECTION)
74
75 #define PERCPU_INIT_START_VAR PASTE(__start_, PERCPU_INIT_SECTION)
76 #define PERCPU_INIT_STOP_VAR PASTE(__stop_, PERCPU_INIT_SECTION)
77
78 #define DEFINE_PERCPU_INIT(func)                                                                                \
79         static void func(void);                                                                                         \
80         void (* const PERCPU_VARNAME(func))(void)                                                       \
81                 __attribute__ ((section (PERCPU_INIT_SECTION_STR))) = (func)
82
83 extern char __attribute__((weak)) PERCPU_START_VAR[];
84 extern char __attribute__((weak)) PERCPU_STOP_VAR[];
85 extern char *percpu_base;
86
87 void percpu_init(void);