ARGOBOTS  1.1
abti_tool.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_TOOL_H_INCLUDED
7 #define ABTI_TOOL_H_INCLUDED
8 
9 static inline ABT_thread ABTI_ythread_get_handle(ABTI_ythread *p_thread);
10 static inline ABT_task ABTI_thread_get_handle(ABTI_thread *p_task);
11 
12 #ifndef ABT_CONFIG_DISABLE_TOOL_INTERFACE
13 static inline ABTI_tool_context *
15 {
16 #ifndef ABT_CONFIG_DISABLE_ERROR_CHECK
17  ABTI_tool_context *p_tctx;
18  if (tctx == ABT_TOOL_CONTEXT_NULL) {
19  p_tctx = NULL;
20  } else {
21  p_tctx = (ABTI_tool_context *)tctx;
22  }
23  return p_tctx;
24 #else
25  return (ABTI_tool_context *)tctx;
26 #endif
27 }
28 
29 static inline ABT_tool_context
31 {
32 #ifndef ABT_CONFIG_DISABLE_ERROR_CHECK
33  ABT_tool_context h_tctx;
34  if (p_tctx == NULL) {
35  h_tctx = ABT_TOOL_CONTEXT_NULL;
36  } else {
37  h_tctx = (ABT_tool_context)p_tctx;
38  }
39  return h_tctx;
40 #else
41  return (ABT_tool_context)p_tctx;
42 #endif
43 }
44 
45 #define ABTI_TOOL_EVENT_TAG_SIZE 20 /* bits */
46 #define ABTI_TOOL_EVENT_TAG_MASK \
47  ((((uint64_t)1 << (uint64_t)ABTI_TOOL_EVENT_TAG_SIZE) - 1) \
48  << (uint64_t)(64 - 1 - ABTI_TOOL_EVENT_TAG_SIZE))
49 #define ABTI_TOOL_EVENT_TAG_INC \
50  ((uint64_t)1 << (uint64_t)(64 - 1 - ABTI_TOOL_EVENT_TAG_SIZE))
51 #define ABTI_TOOL_EVENT_TAG_DIRTY_BIT ((uint64_t)1 << (uint64_t)(64 - 1))
52 
53 static inline void
56  uint64_t event_mask, void *user_arg)
57 {
58  /* The spinlock is needed to avoid data race between two writers. */
60 
61  /*
62  * This atomic writing process is needed to avoid data race between a reader
63  * and a writer. We need to atomically update three values (callback, event
64  * mask, and user_arg) in the following cases:
65  *
66  * A. ES-W writes the three values while ES-R is reading the three values
67  * B. ES-W1 writes and then ES-W2 writes the three values while ES-R is
68  * reading the three values
69  *
70  * The reader will first read the event mask and then load the other two.
71  * The reader then read the event mask again and see if it is 1. the same as
72  * the previous and 2. clean. If both are satisfied, acquire-release memory
73  * order guarantees that the loaded values are ones updated by the same
74  * ABTI_tool_event_thread_update_callback() call, unless the tag value wraps
75  * around (which does not happen practically).
76  */
77 
78  uint64_t current = ABTD_atomic_acquire_load_uint64(
80  uint64_t new_tag =
82  uint64_t new_mask = new_tag | ((event_mask & ABT_TOOL_EVENT_THREAD_ALL) &
84  uint64_t dirty_mask = ABTI_TOOL_EVENT_TAG_DIRTY_BIT | new_mask;
85 
87  dirty_mask);
88  p_global->tool_thread_cb_f = cb_func;
89  p_global->tool_thread_user_arg = user_arg;
91  new_mask);
92 
94 }
95 
96 #endif /* !ABT_CONFIG_DISABLE_TOOL_INTERFACE */
97 
98 static inline void ABTI_tool_event_thread_impl(
99  ABTI_local *p_local, uint64_t event_code, ABTI_thread *p_thread,
100  ABTI_thread *p_caller, ABTI_pool *p_pool, ABTI_thread *p_parent,
101  ABT_sync_event_type sync_event_type, void *p_sync_object)
102 {
103 #ifdef ABT_CONFIG_DISABLE_TOOL_INTERFACE
104  return;
105 #else
106  ABTI_global *p_global = gp_ABTI_global;
107  while (1) {
108  uint64_t current_mask = ABTD_atomic_acquire_load_uint64(
109  &p_global->tool_thread_event_mask_tagged);
110  if (current_mask & event_code) {
111  ABT_tool_thread_callback_fn cb_func_thread =
112  p_global->tool_thread_cb_f;
113  void *user_arg_thread = p_global->tool_thread_user_arg;
114  /* Double check the current event mask. */
115  uint64_t current_mask2 = ABTD_atomic_acquire_load_uint64(
116  &p_global->tool_thread_event_mask_tagged);
117  if (ABTU_unlikely(current_mask != current_mask2 ||
118  (current_mask & ABTI_TOOL_EVENT_TAG_DIRTY_BIT)))
119  continue;
120  ABTI_tool_context tctx;
121  tctx.p_pool = p_pool;
122  tctx.p_parent = p_parent;
123  tctx.p_caller = p_caller;
124  tctx.sync_event_type = sync_event_type;
125  tctx.p_sync_object = p_sync_object;
126 
127  ABTI_xstream *p_local_xstream =
129  ABT_xstream h_xstream =
130  p_local_xstream ? ABTI_xstream_get_handle(p_local_xstream)
132  ABT_thread h_thread = ABTI_thread_get_handle(p_thread);
134  cb_func_thread(h_thread, h_xstream, event_code, h_tctx,
135  user_arg_thread);
136  }
137  return;
138  }
139 #endif /* !ABT_CONFIG_DISABLE_TOOL_INTERFACE */
140 }
141 
142 static inline void ABTI_tool_event_thread_create_impl(ABTI_local *p_local,
143  ABTI_thread *p_thread,
144  ABTI_thread *p_caller,
145  ABTI_pool *p_pool)
146 {
148  p_caller, p_pool, NULL,
150 }
151 
152 static inline void ABTI_tool_event_thread_join_impl(ABTI_local *p_local,
153  ABTI_thread *p_thread,
154  ABTI_thread *p_caller)
155 {
157  p_caller, NULL, NULL,
159 }
160 
161 static inline void ABTI_tool_event_thread_free_impl(ABTI_local *p_local,
162  ABTI_thread *p_thread,
163  ABTI_thread *p_caller)
164 {
166  p_caller, NULL, NULL,
168 }
169 
170 static inline void ABTI_tool_event_thread_revive_impl(ABTI_local *p_local,
171  ABTI_thread *p_thread,
172  ABTI_thread *p_caller,
173  ABTI_pool *p_pool)
174 {
176  p_caller, p_pool, NULL,
178 }
179 
180 static inline void
182  ABTI_thread *p_thread, ABTI_thread *p_prev,
183  ABTI_thread *p_parent)
184 {
186  ABT_TOOL_EVENT_THREAD_RUN, p_thread, p_prev,
187  NULL, p_parent, ABT_SYNC_EVENT_TYPE_UNKNOWN,
188  NULL);
189 }
190 
191 static inline void
193  ABTI_thread *p_thread, ABTI_thread *p_parent)
194 {
196  ABT_TOOL_EVENT_THREAD_FINISH, p_thread, NULL,
197  NULL, p_parent, ABT_SYNC_EVENT_TYPE_UNKNOWN,
198  NULL);
199 }
200 
201 static inline void
203  ABTI_thread *p_thread)
204 {
206  ABT_TOOL_EVENT_THREAD_CANCEL, p_thread, NULL,
207  NULL, NULL, ABT_SYNC_EVENT_TYPE_UNKNOWN, NULL);
208 }
209 
211  ABTI_xstream *p_local_xstream, ABTI_ythread *p_ythread,
212  ABTI_thread *p_parent, ABT_sync_event_type sync_event_type, void *p_sync)
213 {
218  &p_ythread->thread, NULL,
219  p_ythread->thread.p_pool, p_parent,
220  sync_event_type, p_sync);
221 
222  } else {
225  &p_ythread->thread, NULL,
226  p_ythread->thread.p_pool, p_parent,
227  sync_event_type, p_sync);
228  }
229 }
230 
232  ABTI_xstream *p_local_xstream, ABTI_ythread *p_ythread,
233  ABTI_thread *p_parent, ABT_sync_event_type sync_event_type, void *p_sync)
234 {
237  &p_ythread->thread, NULL,
238  p_ythread->thread.p_pool, p_parent,
239  sync_event_type, p_sync);
240 }
241 
243  ABTI_ythread *p_ythread,
244  ABTI_thread *p_caller)
245 {
247  &p_ythread->thread, p_caller,
248  p_ythread->thread.p_pool, NULL,
250 }
251 
252 #ifndef ABT_CONFIG_DISABLE_TOOL_INTERFACE
253 #define ABTI_USE_TOOL_INTERFACE 1
254 #else
255 #define ABTI_USE_TOOL_INTERFACE 0
256 #endif
257 
258 #define ABTI_tool_event_thread_create(p_local, p_thread, p_caller, p_pool) \
259  do { \
260  if (ABTI_USE_TOOL_INTERFACE) { \
261  ABTI_tool_event_thread_create_impl(p_local, p_thread, p_caller, \
262  p_pool); \
263  } \
264  } while (0)
265 
266 #define ABTI_tool_event_thread_join(p_local, p_thread, p_caller) \
267  do { \
268  if (ABTI_USE_TOOL_INTERFACE) { \
269  ABTI_tool_event_thread_join_impl(p_local, p_thread, p_caller); \
270  } \
271  } while (0)
272 
273 #define ABTI_tool_event_thread_free(p_local, p_thread, p_caller) \
274  do { \
275  if (ABTI_USE_TOOL_INTERFACE) { \
276  ABTI_tool_event_thread_free_impl(p_local, p_thread, p_caller); \
277  } \
278  } while (0)
279 
280 #define ABTI_tool_event_thread_revive(p_local, p_thread, p_caller, p_pool) \
281  do { \
282  if (ABTI_USE_TOOL_INTERFACE) { \
283  ABTI_tool_event_thread_revive_impl(p_local, p_thread, p_caller, \
284  p_pool); \
285  } \
286  } while (0)
287 
288 #define ABTI_tool_event_thread_run(p_local_xstream, p_thread, p_prev, \
289  p_parent) \
290  do { \
291  if (ABTI_USE_TOOL_INTERFACE) { \
292  ABTI_tool_event_thread_run_impl(p_local_xstream, p_thread, p_prev, \
293  p_parent); \
294  } \
295  } while (0)
296 
297 #define ABTI_tool_event_thread_finish(p_local_xstream, p_thread, p_parent) \
298  do { \
299  if (ABTI_USE_TOOL_INTERFACE) { \
300  ABTI_tool_event_thread_finish_impl(p_local_xstream, p_thread, \
301  p_parent); \
302  } \
303  } while (0)
304 
305 #define ABTI_tool_event_thread_cancel(p_local_xstream, p_thread) \
306  do { \
307  if (ABTI_USE_TOOL_INTERFACE) { \
308  ABTI_tool_event_thread_cancel_impl(p_local_xstream, p_thread); \
309  } \
310  } while (0)
311 
312 #define ABTI_tool_event_ythread_yield(p_local_xstream, p_ythread, p_parent, \
313  sync_event_type, p_sync) \
314  do { \
315  if (ABTI_USE_TOOL_INTERFACE) { \
316  ABTI_tool_event_ythread_yield_impl(p_local_xstream, p_ythread, \
317  p_parent, sync_event_type, \
318  p_sync); \
319  } \
320  } while (0)
321 
322 #define ABTI_tool_event_ythread_suspend(p_local_xstream, p_ythread, p_parent, \
323  sync_event_type, p_sync) \
324  do { \
325  if (ABTI_USE_TOOL_INTERFACE) { \
326  ABTI_tool_event_ythread_suspend_impl(p_local_xstream, p_ythread, \
327  p_parent, sync_event_type, \
328  p_sync); \
329  } \
330  } while (0)
331 
332 #define ABTI_tool_event_ythread_resume(p_local, p_ythread, p_caller) \
333  do { \
334  if (ABTI_USE_TOOL_INTERFACE) { \
335  ABTI_tool_event_ythread_resume_impl(p_local, p_ythread, p_caller); \
336  } \
337  } while (0)
338 
339 #endif /* ABTI_TOOL_H_INCLUDED */
ABTI_global::tool_writer_lock
ABTD_spinlock tool_writer_lock
Definition: abti.h:241
ABT_TOOL_EVENT_THREAD_CREATE
#define ABT_TOOL_EVENT_THREAD_CREATE
Work-unit-event mask: creating a work unit.
Definition: abt.h:694
ABT_task
struct ABT_thread_opaque * ABT_task
Work unit handle type.
Definition: abt.h:931
ABT_thread
struct ABT_thread_opaque * ABT_thread
Work unit handle type.
Definition: abt.h:890
ABT_TOOL_EVENT_THREAD_RUN
#define ABT_TOOL_EVENT_THREAD_RUN
Work-unit-event mask: running a work unit.
Definition: abt.h:714
ABTI_thread_get_handle
static ABT_task ABTI_thread_get_handle(ABTI_thread *p_task)
ABTI_tool_context_get_ptr
static ABTI_tool_context * ABTI_tool_context_get_ptr(ABT_tool_context tctx)
Definition: abti_tool.h:14
gp_ABTI_global
ABTI_global * gp_ABTI_global
Definition: global.c:18
ABTI_thread::request
ABTD_atomic_uint32 request
Definition: abti.h:382
ABT_TOOL_EVENT_THREAD_REVIVE
#define ABT_TOOL_EVENT_THREAD_REVIVE
Work-unit-event mask: reviving a work unit.
Definition: abt.h:709
ABTI_tool_context
Definition: abti.h:489
ABTI_global::tool_thread_cb_f
ABT_tool_thread_callback_fn tool_thread_cb_f
Definition: abti.h:243
ABTI_tool_event_thread_run_impl
static void ABTI_tool_event_thread_run_impl(ABTI_xstream *p_local_xstream, ABTI_thread *p_thread, ABTI_thread *p_prev, ABTI_thread *p_parent)
Definition: abti_tool.h:181
ABTI_tool_event_thread_cancel_impl
static void ABTI_tool_event_thread_cancel_impl(ABTI_xstream *p_local_xstream, ABTI_thread *p_thread)
Definition: abti_tool.h:202
ABTI_thread
Definition: abti.h:371
ABTI_TOOL_EVENT_TAG_DIRTY_BIT
#define ABTI_TOOL_EVENT_TAG_DIRTY_BIT
Definition: abti_tool.h:51
ABTI_xstream
Definition: abti.h:264
ABT_TOOL_EVENT_THREAD_RESUME
#define ABT_TOOL_EVENT_THREAD_RESUME
Work-unit-event mask: resuming a work unit.
Definition: abt.h:739
ABTI_TOOL_EVENT_TAG_MASK
#define ABTI_TOOL_EVENT_TAG_MASK
Definition: abti_tool.h:46
ABTI_pool
Definition: abti.h:327
ABTD_atomic_acquire_load_uint64
static uint64_t ABTD_atomic_acquire_load_uint64(const ABTD_atomic_uint64 *ptr)
Definition: abtd_atomic.h:962
ABTI_xstream_get_handle
static ABT_xstream ABTI_xstream_get_handle(ABTI_xstream *p_xstream)
Definition: abti_stream.h:26
ABTI_tool_context::p_parent
ABTI_thread * p_parent
Definition: abti.h:493
ABT_SYNC_EVENT_TYPE_UNKNOWN
@ ABT_SYNC_EVENT_TYPE_UNKNOWN
Definition: abt.h:662
ABTI_tool_context::p_sync_object
void * p_sync_object
Definition: abti.h:495
ABTD_atomic_release_store_uint64
static void ABTD_atomic_release_store_uint64(ABTD_atomic_uint64 *ptr, uint64_t val)
Definition: abtd_atomic.h:1124
ABT_sync_event_type
ABT_sync_event_type
Type of synchronization event.
Definition: abt.h:660
ABT_tool_context
struct ABT_tool_context_opaque * ABT_tool_context
Tool context handle type.
Definition: abt.h:1013
ABTI_tool_event_thread_finish_impl
static void ABTI_tool_event_thread_finish_impl(ABTI_xstream *p_local_xstream, ABTI_thread *p_thread, ABTI_thread *p_parent)
Definition: abti_tool.h:192
ABT_xstream
struct ABT_xstream_opaque * ABT_xstream
Execution stream handle type.
Definition: abt.h:789
ABTD_spinlock_acquire
static void ABTD_spinlock_acquire(ABTD_spinlock *p_lock)
Definition: abtd_spinlock.h:28
ABTI_tool_context::sync_event_type
ABT_sync_event_type sync_event_type
Definition: abti.h:494
ABT_TOOL_EVENT_THREAD_CANCEL
#define ABT_TOOL_EVENT_THREAD_CANCEL
Work-unit-event mask: canceling a work unit.
Definition: abt.h:724
ABTD_atomic_relaxed_load_uint32
static uint32_t ABTD_atomic_relaxed_load_uint32(const ABTD_atomic_uint32 *ptr)
Definition: abtd_atomic.h:804
ABTI_tool_event_thread_revive_impl
static void ABTI_tool_event_thread_revive_impl(ABTI_local *p_local, ABTI_thread *p_thread, ABTI_thread *p_caller, ABTI_pool *p_pool)
Definition: abti_tool.h:170
ABTI_global::tool_thread_user_arg
void * tool_thread_user_arg
Definition: abti.h:244
ABTI_tool_event_thread_free_impl
static void ABTI_tool_event_thread_free_impl(ABTI_local *p_local, ABTI_thread *p_thread, ABTI_thread *p_caller)
Definition: abti_tool.h:161
ABT_TOOL_EVENT_THREAD_ALL
#define ABT_TOOL_EVENT_THREAD_ALL
Work-unit-event mask: all events.
Definition: abt.h:744
ABTI_tool_event_thread_join_impl
static void ABTI_tool_event_thread_join_impl(ABTI_local *p_local, ABTI_thread *p_thread, ABTI_thread *p_caller)
Definition: abti_tool.h:152
ABTI_tool_context::p_pool
ABTI_pool * p_pool
Definition: abti.h:491
ABT_TOOL_EVENT_THREAD_YIELD
#define ABT_TOOL_EVENT_THREAD_YIELD
Work-unit-event mask: yielding a work unit.
Definition: abt.h:729
ABTI_tool_context::p_caller
ABTI_thread * p_caller
Definition: abti.h:490
ABTI_ythread_get_handle
static ABT_thread ABTI_ythread_get_handle(ABTI_ythread *p_thread)
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_xstream_get_local
static ABTI_local * ABTI_xstream_get_local(ABTI_xstream *p_xstream)
Definition: abti_stream.h:68
ABTU_unlikely
#define ABTU_unlikely(cond)
Definition: abtu.h:112
ABTI_global::tool_thread_event_mask_tagged
ABTD_atomic_uint64 tool_thread_event_mask_tagged
Definition: abti.h:245
ABT_TOOL_EVENT_THREAD_FINISH
#define ABT_TOOL_EVENT_THREAD_FINISH
Work-unit-event mask: finishing a work unit.
Definition: abt.h:719
ABTI_ythread
Definition: abti.h:406
ABTI_tool_event_thread_update_callback
static void ABTI_tool_event_thread_update_callback(ABTI_global *p_global, ABT_tool_thread_callback_fn cb_func, uint64_t event_mask, void *user_arg)
Definition: abti_tool.h:54
ABTI_tool_event_ythread_resume_impl
static void ABTI_tool_event_ythread_resume_impl(ABTI_local *p_local, ABTI_ythread *p_ythread, ABTI_thread *p_caller)
Definition: abti_tool.h:242
ABT_TOOL_EVENT_THREAD_SUSPEND
#define ABT_TOOL_EVENT_THREAD_SUSPEND
Work-unit-event mask: suspending a work unit.
Definition: abt.h:734
ABTD_spinlock_release
static void ABTD_spinlock_release(ABTD_spinlock *p_lock)
Definition: abtd_spinlock.h:42
ABTI_tool_event_ythread_suspend_impl
static void ABTI_tool_event_ythread_suspend_impl(ABTI_xstream *p_local_xstream, ABTI_ythread *p_ythread, ABTI_thread *p_parent, ABT_sync_event_type sync_event_type, void *p_sync)
Definition: abti_tool.h:231
ABT_TOOL_CONTEXT_NULL
#define ABT_TOOL_CONTEXT_NULL
Definition: abt.h:1074
ABTI_tool_event_ythread_yield_impl
static void ABTI_tool_event_ythread_yield_impl(ABTI_xstream *p_local_xstream, ABTI_ythread *p_ythread, ABTI_thread *p_parent, ABT_sync_event_type sync_event_type, void *p_sync)
Definition: abti_tool.h:210
ABTI_ythread::thread
ABTI_thread thread
Definition: abti.h:407
ABTI_local
struct ABTI_local ABTI_local
Definition: abti.h:110
ABT_XSTREAM_NULL
#define ABT_XSTREAM_NULL
Definition: abt.h:1055
ABTI_THREAD_REQ_BLOCK
#define ABTI_THREAD_REQ_BLOCK
Definition: abti.h:46
ABTI_global
Definition: abti.h:196
ABT_tool_thread_callback_fn
void(* ABT_tool_thread_callback_fn)(ABT_thread, ABT_xstream, uint64_t event, ABT_tool_context context, void *user_arg)
Definition: abt.h:1683
ABTI_thread::p_pool
ABTI_pool * p_pool
Definition: abti.h:383
ABTI_tool_event_thread_impl
static void ABTI_tool_event_thread_impl(ABTI_local *p_local, uint64_t event_code, ABTI_thread *p_thread, ABTI_thread *p_caller, ABTI_pool *p_pool, ABTI_thread *p_parent, ABT_sync_event_type sync_event_type, void *p_sync_object)
Definition: abti_tool.h:98
ABTI_tool_event_thread_create_impl
static void ABTI_tool_event_thread_create_impl(ABTI_local *p_local, ABTI_thread *p_thread, ABTI_thread *p_caller, ABTI_pool *p_pool)
Definition: abti_tool.h:142
ABT_TOOL_EVENT_THREAD_JOIN
#define ABT_TOOL_EVENT_THREAD_JOIN
Work-unit-event mask: joining a work unit.
Definition: abt.h:699
ABT_TOOL_EVENT_THREAD_FREE
#define ABT_TOOL_EVENT_THREAD_FREE
Work-unit-event mask: freeing a work unit.
Definition: abt.h:704
ABTI_TOOL_EVENT_TAG_INC
#define ABTI_TOOL_EVENT_TAG_INC
Definition: abti_tool.h:49
ABTI_tool_context_get_handle
static ABT_tool_context ABTI_tool_context_get_handle(ABTI_tool_context *p_tctx)
Definition: abti_tool.h:30