LLVM OpenMP* Runtime Library
ompt-specific.c
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(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  ompt_lw_taskteam_t *lwt = LWT_FROM_TEAM(team);
54 
55  while(depth > 0) {
56  // next lightweight team (if any)
57  if (lwt) lwt = lwt->parent;
58 
59  // next heavyweight team (if any) after
60  // lightweight teams are exhausted
61  if (!lwt && team) team=team->t.t_parent;
62 
63  depth--;
64  }
65 
66  if (lwt) {
67  // lightweight teams have one task
68  if (size) *size = 1;
69 
70  // return team info for lightweight team
71  return &lwt->ompt_team_info;
72  } else if (team) {
73  // extract size from heavyweight team
74  if (size) *size = team->t.t_nproc;
75 
76  // return team info for heavyweight team
77  return &team->t.ompt_team_info;
78  }
79  }
80 
81  return NULL;
82 }
83 
84 
85 ompt_task_info_t *
86 __ompt_get_taskinfo(int depth)
87 {
88  ompt_task_info_t *info = NULL;
89  kmp_info_t *thr = ompt_get_thread();
90 
91  if (thr) {
92  kmp_taskdata_t *taskdata = thr->th.th_current_task;
93  ompt_lw_taskteam_t *lwt = LWT_FROM_TEAM(taskdata->td_team);
94 
95  while (depth > 0) {
96  // next lightweight team (if any)
97  if (lwt) lwt = lwt->parent;
98 
99  // next heavyweight team (if any) after
100  // lightweight teams are exhausted
101  if (!lwt && taskdata) {
102  taskdata = taskdata->td_parent;
103  if (taskdata) {
104  lwt = LWT_FROM_TEAM(taskdata->td_team);
105  }
106  }
107  depth--;
108  }
109 
110  if (lwt) {
111  info = &lwt->ompt_task_info;
112  } else if (taskdata) {
113  info = &taskdata->ompt_task_info;
114  }
115  }
116 
117  return info;
118 }
119 
120 
121 
122 //******************************************************************************
123 // interface operations
124 //******************************************************************************
125 
126 //----------------------------------------------------------
127 // initialization support
128 //----------------------------------------------------------
129 
130 void
131 __ompt_init_internal()
132 {
133  if (ompt_status & ompt_status_track) {
134  // initialize initial thread for OMPT
135  kmp_info_t *root_thread = ompt_get_thread();
136  __kmp_task_init_ompt(
137  root_thread->th.th_team->t.t_implicit_task_taskdata, 0);
138  __kmp_task_init_ompt(
139  root_thread->th.th_serial_team->t.t_implicit_task_taskdata, 0);
140 
141  // make mandatory callback for creation of initial thread
142  // this needs to occur here rather than in __kmp_register_root because
143  // __kmp_register_root is called before ompt_initialize
144  int gtid = __kmp_get_gtid();
145  if (KMP_UBER_GTID(gtid)) {
146  // initialize the initial thread's idle frame and state
147  root_thread->th.ompt_thread_info.idle_frame = 0;
148  root_thread->th.ompt_thread_info.state = ompt_state_overhead;
149  if ((ompt_status == ompt_status_track_callback) &&
150  ompt_callbacks.ompt_callback(ompt_event_thread_begin)) {
151  __ompt_thread_begin(ompt_thread_initial, gtid);
152  }
153  root_thread->th.ompt_thread_info.state = ompt_state_work_serial;
154  }
155  }
156 }
157 
158 
159 //----------------------------------------------------------
160 // thread support
161 //----------------------------------------------------------
162 
163 ompt_parallel_id_t
164 __ompt_thread_id_new()
165 {
166  static uint64_t ompt_thread_id = 1;
167  return NEXT_ID(&ompt_thread_id, 0);
168 }
169 
170 void
171 __ompt_thread_begin(ompt_thread_type_t thread_type, int gtid)
172 {
173  ompt_callbacks.ompt_callback(ompt_event_thread_begin)(
174  thread_type, GTID_TO_OMPT_THREAD_ID(gtid));
175 }
176 
177 
178 void
179 __ompt_thread_end(ompt_thread_type_t thread_type, int gtid)
180 {
181  ompt_callbacks.ompt_callback(ompt_event_thread_end)(
182  thread_type, GTID_TO_OMPT_THREAD_ID(gtid));
183 }
184 
185 
186 ompt_thread_id_t
187 __ompt_get_thread_id_internal()
188 {
189  // FIXME
190  // until we have a better way of assigning ids, use __kmp_get_gtid
191  // since the return value might be negative, we need to test that before
192  // assigning it to an ompt_thread_id_t, which is unsigned.
193  int id = __kmp_get_gtid();
194  assert(id >= 0);
195 
196  return GTID_TO_OMPT_THREAD_ID(id);
197 }
198 
199 //----------------------------------------------------------
200 // state support
201 //----------------------------------------------------------
202 
203 void
204 __ompt_thread_assign_wait_id(void *variable)
205 {
206  int gtid = __kmp_gtid_get_specific();
207  kmp_info_t *ti = ompt_get_thread_gtid(gtid);
208 
209  ti->th.ompt_thread_info.wait_id = (ompt_wait_id_t) variable;
210 }
211 
212 ompt_state_t
213 __ompt_get_state_internal(ompt_wait_id_t *ompt_wait_id)
214 {
215  kmp_info_t *ti = ompt_get_thread();
216 
217  if (ti) {
218  if (ompt_wait_id)
219  *ompt_wait_id = ti->th.ompt_thread_info.wait_id;
220  return ti->th.ompt_thread_info.state;
221  }
222  return ompt_state_undefined;
223 }
224 
225 //----------------------------------------------------------
226 // idle frame support
227 //----------------------------------------------------------
228 
229 void *
230 __ompt_get_idle_frame_internal(void)
231 {
232  kmp_info_t *ti = ompt_get_thread();
233  return ti ? ti->th.ompt_thread_info.idle_frame : NULL;
234 }
235 
236 
237 //----------------------------------------------------------
238 // parallel region support
239 //----------------------------------------------------------
240 
241 ompt_parallel_id_t
242 __ompt_parallel_id_new(int gtid)
243 {
244  static uint64_t ompt_parallel_id = 1;
245  return gtid >= 0 ? NEXT_ID(&ompt_parallel_id, gtid) : 0;
246 }
247 
248 
249 void *
250 __ompt_get_parallel_function_internal(int depth)
251 {
252  ompt_team_info_t *info = __ompt_get_teaminfo(depth, NULL);
253  void *function = info ? info->microtask : NULL;
254  return function;
255 }
256 
257 
258 ompt_parallel_id_t
259 __ompt_get_parallel_id_internal(int depth)
260 {
261  ompt_team_info_t *info = __ompt_get_teaminfo(depth, NULL);
262  ompt_parallel_id_t id = info ? info->parallel_id : 0;
263  return id;
264 }
265 
266 
267 int
268 __ompt_get_parallel_team_size_internal(int depth)
269 {
270  // initialize the return value with the error value.
271  // if there is a team at the specified depth, the default
272  // value will be overwritten the size of that team.
273  int size = -1;
274  (void) __ompt_get_teaminfo(depth, &size);
275  return size;
276 }
277 
278 
279 //----------------------------------------------------------
280 // lightweight task team support
281 //----------------------------------------------------------
282 
283 void
284 __ompt_lw_taskteam_init(ompt_lw_taskteam_t *lwt, kmp_info_t *thr,
285  int gtid, void *microtask,
286  ompt_parallel_id_t ompt_pid)
287 {
288  lwt->ompt_team_info.parallel_id = ompt_pid;
289  lwt->ompt_team_info.microtask = microtask;
290  lwt->ompt_task_info.task_id = 0;
291  lwt->ompt_task_info.frame.reenter_runtime_frame = 0;
292  lwt->ompt_task_info.frame.exit_runtime_frame = 0;
293  lwt->ompt_task_info.function = NULL;
294  lwt->parent = 0;
295 }
296 
297 
298 void
299 __ompt_lw_taskteam_link(ompt_lw_taskteam_t *lwt, kmp_info_t *thr)
300 {
301  ompt_lw_taskteam_t *my_parent = thr->th.th_team->t.ompt_serialized_team_info;
302  lwt->parent = my_parent;
303  thr->th.th_team->t.ompt_serialized_team_info = lwt;
304 }
305 
306 
307 ompt_lw_taskteam_t *
308 __ompt_lw_taskteam_unlink(kmp_info_t *thr)
309 {
310  ompt_lw_taskteam_t *lwtask = thr->th.th_team->t.ompt_serialized_team_info;
311  if (lwtask) thr->th.th_team->t.ompt_serialized_team_info = lwtask->parent;
312  return lwtask;
313 }
314 
315 
316 //----------------------------------------------------------
317 // task support
318 //----------------------------------------------------------
319 
320 ompt_task_id_t
321 __ompt_task_id_new(int gtid)
322 {
323  static uint64_t ompt_task_id = 1;
324  return NEXT_ID(&ompt_task_id, gtid);
325 }
326 
327 
328 ompt_task_id_t
329 __ompt_get_task_id_internal(int depth)
330 {
331  ompt_task_info_t *info = __ompt_get_taskinfo(depth);
332  ompt_task_id_t task_id = info ? info->task_id : 0;
333  return task_id;
334 }
335 
336 
337 void *
338 __ompt_get_task_function_internal(int depth)
339 {
340  ompt_task_info_t *info = __ompt_get_taskinfo(depth);
341  void *function = info ? info->function : NULL;
342  return function;
343 }
344 
345 
346 ompt_frame_t *
347 __ompt_get_task_frame_internal(int depth)
348 {
349  ompt_task_info_t *info = __ompt_get_taskinfo(depth);
350  ompt_frame_t *frame = info ? frame = &info->frame : NULL;
351  return frame;
352 }
353 
354 
355 //----------------------------------------------------------
356 // team support
357 //----------------------------------------------------------
358 
359 void
360 __ompt_team_assign_id(kmp_team_t *team, ompt_parallel_id_t ompt_pid)
361 {
362  team->t.ompt_team_info.parallel_id = ompt_pid;
363 }
364 
365 
366 //----------------------------------------------------------
367 // runtime version support
368 //----------------------------------------------------------
369 
370 const char *
371 __ompt_get_runtime_version_internal()
372 {
373  return &__kmp_version_lib_ver[KMP_VERSION_MAGIC_LEN];
374 }