ARGOBOTS  1.1
abti_ythread.h
Go to the documentation of this file.
1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3  * See COPYRIGHT in top-level directory.
4  */
5 
6 #ifndef ABTI_YTHREAD_H_INCLUDED
7 #define ABTI_YTHREAD_H_INCLUDED
8 
9 /* Inlined functions for yieldable threads */
10 
12 {
13 #ifndef ABT_CONFIG_DISABLE_ERROR_CHECK
14  ABTI_ythread *p_ythread;
15  if (thread == ABT_THREAD_NULL) {
16  p_ythread = NULL;
17  } else {
18  p_ythread = (ABTI_ythread *)thread;
19  }
20  return p_ythread;
21 #else
22  return (ABTI_ythread *)thread;
23 #endif
24 }
25 
27 {
28 #ifndef ABT_CONFIG_DISABLE_ERROR_CHECK
29  ABT_thread h_thread;
30  if (p_ythread == NULL) {
31  h_thread = ABT_THREAD_NULL;
32  } else {
33  h_thread = (ABT_thread)p_ythread;
34  }
35  return h_thread;
36 #else
37  return (ABT_thread)p_ythread;
38 #endif
39 }
40 
41 static inline ABTI_ythread *
43 {
44  return (ABTI_ythread *)(((char *)p_ctx) - offsetof(ABTI_ythread, ctx));
45 }
46 
47 #if ABT_CONFIG_THREAD_TYPE == ABT_THREAD_TYPE_DYNAMIC_PROMOTION
49 {
50  /*
51  * Create a context and switch to it. The flow of the dynamic promotion
52  * thread is as follows:
53  *
54  * - When a ULT does not yield:
55  * ABTI_xstream_schedule_ythread : call init_and_call_fcontext
56  * init_and_call_fcontext : jump to the stack top
57  * : save the scheduler's context
58  * : call the thread function
59  * thread_f : start thread_f
60  * : [ULT body]
61  * : end thread_f
62  * init_and_call_fcontext : calculate the return address, which is
63  * [1] => the original return address.
64  * : `return`
65  * ABTI_xstream_schedule_ythread : resume the scheduler
66  *
67  * The ULT can return to the original scheduler by `return` if the scheduler
68  * has never been resumed during the execution of the ULT, because the
69  * context of the parent scheduler can be restored in a normal return
70  * procedure. In this case, the context is saved only once.
71  *
72  * - When a ULT yields:
73  * ABTI_xstream_schedule_ythread : call init_and_call_fcontext
74  * init_and_call_fcontext : jump to the stack top
75  * : save the scheduler's context
76  * : call the thread function
77  * thread_f : start thread_f
78  * : [yield in ULT body]
79  * ABTD_ythread_context_dynamic_promote
80  * : rewrite the return address to
81  * ABTD_ythread_terminate_ythread_no_arg
82  * jump_fcontext : save the ULT's context
83  * : restore the scheduler's context
84  * : jump to the scheduler
85  * ABTI_xstream_schedule_ythread : resume the scheduler
86  *
87  * ... After a while, a scheduler resumes this ULT ...
88  *
89  * jump_fcontext : save the scheduler's context
90  * : restore the ULT's context
91  * : jump to the ULT
92  * thread_f : [ULT body (remaining)]
93  * : end thread_f
94  * init_and_call_fcontext : calculate the return address, which is
95  * [2] => ABTD_ythread_terminate_ythread_no_arg
96  * : return
97  * ABTD_ythread_terminate_ythread_no_arg
98  * : call take_fcontext
99  * take_fcontext : restore the scheduler's context
100  * : jump to the scheduler
101  * ABTI_xstream_schedule_ythread : resume the scheduler
102  *
103  * When a ULT yields, ABTD_ythread_terminate_ythread_no_arg is set to
104  * [ptr - 0x08] so that it can "jump" to the normal termination
105  * function by "return" in init_and_call_fcontext. This termination
106  * function calls take_fcontext, so the scheduler is resumed by user-level
107  * context switch.
108  *
109  * For example, the stack will be as follows at [1] and [2] in the x86-64
110  * case. Note that ptr points to the stack top (= p_stack + stacksize).
111  *
112  * In the case of [1] (no suspension):
113  * [0x12345600] : (the original instruction pointer)
114  * ...
115  * [ptr - 0x08] : the original stack pointer (i.e., 0x12345600)
116  * [ptr - 0x10] : unused (for 16-byte alignment)
117  * [ptr - xxxx] : used by thread_f
118  *
119  * In the case of [2] (after suspension):
120  * [ptr - 0x08] : pointing to (p_stack - 0x10)
121  * [ptr - 0x10] : the address of ABTD_ythread_terminate_ythread_no_arg
122  * [ptr - xxxx] : used by thread_f
123  *
124  * This technique was introduced as a "return-on-completion" thread in the
125  * following paper:
126  * Lessons Learned from Analyzing Dynamic Promotion for User-Level
127  * Threading, S. Iwasaki, A. Amer, K. Taura, and P. Balaji (SC '18)
128  */
129  return ABTD_ythread_context_is_dynamic_promoted(&p_ythread->ctx);
130 }
131 
133 {
134  LOG_DEBUG("[U%" PRIu64 "] dynamic-promote ULT\n",
135  ABTI_thread_get_id(&p_ythread->thread));
136  void *p_stack = p_ythread->p_stack;
137  size_t stacksize = p_ythread->stacksize;
138  void *p_stacktop = (void *)(((char *)p_stack) + stacksize);
140 }
141 #endif
142 
144  ABTI_xstream **pp_local_xstream, ABTI_ythread *p_old, ABTI_ythread *p_new,
145  ABT_bool is_finish)
146 {
147 #if ABT_CONFIG_THREAD_TYPE == ABT_THREAD_TYPE_DYNAMIC_PROMOTION
148  /* Dynamic promotion is unnecessary if p_old will be discarded. */
149  if (!ABTI_ythread_is_dynamic_promoted(p_old)) {
151  }
152  if (!ABTI_ythread_is_dynamic_promoted(p_new)) {
153  /* p_new does not have a context, so we first need to make it. */
155  &p_new->ctx);
156  }
157 #endif
158  p_new->thread.p_parent = p_old->thread.p_parent;
159  if (is_finish) {
160  ABTI_tool_event_thread_finish(*pp_local_xstream, &p_old->thread,
161  p_old->thread.p_parent);
162  ABTD_ythread_finish_context(&p_old->ctx, &p_new->ctx);
164  } else {
165  ABTD_ythread_context_switch(&p_old->ctx, &p_new->ctx);
167  ABTI_xstream *p_local_xstream = ABTI_local_get_xstream(p_local);
168  *pp_local_xstream = p_local_xstream;
169  ABTI_thread *p_prev = p_local_xstream->p_thread;
170  p_local_xstream->p_thread = &p_old->thread;
172  return ABTI_thread_get_ythread(p_prev);
173  }
174 }
175 
177  ABTI_xstream **pp_local_xstream, ABTI_ythread *p_old, ABT_bool is_finish,
178  ABT_sync_event_type sync_event_type, void *p_sync)
179 {
181 #if ABT_CONFIG_THREAD_TYPE == ABT_THREAD_TYPE_DYNAMIC_PROMOTION
182  /* Dynamic promotion is unnecessary if p_old will be discarded. */
183  if (!is_finish && !ABTI_ythread_is_dynamic_promoted(p_old))
185  /* The parent's context must have been eagerly initialized. */
187 #endif
188  if (is_finish) {
189  ABTI_tool_event_thread_finish(*pp_local_xstream, &p_old->thread,
190  p_old->thread.p_parent);
191  ABTD_ythread_finish_context(&p_old->ctx, &p_new->ctx);
193  } else {
194  ABTI_tool_event_ythread_yield(*pp_local_xstream, p_old,
195  p_old->thread.p_parent, sync_event_type,
196  p_sync);
197  ABTD_ythread_context_switch(&p_old->ctx, &p_new->ctx);
199  ABTI_xstream *p_local_xstream = ABTI_local_get_xstream(p_local);
200  *pp_local_xstream = p_local_xstream;
201  ABTI_thread *p_prev = p_local_xstream->p_thread;
202  p_local_xstream->p_thread = &p_old->thread;
204  /* Invoke an event of thread run. */
205  ABTI_tool_event_thread_run(p_local_xstream, &p_old->thread, p_prev,
206  p_old->thread.p_parent);
207  return ABTI_thread_get_ythread(p_prev);
208  }
209 }
210 
212  ABTI_xstream **pp_local_xstream, ABTI_ythread *p_old, ABTI_ythread *p_new)
213 {
214  ABTI_xstream *p_local_xstream;
215  p_new->thread.p_parent = &p_old->thread;
216 #if ABT_CONFIG_THREAD_TYPE == ABT_THREAD_TYPE_DYNAMIC_PROMOTION
217  if (!ABTI_ythread_is_dynamic_promoted(p_old)) {
219  }
220  if (!ABTI_ythread_is_dynamic_promoted(p_new)) {
221  void *p_stacktop = ((char *)p_new->p_stack) + p_new->stacksize;
222  LOG_DEBUG("[U%" PRIu64 "] run ULT (dynamic promotion)\n",
223  ABTI_thread_get_id(&p_new->thread));
224  p_local_xstream = *pp_local_xstream;
225  p_local_xstream->p_thread = &p_new->thread;
226  /* Invoke an event of thread run. */
227  ABTI_tool_event_thread_run(p_local_xstream, &p_new->thread,
228  &p_old->thread, &p_old->thread);
230  p_new->thread.p_arg, p_stacktop);
231  /* The scheduler continues from here. If the previous thread has not
232  * run dynamic promotion, ABTI_ythread_context_make_and_call took the
233  * fast path. In this case, the request handling has not been done,
234  * so it must be done here. */
236  p_local_xstream = ABTI_local_get_xstream(p_local);
237  *pp_local_xstream = p_local_xstream;
238  ABTI_thread *p_prev_thread = p_local_xstream->p_thread;
239  ABTI_ASSERT(p_prev_thread->type & ABTI_THREAD_TYPE_YIELDABLE);
240  ABTI_ythread *p_prev = ABTI_thread_get_ythread(p_prev_thread);
241  p_local_xstream->p_thread = &p_old->thread;
242  if (!ABTI_ythread_is_dynamic_promoted(p_prev)) {
243  ABTI_ASSERT(p_prev == p_new);
244  /* Invoke a thread-finish event of the previous thread. */
245  ABTI_tool_event_thread_finish(p_local_xstream, &p_prev->thread,
246  &p_old->thread);
247  /* See ABTDI_thread_terminate for details.
248  * TODO: avoid making a copy of the code. */
249  ABTD_ythread_context *p_ctx = &p_prev->ctx;
250  ABTD_ythread_context *p_link =
252  if (!p_link) {
253  uint32_t req =
257  if (!(req & ABTI_THREAD_REQ_JOIN)) {
258  /* No join request. Let's return. */
259  return p_prev;
260  } else {
261  /* This case means there has been a join request and the
262  * joiner has blocked. We have to wake up the joiner ULT.
263  */
264  do {
266  &p_ctx->p_link);
267  } while (!p_link);
268  }
269  }
270  /* Now p_link != NULL. */
272 #ifndef ABT_CONFIG_ACTIVE_WAIT_POLICY
273  if (p_joiner->thread.type == ABTI_THREAD_TYPE_EXT) {
274  /* p_joiner is a non-yieldable thread (i.e., external thread).
275  * Wake up the waiter via the futex. Note that p_arg is used to
276  * store futex (see thread_join_futexwait()). */
277  ABTD_futex_single *p_futex =
278  (ABTD_futex_single *)p_joiner->thread.p_arg;
279  ABTD_futex_resume(p_futex);
280  } else
281 #endif
282  {
283  /* The scheduler may not use a bypass mechanism, so just makes
284  * p_joiner ready. */
286  p_joiner);
287  }
288  /* We don't need to use the atomic OR operation here because
289  * the ULT will be terminated regardless of other requests. */
292  }
293  return p_prev;
294  }
295 #endif
296  {
297  ABTD_ythread_context_switch(&p_old->ctx, &p_new->ctx);
299  p_local_xstream = ABTI_local_get_xstream(p_local);
300  *pp_local_xstream = p_local_xstream;
301  ABTI_thread *p_prev = p_local_xstream->p_thread;
302  p_local_xstream->p_thread = &p_old->thread;
304  /* p_old keeps running as a parent, so no thread-run event incurs. */
305  return ABTI_thread_get_ythread(p_prev);
306  }
307 }
308 
309 #ifdef ABT_CONFIG_ENABLE_PEEK_CONTEXT
310 static inline void ABTI_ythread_context_peek(ABTI_ythread *p_ythread,
311  void (*peek_func)(void *),
312  void *arg)
313 {
314 #if ABT_CONFIG_THREAD_TYPE == ABT_THREAD_TYPE_DYNAMIC_PROMOTION
315  if (!ABTI_ythread_is_dynamic_promoted(p_ythread)) {
317  p_ythread->p_stack, &p_ythread->ctx);
318  }
319 #endif
320  ABTD_ythread_context_peek(&p_ythread->ctx, peek_func, arg);
321 }
322 #endif
323 
324 /* Return the previous thread. */
325 static inline ABTI_ythread *
327  ABTI_ythread *p_old, ABTI_ythread *p_new)
328 {
329  return ABTI_ythread_context_switch_to_sibling_internal(pp_local_xstream,
330  p_old, p_new,
331  ABT_FALSE);
332 }
333 
335  ABTI_xstream **pp_local_xstream, ABTI_ythread *p_old,
336  ABT_sync_event_type sync_event_type, void *p_sync)
337 {
338  return ABTI_ythread_context_switch_to_parent_internal(pp_local_xstream,
339  p_old, ABT_FALSE,
340  sync_event_type,
341  p_sync);
342 }
343 
344 static inline ABTI_ythread *
346  ABTI_ythread *p_old, ABTI_ythread *p_new)
347 {
348  return ABTI_ythread_context_switch_to_child_internal(pp_local_xstream,
349  p_old, p_new);
350 }
351 
352 ABTU_noreturn static inline void
354  ABTI_ythread *p_old, ABTI_ythread *p_new)
355 {
356  ABTI_ythread_context_switch_to_sibling_internal(&p_local_xstream, p_old,
357  p_new, ABT_TRUE);
359 }
360 
361 ABTU_noreturn static inline void
363  ABTI_ythread *p_old)
364 {
365  ABTI_ythread_context_switch_to_parent_internal(&p_local_xstream, p_old,
366  ABT_TRUE,
368  NULL);
370 }
371 
372 static inline void ABTI_ythread_yield(ABTI_xstream **pp_local_xstream,
373  ABTI_ythread *p_ythread,
374  ABT_sync_event_type sync_event_type,
375  void *p_sync)
376 {
377  LOG_DEBUG("[U%" PRIu64 ":E%d] yield\n",
378  ABTI_thread_get_id(&p_ythread->thread),
379  p_ythread->thread.p_last_xstream->rank);
380 
381  /* Change the state of current running thread */
384 
385  /* Switch to the top scheduler */
386  ABTI_ythread_context_switch_to_parent(pp_local_xstream, p_ythread,
387  sync_event_type, p_sync);
388 
389  /* Back to the original thread */
390  LOG_DEBUG("[U%" PRIu64 ":E%d] resume after yield\n",
391  ABTI_thread_get_id(&p_ythread->thread),
392  p_ythread->thread.p_last_xstream->rank);
393 }
394 
395 #endif /* ABTI_YTHREAD_H_INCLUDED */
ABTI_ythread_context_switch_to_parent_internal
static ABTI_ythread * ABTI_ythread_context_switch_to_parent_internal(ABTI_xstream **pp_local_xstream, ABTI_ythread *p_old, ABT_bool is_finish, ABT_sync_event_type sync_event_type, void *p_sync)
Definition: abti_ythread.h:176
ABT_bool
int ABT_bool
Boolean type.
Definition: abt.h:1001
ABTI_THREAD_REQ_TERMINATE
#define ABTI_THREAD_REQ_TERMINATE
Definition: abti.h:43
ABTI_ythread_get_ptr
static ABTI_ythread * ABTI_ythread_get_ptr(ABT_thread thread)
Definition: abti_ythread.h:11
ABT_THREAD_STATE_READY
@ ABT_THREAD_STATE_READY
Definition: abt.h:417
ABT_thread
struct ABT_thread_opaque * ABT_thread
Work unit handle type.
Definition: abt.h:890
ABTI_ythread_context_switch_to_sibling
static ABTI_ythread * ABTI_ythread_context_switch_to_sibling(ABTI_xstream **pp_local_xstream, ABTI_ythread *p_old, ABTI_ythread *p_new)
Definition: abti_ythread.h:326
ABTI_thread::type
ABTI_thread_type type
Definition: abti.h:375
ABTI_ythread::stacksize
size_t stacksize
Definition: abti.h:410
ABTI_xstream::rank
int rank
Definition: abti.h:269
ABTI_thread::p_arg
void * p_arg
Definition: abti.h:380
ABTU_noreturn
#define ABTU_noreturn
Definition: abtu.h:118
ABTI_THREAD_TYPE_YIELDABLE
#define ABTI_THREAD_TYPE_YIELDABLE
Definition: abti.h:86
ABTI_thread::request
ABTD_atomic_uint32 request
Definition: abti.h:382
ABTI_thread_get_ythread
static ABTI_ythread * ABTI_thread_get_ythread(ABTI_thread *p_thread)
Definition: abti_thread.h:52
ABTI_thread_get_id
ABT_unit_id ABTI_thread_get_id(ABTI_thread *p_thread)
Definition: thread.c:2561
ABT_THREAD_NULL
#define ABT_THREAD_NULL
Definition: abt.h:1062
ABTI_thread
Definition: abti.h:371
ABTD_ythread_context::p_link
ABTD_ythread_context_atomic_ptr p_link
Definition: abtd_fcontext.h:36
ABTI_xstream
Definition: abti.h:264
ABTD_ythread_context
Definition: abtd_fcontext.h:33
ABTI_ythread_get_handle
static ABT_thread ABTI_ythread_get_handle(ABTI_ythread *p_ythread)
Definition: abti_ythread.h:26
ABTI_THREAD_TYPE_EXT
#define ABTI_THREAD_TYPE_EXT
Definition: abti.h:81
ABTI_ythread_context_get_ythread
static ABTI_ythread * ABTI_ythread_context_get_ythread(ABTD_ythread_context *p_ctx)
Definition: abti_ythread.h:42
ABT_SYNC_EVENT_TYPE_UNKNOWN
@ ABT_SYNC_EVENT_TYPE_UNKNOWN
Definition: abt.h:662
ABT_sync_event_type
ABT_sync_event_type
Type of synchronization event.
Definition: abt.h:660
ABTI_thread::state
ABTD_atomic_int state
Definition: abti.h:381
LOG_DEBUG
#define LOG_DEBUG(fmt,...)
Definition: abti_log.h:26
ABTI_ythread_context_switch_to_child_internal
static ABTI_ythread * ABTI_ythread_context_switch_to_child_internal(ABTI_xstream **pp_local_xstream, ABTI_ythread *p_old, ABTI_ythread *p_new)
Definition: abti_ythread.h:211
ABTI_ythread::ctx
ABTD_ythread_context ctx
Definition: abti.h:408
ABTI_ASSERT
#define ABTI_ASSERT(cond)
Definition: abti_error.h:12
ABTD_futex_single
Definition: abtd_futex.h:84
ABTI_tool_event_ythread_yield
#define ABTI_tool_event_ythread_yield(p_local_xstream, p_ythread, p_parent, sync_event_type, p_sync)
Definition: abti_tool.h:312
ABTI_tool_event_thread_run
#define ABTI_tool_event_thread_run(p_local_xstream, p_thread, p_prev, p_parent)
Definition: abti_tool.h:288
ABTI_ythread_finish_context_to_parent
static ABTU_noreturn void ABTI_ythread_finish_context_to_parent(ABTI_xstream *p_local_xstream, ABTI_ythread *p_old)
Definition: abti_ythread.h:362
ABTI_ythread_context_switch_to_parent
static ABTI_ythread * ABTI_ythread_context_switch_to_parent(ABTI_xstream **pp_local_xstream, ABTI_ythread *p_old, ABT_sync_event_type sync_event_type, void *p_sync)
Definition: abti_ythread.h:334
ABTI_local_get_local_uninlined
static ABTI_local * ABTI_local_get_local_uninlined(void)
Definition: abti_local.h:51
ABTI_ythread_dynamic_promote_ythread
static void ABTI_ythread_dynamic_promote_ythread(ABTI_ythread *p_ythread)
Definition: abti_ythread.h:132
ABTI_xstream_get_local
static ABTI_local * ABTI_xstream_get_local(ABTI_xstream *p_xstream)
Definition: abti_stream.h:68
ABT_TRUE
#define ABT_TRUE
True constant for ABT_bool.
Definition: abt.h:748
ABTD_ythread_context_arm_ythread
static void ABTD_ythread_context_arm_ythread(size_t stacksize, void *p_stack, ABTD_ythread_context *p_newctx)
Definition: abtd_ythread.h:55
ABTD_futex_resume
void ABTD_futex_resume(ABTD_futex_single *p_futex)
Definition: abtd_futex.c:216
ABTD_ythread_context_is_dynamic_promoted
static ABT_bool ABTD_ythread_context_is_dynamic_promoted(ABTD_ythread_context *p_ctx)
Definition: abtd_ythread.h:96
ABTD_ythread_context_dynamic_promote_ythread
static void ABTD_ythread_context_dynamic_promote_ythread(void *p_stacktop)
Definition: abtd_ythread.h:114
ABT_FALSE
#define ABT_FALSE
False constant for ABT_bool.
Definition: abt.h:750
ABTI_ythread
Definition: abti.h:406
ABTI_ythread_set_ready
void ABTI_ythread_set_ready(ABTI_local *p_local, ABTI_ythread *p_ythread)
Definition: ythread.c:65
ABTD_ythread_context_switch
static void ABTD_ythread_context_switch(ABTD_ythread_context *p_old, ABTD_ythread_context *p_new)
Definition: abtd_ythread.h:73
ABTI_thread::p_parent
ABTI_thread * p_parent
Definition: abti.h:378
ABTD_atomic_fetch_or_uint32
static uint32_t ABTD_atomic_fetch_or_uint32(ABTD_atomic_uint32 *ptr, uint32_t v)
Definition: abtd_atomic.h:631
ABTI_ythread_context_switch_to_child
static ABTI_ythread * ABTI_ythread_context_switch_to_child(ABTI_xstream **pp_local_xstream, ABTI_ythread *p_old, ABTI_ythread *p_new)
Definition: abti_ythread.h:345
ABTI_thread::p_last_xstream
ABTI_xstream * p_last_xstream
Definition: abti.h:377
ABTI_ythread::p_stack
void * p_stack
Definition: abti.h:409
ABTI_ythread_finish_context_to_sibling
static ABTU_noreturn void ABTI_ythread_finish_context_to_sibling(ABTI_xstream *p_local_xstream, ABTI_ythread *p_old, ABTI_ythread *p_new)
Definition: abti_ythread.h:353
ABTI_ythread::thread
ABTI_thread thread
Definition: abti.h:407
ABTI_local
struct ABTI_local ABTI_local
Definition: abti.h:110
ABTI_ythread_is_dynamic_promoted
static ABT_bool ABTI_ythread_is_dynamic_promoted(ABTI_ythread *p_ythread)
Definition: abti_ythread.h:48
ABTI_ythread_yield
static void ABTI_ythread_yield(ABTI_xstream **pp_local_xstream, ABTI_ythread *p_ythread, ABT_sync_event_type sync_event_type, void *p_sync)
Definition: abti_ythread.h:372
ABTD_ythread_finish_context
static ABTU_noreturn void ABTD_ythread_finish_context(ABTD_ythread_context *p_old, ABTD_ythread_context *p_new)
Definition: abtd_ythread.h:80
ABTI_thread::f_thread
void(* f_thread)(void *)
Definition: abti.h:379
ABTD_atomic_release_store_uint32
static void ABTD_atomic_release_store_uint32(ABTD_atomic_uint32 *ptr, uint32_t val)
Definition: abtd_atomic.h:1100
ABTD_ythread_context_make_and_call
static void ABTD_ythread_context_make_and_call(ABTD_ythread_context *p_old, void(*f_thread)(void *), void *p_arg, void *p_stacktop)
Definition: abtd_ythread.h:88
ABTI_local_get_xstream
static ABTI_xstream * ABTI_local_get_xstream(ABTI_local *p_local)
Definition: abti_local.h:86
ABTU_unreachable
static ABTU_noreturn void ABTU_unreachable(void)
Definition: abtu.h:126
ABTI_ythread_context_switch_to_sibling_internal
static ABTI_ythread * ABTI_ythread_context_switch_to_sibling_internal(ABTI_xstream **pp_local_xstream, ABTI_ythread *p_old, ABTI_ythread *p_new, ABT_bool is_finish)
Definition: abti_ythread.h:143
ABTD_atomic_release_store_int
static void ABTD_atomic_release_store_int(ABTD_atomic_int *ptr, int val)
Definition: abtd_atomic.h:1065
ABTI_tool_event_thread_finish
#define ABTI_tool_event_thread_finish(p_local_xstream, p_thread, p_parent)
Definition: abti_tool.h:297
ABTD_atomic_acquire_load_ythread_context_ptr
static ABTD_ythread_context * ABTD_atomic_acquire_load_ythread_context_ptr(const ABTD_ythread_context_atomic_ptr *ptr)
Definition: abtd_context.h:37
ABTI_THREAD_REQ_JOIN
#define ABTI_THREAD_REQ_JOIN
Definition: abti.h:42