LLVM OpenMP* Runtime Library
ompt-specific.cpp
1 //******************************************************************************
2 // include files
3 //******************************************************************************
4 
5 #include "kmp.h"
6 #include "ompt-internal.h"
7 #include "ompt-specific.h"
8 
9 //******************************************************************************
10 // macros
11 //******************************************************************************
12 
13 #define GTID_TO_OMPT_THREAD_ID(id) ((ompt_thread_id_t) (id >=0) ? id + 1: 0)
14 
15 #define LWT_FROM_TEAM(team) (team)->t.ompt_serialized_team_info;
16 
17 #define OMPT_THREAD_ID_BITS 16
18 
19 // 2013 08 24 - John Mellor-Crummey
20 // ideally, a thread should assign its own ids based on thread private data.
21 // however, the way the intel runtime reinitializes thread data structures
22 // when it creates teams makes it difficult to maintain persistent thread
23 // data. using a shared variable instead is simple. I leave it to intel to
24 // sort out how to implement a higher performance version in their runtime.
25 
26 // when using fetch_and_add to generate the IDs, there isn't any reason to waste
27 // bits for thread id.
28 #if 0
29 #define NEXT_ID(id_ptr,tid) \
30  ((KMP_TEST_THEN_INC64(id_ptr) << OMPT_THREAD_ID_BITS) | (tid))
31 #else
32 #define NEXT_ID(id_ptr,tid) (KMP_TEST_THEN_INC64((volatile kmp_int64 *)id_ptr))
33 #endif
34 
35 //******************************************************************************
36 // private operations
37 //******************************************************************************
38 
39 //----------------------------------------------------------
40 // traverse the team and task hierarchy
41 // note: __ompt_get_teaminfo and __ompt_get_taskinfo
42 // traverse the hierarchy similarly and need to be
43 // kept consistent
44 //----------------------------------------------------------
45 
46 ompt_team_info_t *
47 __ompt_get_teaminfo(int depth, int *size)
48 {
49  kmp_info_t *thr = ompt_get_thread();
50 
51  if (thr) {
52  kmp_team *team = thr->th.th_team;
53  if (team == NULL) return NULL;
54 
55  ompt_lw_taskteam_t *lwt = LWT_FROM_TEAM(team);
56 
57  while(depth > 0) {
58  // next lightweight team (if any)
59  if (lwt) lwt = lwt->parent;
60 
61  // next heavyweight team (if any) after
62  // lightweight teams are exhausted
63  if (!lwt && team) {
64  team=team->t.t_parent;
65  if (team) {
66  lwt = LWT_FROM_TEAM(team);
67  }
68  }
69 
70  depth--;
71  }
72 
73  if (lwt) {
74  // lightweight teams have one task
75  if (size) *size = 1;
76 
77  // return team info for lightweight team
78  return &lwt->ompt_team_info;
79  } else if (team) {
80  // extract size from heavyweight team
81  if (size) *size = team->t.t_nproc;
82 
83  // return team info for heavyweight team
84  return &team->t.ompt_team_info;
85  }
86  }
87 
88  return NULL;
89 }
90 
91 
92 ompt_task_info_t *
93 __ompt_get_taskinfo(int depth)
94 {
95  ompt_task_info_t *info = NULL;
96  kmp_info_t *thr = ompt_get_thread();
97 
98  if (thr) {
99  kmp_taskdata_t *taskdata = thr->th.th_current_task;
100  ompt_lw_taskteam_t *lwt = LWT_FROM_TEAM(taskdata->td_team);
101 
102  while (depth > 0) {
103  // next lightweight team (if any)
104  if (lwt) lwt = lwt->parent;
105 
106  // next heavyweight team (if any) after
107  // lightweight teams are exhausted
108  if (!lwt && taskdata) {
109  taskdata = taskdata->td_parent;
110  if (taskdata) {
111  lwt = LWT_FROM_TEAM(taskdata->td_team);
112  }
113  }
114  depth--;
115  }
116 
117  if (lwt) {
118  info = &lwt->ompt_task_info;
119  } else if (taskdata) {
120  info = &taskdata->ompt_task_info;
121  }
122  }
123 
124  return info;
125 }
126 
127 
128 
129 //******************************************************************************
130 // interface operations
131 //******************************************************************************
132 
133 //----------------------------------------------------------
134 // thread support
135 //----------------------------------------------------------
136 
137 ompt_parallel_id_t
138 __ompt_thread_id_new()
139 {
140  static uint64_t ompt_thread_id = 1;
141  return NEXT_ID(&ompt_thread_id, 0);
142 }
143 
144 void
145 __ompt_thread_begin(ompt_thread_type_t thread_type, int gtid)
146 {
147  ompt_callbacks.ompt_callback(ompt_event_thread_begin)(
148  thread_type, GTID_TO_OMPT_THREAD_ID(gtid));
149 }
150 
151 
152 void
153 __ompt_thread_end(ompt_thread_type_t thread_type, int gtid)
154 {
155  ompt_callbacks.ompt_callback(ompt_event_thread_end)(
156  thread_type, GTID_TO_OMPT_THREAD_ID(gtid));
157 }
158 
159 
160 ompt_thread_id_t
161 __ompt_get_thread_id_internal()
162 {
163  // FIXME
164  // until we have a better way of assigning ids, use __kmp_get_gtid
165  // since the return value might be negative, we need to test that before
166  // assigning it to an ompt_thread_id_t, which is unsigned.
167  int id = __kmp_get_gtid();
168  assert(id >= 0);
169 
170  return GTID_TO_OMPT_THREAD_ID(id);
171 }
172 
173 //----------------------------------------------------------
174 // state support
175 //----------------------------------------------------------
176 
177 void
178 __ompt_thread_assign_wait_id(void *variable)
179 {
180  int gtid = __kmp_gtid_get_specific();
181  kmp_info_t *ti = ompt_get_thread_gtid(gtid);
182 
183  ti->th.ompt_thread_info.wait_id = (ompt_wait_id_t) variable;
184 }
185 
186 ompt_state_t
187 __ompt_get_state_internal(ompt_wait_id_t *ompt_wait_id)
188 {
189  kmp_info_t *ti = ompt_get_thread();
190 
191  if (ti) {
192  if (ompt_wait_id)
193  *ompt_wait_id = ti->th.ompt_thread_info.wait_id;
194  return ti->th.ompt_thread_info.state;
195  }
196  return ompt_state_undefined;
197 }
198 
199 //----------------------------------------------------------
200 // idle frame support
201 //----------------------------------------------------------
202 
203 void *
204 __ompt_get_idle_frame_internal(void)
205 {
206  kmp_info_t *ti = ompt_get_thread();
207  return ti ? ti->th.ompt_thread_info.idle_frame : NULL;
208 }
209 
210 
211 //----------------------------------------------------------
212 // parallel region support
213 //----------------------------------------------------------
214 
215 ompt_parallel_id_t
216 __ompt_parallel_id_new(int gtid)
217 {
218  static uint64_t ompt_parallel_id = 1;
219  return gtid >= 0 ? NEXT_ID(&ompt_parallel_id, gtid) : 0;
220 }
221 
222 
223 void *
224 __ompt_get_parallel_function_internal(int depth)
225 {
226  ompt_team_info_t *info = __ompt_get_teaminfo(depth, NULL);
227  void *function = info ? info->microtask : NULL;
228  return function;
229 }
230 
231 
232 ompt_parallel_id_t
233 __ompt_get_parallel_id_internal(int depth)
234 {
235  ompt_team_info_t *info = __ompt_get_teaminfo(depth, NULL);
236  ompt_parallel_id_t id = info ? info->parallel_id : 0;
237  return id;
238 }
239 
240 
241 int
242 __ompt_get_parallel_team_size_internal(int depth)
243 {
244  // initialize the return value with the error value.
245  // if there is a team at the specified depth, the default
246  // value will be overwritten the size of that team.
247  int size = -1;
248  (void) __ompt_get_teaminfo(depth, &size);
249  return size;
250 }
251 
252 
253 //----------------------------------------------------------
254 // lightweight task team support
255 //----------------------------------------------------------
256 
257 void
258 __ompt_lw_taskteam_init(ompt_lw_taskteam_t *lwt, kmp_info_t *thr,
259  int gtid, void *microtask,
260  ompt_parallel_id_t ompt_pid)
261 {
262  lwt->ompt_team_info.parallel_id = ompt_pid;
263  lwt->ompt_team_info.microtask = microtask;
264  lwt->ompt_task_info.task_id = 0;
265  lwt->ompt_task_info.frame.reenter_runtime_frame = NULL;
266  lwt->ompt_task_info.frame.exit_runtime_frame = NULL;
267  lwt->ompt_task_info.function = NULL;
268  lwt->parent = 0;
269 }
270 
271 
272 void
273 __ompt_lw_taskteam_link(ompt_lw_taskteam_t *lwt, kmp_info_t *thr)
274 {
275  ompt_lw_taskteam_t *my_parent = thr->th.th_team->t.ompt_serialized_team_info;
276  lwt->parent = my_parent;
277  thr->th.th_team->t.ompt_serialized_team_info = lwt;
278 }
279 
280 
281 ompt_lw_taskteam_t *
282 __ompt_lw_taskteam_unlink(kmp_info_t *thr)
283 {
284  ompt_lw_taskteam_t *lwtask = thr->th.th_team->t.ompt_serialized_team_info;
285  if (lwtask) thr->th.th_team->t.ompt_serialized_team_info = lwtask->parent;
286  return lwtask;
287 }
288 
289 
290 //----------------------------------------------------------
291 // task support
292 //----------------------------------------------------------
293 
294 ompt_task_id_t
295 __ompt_task_id_new(int gtid)
296 {
297  static uint64_t ompt_task_id = 1;
298  return NEXT_ID(&ompt_task_id, gtid);
299 }
300 
301 
302 ompt_task_id_t
303 __ompt_get_task_id_internal(int depth)
304 {
305  ompt_task_info_t *info = __ompt_get_taskinfo(depth);
306  ompt_task_id_t task_id = info ? info->task_id : 0;
307  return task_id;
308 }
309 
310 
311 void *
312 __ompt_get_task_function_internal(int depth)
313 {
314  ompt_task_info_t *info = __ompt_get_taskinfo(depth);
315  void *function = info ? info->function : NULL;
316  return function;
317 }
318 
319 
320 ompt_frame_t *
321 __ompt_get_task_frame_internal(int depth)
322 {
323  ompt_task_info_t *info = __ompt_get_taskinfo(depth);
324  ompt_frame_t *frame = info ? frame = &info->frame : NULL;
325  return frame;
326 }
327 
328 
329 //----------------------------------------------------------
330 // team support
331 //----------------------------------------------------------
332 
333 void
334 __ompt_team_assign_id(kmp_team_t *team, ompt_parallel_id_t ompt_pid)
335 {
336  team->t.ompt_team_info.parallel_id = ompt_pid;
337 }