ARGOBOTS  be805649b56a69fc4df1b6bc4efbc8911b854459
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 *
14 ABTI_tool_context_get_ptr(ABT_tool_context tctx)
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
54 ABTI_tool_event_thread_update_callback(ABTI_global *p_global,
56  uint64_t event_mask, void *user_arg)
57 {
58  /* The spinlock is needed to avoid data race between two writers. */
59  ABTD_spinlock_acquire(&p_global->tool_writer_lock);
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(
79  &p_global->tool_thread_event_mask_tagged);
80  uint64_t new_tag =
81  (current + ABTI_TOOL_EVENT_TAG_INC) & ABTI_TOOL_EVENT_TAG_MASK;
82  uint64_t new_mask = new_tag | ((event_mask & ABT_TOOL_EVENT_THREAD_ALL) &
83  ~ABTI_TOOL_EVENT_TAG_DIRTY_BIT);
84  uint64_t dirty_mask = ABTI_TOOL_EVENT_TAG_DIRTY_BIT | new_mask;
85 
86  ABTD_atomic_release_store_uint64(&p_global->tool_thread_event_mask_tagged,
87  dirty_mask);
88  p_global->tool_thread_cb_f = cb_func;
89  p_global->tool_thread_user_arg = user_arg;
90  ABTD_atomic_release_store_uint64(&p_global->tool_thread_event_mask_tagged,
91  new_mask);
92 
93  ABTD_spinlock_release(&p_global->tool_writer_lock);
94 }
95 
96 static inline void
97 ABTI_tool_event_thread(ABTI_local *p_local, uint64_t event_code,
98  ABTI_thread *p_thread, ABTI_thread *p_caller,
99  ABTI_pool *p_pool, ABTI_thread *p_parent,
100  ABT_sync_event_type sync_event_type, void *p_sync_object)
101 {
102  if (p_thread->type & ABTI_THREAD_TYPE_ROOT)
103  return; /* A root thread should not be exposed to the user. */
104  ABTI_global *p_global = gp_ABTI_global;
105  while (1) {
106  uint64_t current_mask = ABTD_atomic_acquire_load_uint64(
107  &p_global->tool_thread_event_mask_tagged);
108  if (current_mask & event_code) {
109  ABT_tool_thread_callback_fn cb_func_thread =
110  p_global->tool_thread_cb_f;
111  void *user_arg_thread = p_global->tool_thread_user_arg;
112  /* Double check the current event mask. */
113  uint64_t current_mask2 = ABTD_atomic_acquire_load_uint64(
114  &p_global->tool_thread_event_mask_tagged);
115  if (ABTU_unlikely(current_mask != current_mask2 ||
116  (current_mask & ABTI_TOOL_EVENT_TAG_DIRTY_BIT)))
117  continue;
118  ABTI_tool_context tctx;
119  tctx.p_pool = p_pool;
120  tctx.p_parent = p_parent;
121  tctx.p_caller = p_caller;
122  tctx.sync_event_type = sync_event_type;
123  tctx.p_sync_object = p_sync_object;
124 
125  ABTI_xstream *p_local_xstream =
126  ABTI_local_get_xstream_or_null(p_local);
127  ABT_xstream h_xstream =
128  p_local_xstream ? ABTI_xstream_get_handle(p_local_xstream)
130  ABT_thread h_thread = ABTI_thread_get_handle(p_thread);
131  ABT_tool_context h_tctx = ABTI_tool_context_get_handle(&tctx);
132  cb_func_thread(h_thread, h_xstream, event_code, h_tctx,
133  user_arg_thread);
134  }
135  return;
136  }
137 }
138 
139 #endif /* !ABT_CONFIG_DISABLE_TOOL_INTERFACE */
140 
141 #endif /* ABTI_TOOL_H_INCLUDED */
ABT_task
struct ABT_thread_opaque * ABT_task
Work unit handle type.
Definition: abt.h:949
ABT_thread
struct ABT_thread_opaque * ABT_thread
Work unit handle type.
Definition: abt.h:908
gp_ABTI_global
ABTI_global * gp_ABTI_global
Definition: global.c:19
ABT_sync_event_type
ABT_sync_event_type
Type of synchronization event.
Definition: abt.h:672
ABT_tool_context
struct ABT_tool_context_opaque * ABT_tool_context
Tool context handle type.
Definition: abt.h:1031
ABT_xstream
struct ABT_xstream_opaque * ABT_xstream
Execution stream handle type.
Definition: abt.h:802
ABT_TOOL_EVENT_THREAD_ALL
#define ABT_TOOL_EVENT_THREAD_ALL
Work-unit-event mask: all events.
Definition: abt.h:756
ABTU_unlikely
#define ABTU_unlikely(cond)
Definition: abtu.h:120
ABT_TOOL_CONTEXT_NULL
#define ABT_TOOL_CONTEXT_NULL
Definition: abt.h:1093
ABT_XSTREAM_NULL
#define ABT_XSTREAM_NULL
Definition: abt.h:1074
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:2218