ARGOBOTS  23067fa015f4b179569e2d52278c1072e674eb1e
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
abtd_thread.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 ABTD_thread_terminate(ABTI_xstream *p_local_xstream,
9  ABTI_thread *p_thread);
10 
11 void ABTD_thread_func_wrapper(void *p_arg)
12 {
13  ABTD_thread_context *p_ctx = (ABTD_thread_context *)p_arg;
15  ABTI_xstream *p_local_xstream = p_thread->unit_def.p_last_xstream;
16  ABTI_tool_event_thread_run(p_local_xstream, p_thread,
17  p_local_xstream->p_unit,
18  p_thread->unit_def.p_parent);
19  p_local_xstream->p_unit = &p_thread->unit_def;
20 
21  p_thread->unit_def.f_unit(p_thread->unit_def.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();
27  ABTD_thread_terminate(p_local_xstream, p_thread);
28 }
29 
30 void ABTD_thread_exit(ABTI_xstream *p_local_xstream, ABTI_thread *p_thread)
31 {
32  ABTD_thread_terminate(p_local_xstream, p_thread);
33 }
34 
35 static inline void ABTD_thread_terminate(ABTI_xstream *p_local_xstream,
36  ABTI_thread *p_thread)
37 {
38  ABTD_thread_context *p_ctx = &p_thread->ctx;
39  ABTD_thread_context *p_link =
41  if (p_link) {
42  /* If p_link is set, it means that other ULT has called the join. */
43  ABTI_thread *p_joiner = ABTI_thread_context_get_thread(p_link);
44  if (p_thread->unit_def.p_last_xstream ==
45  p_joiner->unit_def.p_last_xstream) {
46  /* Only when the current ULT is on the same ES as p_joiner's,
47  * we can jump to the joiner ULT. */
50  LOG_DEBUG("[U%" PRIu64 ":E%d] terminated\n",
51  ABTI_thread_get_id(p_thread),
52  p_thread->unit_def.p_last_xstream->rank);
53 
54  /* Note that a parent ULT cannot be a joiner. */
55  ABTI_tool_event_thread_resume(p_local_xstream, p_joiner,
56  &p_thread->unit_def);
57  ABTI_thread_finish_context_to_sibling(p_local_xstream, p_thread,
58  p_joiner);
59  return;
60  } else {
61  /* If the current ULT's associated ES is different from p_joiner's,
62  * we can't directly jump to p_joiner. Instead, we wake up
63  * p_joiner here so that p_joiner's scheduler can resume it. */
64  ABTI_thread_set_ready(p_local_xstream, p_joiner);
65 
66  /* We don't need to use the atomic OR operation here because the ULT
67  * will be terminated regardless of other requests. */
70  }
71  } else {
72  uint32_t req = ABTD_atomic_fetch_or_uint32(&p_thread->unit_def.request,
75  if (req & ABTI_UNIT_REQ_JOIN) {
76  /* This case means there has been a join request and the joiner has
77  * blocked. We have to wake up the joiner ULT. */
78  do {
79  p_link =
81  } while (!p_link);
82  ABTI_thread_set_ready(p_local_xstream,
84  }
85  }
86 
87  /* No other ULT is waiting or blocked for this ULT. Since a context does not
88  * switch to another context when it finishes, we need to explicitly switch
89  * to the parent. */
90  ABTI_thread_finish_context_to_parent(p_local_xstream, p_thread);
91 }
92 
93 #if ABT_CONFIG_THREAD_TYPE == ABT_THREAD_TYPE_DYNAMIC_PROMOTION
95 {
96  ABTI_xstream *p_local_xstream = ABTI_local_get_xstream();
97  /* This function is called by `return` in ABTD_thread_context_make_and_call,
98  * so it cannot take the argument. We get the thread descriptor from TLS. */
99  ABTI_unit *p_unit = p_local_xstream->p_unit;
101  ABTD_thread_terminate(p_local_xstream, ABTI_unit_get_thread(p_unit));
102 }
103 #endif
104 
105 void ABTD_thread_cancel(ABTI_xstream *p_local_xstream, ABTI_thread *p_thread)
106 {
107  /* When we cancel a ULT, if other ULT is blocked to join the canceled ULT,
108  * we have to wake up the joiner ULT. However, unlike the case when the
109  * ULT has finished its execution and calls ABTD_thread_terminate/exit,
110  * this function is called by the scheduler. Therefore, we should not
111  * context switch to the joiner ULT and need to always wake it up. */
112  ABTD_thread_context *p_ctx = &p_thread->ctx;
113 
115  /* If p_link is set, it means that other ULT has called the join. */
118  ABTI_thread_set_ready(p_local_xstream, p_joiner);
119  } else {
120  uint32_t req = ABTD_atomic_fetch_or_uint32(&p_thread->unit_def.request,
123  if (req & ABTI_UNIT_REQ_JOIN) {
124  /* This case means there has been a join request and the joiner has
125  * blocked. We have to wake up the joiner ULT. */
127  &p_ctx->p_link) == NULL)
128  ;
131  ABTI_thread_set_ready(p_local_xstream, p_joiner);
132  }
133  }
134  ABTI_tool_event_thread_cancel(p_local_xstream, p_thread);
135 }
136 
137 void ABTD_thread_print_context(ABTI_thread *p_thread, FILE *p_os, int indent)
138 {
139  char *prefix = ABTU_get_indent_str(indent);
140  ABTD_thread_context *p_ctx = &p_thread->ctx;
141  fprintf(p_os, "%sp_ctx : %p\n", prefix, p_ctx->p_ctx);
142  fprintf(p_os, "%sp_link : %p\n", prefix,
144  &p_ctx->p_link));
145  fflush(p_os);
146  ABTU_free(prefix);
147 }
void ABTD_thread_exit(ABTI_xstream *p_local_xstream, ABTI_thread *p_thread)
Definition: abtd_thread.c:30
ABTD_thread_context ctx
Definition: abti.h:360
ABTD_atomic_int state
Definition: abti.h:334
#define ABTI_UNIT_REQ_JOIN
Definition: abti.h:33
char * ABTU_get_indent_str(int indent)
Definition: util.c:12
static void ABTD_thread_terminate(ABTI_xstream *p_local_xstream, ABTI_thread *p_thread)
Definition: abtd_thread.c:35
static void ABTD_atomic_release_store_int(ABTD_atomic_int *ptr, int val)
Definition: abtd_atomic.h:924
ABTD_atomic_uint32 request
Definition: abti.h:335
ABTI_xstream * p_last_xstream
Definition: abti.h:330
ABTI_unit_type type
Definition: abti.h:328
static void ABTD_atomic_release_store_uint32(ABTD_atomic_uint32 *ptr, uint32_t val)
Definition: abtd_atomic.h:947
static ABTU_noreturn void ABTI_thread_finish_context_to_parent(ABTI_xstream *p_local_xstream, ABTI_thread *p_old)
Definition: abti_thread.h:334
void * p_arg
Definition: abti.h:333
#define ABTI_tool_event_thread_resume(p_local_xstream, p_thread, p_caller)
Definition: abti_tool.h:455
ABTI_unit * p_unit
Definition: abti.h:257
static ABTD_thread_context * ABTD_atomic_acquire_load_thread_context_ptr(const ABTD_thread_context_atomic_ptr *ptr)
Definition: abtd_context.h:28
static uint32_t ABTD_atomic_fetch_or_uint32(ABTD_atomic_uint32 *ptr, uint32_t v)
Definition: abtd_atomic.h:538
ABT_unit_id ABTI_thread_get_id(ABTI_thread *p_thread)
Definition: thread.c:2235
void ABTD_thread_cancel(ABTI_xstream *p_local_xstream, ABTI_thread *p_thread)
Definition: abtd_thread.c:105
void ABTD_thread_func_wrapper(void *p_arg)
Definition: abtd_thread.c:11
int rank
Definition: abti.h:244
#define ABTI_UNIT_REQ_TERMINATE
Definition: abti.h:37
static ABTI_thread * ABTI_unit_get_thread(ABTI_unit *p_unit)
Definition: abti_unit.h:97
static ABTI_thread * ABTI_thread_context_get_thread(ABTD_thread_context *p_ctx)
Definition: abti_thread.h:42
void ABTD_thread_terminate_no_arg()
Definition: abtd_thread.c:94
ABTI_unit unit_def
Definition: abti.h:361
void ABTD_thread_print_context(ABTI_thread *p_thread, FILE *p_os, int indent)
Definition: abtd_thread.c:137
ABTD_thread_context_atomic_ptr p_link
Definition: abtd_context.h:49
static ABTI_xstream * ABTI_local_get_xstream(void)
Definition: abti_local.h:41
ABTI_unit * p_parent
Definition: abti.h:331
int ABTI_thread_set_ready(ABTI_xstream *p_local_xstream, ABTI_thread *p_thread)
Definition: thread.c:2054
#define ABTI_ASSERT(cond)
Definition: abti_error.h:18
#define LOG_DEBUG(fmt,...)
Definition: abti_log.h:30
#define ABTI_tool_event_thread_cancel(p_local_xstream, p_thread)
Definition: abti_tool.h:428
static ABTU_noreturn void ABTI_thread_finish_context_to_sibling(ABTI_xstream *p_local_xstream, ABTI_thread *p_old, ABTI_thread *p_new)
Definition: abti_thread.h:325
static ABT_bool ABTI_unit_type_is_thread(ABTI_unit_type type)
Definition: abti_unit.h:53
#define ABTI_tool_event_thread_run(p_local_xstream, p_thread, p_prev,p_parent)
Definition: abti_tool.h:411
static void ABTU_free(void *ptr)
Definition: abtu.h:111
void(* f_unit)(void *)
Definition: abti.h:332
static ABTD_thread_context * ABTD_atomic_relaxed_load_thread_context_ptr(const ABTD_thread_context_atomic_ptr *ptr)
Definition: abtd_context.h:22