1/* @title: Per-Domain dynamic objects */
2#pragma once
3#include <compiler.h>
4#include <global.h>
5#include <linker/symbols.h>
6#include <smp/domain.h>
7#include <stddef.h>
8#include <stdint.h>
9
10struct perdomain_descriptor;
11typedef void (*perdomain_descriptor_constructor)(void *, size_t);
12
13struct perdomain_descriptor {
14 const char *name;
15 size_t size;
16 size_t align;
17 void **perdomain_ptrs;
18 perdomain_descriptor_constructor constructor;
19 atomic_bool ready;
20};
21
22LINKER_SECTION_DEFINE(struct perdomain_descriptor, perdomain_desc);
23
24#define PERDOMAIN_DECLARE(__n, __type, __ctor) \
25 static typeof(__type) __perdomain_##__n __unused; \
26 static struct perdomain_descriptor __perdomain_desc_##__n; \
27 static void __perdomain_ctor_##__n(void *inst, size_t domain) { \
28 void (*const __typed_ctor)(typeof(__type) *, size_t) = (__ctor); \
29 if (__typed_ctor != NULL) \
30 __typed_ctor((typeof(__type) *) inst, domain); \
31 if (domain == global.domain_count - 1) \
32 atomic_store(&__perdomain_desc_##__n.ready, true); \
33 } \
34 static LINKER_SECTION_OBJECT(struct perdomain_descriptor, perdomain_desc) \
35 __perdomain_desc_##__n = { \
36 .name = #__n, \
37 .size = sizeof(typeof(__type)), \
38 .align = _Alignof(typeof(__type)), \
39 .perdomain_ptrs = NULL, \
40 .constructor = __perdomain_ctor_##__n, \
41 .ready = false, \
42 }; \
43 static struct perdomain_descriptor *const __perdomain_desc_ref_##__n \
44 __unused = &__perdomain_desc_##__n
45
46#define PERDOMAIN_EXPORT_AS(sym_name, name) \
47 extern struct perdomain_descriptor __perdomain_desc_sym_##sym_name \
48 __attribute__((alias("__perdomain_desc_" #name), used))
49
50#define PERDOMAIN_EXPORT(name) PERDOMAIN_EXPORT_AS(name, name)
51
52#define PERDOMAIN_DEFINE_AS(name, sym_name, type) \
53 extern struct perdomain_descriptor __perdomain_desc_sym_##sym_name; \
54 static typeof(type) __perdomain_##name __unused; \
55 static struct perdomain_descriptor *const __perdomain_desc_ref_##name \
56 __unused = &__perdomain_desc_sym_##sym_name
57
58#define PERDOMAIN_DEFINE(name, type) PERDOMAIN_DEFINE_AS(name, name, type)
59
60#define PERDOMAIN(name) &(__perdomain_##name)
61#define PERDOMAIN_READY(name) \
62 (atomic_load(&(__perdomain_desc_ref_##name)->ready))
63
64#define PERDOMAIN_PTR_FOR_DOMAIN(name, d) \
65 ({ \
66 (void) kassert(PERDOMAIN_READY(name)); \
67 ((typeof(__perdomain_##name) *) (__perdomain_desc_ref_##name) \
68 ->perdomain_ptrs[d]); \
69 })
70
71#define PERDOMAIN_READ_FOR_DOMAIN(name, d) \
72 (*((typeof(__perdomain_##name) *) PERDOMAIN_PTR_FOR_DOMAIN(name, d)))
73
74#define PERDOMAIN_PTR(clr, name) \
75 PERDOMAIN_PTR_FOR_DOMAIN(name, domain_local_id(clr))
76#define PERDOMAIN_READ(clr, name) \
77 (*((typeof(__perdomain_##name) *) PERDOMAIN_PTR(clr, name)))
78
79#define PERDOMAIN_WRITE(clr, name, val) (PERDOMAIN_READ(clr, name) = (val))
80
81#define perdomain_for_each_internal(name, var, domain) \
82 for (domain_id_t domain = 0; domain < global.domain_count; domain++) \
83 for (var = PERDOMAIN_PTR_FOR_DOMAIN(name, domain); var != NULL; \
84 var = NULL)
85
86#define perdomain_for_each_internal_3(name, var, domain) \
87 perdomain_for_each_internal(name, var, domain)
88#define perdomain_for_each_internal_2(name, var) \
89 perdomain_for_each_internal(name, var, __domain)
90
91#define perdomain_for_each(...) \
92 _DISPATCH(perdomain_for_each_internal, PP_NARG(__VA_ARGS__))(__VA_ARGS__)
93
94void perdomain_obj_init(void);
95