qio: Remove the old qnonblock()
[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 PASTE_THEM(x, y) x ## y
43 #define PASTE(x, y) PASTE_THEM(x, y)
44
45 #define PERCPU_VARNAME(var) PASTE(__percpu_, var)
46
47 #define PERCPU_START_VAR PASTE(__start_, PERCPU_SECTION)
48 #define PERCPU_STOP_VAR PASTE(__stop_, PERCPU_SECTION)
49
50 #define PERCPU_SIZE (PERCPU_STOP_VAR - PERCPU_START_VAR)
51 #define PERCPU_OFFSET(var) ((char *) &(var) - PERCPU_START_VAR)
52
53 #define __PERCPU_VARPTR(var, cpu)                                                                               \
54         ({                                                                                                                                      \
55                 typeof(var) *__cv;                                                                                              \
56                 if (likely(percpu_base))                                                                                \
57                         __cv = (typeof(var) *) (percpu_base + cpu * PERCPU_SIZE +       \
58                                                     PERCPU_OFFSET(var));                                \
59                 else                                                                                                                    \
60                         __cv = &var;                                                                                            \
61                 __cv;                                                                                                                   \
62         })
63 #define _PERCPU_VARPTR(var, cpu) __PERCPU_VARPTR(PERCPU_VARNAME(var), cpu)
64 #define PERCPU_VARPTR(var) __PERCPU_VARPTR(PERCPU_VARNAME(var), core_id())
65
66 #define _PERCPU_VAR(var, cpu) (*__PERCPU_VARPTR(PERCPU_VARNAME(var), cpu))
67 #define PERCPU_VAR(var) (*__PERCPU_VARPTR(PERCPU_VARNAME(var), core_id()))
68
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)))
74
75 #define PERCPU_INIT_SECTION __percpu_init
76 #define PERCPU_INIT_SECTION_STR STRINGIFY(PERCPU_INIT_SECTION)
77
78 #define PERCPU_INIT_START_VAR PASTE(__start_, PERCPU_INIT_SECTION)
79 #define PERCPU_INIT_STOP_VAR PASTE(__stop_, PERCPU_INIT_SECTION)
80
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)
85
86 extern char __attribute__((weak)) PERCPU_START_VAR[];
87 extern char __attribute__((weak)) PERCPU_STOP_VAR[];
88 extern char *percpu_base;
89
90 void percpu_init(void);