3 struct Per_cpu_ctor_data
5 void (*func)(void *, unsigned);
9 #define DEFINE_PER_CPU_CTOR_UID(b) __per_cpu_ctor_ ## b
10 #define DEFINE_PER_CPU_CTOR_DATA(id) \
11 __attribute__((section(".bss.per_cpu_ctor_data"),used)) \
12 static Per_cpu_ctor_data DEFINE_PER_CPU_CTOR_UID(id);
16 #define DEFINE_PER_CPU_CTOR_DATA(id)
20 #include "static_init.h"
22 #include "context_base.h"
23 #include <type_traits>
25 #define DEFINE_PER_CPU_P(p) \
26 DEFINE_PER_CPU_CTOR_DATA(__COUNTER__) \
27 __attribute__((section(".per_cpu.data"),init_priority(0xfffe - p)))
29 #define DEFINE_PER_CPU DEFINE_PER_CPU_P(9)
30 #define DEFINE_PER_CPU_LATE DEFINE_PER_CPU_P(19)
35 static void init_ctors();
36 static void run_ctors(unsigned cpu);
37 static void run_late_ctors(unsigned cpu);
38 static bool valid(unsigned cpu);
41 template< typename T > class Per_cpu_ptr;
43 template< typename T >
44 class Per_cpu : private Per_cpu_data
46 friend class Per_cpu_ptr<T>;
50 T const &cpu(unsigned) const;
53 T const ¤t() const { return cpu(current_cpu()); }
54 T ¤t() { return cpu(current_cpu()); }
57 explicit Per_cpu(bool);
59 template<typename TEST>
60 unsigned find_cpu(TEST const &test) const
62 for (unsigned i = 0; i < Config::Max_num_cpus; ++i)
63 if (valid(i) && test(cpu(i)))
73 template< typename T >
74 class Per_cpu_ptr : private Per_cpu_data
77 typedef typename cxx::conditional<
78 cxx::is_const<T>::value,
79 Per_cpu<typename cxx::remove_cv<T>::type> const,
80 Per_cpu<typename cxx::remove_cv<T>::type> >::type Per_cpu_type;
83 Per_cpu_ptr(Per_cpu_type *o) : _p(&o->_d) {}
84 Per_cpu_ptr &operator = (Per_cpu_type *o)
91 T ¤t() { return cpu(current_cpu()); }
98 //---------------------------------------------------------------------------
101 #include <construction.h>
105 Per_cpu_data::valid(unsigned cpu)
116 template< typename T >
117 T const &Per_cpu<T>::cpu(unsigned) const { return _d; }
120 template< typename T >
121 T &Per_cpu<T>::cpu(unsigned) { return _d; }
124 template< typename T >
125 Per_cpu<T>::Per_cpu()
129 template< typename T >
130 Per_cpu<T>::Per_cpu(bool) : _d(0)
134 template< typename T >
135 T &Per_cpu_ptr<T>::cpu(unsigned) { return *_p; }
140 Per_cpu_data::init_ctors()
146 Per_cpu_data::run_ctors(unsigned)
148 extern ctor_function_t __PER_CPU_INIT_ARRAY_START__[];
149 extern ctor_function_t __PER_CPU_INIT_ARRAY_END__[];
150 run_ctor_functions(__PER_CPU_INIT_ARRAY_START__, __PER_CPU_INIT_ARRAY_END__);
152 extern ctor_function_t __PER_CPU_CTORS_LIST__[];
153 extern ctor_function_t __PER_CPU_CTORS_END__[];
154 run_ctor_functions(__PER_CPU_CTORS_LIST__, __PER_CPU_CTORS_END__);
159 Per_cpu_data::run_late_ctors(unsigned)
161 extern ctor_function_t __PER_CPU_LATE_INIT_ARRAY_START__[];
162 extern ctor_function_t __PER_CPU_LATE_INIT_ARRAY_END__[];
163 run_ctor_functions(__PER_CPU_LATE_INIT_ARRAY_START__,
164 __PER_CPU_LATE_INIT_ARRAY_END__);
166 extern ctor_function_t __PER_CPU_LATE_CTORS_LIST__[];
167 extern ctor_function_t __PER_CPU_LATE_CTORS_END__[];
168 run_ctor_functions(__PER_CPU_LATE_CTORS_LIST__, __PER_CPU_LATE_CTORS_END__);
172 //---------------------------------------------------------------------------
184 typedef Per_cpu_ctor_data Ctor;
189 void push_back(void (*func)(void*,unsigned), void *base);
190 unsigned len() const { return _len; }
191 Ctor const &operator [] (unsigned idx) const
193 extern Ctor _per_cpu_ctor_data_start[];
194 return _per_cpu_ctor_data_start[idx];
202 enum { Num_cpus = Config::Max_num_cpus + 1 }; // add one for the never running CPU
203 static long _offsets[Num_cpus] asm ("PER_CPU_OFFSETS");
204 static unsigned late_ctor_start;
205 static Ctor_vector ctors;
209 //---------------------------------------------------------------------------
213 #include <construction.h>
216 long Per_cpu_data::_offsets[Per_cpu_data::Num_cpus];
217 unsigned Per_cpu_data::late_ctor_start;
218 Per_cpu_data::Ctor_vector Per_cpu_data::ctors;
222 Per_cpu_data::Ctor_vector::push_back(void (*func)(void*,unsigned), void *base)
224 extern Ctor _per_cpu_ctor_data_start[];
225 extern Ctor _per_cpu_ctor_data_end[];
227 if (_per_cpu_ctor_data_start + _len >= _per_cpu_ctor_data_end)
228 panic("out of per_cpu_ctor_space");
230 Ctor &c = _per_cpu_ctor_data_start[_len++];
238 Per_cpu_data::valid(unsigned cpu)
239 { return cpu < Num_cpus && _offsets[cpu] != -1; }
241 IMPLEMENT inline template< typename T >
242 T const &Per_cpu<T>::cpu(unsigned cpu) const
243 { return *reinterpret_cast<T const *>((char const *)&_d + _offsets[cpu]); }
245 IMPLEMENT inline template< typename T >
246 T &Per_cpu<T>::cpu(unsigned cpu)
247 { return *reinterpret_cast<T*>((char *)&_d + _offsets[cpu]); }
250 template< typename T >
251 Per_cpu<T>::Per_cpu()
253 //printf(" Per_cpu<T>() [this=%p])\n", this);
254 ctors.push_back(&ctor_wo_arg, this);
258 template< typename T >
259 Per_cpu<T>::Per_cpu(bool) : _d(0)
261 //printf(" Per_cpu<T>(bool) [this=%p])\n", this);
262 ctors.push_back(&ctor_w_arg, this);
266 template< typename T >
267 void Per_cpu<T>::ctor_wo_arg(void *obj, unsigned cpu)
269 //printf("Per_cpu<T>::ctor_wo_arg(obj=%p, cpu=%u -> %p)\n", obj, cpu, &(reinterpret_cast<Per_cpu<T>*>(obj)->cpu(cpu)));
270 new (&reinterpret_cast<Per_cpu<T>*>(obj)->cpu(cpu)) T;
274 template< typename T >
275 void Per_cpu<T>::ctor_w_arg(void *obj, unsigned cpu)
277 //printf("Per_cpu<T>::ctor_w_arg(obj=%p, cpu=%u -> %p)\n", obj, cpu, &reinterpret_cast<Per_cpu<T>*>(obj)->cpu(cpu));
278 new (&reinterpret_cast<Per_cpu<T>*>(obj)->cpu(cpu)) T(cpu);
282 template< typename T >
283 T &Per_cpu_ptr<T>::cpu(unsigned cpu)
284 { return *reinterpret_cast<T *>(reinterpret_cast<Address>(_p) + _offsets[cpu]); }
288 Per_cpu_data::init_ctors()
290 for (unsigned i = 0; i < Num_cpus; ++i)
296 Per_cpu_data::run_ctors(unsigned cpu)
298 extern ctor_function_t __PER_CPU_INIT_ARRAY_START__[];
299 extern ctor_function_t __PER_CPU_INIT_ARRAY_END__[];
300 extern ctor_function_t __PER_CPU_CTORS_LIST__[];
301 extern ctor_function_t __PER_CPU_CTORS_END__[];
304 run_ctor_functions(__PER_CPU_INIT_ARRAY_START__, __PER_CPU_INIT_ARRAY_END__);
305 run_ctor_functions(__PER_CPU_CTORS_LIST__, __PER_CPU_CTORS_END__);
306 late_ctor_start = ctors.len();
310 for (unsigned i = 0; i < late_ctor_start; ++i)
311 ctors[i].func(ctors[i].base, cpu);
316 Per_cpu_data::run_late_ctors(unsigned cpu)
318 extern ctor_function_t __PER_CPU_LATE_INIT_ARRAY_START__[];
319 extern ctor_function_t __PER_CPU_LATE_INIT_ARRAY_END__[];
320 extern ctor_function_t __PER_CPU_LATE_CTORS_LIST__[];
321 extern ctor_function_t __PER_CPU_LATE_CTORS_END__[];
324 run_ctor_functions(__PER_CPU_LATE_INIT_ARRAY_START__, __PER_CPU_LATE_INIT_ARRAY_END__);
325 run_ctor_functions(__PER_CPU_LATE_CTORS_LIST__, __PER_CPU_LATE_CTORS_END__);
329 unsigned c = ctors.len();
330 for (unsigned i = late_ctor_start; i < c; ++i)
331 ctors[i].func(ctors[i].base, cpu);