ARGOBOTS  1.1
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 #ifdef ABT_CONFIG_ENABLE_STACK_UNWIND
9 
10 #ifndef ABT_CONFIG_ENABLE_PEEK_CONTEXT
11 #error "ABT_CONFIG_ENABLE_PEEK_CONTEXT must be enabled"
12 #endif
13 
14 #define UNW_LOCAL_ONLY
15 #include <libunwind.h>
16 struct unwind_stack_t {
17  FILE *fp;
18 };
19 static void ythread_unwind_stack(void *arg);
20 
21 #endif
22 
24 {
25  /* The root thread cannot be blocked */
27 
28  /* To prevent the scheduler from adding the ULT to the pool */
30 
31  /* Change the ULT's state to BLOCKED */
34 
35  /* Increase the number of blocked ULTs */
36  ABTI_pool *p_pool = p_ythread->thread.p_pool;
38 
39  LOG_DEBUG("[U%" PRIu64 ":E%d] blocked\n",
40  ABTI_thread_get_id(&p_ythread->thread),
41  p_ythread->thread.p_last_xstream->rank);
42 }
43 
44 /* NOTE: This routine should be called after ABTI_ythread_set_blocked. */
45 void ABTI_ythread_suspend(ABTI_xstream **pp_local_xstream,
46  ABTI_ythread *p_ythread,
47  ABT_sync_event_type sync_event_type, void *p_sync)
48 {
49  ABTI_xstream *p_local_xstream = *pp_local_xstream;
50  ABTI_ASSERT(&p_ythread->thread == p_local_xstream->p_thread);
51  ABTI_ASSERT(p_ythread->thread.p_last_xstream == p_local_xstream);
52 
53  /* Switch to the scheduler, i.e., suspend p_ythread */
54  LOG_DEBUG("[U%" PRIu64 ":E%d] suspended\n",
55  ABTI_thread_get_id(&p_ythread->thread), p_local_xstream->rank);
56  ABTI_ythread_context_switch_to_parent(pp_local_xstream, p_ythread,
57  sync_event_type, p_sync);
58 
59  /* The suspended ULT resumes its execution from here. */
60  LOG_DEBUG("[U%" PRIu64 ":E%d] resumed\n",
61  ABTI_thread_get_id(&p_ythread->thread),
62  p_ythread->thread.p_last_xstream->rank);
63 }
64 
66 {
67  /* The ULT must be in BLOCKED state. */
70 
71  /* We should wait until the scheduler of the blocked ULT resets the BLOCK
72  * request. Otherwise, the ULT can be pushed to a pool here and be
73  * scheduled by another scheduler if it is pushed to a shared pool. */
74  while (ABTD_atomic_acquire_load_uint32(&p_ythread->thread.request) &
77 
78  LOG_DEBUG("[U%" PRIu64 ":E%d] set ready\n",
79  ABTI_thread_get_id(&p_ythread->thread),
80  p_ythread->thread.p_last_xstream->rank);
81 
82  ABTI_tool_event_ythread_resume(p_local, p_ythread,
84  ? ABTI_local_get_xstream(p_local)
85  ->p_thread
86  : NULL);
87  /* p_ythread->thread.p_pool is loaded before ABTI_POOL_ADD_THREAD to keep
88  * num_blocked consistent. Otherwise, other threads might pop p_ythread
89  * that has been pushed in ABTI_POOL_ADD_THREAD and change
90  * p_ythread->thread.p_pool by ABT_unit_set_associated_pool. */
91  ABTI_pool *p_pool = p_ythread->thread.p_pool;
92 
93  /* Add the ULT to its associated pool */
94  ABTI_pool_add_thread(&p_ythread->thread);
95 
96  /* Decrease the number of blocked threads */
98 }
99 
101  FILE *p_os)
102 {
103  ABTD_ythread_print_context(p_ythread, p_os, 0);
104  fprintf(p_os,
105  "stack : %p\n"
106  "stacksize : %" PRIu64 "\n",
107  p_ythread->p_stack, (uint64_t)p_ythread->stacksize);
108 
109 #ifdef ABT_CONFIG_ENABLE_STACK_UNWIND
110  {
111  /* Peeking a running context is specially forbidden. Though it is
112  * incomplete, let's quickly check if a thread is running. */
114  &p_ythread->thread.state);
115  if (state == ABT_THREAD_STATE_READY ||
116  state == ABT_THREAD_STATE_BLOCKED) {
117  struct unwind_stack_t arg;
118  arg.fp = p_os;
119  ABTI_ythread_context_peek(p_ythread, ythread_unwind_stack, &arg);
120  }
121  }
122 #endif
123 
124  void *p_stack = p_ythread->p_stack;
125  size_t i, j, stacksize = p_ythread->stacksize;
126  if (stacksize == 0 || p_stack == NULL) {
127  /* Some threads do not have p_stack (e.g., the main thread) */
128  fprintf(p_os, "no stack\n");
129  fflush(0);
130  return;
131  }
132 
133  char buffer[32];
134  const size_t value_width = 8;
135  const int num_bytes = sizeof(buffer);
136 
137  for (i = 0; i < stacksize; i += num_bytes) {
138  if (stacksize >= i + num_bytes) {
139  memcpy(buffer, &((uint8_t *)p_stack)[i], num_bytes);
140  } else {
141  memset(buffer, 0, num_bytes);
142  memcpy(buffer, &((uint8_t *)p_stack)[i], stacksize - i);
143  }
144  /* Print the stack address */
145 #if SIZEOF_VOID_P == 8
146  fprintf(p_os, "%016" PRIxPTR ":",
147  (uintptr_t)(&((uint8_t *)p_stack)[i]));
148 #elif SIZEOF_VOID_P == 4
149  fprintf(p_os, "%08" PRIxPTR ":", (uintptr_t)(&((uint8_t *)p_stack)[i]));
150 #else
151 #error "unknown pointer size"
152 #endif
153  /* Print the raw stack data */
154  for (j = 0; j < num_bytes / value_width; j++) {
155  if (value_width == 8) {
156  uint64_t val = ((uint64_t *)buffer)[j];
157  fprintf(p_os, " %016" PRIx64, val);
158  } else if (value_width == 4) {
159  uint32_t val = ((uint32_t *)buffer)[j];
160  fprintf(p_os, " %08" PRIx32, val);
161  } else if (value_width == 2) {
162  uint16_t val = ((uint16_t *)buffer)[j];
163  fprintf(p_os, " %04" PRIx16, val);
164  } else {
165  uint8_t val = ((uint8_t *)buffer)[j];
166  fprintf(p_os, " %02" PRIx8, val);
167  }
168  if (j == (num_bytes / value_width) - 1)
169  fprintf(p_os, "\n");
170  }
171  }
172  fflush(p_os);
173 }
174 
175 #ifdef ABT_CONFIG_ENABLE_STACK_UNWIND
176 ABTU_no_sanitize_address static int ythread_unwind_stack_impl(FILE *fp)
177 {
178  unw_cursor_t cursor;
179  unw_context_t uc;
180  unw_word_t ip, sp;
181  int ret, level = -1;
182 
183  ret = unw_getcontext(&uc);
184  if (ret != 0)
185  return ABT_ERR_OTHER;
186 
187  ret = unw_init_local(&cursor, &uc);
188  if (ret != 0)
189  return ABT_ERR_OTHER;
190 
191  while (unw_step(&cursor) > 0 && level < 50) {
192  level++;
193 
194  ret = unw_get_reg(&cursor, UNW_REG_IP, &ip);
195  if (ret != 0)
196  return ABT_ERR_OTHER;
197 
198  ret = unw_get_reg(&cursor, UNW_REG_SP, &sp);
199  if (ret != 0)
200  return ABT_ERR_OTHER;
201 
202  char proc_name[256];
203  unw_word_t offset;
204  ret = unw_get_proc_name(&cursor, proc_name, 256, &offset);
205  if (ret != 0)
206  return ABT_ERR_OTHER;
207 
208  /* Print function stack. */
209  fprintf(fp, "#%d %p in %s () <+%d> (%s = %p)\n", level,
210  (void *)((uintptr_t)ip), proc_name, (int)offset,
211  unw_regname(UNW_REG_SP), (void *)((uintptr_t)sp));
212  }
213  return ABT_SUCCESS;
214 }
215 
216 static void ythread_unwind_stack(void *arg)
217 {
218  struct unwind_stack_t *p_arg = (struct unwind_stack_t *)arg;
219  if (ythread_unwind_stack_impl(p_arg->fp) != ABT_SUCCESS) {
220  fprintf(p_arg->fp, "libunwind error\n");
221  }
222 }
223 
224 #endif /* ABT_CONFIG_ENABLE_STACK_UNWIND */
ABTI_ythread_set_ready
void ABTI_ythread_set_ready(ABTI_local *p_local, ABTI_ythread *p_ythread)
Definition: ythread.c:65
ABTI_THREAD_TYPE_ROOT
#define ABTI_THREAD_TYPE_ROOT
Definition: abti.h:83
ABT_THREAD_STATE_READY
@ ABT_THREAD_STATE_READY
Definition: abt.h:417
ABTD_atomic_acquire_load_uint32
static uint32_t ABTD_atomic_acquire_load_uint32(const ABTD_atomic_uint32 *ptr)
Definition: abtd_atomic.h:928
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::request
ABTD_atomic_uint32 request
Definition: abti.h:382
ABTI_thread_get_id
ABT_unit_id ABTI_thread_get_id(ABTI_thread *p_thread)
Definition: thread.c:2561
ABTI_ythread_set_blocked
void ABTI_ythread_set_blocked(ABTI_ythread *p_ythread)
Definition: ythread.c:23
ABTI_xstream
Definition: abti.h:264
ABT_thread_state
ABT_thread_state
State of a work unit.
Definition: abt.h:415
ABTI_pool
Definition: abti.h:327
ABT_sync_event_type
ABT_sync_event_type
Type of synchronization event.
Definition: abt.h:660
ABT_THREAD_STATE_BLOCKED
@ ABT_THREAD_STATE_BLOCKED
Definition: abt.h:421
abti.h
ABTI_pool_add_thread
static void ABTI_pool_add_thread(ABTI_thread *p_thread)
Definition: abti_pool.h:59
ABTI_thread::state
ABTD_atomic_int state
Definition: abti.h:381
ABTD_atomic_pause
static void ABTD_atomic_pause(void)
Definition: abtd_atomic.h:1257
LOG_DEBUG
#define LOG_DEBUG(fmt,...)
Definition: abti_log.h:26
ABTI_ASSERT
#define ABTI_ASSERT(cond)
Definition: abti_error.h:12
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
ABT_SUCCESS
#define ABT_SUCCESS
Error code: the routine returns successfully.
Definition: abt.h:92
ABTD_atomic_acquire_load_int
static int ABTD_atomic_acquire_load_int(const ABTD_atomic_int *ptr)
Definition: abtd_atomic.h:878
ABTI_tool_event_ythread_resume
#define ABTI_tool_event_ythread_resume(p_local, p_ythread, p_caller)
Definition: abti_tool.h:332
ABTI_local_get_xstream_or_null
static ABTI_xstream * ABTI_local_get_xstream_or_null(ABTI_local *p_local)
Definition: abti_local.h:77
ABTI_ythread
Definition: abti.h:406
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
ABTU_no_sanitize_address
#define ABTU_no_sanitize_address
Definition: abtu.h:200
ABT_ERR_OTHER
#define ABT_ERR_OTHER
Error code: other error.
Definition: abt.h:109
ABTI_ythread::thread
ABTI_thread thread
Definition: abti.h:407
ABTI_pool_inc_num_blocked
static void ABTI_pool_inc_num_blocked(ABTI_pool *p_pool)
Definition: abti_pool.h:42
ABTI_local
struct ABTI_local ABTI_local
Definition: abti.h:110
ABTI_ythread_suspend
void ABTI_ythread_suspend(ABTI_xstream **pp_local_xstream, ABTI_ythread *p_ythread, ABT_sync_event_type sync_event_type, void *p_sync)
Definition: ythread.c:45
ABTI_THREAD_REQ_BLOCK
#define ABTI_THREAD_REQ_BLOCK
Definition: abti.h:46
ABTI_ythread_print_stack
ABTU_no_sanitize_address void ABTI_ythread_print_stack(ABTI_ythread *p_ythread, FILE *p_os)
Definition: ythread.c:100
ABTI_thread::p_pool
ABTI_pool * p_pool
Definition: abti.h:383
ABTI_local_get_xstream
static ABTI_xstream * ABTI_local_get_xstream(ABTI_local *p_local)
Definition: abti_local.h:86
ABTD_atomic_release_store_int
static void ABTD_atomic_release_store_int(ABTD_atomic_int *ptr, int val)
Definition: abtd_atomic.h:1065
ABTI_pool_dec_num_blocked
static void ABTI_pool_dec_num_blocked(ABTI_pool *p_pool)
Definition: abti_pool.h:48
ABTI_thread_set_request
static void ABTI_thread_set_request(ABTI_thread *p_thread, uint32_t req)
Definition: abti_thread.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