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 // link the taskteam into the list of taskteams:
287 ompt_lw_taskteam_t
*my_parent
=
288 thr
->th
.th_team
->t
.ompt_serialized_team_info
;
289 link_lwt
->parent
= my_parent
;
290 thr
->th
.th_team
->t
.ompt_serialized_team_info
= link_lwt
;
292 if (ompd_state
& OMPD_ENABLE_BP
) {
293 ompd_bp_parallel_begin();
297 ompt_task_info_t tmp_task
= lwt
->ompt_task_info
;
298 link_lwt
->ompt_task_info
= *OMPT_CUR_TASK_INFO(thr
);
299 *OMPT_CUR_TASK_INFO(thr
) = tmp_task
;
301 // this is the first serialized team, so we just store the values in the
302 // team and drop the taskteam-object
303 *OMPT_CUR_TEAM_INFO(thr
) = lwt
->ompt_team_info
;
305 if (ompd_state
& OMPD_ENABLE_BP
) {
306 ompd_bp_parallel_begin();
309 *OMPT_CUR_TASK_INFO(thr
) = lwt
->ompt_task_info
;
313 void __ompt_lw_taskteam_unlink(kmp_info_t
*thr
) {
314 ompt_lw_taskteam_t
*lwtask
= thr
->th
.th_team
->t
.ompt_serialized_team_info
;
316 ompt_task_info_t tmp_task
= lwtask
->ompt_task_info
;
317 lwtask
->ompt_task_info
= *OMPT_CUR_TASK_INFO(thr
);
318 *OMPT_CUR_TASK_INFO(thr
) = tmp_task
;
320 if (ompd_state
& OMPD_ENABLE_BP
) {
321 ompd_bp_parallel_end();
324 thr
->th
.th_team
->t
.ompt_serialized_team_info
= lwtask
->parent
;
326 ompt_team_info_t tmp_team
= lwtask
->ompt_team_info
;
327 lwtask
->ompt_team_info
= *OMPT_CUR_TEAM_INFO(thr
);
328 *OMPT_CUR_TEAM_INFO(thr
) = tmp_team
;
338 //----------------------------------------------------------
340 //----------------------------------------------------------
342 int __ompt_get_task_info_internal(int ancestor_level
, int *type
,
343 ompt_data_t
**task_data
,
344 ompt_frame_t
**task_frame
,
345 ompt_data_t
**parallel_data
,
347 if (__kmp_get_gtid() < 0)
350 if (ancestor_level
< 0)
353 // copied from __ompt_get_scheduling_taskinfo
354 ompt_task_info_t
*info
= NULL
;
355 ompt_team_info_t
*team_info
= NULL
;
356 kmp_info_t
*thr
= ompt_get_thread();
357 int level
= ancestor_level
;
360 kmp_taskdata_t
*taskdata
= thr
->th
.th_current_task
;
361 if (taskdata
== NULL
)
363 kmp_team
*team
= thr
->th
.th_team
, *prev_team
= NULL
;
366 ompt_lw_taskteam_t
*lwt
= NULL
,
367 *next_lwt
= LWT_FROM_TEAM(taskdata
->td_team
),
370 while (ancestor_level
> 0) {
371 // needed for thread_num
374 // next lightweight team (if any)
378 // next heavyweight team (if any) after
379 // lightweight teams are exhausted
380 if (!lwt
&& taskdata
) {
381 // first try scheduling parent (for explicit task scheduling)
382 if (taskdata
->ompt_task_info
.scheduling_parent
) {
383 taskdata
= taskdata
->ompt_task_info
.scheduling_parent
;
384 } else if (next_lwt
) {
388 // then go for implicit tasks
389 taskdata
= taskdata
->td_parent
;
392 team
= team
->t
.t_parent
;
394 next_lwt
= LWT_FROM_TEAM(taskdata
->td_team
);
402 info
= &lwt
->ompt_task_info
;
403 team_info
= &lwt
->ompt_team_info
;
405 *type
= ompt_task_implicit
;
407 } else if (taskdata
) {
408 info
= &taskdata
->ompt_task_info
;
409 team_info
= &team
->t
.ompt_team_info
;
411 if (taskdata
->td_parent
) {
412 *type
= (taskdata
->td_flags
.tasktype
? ompt_task_explicit
413 : ompt_task_implicit
) |
414 TASK_TYPE_DETAILS_FORMAT(taskdata
);
416 *type
= ompt_task_initial
;
421 *task_data
= info
? &info
->task_data
: NULL
;
424 // OpenMP spec asks for the scheduling task to be returned.
425 *task_frame
= info
? &info
->frame
: NULL
;
428 *parallel_data
= team_info
? &(team_info
->parallel_data
) : NULL
;
432 *thread_num
= __kmp_get_tid();
436 *thread_num
= prev_team
->t
.t_master_tid
;
437 // *thread_num = team->t.t_master_tid;
444 int __ompt_get_task_memory_internal(void **addr
, size_t *size
, int blocknum
) {
446 return 0; // support only a single block
448 kmp_info_t
*thr
= ompt_get_thread();
452 kmp_taskdata_t
*taskdata
= thr
->th
.th_current_task
;
453 kmp_task_t
*task
= KMP_TASKDATA_TO_TASK(taskdata
);
455 if (taskdata
->td_flags
.tasktype
!= TASK_EXPLICIT
)
456 return 0; // support only explicit task
459 int64_t ret_size
= taskdata
->td_size_alloc
- sizeof(kmp_taskdata_t
);
461 // kmp_task_t->data1 is an optional member
462 if (taskdata
->td_flags
.destructors_thunk
)
463 ret_addr
= &task
->data1
+ 1;
465 ret_addr
= &task
->part_id
+ 1;
467 ret_size
-= (char *)(ret_addr
) - (char *)(task
);
472 *size
= (size_t)ret_size
;
476 //----------------------------------------------------------
478 //----------------------------------------------------------
480 void __ompt_team_assign_id(kmp_team_t
*team
, ompt_data_t ompt_pid
) {
481 team
->t
.ompt_team_info
.parallel_data
= ompt_pid
;
484 //----------------------------------------------------------
486 //----------------------------------------------------------
488 static uint64_t __ompt_get_unique_id_internal() {
489 static uint64_t thread
= 1;
490 static THREAD_LOCAL
uint64_t ID
= 0;
492 uint64_t new_thread
= KMP_TEST_THEN_INC64((kmp_int64
*)&thread
);
493 ID
= new_thread
<< (sizeof(uint64_t) * 8 - OMPT_THREAD_ID_BITS
);
498 ompt_sync_region_t
__ompt_get_barrier_kind(enum barrier_type bt
,
500 if (bt
== bs_forkjoin_barrier
)
501 return ompt_sync_region_barrier_implicit
;
503 if (bt
!= bs_plain_barrier
)
504 return ompt_sync_region_barrier_implementation
;
506 if (!thr
->th
.th_ident
)
507 return ompt_sync_region_barrier
;
509 kmp_int32 flags
= thr
->th
.th_ident
->flags
;
511 if ((flags
& KMP_IDENT_BARRIER_EXPL
) != 0)
512 return ompt_sync_region_barrier_explicit
;
514 if ((flags
& KMP_IDENT_BARRIER_IMPL
) != 0)
515 return ompt_sync_region_barrier_implicit
;
517 return ompt_sync_region_barrier_implementation
;