ARGOBOTS  1227c643f7a7f974f1f1778a9ffebd29d7dafecf
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
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
30 ABTI_tool_context_get_handle(ABTI_tool_context *p_tctx)
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
55  uint64_t event_mask_thread,
56  void *user_arg)
57 {
58  /* The spinlock is needed to avoid data race between two writers. */
59  ABTI_global *p_global = gp_ABTI_global;
60  ABTI_spinlock_acquire(&p_global->tool_writer_lock);
61 
62  /*
63  * This atomic writing process is needed to avoid data race between a reader
64  * and a writer. We need to atomically update three values (callback, event
65  * mask, and user_arg) in the following cases:
66  *
67  * A. ES-W writes the three values while ES-R is reading the three values
68  * B. ES-W1 writes and then ES-W2 writes the three values while ES-R is
69  * reading the three values
70  *
71  * The reader will first read the event mask and then load the other two.
72  * The reader then read the event mask again and see if it is 1. the same as
73  * the previous and 2. clean. If both are satisfied, acquire-release memory
74  * order guarantees that the loaded values are ones updated by the same
75  * ABTI_tool_event_thread_update_callback() call, unless the tag value wraps
76  * around (which does not happen practically).
77  */
78 
79  uint64_t current = ABTD_atomic_acquire_load_uint64(
80  &p_global->tool_thread_event_mask_tagged);
81  uint64_t new_tag =
83  uint64_t new_mask =
84  new_tag | (((event_mask_thread & ABT_TOOL_EVENT_THREAD_ALL) |
85  (current & ABT_TOOL_EVENT_TASK_ALL)) &
87  uint64_t dirty_mask = ABTI_TOOL_EVENT_TAG_DIRTY_BIT | new_mask;
88 
89  ABTD_atomic_release_store_uint64(&p_global->tool_thread_event_mask_tagged,
90  dirty_mask);
91  p_global->tool_thread_cb_f = cb_func;
92  p_global->tool_thread_user_arg = user_arg;
93  ABTD_atomic_release_store_uint64(&p_global->tool_thread_event_mask_tagged,
94  new_mask);
95 
96  ABTI_spinlock_release(&p_global->tool_writer_lock);
97 }
98 
99 static inline void
101  uint64_t event_mask_task, void *user_arg)
102 {
103  ABTI_global *p_global = gp_ABTI_global;
104  /* The spinlock is needed to avoid data race between two writers. */
105  ABTI_spinlock_acquire(&p_global->tool_writer_lock);
106 
107  /* This following writing process is needed to avoid data race between a
108  * reader and a writer. */
109  uint64_t current = ABTD_atomic_acquire_load_uint64(
110  &p_global->tool_thread_event_mask_tagged);
111  uint64_t new_tag =
113  uint64_t new_mask =
114  new_tag | (((event_mask_task & ABT_TOOL_EVENT_TASK_ALL) |
115  (current & ABT_TOOL_EVENT_THREAD_ALL)) &
117  uint64_t dirty_mask = ABTI_TOOL_EVENT_TAG_DIRTY_BIT | new_mask;
118 
119  ABTD_atomic_release_store_uint64(&p_global->tool_thread_event_mask_tagged,
120  dirty_mask);
121  p_global->tool_task_cb_f = cb_func;
122  p_global->tool_task_user_arg = user_arg;
123  ABTD_atomic_release_store_uint64(&p_global->tool_thread_event_mask_tagged,
124  new_mask);
125 
126  ABTI_spinlock_release(&p_global->tool_writer_lock);
127 }
128 
129 #endif /* !ABT_CONFIG_DISABLE_TOOL_INTERFACE */
130 
131 static inline void ABTI_tool_event_thread_impl(
132  ABTI_local *p_local, uint64_t event_code, ABTI_thread *p_thread,
133  ABTI_thread *p_caller, ABTI_pool *p_pool, ABTI_thread *p_parent,
134  ABT_sync_event_type sync_event_type, void *p_sync_object)
135 {
136 #ifdef ABT_CONFIG_DISABLE_TOOL_INTERFACE
137  return;
138 #else
139  ABTI_ythread *p_ythread = ABTI_thread_get_ythread_or_null(p_thread);
140  if (!p_ythread) {
141  /* Use an event code for a tasklet-type thread. */
142  event_code *= ABT_TOOL_EVENT_TASK_CREATE;
143  }
144  ABTI_global *p_global = gp_ABTI_global;
145  while (1) {
146  uint64_t current_mask = ABTD_atomic_acquire_load_uint64(
147  &p_global->tool_thread_event_mask_tagged);
148  if (current_mask & event_code) {
149  ABT_tool_thread_callback_fn cb_func_thread =
150  p_global->tool_thread_cb_f;
151  ABT_tool_task_callback_fn cb_func_task = p_global->tool_task_cb_f;
152  void *user_arg_thread = p_global->tool_thread_user_arg;
153  void *user_arg_task = p_global->tool_task_user_arg;
154  /* Double check the current event mask. */
155  uint64_t current_mask2 = ABTD_atomic_acquire_load_uint64(
156  &p_global->tool_thread_event_mask_tagged);
157  if (ABTU_unlikely(current_mask != current_mask2 ||
158  (current_mask & ABTI_TOOL_EVENT_TAG_DIRTY_BIT)))
159  continue;
160  ABTI_tool_context tctx;
161  tctx.p_pool = p_pool;
162  tctx.p_parent = p_parent;
163  tctx.p_caller = p_caller;
164  tctx.sync_event_type = sync_event_type;
165  tctx.p_sync_object = p_sync_object;
166 
167  ABTI_xstream *p_local_xstream =
169  ABT_xstream h_xstream =
170  p_local_xstream ? ABTI_xstream_get_handle(p_local_xstream)
172  if (p_ythread) {
173  if (p_ythread->thread.type & ABTI_THREAD_TYPE_ROOT) {
174  /* Root thread should not be visible to users. */
175  return;
176  }
177  ABT_thread h_thread = ABTI_ythread_get_handle(p_ythread);
179  cb_func_thread(h_thread, h_xstream, event_code, h_tctx,
180  user_arg_thread);
181  } else {
182  ABT_task h_task = ABTI_thread_get_handle(p_thread);
184  cb_func_task(h_task, h_xstream, event_code, h_tctx,
185  user_arg_task);
186  }
187  }
188  return;
189  }
190 #endif /* !ABT_CONFIG_DISABLE_TOOL_INTERFACE */
191 }
192 
193 static inline void ABTI_tool_event_thread_create_impl(ABTI_local *p_local,
194  ABTI_thread *p_thread,
195  ABTI_thread *p_caller,
196  ABTI_pool *p_pool)
197 {
199  p_caller, p_pool, NULL,
201 }
202 
203 static inline void ABTI_tool_event_thread_join_impl(ABTI_local *p_local,
204  ABTI_thread *p_thread,
205  ABTI_thread *p_caller)
206 {
208  p_caller, NULL, NULL,
210 }
211 
212 static inline void ABTI_tool_event_thread_free_impl(ABTI_local *p_local,
213  ABTI_thread *p_thread,
214  ABTI_thread *p_caller)
215 {
217  p_caller, NULL, NULL,
219 }
220 
221 static inline void ABTI_tool_event_thread_revive_impl(ABTI_local *p_local,
222  ABTI_thread *p_thread,
223  ABTI_thread *p_caller,
224  ABTI_pool *p_pool)
225 {
227  p_caller, p_pool, NULL,
229 }
230 
231 static inline void
233  ABTI_thread *p_thread, ABTI_thread *p_prev,
234  ABTI_thread *p_parent)
235 {
237  ABT_TOOL_EVENT_THREAD_RUN, p_thread, p_prev,
238  NULL, p_parent, ABT_SYNC_EVENT_TYPE_UNKNOWN,
239  NULL);
240 }
241 
242 static inline void
244  ABTI_thread *p_thread, ABTI_thread *p_parent)
245 {
247  ABT_TOOL_EVENT_THREAD_FINISH, p_thread, NULL,
248  NULL, p_parent, ABT_SYNC_EVENT_TYPE_UNKNOWN,
249  NULL);
250 }
251 
252 static inline void
254  ABTI_thread *p_thread)
255 {
257  ABT_TOOL_EVENT_THREAD_CANCEL, p_thread, NULL,
258  NULL, NULL, ABT_SYNC_EVENT_TYPE_UNKNOWN, NULL);
259 }
260 
262  ABTI_xstream *p_local_xstream, ABTI_ythread *p_ythread,
263  ABTI_thread *p_parent, ABT_sync_event_type sync_event_type, void *p_sync)
264 {
269  &p_ythread->thread, NULL,
270  p_ythread->thread.p_pool, p_parent,
271  sync_event_type, p_sync);
272 
273  } else {
276  &p_ythread->thread, NULL,
277  p_ythread->thread.p_pool, p_parent,
278  sync_event_type, p_sync);
279  }
280 }
281 
283  ABTI_xstream *p_local_xstream, ABTI_ythread *p_ythread,
284  ABTI_thread *p_parent, ABT_sync_event_type sync_event_type, void *p_sync)
285 {
288  &p_ythread->thread, NULL,
289  p_ythread->thread.p_pool, p_parent,
290  sync_event_type, p_sync);
291 }
292 
294  ABTI_ythread *p_ythread,
295  ABTI_thread *p_caller)
296 {
298  &p_ythread->thread, p_caller,
299  p_ythread->thread.p_pool, NULL,
301 }
302 
303 #ifndef ABT_CONFIG_DISABLE_TOOL_INTERFACE
304 #define ABTI_USE_TOOL_INTERFACE 1
305 #else
306 #define ABTI_USE_TOOL_INTERFACE 0
307 #endif
308 
309 #define ABTI_tool_event_thread_create(p_local, p_thread, p_caller, p_pool) \
310  do { \
311  if (ABTI_USE_TOOL_INTERFACE) { \
312  ABTI_tool_event_thread_create_impl(p_local, p_thread, p_caller, \
313  p_pool); \
314  } \
315  } while (0)
316 
317 #define ABTI_tool_event_thread_join(p_local, p_thread, p_caller) \
318  do { \
319  if (ABTI_USE_TOOL_INTERFACE) { \
320  ABTI_tool_event_thread_join_impl(p_local, p_thread, p_caller); \
321  } \
322  } while (0)
323 
324 #define ABTI_tool_event_thread_free(p_local, p_thread, p_caller) \
325  do { \
326  if (ABTI_USE_TOOL_INTERFACE) { \
327  ABTI_tool_event_thread_free_impl(p_local, p_thread, p_caller); \
328  } \
329  } while (0)
330 
331 #define ABTI_tool_event_thread_revive(p_local, p_thread, p_caller, p_pool) \
332  do { \
333  if (ABTI_USE_TOOL_INTERFACE) { \
334  ABTI_tool_event_thread_revive_impl(p_local, p_thread, p_caller, \
335  p_pool); \
336  } \
337  } while (0)
338 
339 #define ABTI_tool_event_thread_run(p_local_xstream, p_thread, p_prev, \
340  p_parent) \
341  do { \
342  if (ABTI_USE_TOOL_INTERFACE) { \
343  ABTI_tool_event_thread_run_impl(p_local_xstream, p_thread, p_prev, \
344  p_parent); \
345  } \
346  } while (0)
347 
348 #define ABTI_tool_event_thread_finish(p_local_xstream, p_thread, p_parent) \
349  do { \
350  if (ABTI_USE_TOOL_INTERFACE) { \
351  ABTI_tool_event_thread_finish_impl(p_local_xstream, p_thread, \
352  p_parent); \
353  } \
354  } while (0)
355 
356 #define ABTI_tool_event_thread_cancel(p_local_xstream, p_thread) \
357  do { \
358  if (ABTI_USE_TOOL_INTERFACE) { \
359  ABTI_tool_event_thread_cancel_impl(p_local_xstream, p_thread); \
360  } \
361  } while (0)
362 
363 #define ABTI_tool_event_ythread_yield(p_local_xstream, p_ythread, p_parent, \
364  sync_event_type, p_sync) \
365  do { \
366  if (ABTI_USE_TOOL_INTERFACE) { \
367  ABTI_tool_event_ythread_yield_impl(p_local_xstream, p_ythread, \
368  p_parent, sync_event_type, \
369  p_sync); \
370  } \
371  } while (0)
372 
373 #define ABTI_tool_event_ythread_suspend(p_local_xstream, p_ythread, p_parent, \
374  sync_event_type, p_sync) \
375  do { \
376  if (ABTI_USE_TOOL_INTERFACE) { \
377  ABTI_tool_event_ythread_suspend_impl(p_local_xstream, p_ythread, \
378  p_parent, sync_event_type, \
379  p_sync); \
380  } \
381  } while (0)
382 
383 #define ABTI_tool_event_ythread_resume(p_local, p_ythread, p_caller) \
384  do { \
385  if (ABTI_USE_TOOL_INTERFACE) { \
386  ABTI_tool_event_ythread_resume_impl(p_local, p_ythread, p_caller); \
387  } \
388  } while (0)
389 
390 #endif /* ABTI_TOOL_H_INCLUDED */
#define ABT_TOOL_EVENT_THREAD_REVIVE
Definition: abt.h:264
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:193
ABTI_pool * p_pool
Definition: abti.h:324
static ABTI_ythread * ABTI_thread_get_ythread_or_null(ABTI_thread *p_thread)
Definition: abti_thread.h:59
ABTD_atomic_uint32 request
Definition: abti.h:323
static ABT_xstream ABTI_xstream_get_handle(ABTI_xstream *p_xstream)
Definition: abti_stream.h:26
struct ABT_xstream_opaque * ABT_xstream
Definition: abt.h:313
static void ABTD_atomic_release_store_uint64(ABTD_atomic_uint64 *ptr, uint64_t val)
Definition: abtd_atomic.h:971
#define ABT_XSTREAM_NULL
Definition: abt.h:409
static void ABTI_tool_event_task_update_callback(ABT_tool_task_callback_fn cb_func, uint64_t event_mask_task, void *user_arg)
Definition: abti_tool.h:100
struct ABTI_local ABTI_local
Definition: abti.h:101
#define ABTU_unlikely(cond)
Definition: abtu.h:18
#define ABT_TOOL_EVENT_TASK_CREATE
Definition: abt.h:274
ABTI_thread_type type
Definition: abti.h:316
#define ABT_TOOL_EVENT_THREAD_RUN
Definition: abt.h:265
struct ABT_thread_opaque * ABT_task
Definition: abt.h:353
#define ABTI_TOOL_EVENT_TAG_MASK
Definition: abti_tool.h:46
#define ABT_TOOL_CONTEXT_NULL
Definition: abt.h:427
static void ABTI_tool_event_thread_cancel_impl(ABTI_xstream *p_local_xstream, ABTI_thread *p_thread)
Definition: abti_tool.h:253
static void ABTI_tool_event_thread_update_callback(ABT_tool_thread_callback_fn cb_func, uint64_t event_mask_thread, void *user_arg)
Definition: abti_tool.h:54
static ABT_task ABTI_thread_get_handle(ABTI_thread *p_task)
#define ABTI_TOOL_EVENT_TAG_INC
Definition: abti_tool.h:49
#define ABT_TOOL_EVENT_THREAD_JOIN
Definition: abt.h:262
void(* ABT_tool_thread_callback_fn)(ABT_thread, ABT_xstream, uint64_t event, ABT_tool_context context, void *user_arg)
Definition: abt.h:515
#define ABTI_THREAD_REQ_BLOCK
Definition: abti.h:45
#define ABT_TOOL_EVENT_THREAD_CANCEL
Definition: abt.h:267
struct ABT_thread_opaque * ABT_thread
Definition: abt.h:343
#define ABTI_THREAD_TYPE_ROOT
Definition: abti.h:74
#define ABT_TOOL_EVENT_THREAD_SUSPEND
Definition: abt.h:269
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:243
#define ABT_TOOL_EVENT_THREAD_ALL
Definition: abt.h:271
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:261
static void ABTI_spinlock_release(ABTI_spinlock *p_lock)
Definition: abti_spinlock.h:31
static ABTI_tool_context * ABTI_tool_context_get_ptr(ABT_tool_context tctx)
Definition: abti_tool.h:14
ABTI_global * gp_ABTI_global
Definition: global.c:14
ABTI_thread thread
Definition: abti.h:348
#define ABT_TOOL_EVENT_THREAD_FINISH
Definition: abt.h:266
static uint64_t ABTD_atomic_acquire_load_uint64(const ABTD_atomic_uint64 *ptr)
Definition: abtd_atomic.h:831
static void ABTI_tool_event_ythread_resume_impl(ABTI_local *p_local, ABTI_ythread *p_ythread, ABTI_thread *p_caller)
Definition: abti_tool.h:293
static void ABTI_spinlock_acquire(ABTI_spinlock *p_lock)
Definition: abti_spinlock.h:23
struct ABT_tool_context_opaque * ABT_tool_context
Definition: abt.h:377
static void ABTI_tool_event_thread_join_impl(ABTI_local *p_local, ABTI_thread *p_thread, ABTI_thread *p_caller)
Definition: abti_tool.h:203
#define ABT_TOOL_EVENT_THREAD_YIELD
Definition: abt.h:268
static uint32_t ABTD_atomic_relaxed_load_uint32(const ABTD_atomic_uint32 *ptr)
Definition: abtd_atomic.h:689
static ABT_thread ABTI_ythread_get_handle(ABTI_ythread *p_thread)
#define ABT_TOOL_EVENT_THREAD_RESUME
Definition: abt.h:270
#define ABT_TOOL_EVENT_THREAD_CREATE
Definition: abt.h:261
#define ABT_TOOL_EVENT_THREAD_FREE
Definition: abt.h:263
static void ABTI_tool_event_thread_free_impl(ABTI_local *p_local, ABTI_thread *p_thread, ABTI_thread *p_caller)
Definition: abti_tool.h:212
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:221
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:131
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:282
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:232
static ABTI_local * ABTI_xstream_get_local(ABTI_xstream *p_xstream)
Definition: abti_stream.h:67
ABT_sync_event_type
Definition: abt.h:244
void(* ABT_tool_task_callback_fn)(ABT_task, ABT_xstream, uint64_t event, ABT_tool_context context, void *user_arg)
Definition: abt.h:517
#define ABTI_TOOL_EVENT_TAG_DIRTY_BIT
Definition: abti_tool.h:51
static ABTI_xstream * ABTI_local_get_xstream_or_null(ABTI_local *p_local)
Definition: abti_local.h:77
#define ABT_TOOL_EVENT_TASK_ALL
Definition: abt.h:281
static ABT_tool_context ABTI_tool_context_get_handle(ABTI_tool_context *p_tctx)
Definition: abti_tool.h:30