2 * ompt-specific.cpp -- OMPT internal functions
5 //===----------------------------------------------------------------------===//
7 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
8 // See https://llvm.org/LICENSE.txt for license information.
9 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
11 //===----------------------------------------------------------------------===//
13 //******************************************************************************
15 //******************************************************************************
18 #include "ompt-specific.h"
25 #define THREAD_LOCAL __declspec(thread)
27 #define THREAD_LOCAL __thread
30 #define OMPT_WEAK_ATTRIBUTE KMP_WEAK_ATTRIBUTE_INTERNAL
32 //******************************************************************************
34 //******************************************************************************
36 #define LWT_FROM_TEAM(team) (team)->t.ompt_serialized_team_info
38 #define OMPT_THREAD_ID_BITS 16
40 //******************************************************************************
42 //******************************************************************************
44 //----------------------------------------------------------
45 // traverse the team and task hierarchy
46 // note: __ompt_get_teaminfo and __ompt_get_task_info_object
47 // traverse the hierarchy similarly and need to be
49 //----------------------------------------------------------
51 ompt_team_info_t
*__ompt_get_teaminfo(int depth
, int *size
) {
52 kmp_info_t
*thr
= ompt_get_thread();
55 kmp_team
*team
= thr
->th
.th_team
;
59 ompt_lw_taskteam_t
*next_lwt
= LWT_FROM_TEAM(team
), *lwt
= NULL
;
62 // next lightweight team (if any)
66 // next heavyweight team (if any) after
67 // lightweight teams are exhausted
73 team
= team
->t
.t_parent
;
75 next_lwt
= LWT_FROM_TEAM(team
);
84 // lightweight teams have one task
88 // return team info for lightweight team
89 return &lwt
->ompt_team_info
;
91 // extract size from heavyweight team
93 *size
= team
->t
.t_nproc
;
95 // return team info for heavyweight team
96 return &team
->t
.ompt_team_info
;
103 ompt_task_info_t
*__ompt_get_task_info_object(int depth
) {
104 ompt_task_info_t
*info
= NULL
;
105 kmp_info_t
*thr
= ompt_get_thread();
108 kmp_taskdata_t
*taskdata
= thr
->th
.th_current_task
;
109 ompt_lw_taskteam_t
*lwt
= NULL
,
110 *next_lwt
= LWT_FROM_TEAM(taskdata
->td_team
);
113 // next lightweight team (if any)
117 // next heavyweight team (if any) after
118 // lightweight teams are exhausted
119 if (!lwt
&& taskdata
) {
124 taskdata
= taskdata
->td_parent
;
126 next_lwt
= LWT_FROM_TEAM(taskdata
->td_team
);
134 info
= &lwt
->ompt_task_info
;
135 } else if (taskdata
) {
136 info
= &taskdata
->ompt_task_info
;
143 ompt_task_info_t
*__ompt_get_scheduling_taskinfo(int depth
) {
144 ompt_task_info_t
*info
= NULL
;
145 kmp_info_t
*thr
= ompt_get_thread();
148 kmp_taskdata_t
*taskdata
= thr
->th
.th_current_task
;
150 ompt_lw_taskteam_t
*lwt
= NULL
,
151 *next_lwt
= LWT_FROM_TEAM(taskdata
->td_team
);
154 // next lightweight team (if any)
158 // next heavyweight team (if any) after
159 // lightweight teams are exhausted
160 if (!lwt
&& taskdata
) {
161 // first try scheduling parent (for explicit task scheduling)
162 if (taskdata
->ompt_task_info
.scheduling_parent
) {
163 taskdata
= taskdata
->ompt_task_info
.scheduling_parent
;
164 } else if (next_lwt
) {
168 // then go for implicit tasks
169 taskdata
= taskdata
->td_parent
;
171 next_lwt
= LWT_FROM_TEAM(taskdata
->td_team
);
179 info
= &lwt
->ompt_task_info
;
180 } else if (taskdata
) {
181 info
= &taskdata
->ompt_task_info
;
188 //******************************************************************************
189 // interface operations
190 //******************************************************************************
192 //----------------------------------------------------------
194 //----------------------------------------------------------
196 ompt_data_t
*__ompt_get_thread_data_internal() {
197 if (__kmp_get_gtid() >= 0) {
198 kmp_info_t
*thread
= ompt_get_thread();
201 return &(thread
->th
.ompt_thread_info
.thread_data
);
206 //----------------------------------------------------------
208 //----------------------------------------------------------
210 void __ompt_thread_assign_wait_id(void *variable
) {
211 kmp_info_t
*ti
= ompt_get_thread();
214 ti
->th
.ompt_thread_info
.wait_id
= (ompt_wait_id_t
)(uintptr_t)variable
;
217 int __ompt_get_state_internal(ompt_wait_id_t
*omp_wait_id
) {
218 kmp_info_t
*ti
= ompt_get_thread();
222 *omp_wait_id
= ti
->th
.ompt_thread_info
.wait_id
;
223 return ti
->th
.ompt_thread_info
.state
;
225 return ompt_state_undefined
;
228 //----------------------------------------------------------
229 // parallel region support
230 //----------------------------------------------------------
232 int __ompt_get_parallel_info_internal(int ancestor_level
,
233 ompt_data_t
**parallel_data
,
235 if (__kmp_get_gtid() >= 0) {
236 ompt_team_info_t
*info
;
238 info
= __ompt_get_teaminfo(ancestor_level
, team_size
);
240 info
= __ompt_get_teaminfo(ancestor_level
, NULL
);
243 *parallel_data
= info
? &(info
->parallel_data
) : NULL
;
251 //----------------------------------------------------------
252 // lightweight task team support
253 //----------------------------------------------------------
255 void __ompt_lw_taskteam_init(ompt_lw_taskteam_t
*lwt
, kmp_info_t
*thr
, int gtid
,
256 ompt_data_t
*ompt_pid
, void *codeptr
) {
257 // initialize parallel_data with input, return address to parallel_data on
259 lwt
->ompt_team_info
.parallel_data
= *ompt_pid
;
260 lwt
->ompt_team_info
.master_return_address
= codeptr
;
261 lwt
->ompt_task_info
.task_data
.value
= 0;
262 lwt
->ompt_task_info
.frame
.enter_frame
= ompt_data_none
;
263 lwt
->ompt_task_info
.frame
.exit_frame
= ompt_data_none
;
264 lwt
->ompt_task_info
.scheduling_parent
= NULL
;
269 void __ompt_lw_taskteam_link(ompt_lw_taskteam_t
*lwt
, kmp_info_t
*thr
,
270 int on_heap
, bool always
) {
271 ompt_lw_taskteam_t
*link_lwt
= lwt
;
273 thr
->th
.th_team
->t
.t_serialized
>
274 1) { // we already have a team, so link the new team and swap values
275 if (on_heap
) { // the lw_taskteam cannot stay on stack, allocate it on heap
277 (ompt_lw_taskteam_t
*)__kmp_allocate(sizeof(ompt_lw_taskteam_t
));
279 link_lwt
->heap
= on_heap
;
281 // would be swap in the (on_stack) case.
282 ompt_team_info_t tmp_team
= lwt
->ompt_team_info
;
283 link_lwt
->ompt_team_info
= *OMPT_CUR_TEAM_INFO(thr
);
284 *OMPT_CUR_TEAM_INFO(thr
) = tmp_team
;
286 ompt_task_info_t tmp_task
= lwt
->ompt_task_info
;
287 link_lwt
->ompt_task_info
= *OMPT_CUR_TASK_INFO(thr
);
288 *OMPT_CUR_TASK_INFO(thr
) = tmp_task
;
290 // link the taskteam into the list of taskteams:
291 ompt_lw_taskteam_t
*my_parent
=
292 thr
->th
.th_team
->t
.ompt_serialized_team_info
;
293 link_lwt
->parent
= my_parent
;
294 thr
->th
.th_team
->t
.ompt_serialized_team_info
= link_lwt
;
296 // this is the first serialized team, so we just store the values in the
297 // team and drop the taskteam-object
298 *OMPT_CUR_TEAM_INFO(thr
) = lwt
->ompt_team_info
;
299 *OMPT_CUR_TASK_INFO(thr
) = lwt
->ompt_task_info
;
303 void __ompt_lw_taskteam_unlink(kmp_info_t
*thr
) {
304 ompt_lw_taskteam_t
*lwtask
= thr
->th
.th_team
->t
.ompt_serialized_team_info
;
306 thr
->th
.th_team
->t
.ompt_serialized_team_info
= lwtask
->parent
;
308 ompt_team_info_t tmp_team
= lwtask
->ompt_team_info
;
309 lwtask
->ompt_team_info
= *OMPT_CUR_TEAM_INFO(thr
);
310 *OMPT_CUR_TEAM_INFO(thr
) = tmp_team
;
312 ompt_task_info_t tmp_task
= lwtask
->ompt_task_info
;
313 lwtask
->ompt_task_info
= *OMPT_CUR_TASK_INFO(thr
);
314 *OMPT_CUR_TASK_INFO(thr
) = tmp_task
;
324 //----------------------------------------------------------
326 //----------------------------------------------------------
328 int __ompt_get_task_info_internal(int ancestor_level
, int *type
,
329 ompt_data_t
**task_data
,
330 ompt_frame_t
**task_frame
,
331 ompt_data_t
**parallel_data
,
333 if (__kmp_get_gtid() < 0)
336 if (ancestor_level
< 0)
339 // copied from __ompt_get_scheduling_taskinfo
340 ompt_task_info_t
*info
= NULL
;
341 ompt_team_info_t
*team_info
= NULL
;
342 kmp_info_t
*thr
= ompt_get_thread();
343 int level
= ancestor_level
;
346 kmp_taskdata_t
*taskdata
= thr
->th
.th_current_task
;
347 if (taskdata
== NULL
)
349 kmp_team
*team
= thr
->th
.th_team
, *prev_team
= NULL
;
352 ompt_lw_taskteam_t
*lwt
= NULL
,
353 *next_lwt
= LWT_FROM_TEAM(taskdata
->td_team
),
356 while (ancestor_level
> 0) {
357 // needed for thread_num
360 // next lightweight team (if any)
364 // next heavyweight team (if any) after
365 // lightweight teams are exhausted
366 if (!lwt
&& taskdata
) {
367 // first try scheduling parent (for explicit task scheduling)
368 if (taskdata
->ompt_task_info
.scheduling_parent
) {
369 taskdata
= taskdata
->ompt_task_info
.scheduling_parent
;
370 } else if (next_lwt
) {
374 // then go for implicit tasks
375 taskdata
= taskdata
->td_parent
;
378 team
= team
->t
.t_parent
;
380 next_lwt
= LWT_FROM_TEAM(taskdata
->td_team
);
388 info
= &lwt
->ompt_task_info
;
389 team_info
= &lwt
->ompt_team_info
;
391 *type
= ompt_task_implicit
;
393 } else if (taskdata
) {
394 info
= &taskdata
->ompt_task_info
;
395 team_info
= &team
->t
.ompt_team_info
;
397 if (taskdata
->td_parent
) {
398 *type
= (taskdata
->td_flags
.tasktype
? ompt_task_explicit
399 : ompt_task_implicit
) |
400 TASK_TYPE_DETAILS_FORMAT(taskdata
);
402 *type
= ompt_task_initial
;
407 *task_data
= info
? &info
->task_data
: NULL
;
410 // OpenMP spec asks for the scheduling task to be returned.
411 *task_frame
= info
? &info
->frame
: NULL
;
414 *parallel_data
= team_info
? &(team_info
->parallel_data
) : NULL
;
418 *thread_num
= __kmp_get_tid();
422 *thread_num
= prev_team
->t
.t_master_tid
;
423 // *thread_num = team->t.t_master_tid;
430 int __ompt_get_task_memory_internal(void **addr
, size_t *size
, int blocknum
) {
432 return 0; // support only a single block
434 kmp_info_t
*thr
= ompt_get_thread();
438 kmp_taskdata_t
*taskdata
= thr
->th
.th_current_task
;
439 kmp_task_t
*task
= KMP_TASKDATA_TO_TASK(taskdata
);
441 if (taskdata
->td_flags
.tasktype
!= TASK_EXPLICIT
)
442 return 0; // support only explicit task
445 int64_t ret_size
= taskdata
->td_size_alloc
- sizeof(kmp_taskdata_t
);
447 // kmp_task_t->data1 is an optional member
448 if (taskdata
->td_flags
.destructors_thunk
)
449 ret_addr
= &task
->data1
+ 1;
451 ret_addr
= &task
->part_id
+ 1;
453 ret_size
-= (char *)(ret_addr
) - (char *)(task
);
462 //----------------------------------------------------------
464 //----------------------------------------------------------
466 void __ompt_team_assign_id(kmp_team_t
*team
, ompt_data_t ompt_pid
) {
467 team
->t
.ompt_team_info
.parallel_data
= ompt_pid
;
470 //----------------------------------------------------------
472 //----------------------------------------------------------
474 static uint64_t __ompt_get_unique_id_internal() {
475 static uint64_t thread
= 1;
476 static THREAD_LOCAL
uint64_t ID
= 0;
478 uint64_t new_thread
= KMP_TEST_THEN_INC64((kmp_int64
*)&thread
);
479 ID
= new_thread
<< (sizeof(uint64_t) * 8 - OMPT_THREAD_ID_BITS
);
484 ompt_sync_region_t
__ompt_get_barrier_kind(enum barrier_type bt
,
486 if (bt
== bs_forkjoin_barrier
)
487 return ompt_sync_region_barrier_implicit
;
489 if (bt
!= bs_plain_barrier
)
490 return ompt_sync_region_barrier_implementation
;
492 if (!thr
->th
.th_ident
)
493 return ompt_sync_region_barrier
;
495 kmp_int32 flags
= thr
->th
.th_ident
->flags
;
497 if ((flags
& KMP_IDENT_BARRIER_EXPL
) != 0)
498 return ompt_sync_region_barrier_explicit
;
500 if ((flags
& KMP_IDENT_BARRIER_IMPL
) != 0)
501 return ompt_sync_region_barrier_implicit
;
503 return ompt_sync_region_barrier_implementation
;