ARGOBOTS  1.1
abtd_ythread.c
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 #include "abti.h"
7 
8 static inline void ythread_terminate(ABTI_xstream *p_local_xstream,
9  ABTI_ythread *p_ythread);
10 
11 void ABTD_ythread_func_wrapper(void *p_arg)
12 {
15  ABTI_xstream *p_local_xstream = p_ythread->thread.p_last_xstream;
16  ABTI_tool_event_thread_run(p_local_xstream, &p_ythread->thread,
17  p_local_xstream->p_thread,
18  p_ythread->thread.p_parent);
19  p_local_xstream->p_thread = &p_ythread->thread;
20 
21  p_ythread->thread.f_thread(p_ythread->thread.p_arg);
22 
23  /* This ABTI_local_get_xstream() is controversial since it is called after
24  * the context-switchable function (i.e., thread_func()). We assume that
25  * the compiler does not load TLS offset etc before thread_func(). */
26  p_local_xstream = ABTI_local_get_xstream(ABTI_local_get_local());
27  ythread_terminate(p_local_xstream, p_ythread);
28 }
29 
30 void ABTD_ythread_exit(ABTI_xstream *p_local_xstream, ABTI_ythread *p_ythread)
31 {
32  ythread_terminate(p_local_xstream, p_ythread);
33 }
34 
35 static inline void ythread_terminate(ABTI_xstream *p_local_xstream,
36  ABTI_ythread *p_ythread)
37 {
38  ABTD_ythread_context *p_ctx = &p_ythread->ctx;
39  ABTD_ythread_context *p_link =
41  if (!p_link) {
42  uint32_t req =
46  if (!(req & ABTI_THREAD_REQ_JOIN)) {
47  /* This case means there is no join request. Let's go back to the
48  * parent ULT */
49  ABTI_ythread_finish_context_to_parent(p_local_xstream, p_ythread);
51  } else {
52  /* This case means there has been a join request and the joiner has
53  * blocked. We have to wake up the joiner ULT. */
54  do {
56  &p_ctx->p_link);
57  } while (!p_link);
58  }
59  }
60  /* Now p_link != NULL. */
62 #ifndef ABT_CONFIG_ACTIVE_WAIT_POLICY
63  if (p_joiner->thread.type == ABTI_THREAD_TYPE_EXT) {
64  /* p_joiner is a non-yieldable thread (i.e., external thread). Wake up
65  * the waiter via the futex. Note that p_arg is used to store futex
66  * (see thread_join_futexwait()). */
67  ABTD_futex_single *p_futex =
68  (ABTD_futex_single *)p_joiner->thread.p_arg;
69  ABTD_futex_resume(p_futex);
70  } else
71 #endif
72  if (p_ythread->thread.p_last_xstream ==
73  p_joiner->thread.p_last_xstream &&
74  !(p_ythread->thread.type & ABTI_THREAD_TYPE_MAIN_SCHED)) {
75  /* Only when the current ULT is on the same ES as p_joiner's,
76  * we can jump to the joiner ULT. */
79  LOG_DEBUG("[U%" PRIu64 ":E%d] terminated\n",
80  ABTI_thread_get_id(&p_ythread->thread),
81  p_ythread->thread.p_last_xstream->rank);
82  /* Note that a parent ULT cannot be a joiner. */
84  p_joiner, &p_ythread->thread);
85  ABTI_ythread_finish_context_to_sibling(p_local_xstream, p_ythread,
86  p_joiner);
88  } else {
89  /* If the current ULT's associated ES is different from p_joiner's, we
90  * can't directly jump to p_joiner. Instead, we wake up p_joiner here
91  * so that p_joiner's scheduler can resume it. Note that the main
92  * scheduler needs to jump back to the root scheduler, so the main
93  * scheduler needs to take this path. */
95  p_joiner);
96  }
97  /* We don't need to use the atomic OR operation here because the ULT
98  * will be terminated regardless of other requests. */
101  /* The waiter has been resumed. Let's switch to the parent. */
102  ABTI_ythread_finish_context_to_parent(p_local_xstream, p_ythread);
104 }
105 
106 #if ABT_CONFIG_THREAD_TYPE == ABT_THREAD_TYPE_DYNAMIC_PROMOTION
108 {
109  ABTI_local *p_local = ABTI_local_get_local();
110  ABTI_xstream *p_local_xstream = ABTI_local_get_xstream(p_local);
111  /* This function is called by `return` in
112  * ABTD_ythread_context_make_and_call, so it cannot take the argument. We
113  * get the thread descriptor from TLS. */
114  ABTI_thread *p_thread = p_local_xstream->p_thread;
116  ythread_terminate(p_local_xstream, ABTI_thread_get_ythread(p_thread));
117 }
118 #endif
119 
120 void ABTD_ythread_cancel(ABTI_xstream *p_local_xstream, ABTI_ythread *p_ythread)
121 {
122  /* When we cancel a ULT, if other ULT is blocked to join the canceled ULT,
123  * we have to wake up the joiner ULT. However, unlike the case when the
124  * ULT has finished its execution and calls ythread_terminate/exit,
125  * this function is called by the scheduler. Therefore, we should not
126  * context switch to the joiner ULT and need to always wake it up. */
127  ABTD_ythread_context *p_ctx = &p_ythread->ctx;
128 
130  /* If p_link is set, it means that other ULT has called the join. */
134  p_joiner);
135  } else {
136  uint32_t req =
140  if (req & ABTI_THREAD_REQ_JOIN) {
141  /* This case means there has been a join request and the joiner has
142  * blocked. We have to wake up the joiner ULT. */
144  &p_ctx->p_link) == NULL)
145  ;
149  p_joiner);
150  }
151  }
152  ABTI_tool_event_thread_cancel(p_local_xstream, &p_ythread->thread);
153 }
154 
155 void ABTD_ythread_print_context(ABTI_ythread *p_ythread, FILE *p_os, int indent)
156 {
157  ABTD_ythread_context *p_ctx = &p_ythread->ctx;
158  fprintf(p_os, "%*sp_ctx : %p\n", indent, "", p_ctx->p_ctx);
159  fprintf(p_os, "%*sp_link : %p\n", indent, "",
161  &p_ctx->p_link));
162  fflush(p_os);
163 }
ABT_THREAD_STATE_TERMINATED
@ ABT_THREAD_STATE_TERMINATED
Definition: abt.h:423
ABTI_THREAD_REQ_TERMINATE
#define ABTI_THREAD_REQ_TERMINATE
Definition: abti.h:43
ABTI_thread::type
ABTI_thread_type type
Definition: abti.h:375
ABTI_xstream::rank
int rank
Definition: abti.h:269
ABTD_atomic_relaxed_load_ythread_context_ptr
static ABTD_ythread_context * ABTD_atomic_relaxed_load_ythread_context_ptr(const ABTD_ythread_context_atomic_ptr *ptr)
Definition: abtd_context.h:30
ABTI_thread::p_arg
void * p_arg
Definition: abti.h:380
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
ABTD_ythread_cancel
void ABTD_ythread_cancel(ABTI_xstream *p_local_xstream, ABTI_ythread *p_ythread)
Definition: abtd_ythread.c:120
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_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
ABTD_ythread_exit
void ABTD_ythread_exit(ABTI_xstream *p_local_xstream, ABTI_ythread *p_ythread)
Definition: abtd_ythread.c:30
abti.h
ythread_terminate
static void ythread_terminate(ABTI_xstream *p_local_xstream, ABTI_ythread *p_ythread)
Definition: abtd_ythread.c:35
ABTI_thread::state
ABTD_atomic_int state
Definition: abti.h:381
LOG_DEBUG
#define LOG_DEBUG(fmt,...)
Definition: abti_log.h:26
ABTI_ythread::ctx
ABTD_ythread_context ctx
Definition: abti.h:408
ABTD_ythread_func_wrapper
void ABTD_ythread_func_wrapper(void *p_arg)
Definition: abtd_ythread.c:11
ABTI_ASSERT
#define ABTI_ASSERT(cond)
Definition: abti_error.h:12
ABTD_futex_single
Definition: abtd_futex.h:84
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_local_get_local
static ABTI_local * ABTI_local_get_local(void)
Definition: abti_local.h:41
ABTD_ythread_context::p_ctx
void * p_ctx
Definition: abtd_fcontext.h:34
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_tool_event_ythread_resume
#define ABTI_tool_event_ythread_resume(p_local, p_ythread, p_caller)
Definition: abti_tool.h:332
ABTI_xstream_get_local
static ABTI_local * ABTI_xstream_get_local(ABTI_xstream *p_xstream)
Definition: abti_stream.h:68
ABTD_ythread_print_context
void ABTD_ythread_print_context(ABTI_ythread *p_ythread, FILE *p_os, int indent)
Definition: abtd_ythread.c:155
ABTD_futex_resume
void ABTD_futex_resume(ABTD_futex_single *p_futex)
Definition: abtd_futex.c:216
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
ABTI_THREAD_TYPE_MAIN_SCHED
#define ABTI_THREAD_TYPE_MAIN_SCHED
Definition: abti.h:85
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_thread::p_last_xstream
ABTI_xstream * p_last_xstream
Definition: abti.h:377
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_tool_event_thread_cancel
#define ABTI_tool_event_thread_cancel(p_local_xstream, p_thread)
Definition: abti_tool.h:305
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
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
ABTD_ythread_terminate_no_arg
void ABTD_ythread_terminate_no_arg()
Definition: abtd_ythread.c:107
ABTD_atomic_release_store_int
static void ABTD_atomic_release_store_int(ABTD_atomic_int *ptr, int val)
Definition: abtd_atomic.h:1065
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