1/* @title: Per-CPU dynamic objects */
2#pragma once
3#include <compiler.h>
4#include <linker/symbols.h>
5#include <smp/core.h>
6#include <stddef.h>
7#include <stdint.h>
8
9struct percpu_descriptor;
10typedef void (*percpu_descriptor_constructor)(void *, size_t);
11
12struct percpu_descriptor {
13 const char *name;
14 size_t size;
15 size_t align;
16 void **percpu_ptrs;
17 percpu_descriptor_constructor constructor;
18};
19
20LINKER_SECTION_DEFINE(struct percpu_descriptor, percpu_desc);
21
22#define PERCPU_DECLARE(__n, __type, __ctor) \
23 extern __type __percpu_##__n; \
24 static void __percpu_ctor_##__n(void *inst, size_t cpu) { \
25 if ((__ctor) != NULL) \
26 __ctor((__type *) inst, cpu); \
27 } \
28 LINKER_SECTION_OBJECT(struct percpu_descriptor, percpu_desc) \
29 __percpu_desc_##__n = { \
30 .name = #__n, \
31 .size = sizeof(__type), \
32 .align = _Alignof(__type), \
33 .percpu_ptrs = NULL, \
34 .constructor = __percpu_ctor_##__n, \
35 }; \
36 __type __percpu_##__n
37
38void percpu_obj_init(void);
39
40#define PERCPU_PTR_FOR_CPU(name, cpu) \
41 ((typeof(__percpu_##name) *) __percpu_desc_##name.percpu_ptrs[cpu])
42#define PERCPU_READ_FOR_CPU(name, cpu) \
43 (*((typeof(__percpu_##name) *) PERCPU_PTR_FOR_CPU(name, cpu)))
44
45#define PERCPU_PTR(name) PERCPU_PTR_FOR_CPU(name, smp_core_id())
46#define PERCPU_READ(name) (*((typeof(__percpu_##name) *) PERCPU_PTR(name)))
47
48#define PERCPU_WRITE(name, val) (PERCPU_READ(name) = (val))
49