6 #ifndef ABTI_KEY_H_INCLUDED
7 #define ABTI_KEY_H_INCLUDED
11 static inline ABTI_key *ABTI_key_get_ptr(
ABT_key key)
13 #ifndef ABT_CONFIG_DISABLE_ERROR_CHECK
18 p_key = (ABTI_key *)key;
22 return (ABTI_key *)key;
26 static inline ABT_key ABTI_key_get_handle(ABTI_key *p_key)
28 #ifndef ABT_CONFIG_DISABLE_ERROR_CHECK
42 #define ABTI_KEY_STATIC_INITIALIZER(f_destructor, id) \
47 #define ABTI_KEY_ID_STACKABLE_SCHED 0
48 #define ABTI_KEY_ID_MIGRATION 1
49 #define ABTI_KEY_ID_END_ 2
51 typedef struct ABTI_ktable_mem_header {
52 struct ABTI_ktable_mem_header *p_next;
54 } ABTI_ktable_mem_header;
56 #define ABTI_KTABLE_DESC_SIZE \
57 (ABTI_MEM_POOL_DESC_SIZE - sizeof(ABTI_ktable_mem_header))
59 #define ABTI_KTABLE_LOCKED ((ABTI_ktable *)0x1)
60 static inline int ABTI_ktable_is_valid(ABTI_ktable *p_ktable)
63 return (((uintptr_t)(
void *)p_ktable) & (~((uintptr_t)(
void *)0x1))) !=
64 ((uintptr_t)(
void *)0x0);
67 ABTU_ret_err static inline int ABTI_ktable_create(ABTI_global *p_global,
69 ABTI_ktable **pp_ktable)
71 ABTI_ktable *p_ktable;
72 uint32_t key_table_size = p_global->key_table_size;
74 ABTI_ASSERT((key_table_size & (key_table_size - 1)) == 0);
79 sizeof(ABTD_atomic_ptr) * key_table_size,
83 if (
ABTU_likely(ktable_size <= ABTI_KTABLE_DESC_SIZE)) {
86 int abt_errno = ABTI_mem_alloc_desc(p_local, &p_mem);
87 ABTI_CHECK_ERROR(abt_errno);
88 ABTI_ktable_mem_header *p_header = (ABTI_ktable_mem_header *)p_mem;
90 (ABTI_ktable *)(((
char *)p_mem) +
sizeof(ABTI_ktable_mem_header));
91 p_header->p_next = NULL;
92 p_header->is_from_mempool =
ABT_TRUE;
93 p_ktable->p_used_mem = p_mem;
94 p_ktable->p_extra_mem = (
void *)(((
char *)p_ktable) + ktable_size);
95 p_ktable->extra_mem_size = ABTI_KTABLE_DESC_SIZE - ktable_size;
100 ABTU_malloc(ktable_size +
sizeof(ABTI_ktable_mem_header), &p_mem);
101 ABTI_CHECK_ERROR(abt_errno);
102 ABTI_ktable_mem_header *p_header = (ABTI_ktable_mem_header *)p_mem;
104 (ABTI_ktable *)(((
char *)p_mem) +
sizeof(ABTI_ktable_mem_header));
105 p_header->p_next = NULL;
107 p_ktable->p_used_mem = p_mem;
108 p_ktable->p_extra_mem = NULL;
109 p_ktable->extra_mem_size = 0;
111 p_ktable->size = key_table_size;
112 ABTD_spinlock_clear(&p_ktable->lock);
113 memset(p_ktable->p_elems, 0,
sizeof(ABTD_atomic_ptr) * key_table_size);
114 *pp_ktable = p_ktable;
118 ABTU_ret_err static inline int ABTI_ktable_alloc_elem(ABTI_local *p_local,
119 ABTI_ktable *p_ktable,
124 size_t extra_mem_size = p_ktable->extra_mem_size;
125 if (size <= extra_mem_size) {
127 void *p_mem = p_ktable->p_extra_mem;
128 p_ktable->p_extra_mem = (
void *)(((
char *)p_mem) + size);
129 p_ktable->extra_mem_size = extra_mem_size - size;
132 }
else if (
ABTU_likely(size <= ABTI_KTABLE_DESC_SIZE)) {
135 int abt_errno = ABTI_mem_alloc_desc(p_local, &p_mem);
136 ABTI_CHECK_ERROR(abt_errno);
137 ABTI_ktable_mem_header *p_header = (ABTI_ktable_mem_header *)p_mem;
138 p_header->p_next = (ABTI_ktable_mem_header *)p_ktable->p_used_mem;
139 p_header->is_from_mempool =
ABT_TRUE;
140 p_ktable->p_used_mem = (
void *)p_header;
141 p_mem = (
void *)(((
char *)p_mem) +
sizeof(ABTI_ktable_mem_header));
142 p_ktable->p_extra_mem = (
void *)(((
char *)p_mem) + size);
143 p_ktable->extra_mem_size = ABTI_KTABLE_DESC_SIZE - size;
150 ABTU_malloc(size +
sizeof(ABTI_ktable_mem_header), &p_mem);
151 ABTI_CHECK_ERROR(abt_errno);
152 ABTI_ktable_mem_header *p_header = (ABTI_ktable_mem_header *)p_mem;
153 p_header->p_next = (ABTI_ktable_mem_header *)p_ktable->p_used_mem;
155 p_ktable->p_used_mem = (
void *)p_header;
156 p_mem = (
void *)(((
char *)p_mem) +
sizeof(ABTI_ktable_mem_header));
162 static inline uint32_t ABTI_ktable_get_idx(ABTI_key *p_key,
int size)
164 return p_key->id & (size - 1);
168 ABTI_ktable_set_impl(ABTI_local *p_local, ABTI_ktable *p_ktable,
169 ABTI_key *p_key,
void *value,
ABT_bool is_safe)
172 ABTD_atomic_ptr *pp_elem;
176 idx = ABTI_ktable_get_idx(p_key, p_ktable->size);
177 pp_elem = &p_ktable->p_elems[idx];
178 p_elem = (ABTI_ktelem *)ABTD_atomic_acquire_load_ptr(pp_elem);
179 uint32_t key_id = p_key->id;
181 if (p_elem->key_id == key_id) {
182 p_elem->value = value;
185 pp_elem = &p_elem->p_next;
186 p_elem = (ABTI_ktelem *)ABTD_atomic_acquire_load_ptr(pp_elem);
191 ABTD_spinlock_acquire(&p_ktable->lock);
193 p_elem = (ABTI_ktelem *)ABTD_atomic_acquire_load_ptr(pp_elem);
195 if (p_elem->key_id == key_id) {
197 ABTD_spinlock_release(&p_ktable->lock);
198 p_elem->value = value;
201 pp_elem = &p_elem->p_next;
202 p_elem = (ABTI_ktelem *)ABTD_atomic_acquire_load_ptr(pp_elem);
208 int abt_errno = ABTI_ktable_alloc_elem(p_local, p_ktable, ktelem_size,
210 if (ABTI_IS_ERROR_CHECK_ENABLED && abt_errno !=
ABT_SUCCESS) {
212 ABTD_spinlock_release(&p_ktable->lock);
215 p_elem->f_destructor = p_key->f_destructor;
216 p_elem->key_id = p_key->id;
217 p_elem->value = value;
218 ABTD_atomic_relaxed_store_ptr(&p_elem->p_next, NULL);
219 ABTD_atomic_release_store_ptr(pp_elem, p_elem);
221 ABTD_spinlock_release(&p_ktable->lock);
225 ABTU_ret_err static inline int ABTI_ktable_set(ABTI_global *p_global,
227 ABTD_atomic_ptr *pp_ktable,
228 ABTI_key *p_key,
void *value)
231 ABTI_ktable *p_ktable = ABTD_atomic_acquire_load_ptr(pp_ktable);
235 if (ABTD_atomic_bool_cas_weak_ptr(pp_ktable, NULL,
236 ABTI_KTABLE_LOCKED)) {
238 abt_errno = ABTI_ktable_create(p_global, p_local, &p_ktable);
240 ABTD_atomic_release_store_ptr(pp_ktable, NULL);
241 ABTI_HANDLE_ERROR(abt_errno);
245 ABTD_atomic_release_store_ptr(pp_ktable, p_ktable);
250 p_ktable = ABTD_atomic_acquire_load_ptr(pp_ktable);
251 if (p_ktable == NULL) {
256 while (p_ktable == ABTI_KTABLE_LOCKED) {
258 p_ktable = ABTD_atomic_acquire_load_ptr(pp_ktable);
265 abt_errno = ABTI_ktable_set_impl(p_local, p_ktable, p_key, value,
ABT_TRUE);
266 ABTI_CHECK_ERROR(abt_errno);
271 ABTI_ktable_set_unsafe(ABTI_global *p_global, ABTI_local *p_local,
272 ABTI_ktable **pp_ktable, ABTI_key *p_key,
void *value)
275 ABTI_ktable *p_ktable = *pp_ktable;
277 abt_errno = ABTI_ktable_create(p_global, p_local, &p_ktable);
278 ABTI_CHECK_ERROR(abt_errno);
279 *pp_ktable = p_ktable;
282 ABTI_ktable_set_impl(p_local, p_ktable, p_key, value,
ABT_FALSE);
283 ABTI_CHECK_ERROR(abt_errno);
287 static inline void *ABTI_ktable_get(ABTD_atomic_ptr *pp_ktable, ABTI_key *p_key)
289 ABTI_ktable *p_ktable = ABTD_atomic_acquire_load_ptr(pp_ktable);
290 if (ABTI_ktable_is_valid(p_ktable)) {
294 idx = ABTI_ktable_get_idx(p_key, p_ktable->size);
295 p_elem = (ABTI_ktelem *)ABTD_atomic_acquire_load_ptr(
296 &p_ktable->p_elems[idx]);
297 uint32_t key_id = p_key->id;
299 if (p_elem->key_id == key_id) {
300 return p_elem->value;
303 (ABTI_ktelem *)ABTD_atomic_acquire_load_ptr(&p_elem->p_next);