3 #include "static_init.h"
5 #define DEFINE_PER_CPU_P(p) __attribute__((section(".per_cpu.data"),init_priority(0xfffe - p)))
6 #define DEFINE_PER_CPU DEFINE_PER_CPU_P(9)
8 class Mapped_allocator;
13 static void init_ctors(Mapped_allocator *a);
14 static void run_ctors(unsigned cpu);
15 static bool valid(unsigned cpu);
18 template< typename T >
19 class Per_cpu : private Per_cpu_data
22 T const &cpu(unsigned) const;
26 explicit Per_cpu(bool);
31 //---------------------------------------------------------------------------
42 //---------------------------------------------------------------------------
47 Per_cpu_data::valid(unsigned cpu)
58 template< typename T >
59 T const &Per_cpu<T>::cpu(unsigned) const { return _d; }
62 template< typename T >
63 T &Per_cpu<T>::cpu(unsigned) { return _d; }
66 template< typename T >
71 template< typename T >
72 Per_cpu<T>::Per_cpu(bool) : _d(0)
77 Per_cpu_data::init_ctors(Mapped_allocator *)
79 typedef void (*ctor)(void);
80 extern ctor __PER_CPU_CTORS_LIST__[];
81 extern ctor __PER_CPU_CTORS_END__[];
82 for (unsigned i = __PER_CPU_CTORS_LIST__ - __PER_CPU_CTORS_END__; i > 0; --i)
84 //printf("Per_cpu: init ctor %u (%p)\n", i-1, &__PER_CPU_CTORS_END__[i-1]);
85 __PER_CPU_CTORS_END__[i-1]();
91 Per_cpu_data::run_ctors(unsigned)
95 //---------------------------------------------------------------------------
105 T _d; // __attribute__((aligned(__alignof__(T))));
114 void (*func)(void *, unsigned);
121 Ctor_vector() : _len(0), _capacity(10), _v(0) {}
122 void push_back(void (*func)(void*,unsigned), void *base, Mapped_allocator *a);
123 unsigned len() const { return _len; }
124 Ctor const &operator [] (unsigned idx) const { return _v[idx]; }
132 static long _offsets[Config::Max_num_cpus] asm ("PER_CPU_OFFSETS");
133 static Ctor_vector ctors;
134 static Mapped_allocator *alloc;
138 //---------------------------------------------------------------------------
141 #include "mapped_alloc.h"
144 long Per_cpu_data::_offsets[Config::Max_num_cpus];
145 Per_cpu_data::Ctor_vector Per_cpu_data::ctors INIT_PRIORITY(EARLY_INIT_PRIO);
146 Mapped_allocator *Per_cpu_data::alloc;
150 Per_cpu_data::Ctor_vector::push_back(void (*func)(void*,unsigned),
151 void *base, Mapped_allocator *a)
154 _v = (Ctor*)a->unaligned_alloc(1 << _capacity);
156 if (_len >= ((1 << _capacity) / sizeof(Ctor)))
158 void *b = a->unaligned_alloc(1 << (_capacity+1));
159 memcpy(b, _v, 1 << _capacity);
160 a->unaligned_free(1 << _capacity, _v);
165 Ctor &c = _v[_len++];
170 // the third argument is just there to not have the same type as the normal
171 // new operator used in standard environments which would clash with these
172 // (this file is implicitly in unit tests)
173 inline void *operator new (size_t, void *p, bool) { return p; }
174 inline void *operator new [] (size_t, void *p, bool) { return p; }
178 Per_cpu_data::valid(unsigned cpu)
179 { return cpu < Config::Max_num_cpus && _offsets[cpu] != -1; }
181 IMPLEMENT inline template< typename T >
182 T const &Per_cpu<T>::cpu(unsigned cpu) const
183 { return *reinterpret_cast<T const *>((char const *)&_d + _offsets[cpu]); }
185 IMPLEMENT inline template< typename T >
186 T &Per_cpu<T>::cpu(unsigned cpu)
187 { return *reinterpret_cast<T*>((char *)&_d + _offsets[cpu]); }
190 template< typename T >
191 Per_cpu<T>::Per_cpu()
193 //printf(" Per_cpu<T>() [this=%p])\n", this);
194 ctors.push_back(&ctor_wo_arg, this, alloc);
198 template< typename T >
199 Per_cpu<T>::Per_cpu(bool) : _d(0)
201 //printf(" Per_cpu<T>(bool) [this=%p])\n", this);
202 ctors.push_back(&ctor_w_arg, this, alloc);
206 template< typename T >
207 void Per_cpu<T>::ctor_wo_arg(void *obj, unsigned cpu)
209 //printf("Per_cpu<T>::ctor_wo_arg(obj=%p, cpu=%u -> %p)\n", obj, cpu, &(reinterpret_cast<Per_cpu<T>*>(obj)->cpu(cpu)));
210 new (&reinterpret_cast<Per_cpu<T>*>(obj)->cpu(cpu), true) T();
214 template< typename T >
215 void Per_cpu<T>::ctor_w_arg(void *obj, unsigned cpu)
217 //printf("Per_cpu<T>::ctor_w_arg(obj=%p, cpu=%u -> %p)\n", obj, cpu, &reinterpret_cast<Per_cpu<T>*>(obj)->cpu(cpu));
218 new (&reinterpret_cast<Per_cpu<T>*>(obj)->cpu(cpu), true) T(cpu);
223 Per_cpu_data::init_ctors(Mapped_allocator *a)
225 typedef void (*ctor)(void);
226 extern ctor __PER_CPU_CTORS_LIST__[];
227 extern ctor __PER_CPU_CTORS_END__[];
229 for (unsigned i = __PER_CPU_CTORS_LIST__ - __PER_CPU_CTORS_END__; i > 0; --i)
231 //printf("Per_cpu: init ctor %u (%p)\n", i-1, &__PER_CPU_CTORS_END__[i-1]);
232 __PER_CPU_CTORS_END__[i-1]();
235 for (unsigned i = 0; i < Config::Max_num_cpus; ++i)
241 Per_cpu_data::run_ctors(unsigned cpu)
246 unsigned c = ctors.len();
247 for (unsigned i = 0; i < c; ++i)
248 ctors[i].func(ctors[i].base, cpu);