6 #ifndef ABTI_MEM_H_INCLUDED
7 #define ABTI_MEM_H_INCLUDED
14 #define ABTI_MEM_POOL_DESC_ELEM_SIZE \
15 ABTU_roundup_size(sizeof(ABTI_ythread), ABT_CONFIG_STATIC_CACHELINE_SIZE)
18 ABTI_MEM_LP_MALLOC = 0,
20 ABTI_MEM_LP_MMAP_HP_RP,
21 ABTI_MEM_LP_MMAP_HP_THP,
26 ABTU_ret_err int ABTI_mem_init_local(ABTI_global *p_global,
27 ABTI_xstream *p_local_xstream);
28 void ABTI_mem_finalize(ABTI_global *p_global);
29 void ABTI_mem_finalize_local(ABTI_xstream *p_local_xstream);
30 int ABTI_mem_check_lp_alloc(ABTI_global *p_global,
int lp_alloc);
32 #define ABTI_STACK_CANARY_VALUE ((uint64_t)0xbaadc0debaadc0de)
35 #if ABT_CONFIG_STACK_CHECK_TYPE == ABTI_STACK_CHECK_TYPE_CANARY
36 static inline void ABTI_mem_write_stack_canary(
void *p_stack)
41 i +=
sizeof(uint64_t)) {
42 ((uint64_t *)p_stack)[i] = ABTI_STACK_CANARY_VALUE;
46 static inline void ABTI_mem_check_stack_canary(
void *p_stack)
50 i +=
sizeof(uint64_t)) {
51 ABTI_ASSERT(((uint64_t *)p_stack)[i] == ABTI_STACK_CANARY_VALUE);
57 static inline void ABTI_mem_register_stack(
const ABTI_global *p_global,
58 void *p_stacktop,
size_t stacksize,
61 void *p_stack = (
void *)(((
char *)p_stacktop) - stacksize);
62 if (mprotect_if_needed) {
63 if (p_global->stack_guard_kind == ABTI_STACK_GUARD_MPROTECT ||
64 p_global->stack_guard_kind == ABTI_STACK_GUARD_MPROTECT_STRICT) {
68 p_global->sys_page_size),
70 if (p_global->stack_guard_kind ==
71 ABTI_STACK_GUARD_MPROTECT_STRICT) {
76 #if ABT_CONFIG_STACK_CHECK_TYPE == ABTI_STACK_CHECK_TYPE_CANARY
78 ABTI_mem_write_stack_canary(p_stack);
83 #if ABT_CONFIG_STACK_CHECK_TYPE == ABTI_STACK_CHECK_TYPE_CANARY
84 if (!(p_global->stack_guard_kind == ABTI_STACK_GUARD_MPROTECT ||
85 p_global->stack_guard_kind == ABTI_STACK_GUARD_MPROTECT_STRICT) &&
87 ABTI_mem_write_stack_canary(p_stack);
91 ABTI_VALGRIND_REGISTER_STACK(p_stack, stacksize);
94 static inline void ABTI_mem_unregister_stack(
const ABTI_global *p_global,
95 void *p_stacktop,
size_t stacksize,
98 void *p_stack = (
void *)(((
char *)p_stacktop) - stacksize);
99 if (mprotect_if_needed) {
100 if (p_global->stack_guard_kind == ABTI_STACK_GUARD_MPROTECT ||
101 p_global->stack_guard_kind == ABTI_STACK_GUARD_MPROTECT_STRICT) {
105 p_global->sys_page_size),
112 #if ABT_CONFIG_STACK_CHECK_TYPE == ABTI_STACK_CHECK_TYPE_CANARY
114 ABTI_mem_check_stack_canary(p_stack);
119 #if ABT_CONFIG_STACK_CHECK_TYPE == ABTI_STACK_CHECK_TYPE_CANARY
120 if (!(p_global->stack_guard_kind == ABTI_STACK_GUARD_MPROTECT ||
121 p_global->stack_guard_kind == ABTI_STACK_GUARD_MPROTECT_STRICT) &&
123 ABTI_mem_check_stack_canary(p_stack);
127 ABTI_VALGRIND_UNREGISTER_STACK(p_stack);
130 ABTU_ret_err static inline int ABTI_mem_alloc_nythread(ABTI_local *p_local,
131 ABTI_thread **pp_thread)
133 ABTI_STATIC_ASSERT(
sizeof(ABTI_thread) <= ABTI_MEM_POOL_DESC_ELEM_SIZE);
134 ABTI_thread *p_thread;
135 #ifdef ABT_CONFIG_USE_MEM_POOL
136 ABTI_xstream *p_local_xstream = ABTI_local_get_xstream_or_null(p_local);
137 if (!ABTI_IS_EXT_THREAD_ENABLED || p_local_xstream) {
139 int abt_errno = ABTI_mem_pool_alloc(&p_local_xstream->mem_pool_desc,
141 ABTI_CHECK_ERROR(abt_errno);
142 p_thread->type = ABTI_THREAD_TYPE_MEM_MEMPOOL_DESC;
147 ABTU_malloc(ABTI_MEM_POOL_DESC_ELEM_SIZE, (
void **)&p_thread);
148 ABTI_CHECK_ERROR(abt_errno);
149 p_thread->type = ABTI_THREAD_TYPE_MEM_MALLOC_DESC;
151 *pp_thread = p_thread;
155 static inline void ABTI_mem_free_nythread_mempool_impl(ABTI_global *p_global,
157 ABTI_thread *p_thread)
160 #ifdef ABT_CONFIG_USE_MEM_POOL
161 ABTI_xstream *p_local_xstream = ABTI_local_get_xstream_or_null(p_local);
162 #ifdef ABT_CONFIG_DISABLE_EXT_THREAD
164 ABTI_mem_pool_free(&p_local_xstream->mem_pool_desc, p_thread);
166 if (p_local_xstream) {
168 ABTI_mem_pool_free(&p_local_xstream->mem_pool_desc, p_thread);
171 ABTD_spinlock_acquire(&p_global->mem_pool_desc_lock);
172 ABTI_mem_pool_free(&p_global->mem_pool_desc_ext, p_thread);
173 ABTD_spinlock_release(&p_global->mem_pool_desc_lock);
183 ABTI_mem_alloc_ythread_desc_impl(ABTI_local *p_local,
ABT_bool use_lazy_stack,
184 ABTI_ythread **pp_ythread)
186 ABTI_STATIC_ASSERT(
sizeof(ABTI_ythread) <= ABTI_MEM_POOL_DESC_ELEM_SIZE);
187 ABTI_ythread *p_ythread;
188 #ifdef ABT_CONFIG_USE_MEM_POOL
189 ABTI_xstream *p_local_xstream = ABTI_local_get_xstream_or_null(p_local);
190 if (!ABTI_IS_EXT_THREAD_ENABLED || p_local_xstream) {
192 int abt_errno = ABTI_mem_pool_alloc(&p_local_xstream->mem_pool_desc,
193 (
void **)&p_ythread);
194 ABTI_CHECK_ERROR(abt_errno);
195 p_ythread->thread.type =
197 ? ABTI_THREAD_TYPE_MEM_MEMPOOL_DESC_MEMPOOL_LAZY_STACK
198 : ABTI_THREAD_TYPE_MEM_MEMPOOL_DESC;
203 ABTU_malloc(ABTI_MEM_POOL_DESC_ELEM_SIZE, (
void **)&p_ythread);
204 ABTI_CHECK_ERROR(abt_errno);
205 p_ythread->thread.type =
206 use_lazy_stack ? ABTI_THREAD_TYPE_MEM_MALLOC_DESC_MEMPOOL_LAZY_STACK
207 : ABTI_THREAD_TYPE_MEM_MALLOC_DESC;
209 *pp_ythread = p_ythread;
213 static inline void ABTI_mem_free_ythread_desc_mempool_impl(
214 ABTI_global *p_global, ABTI_local *p_local, ABTI_ythread *p_ythread)
217 #ifdef ABT_CONFIG_USE_MEM_POOL
218 ABTI_xstream *p_local_xstream = ABTI_local_get_xstream_or_null(p_local);
219 #ifdef ABT_CONFIG_DISABLE_EXT_THREAD
221 ABTI_mem_pool_free(&p_local_xstream->mem_pool_desc, p_ythread);
223 if (p_local_xstream) {
225 ABTI_mem_pool_free(&p_local_xstream->mem_pool_desc, p_ythread);
228 ABTD_spinlock_acquire(&p_global->mem_pool_desc_lock);
229 ABTI_mem_pool_free(&p_global->mem_pool_desc_ext, p_ythread);
230 ABTD_spinlock_release(&p_global->mem_pool_desc_lock);
239 #ifdef ABT_CONFIG_USE_MEM_POOL
240 ABTU_ret_err static inline int ABTI_mem_alloc_ythread_mempool_desc_stack_impl(
241 ABTI_mem_pool_local_pool *p_mem_pool_stack,
size_t stacksize,
242 ABTI_ythread **pp_ythread,
void **pp_stacktop)
247 int abt_errno = ABTI_mem_pool_alloc(p_mem_pool_stack, &p_ythread);
248 ABTI_CHECK_ERROR(abt_errno);
250 *pp_stacktop = (
void *)p_ythread;
251 *pp_ythread = (ABTI_ythread *)p_ythread;
256 ABTU_ret_err static inline int ABTI_mem_alloc_ythread_malloc_desc_stack_impl(
257 size_t stacksize, ABTI_ythread **pp_ythread,
void **pp_stacktop)
260 size_t alloc_stacksize =
264 ABTU_malloc(alloc_stacksize +
sizeof(ABTI_ythread), (
void **)&p_stack);
265 ABTI_CHECK_ERROR(abt_errno);
267 *pp_stacktop = (
void *)(p_stack + alloc_stacksize);
268 *pp_ythread = (ABTI_ythread *)(p_stack + alloc_stacksize);
273 ABTI_mem_alloc_ythread_mempool_desc_stack(ABTI_global *p_global,
274 ABTI_local *p_local,
size_t stacksize,
275 ABTI_ythread **pp_ythread)
277 ABTI_UB_ASSERT(stacksize == p_global->thread_stacksize);
278 ABTI_ythread *p_ythread;
279 #ifdef ABT_CONFIG_USE_MEM_POOL
280 #ifdef ABT_CONFIG_DISABLE_LAZY_STACK_ALLOC
285 if (use_lazy_stack) {
288 ABTI_mem_alloc_ythread_desc_impl(p_local,
ABT_TRUE, &p_ythread);
289 ABTI_CHECK_ERROR(abt_errno);
291 ABTD_ythread_context_init_lazy(&p_ythread->ctx, stacksize);
292 *pp_ythread = p_ythread;
297 ABTI_xstream *p_local_xstream = ABTI_local_get_xstream_or_null(p_local);
298 if (!ABTI_IS_EXT_THREAD_ENABLED || p_local_xstream) {
299 int abt_errno = ABTI_mem_alloc_ythread_mempool_desc_stack_impl(
300 &p_local_xstream->mem_pool_stack, stacksize, &p_ythread,
302 ABTI_CHECK_ERROR(abt_errno);
303 p_ythread->thread.type = ABTI_THREAD_TYPE_MEM_MEMPOOL_DESC_STACK;
304 ABTI_mem_register_stack(p_global, p_stacktop, stacksize,
ABT_FALSE);
308 ABTI_mem_alloc_ythread_malloc_desc_stack_impl(stacksize,
311 ABTI_CHECK_ERROR(abt_errno);
312 p_ythread->thread.type = ABTI_THREAD_TYPE_MEM_MALLOC_DESC_STACK;
313 ABTI_mem_register_stack(p_global, p_stacktop, stacksize,
ABT_TRUE);
316 ABTD_ythread_context_init(&p_ythread->ctx, p_stacktop, stacksize);
317 *pp_ythread = p_ythread;
323 ABTI_mem_alloc_ythread_malloc_desc_stack_impl(stacksize, &p_ythread,
325 ABTI_CHECK_ERROR(abt_errno);
326 p_ythread->thread.type = ABTI_THREAD_TYPE_MEM_MALLOC_DESC_STACK;
327 ABTI_mem_register_stack(p_global, p_stacktop, stacksize,
ABT_TRUE);
329 ABTD_ythread_context_init(&p_ythread->ctx, p_stacktop, stacksize);
330 *pp_ythread = p_ythread;
336 ABTI_mem_alloc_ythread_default(ABTI_global *p_global, ABTI_local *p_local,
337 ABTI_ythread **pp_ythread)
339 size_t stacksize = p_global->thread_stacksize;
340 return ABTI_mem_alloc_ythread_mempool_desc_stack(p_global, p_local,
341 stacksize, pp_ythread);
344 ABTU_ret_err static inline int ABTI_mem_alloc_ythread_malloc_desc_stack(
345 ABTI_global *p_global,
size_t stacksize, ABTI_ythread **pp_ythread)
347 ABTI_ythread *p_ythread;
350 ABTI_mem_alloc_ythread_malloc_desc_stack_impl(stacksize, &p_ythread,
352 ABTI_CHECK_ERROR(abt_errno);
355 p_ythread->thread.type = ABTI_THREAD_TYPE_MEM_MALLOC_DESC_STACK;
356 ABTD_ythread_context_init(&p_ythread->ctx, p_stacktop, stacksize);
357 ABTI_mem_register_stack(p_global, p_stacktop, stacksize,
ABT_TRUE);
358 *pp_ythread = p_ythread;
363 ABTI_mem_alloc_ythread_mempool_desc(ABTI_global *p_global, ABTI_local *p_local,
364 size_t stacksize,
void *p_stacktop,
365 ABTI_ythread **pp_ythread)
367 ABTI_ythread *p_ythread;
370 ABTI_STATIC_ASSERT(
sizeof(ABTI_ythread) <= ABTI_MEM_POOL_DESC_ELEM_SIZE);
371 ABTI_STATIC_ASSERT(offsetof(ABTI_ythread, thread) == 0);
373 ABTI_mem_alloc_nythread(p_local, (ABTI_thread **)&p_ythread);
374 ABTI_CHECK_ERROR(abt_errno);
376 ABTD_ythread_context_init(&p_ythread->ctx, p_stacktop, stacksize);
377 ABTI_mem_register_stack(p_global, p_stacktop, stacksize,
ABT_TRUE);
378 *pp_ythread = p_ythread;
382 static inline void ABTI_mem_free_thread(ABTI_global *p_global,
384 ABTI_thread *p_thread)
387 #ifdef ABT_CONFIG_USE_MEM_POOL
388 if (p_thread->type & ABTI_THREAD_TYPE_MEM_MEMPOOL_DESC_STACK) {
389 ABTI_ythread *p_ythread = ABTI_thread_get_ythread(p_thread);
390 ABTI_mem_unregister_stack(p_global,
391 ABTD_ythread_context_get_stacktop(
393 ABTD_ythread_context_get_stacksize(
397 ABTI_xstream *p_local_xstream = ABTI_local_get_xstream_or_null(p_local);
399 #ifndef ABT_CONFIG_DISABLE_EXT_THREAD
400 if (p_local_xstream == NULL) {
402 ABTD_spinlock_acquire(&p_global->mem_pool_stack_lock);
403 ABTI_mem_pool_free(&p_global->mem_pool_stack_ext, p_ythread);
404 ABTD_spinlock_release(&p_global->mem_pool_stack_lock);
408 ABTI_mem_pool_free(&p_local_xstream->mem_pool_stack, p_ythread);
412 ABTI_THREAD_TYPE_MEM_MEMPOOL_DESC_MEMPOOL_LAZY_STACK) {
413 ABTI_ythread *p_ythread = ABTI_thread_get_ythread(p_thread);
415 ABTI_UB_ASSERT(!ABTD_ythread_context_has_stack(&p_ythread->ctx));
416 ABTI_mem_free_ythread_desc_mempool_impl(p_global, p_local, p_ythread);
417 }
else if (p_thread->type & ABTI_THREAD_TYPE_MEM_MEMPOOL_DESC) {
419 ABTI_ythread *p_ythread = ABTI_thread_get_ythread_or_null(p_thread);
421 ABTI_mem_unregister_stack(p_global,
422 ABTD_ythread_context_get_stacktop(
424 ABTD_ythread_context_get_stacksize(
427 ABTI_mem_free_ythread_desc_mempool_impl(p_global, p_local,
430 ABTI_mem_free_nythread_mempool_impl(p_global, p_local, p_thread);
432 }
else if (p_thread->type & ABTI_THREAD_TYPE_MEM_MALLOC_DESC_STACK) {
433 ABTI_ythread *p_ythread = ABTI_thread_get_ythread(p_thread);
434 void *p_stacktop = ABTD_ythread_context_get_stacktop(&p_ythread->ctx);
435 size_t stacksize = ABTD_ythread_context_get_stacksize(&p_ythread->ctx);
436 ABTI_mem_unregister_stack(p_global, p_stacktop, stacksize,
ABT_TRUE);
437 void *p_stack = (
void *)(((
char *)p_stacktop) - stacksize);
439 }
else if (p_thread->type &
440 ABTI_THREAD_TYPE_MEM_MALLOC_DESC_MEMPOOL_LAZY_STACK) {
441 ABTI_ythread *p_ythread = ABTI_thread_get_ythread(p_thread);
443 ABTI_UB_ASSERT(!ABTD_ythread_context_has_stack(&p_ythread->ctx));
446 ABTI_ASSERT(p_thread->type & ABTI_THREAD_TYPE_MEM_MALLOC_DESC);
447 ABTI_STATIC_ASSERT(offsetof(ABTI_ythread, thread) == 0);
448 ABTI_ythread *p_ythread = ABTI_thread_get_ythread_or_null(p_thread);
450 ABTI_mem_unregister_stack(p_global,
451 ABTD_ythread_context_get_stacktop(
453 ABTD_ythread_context_get_stacksize(
461 ABTI_mem_alloc_ythread_mempool_stack(ABTI_xstream *p_local_xstream,
462 ABTI_ythread *p_ythread)
464 #ifdef ABT_CONFIG_USE_MEM_POOL
465 ABTI_UB_ASSERT(p_ythread->thread.type &
466 (ABTI_THREAD_TYPE_MEM_MEMPOOL_DESC_MEMPOOL_LAZY_STACK |
467 ABTI_THREAD_TYPE_MEM_MALLOC_DESC_MEMPOOL_LAZY_STACK));
470 ABTI_mem_pool_alloc(&p_local_xstream->mem_pool_stack, &p_stacktop);
471 ABTI_CHECK_ERROR(abt_errno);
472 ABTD_ythread_context_lazy_set_stack(&p_ythread->ctx, p_stacktop);
482 ABTI_mem_free_ythread_mempool_stack(ABTI_xstream *p_local_xstream,
483 ABTI_ythread *p_ythread)
485 #ifdef ABT_CONFIG_USE_MEM_POOL
486 ABTI_UB_ASSERT(p_ythread->thread.type &
487 (ABTI_THREAD_TYPE_MEM_MEMPOOL_DESC_MEMPOOL_LAZY_STACK |
488 ABTI_THREAD_TYPE_MEM_MALLOC_DESC_MEMPOOL_LAZY_STACK));
489 void *p_stacktop = ABTD_ythread_context_get_stacktop(&p_ythread->ctx);
490 ABTD_ythread_context_lazy_unset_stack(&p_ythread->ctx);
491 ABTI_mem_pool_free(&p_local_xstream->mem_pool_stack, p_stacktop);
501 #define ABTI_MEM_POOL_DESC_SIZE (ABTI_MEM_POOL_DESC_ELEM_SIZE - 4)
503 ABTU_ret_err static inline int ABTI_mem_alloc_desc(ABTI_local *p_local,
506 #ifndef ABT_CONFIG_USE_MEM_POOL
507 return ABTU_malloc(ABTI_MEM_POOL_DESC_SIZE, pp_desc);
510 ABTI_xstream *p_local_xstream = ABTI_local_get_xstream_or_null(p_local);
511 if (ABTI_IS_EXT_THREAD_ENABLED && p_local_xstream == NULL) {
513 int abt_errno =
ABTU_malloc(ABTI_MEM_POOL_DESC_SIZE, &p_desc);
514 ABTI_CHECK_ERROR(abt_errno);
515 *(uint32_t *)(((
char *)p_desc) + ABTI_MEM_POOL_DESC_SIZE) = 1;
521 ABTI_mem_pool_alloc(&p_local_xstream->mem_pool_desc, &p_desc);
522 ABTI_CHECK_ERROR(abt_errno);
524 *(uint32_t *)(((
char *)p_desc) + ABTI_MEM_POOL_DESC_SIZE) = 0;
531 static inline void ABTI_mem_free_desc(ABTI_global *p_global,
532 ABTI_local *p_local,
void *p_desc)
534 #ifndef ABT_CONFIG_USE_MEM_POOL
537 ABTI_xstream *p_local_xstream = ABTI_local_get_xstream_or_null(p_local);
538 #ifndef ABT_CONFIG_DISABLE_EXT_THREAD
539 if (*(uint32_t *)(((
char *)p_desc) + ABTI_MEM_POOL_DESC_SIZE)) {
543 }
else if (!p_local_xstream) {
545 ABTD_spinlock_acquire(&p_global->mem_pool_desc_lock);
546 ABTI_mem_pool_free(&p_global->mem_pool_desc_ext, p_desc);
547 ABTD_spinlock_release(&p_global->mem_pool_desc_lock);
551 ABTI_mem_pool_free(&p_local_xstream->mem_pool_desc, p_desc);