Add AKAROS_TOOLCHAINS (XCC)
[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  * Static percpu variables:
6  *
7  * The per CPU utility macros allow file local declaration of per CPU variables.
8  * When a struct my_struct needs to have a per CPU instance, one would declare
9  * something like:
10  *
11  *   static DEFINE_PERCPU(struct my_struct, my_data);
12  *
13  * The per CPU data can then be accessed with either of those forms:
14  *
15  *   struct my_struct *ptr = PERCPU_VARPTR(my_data);
16  *   PERCPU_VAR(my_data).field = 17;
17  *
18  * When the per CPU data has complex initialization, it is possible to register
19  * functions which will be called immediately after the per CPU data is created:
20  *
21  *   DEFINE_PERCPU_INIT(my_init);
22  *
23  * Then the my_init() function would just:
24  *
25  *   static void my_init(void)
26  *   {
27  *       for (int i = 0; i < num_cores; i++) {
28  *           struct my_struct *ptr = _PERCPU_VARPTR(my_data, i);
29  *
30  *           // Initialize ptr data
31  *       }
32  *   }
33  *
34  *
35  * Dynamic percpu variables:
36  *
37  * You can also declare per-cpu variables dynamically, though it's not quite the
38  * same as the static variables.  Careful - We return *pointers*, and our users
39  * need to dereference them when using any of the PERCPU_ helpers.
40  *
41  * Example (per core u64s)  Note each *use* dereferences 'foos':
42  *
43  * uint64_t *foos = percpu_zalloc(uint64_t, MEM_WAIT);
44  *
45  * // Each core increments
46  * PERCPU_VAR(*foos)++;
47  *
48  * // One core can print them all out
49  * for_each_core(i)
50  *      printk("Addr %p, value %lu\n", _PERCPU_VARPTR(*foos, i),
51  *             _PERCPU_VAR(*foos, i));
52  *
53  * // Free, but don't deref here.  'foos' is your handle.
54  * percpu_free(foos);
55  */
56
57 #pragma once
58
59 #include <sys/types.h>
60 #include <arch/topology.h>
61 #include <ros/common.h>
62
63 #define PERCPU_SECTION __percpu
64 #define PERCPU_SECTION_STR STRINGIFY(PERCPU_SECTION)
65
66 #define PERCPU_START_VAR PASTE(__start_, PERCPU_SECTION)
67 #define PERCPU_STOP_VAR PASTE(__stop_, PERCPU_SECTION)
68
69 #define PERCPU_DYN_SIZE 1024
70 #define PERCPU_STATIC_SIZE (PERCPU_STOP_VAR - PERCPU_START_VAR)
71 #define PERCPU_SIZE (PERCPU_STATIC_SIZE + PERCPU_DYN_SIZE)
72 #define PERCPU_OFFSET(var) ((char *) &(var) - PERCPU_START_VAR)
73
74 #define __PERCPU_VARPTR(var, cpu)                                       \
75 ({                                                                      \
76         typeof(var) *__cv;                                              \
77         if (likely(percpu_base))                                        \
78                 __cv = (typeof(var) *) (percpu_base + cpu * PERCPU_SIZE + \
79                                         PERCPU_OFFSET(var));            \
80         else                                                            \
81                 __cv = &var;                                            \
82         __cv;                                                           \
83 })
84 #define _PERCPU_VARPTR(var, cpu) __PERCPU_VARPTR(var, cpu)
85 #define PERCPU_VARPTR(var) __PERCPU_VARPTR(var, core_id())
86
87 #define _PERCPU_VAR(var, cpu) (*__PERCPU_VARPTR(var, cpu))
88 #define PERCPU_VAR(var) (*__PERCPU_VARPTR(var, core_id()))
89
90 #define DEFINE_PERCPU(type, var)                                                \
91         __typeof__(type) var __attribute__ ((section (PERCPU_SECTION_STR)))
92 #define DECLARE_PERCPU(type, var)                                       \
93         extern __typeof__(type) var                                     \
94                 __attribute__ ((section (PERCPU_SECTION_STR)))
95
96 #define PERCPU_INIT_SECTION __percpu_init
97 #define PERCPU_INIT_SECTION_STR STRINGIFY(PERCPU_INIT_SECTION)
98
99 #define PERCPU_INIT_START_VAR PASTE(__start_, PERCPU_INIT_SECTION)
100 #define PERCPU_INIT_STOP_VAR PASTE(__stop_, PERCPU_INIT_SECTION)
101
102 #define PERCPU_INIT_NAME(func) PASTE(__percpu_, func)
103 #define DEFINE_PERCPU_INIT(func)                                        \
104         static void func(void);                                         \
105         void (* const PERCPU_INIT_NAME(func))(void)                     \
106                 __attribute__ ((section (PERCPU_INIT_SECTION_STR))) = (func)
107
108 extern char __attribute__((weak)) PERCPU_START_VAR[];
109 extern char __attribute__((weak)) PERCPU_STOP_VAR[];
110 extern char *percpu_base;
111
112 void percpu_init(void);
113
114 #define percpu_alloc(x, flags) __percpu_alloc(sizeof(x), __alignof__(x), flags)
115 #define percpu_zalloc(x, flags) __percpu_zalloc(sizeof(x), __alignof__(x), \
116                                                 flags)
117 #define percpu_free(x) __percpu_free(x, sizeof(*x))
118
119 void *__percpu_alloc(size_t size, size_t align, int flags);
120 void *__percpu_zalloc(size_t size, size_t align, int flags);
121 void __percpu_free(void *base, size_t size);