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 //******************************************************************************
191 //----------------------------------------------------------
192 // initialization support
193 //----------------------------------------------------------
195 void __ompt_force_initialization() { __kmp_serial_initialize(); }
197 //----------------------------------------------------------
199 //----------------------------------------------------------
201 ompt_data_t
*__ompt_get_thread_data_internal() {
202 if (__kmp_get_gtid() >= 0) {
203 kmp_info_t
*thread
= ompt_get_thread();
206 return &(thread
->th
.ompt_thread_info
.thread_data
);
211 //----------------------------------------------------------
213 //----------------------------------------------------------
215 void __ompt_thread_assign_wait_id(void *variable
) {
216 kmp_info_t
*ti
= ompt_get_thread();
219 ti
->th
.ompt_thread_info
.wait_id
= (ompt_wait_id_t
)(uintptr_t)variable
;
222 int __ompt_get_state_internal(ompt_wait_id_t
*omp_wait_id
) {
223 kmp_info_t
*ti
= ompt_get_thread();
227 *omp_wait_id
= ti
->th
.ompt_thread_info
.wait_id
;
228 return ti
->th
.ompt_thread_info
.state
;
230 return ompt_state_undefined
;
233 //----------------------------------------------------------
234 // parallel region support
235 //----------------------------------------------------------
237 int __ompt_get_parallel_info_internal(int ancestor_level
,
238 ompt_data_t
**parallel_data
,
240 if (__kmp_get_gtid() >= 0) {
241 ompt_team_info_t
*info
;
243 info
= __ompt_get_teaminfo(ancestor_level
, team_size
);
245 info
= __ompt_get_teaminfo(ancestor_level
, NULL
);
248 *parallel_data
= info
? &(info
->parallel_data
) : NULL
;
256 //----------------------------------------------------------
257 // lightweight task team support
258 //----------------------------------------------------------
260 void __ompt_lw_taskteam_init(ompt_lw_taskteam_t
*lwt
, kmp_info_t
*thr
, int gtid
,
261 ompt_data_t
*ompt_pid
, void *codeptr
) {
262 // initialize parallel_data with input, return address to parallel_data on
264 lwt
->ompt_team_info
.parallel_data
= *ompt_pid
;
265 lwt
->ompt_team_info
.master_return_address
= codeptr
;
266 lwt
->ompt_task_info
.task_data
.value
= 0;
267 lwt
->ompt_task_info
.frame
.enter_frame
= ompt_data_none
;
268 lwt
->ompt_task_info
.frame
.exit_frame
= ompt_data_none
;
269 lwt
->ompt_task_info
.scheduling_parent
= NULL
;
274 void __ompt_lw_taskteam_link(ompt_lw_taskteam_t
*lwt
, kmp_info_t
*thr
,
275 int on_heap
, bool always
) {
276 ompt_lw_taskteam_t
*link_lwt
= lwt
;
278 thr
->th
.th_team
->t
.t_serialized
>
279 1) { // we already have a team, so link the new team and swap values
280 if (on_heap
) { // the lw_taskteam cannot stay on stack, allocate it on heap
282 (ompt_lw_taskteam_t
*)__kmp_allocate(sizeof(ompt_lw_taskteam_t
));
284 link_lwt
->heap
= on_heap
;
286 // would be swap in the (on_stack) case.
287 ompt_team_info_t tmp_team
= lwt
->ompt_team_info
;
288 link_lwt
->ompt_team_info
= *OMPT_CUR_TEAM_INFO(thr
);
289 *OMPT_CUR_TEAM_INFO(thr
) = tmp_team
;
291 // link the taskteam into the list of taskteams:
292 ompt_lw_taskteam_t
*my_parent
=
293 thr
->th
.th_team
->t
.ompt_serialized_team_info
;
294 link_lwt
->parent
= my_parent
;
295 thr
->th
.th_team
->t
.ompt_serialized_team_info
= link_lwt
;
297 if (ompd_state
& OMPD_ENABLE_BP
) {
298 ompd_bp_parallel_begin();
302 ompt_task_info_t tmp_task
= lwt
->ompt_task_info
;
303 link_lwt
->ompt_task_info
= *OMPT_CUR_TASK_INFO(thr
);
304 *OMPT_CUR_TASK_INFO(thr
) = tmp_task
;
306 // this is the first serialized team, so we just store the values in the
307 // team and drop the taskteam-object
308 *OMPT_CUR_TEAM_INFO(thr
) = lwt
->ompt_team_info
;
310 if (ompd_state
& OMPD_ENABLE_BP
) {
311 ompd_bp_parallel_begin();
314 *OMPT_CUR_TASK_INFO(thr
) = lwt
->ompt_task_info
;
318 void __ompt_lw_taskteam_unlink(kmp_info_t
*thr
) {
319 ompt_lw_taskteam_t
*lwtask
= thr
->th
.th_team
->t
.ompt_serialized_team_info
;
321 ompt_task_info_t tmp_task
= lwtask
->ompt_task_info
;
322 lwtask
->ompt_task_info
= *OMPT_CUR_TASK_INFO(thr
);
323 *OMPT_CUR_TASK_INFO(thr
) = tmp_task
;
325 if (ompd_state
& OMPD_ENABLE_BP
) {
326 ompd_bp_parallel_end();
329 thr
->th
.th_team
->t
.ompt_serialized_team_info
= lwtask
->parent
;
331 ompt_team_info_t tmp_team
= lwtask
->ompt_team_info
;
332 lwtask
->ompt_team_info
= *OMPT_CUR_TEAM_INFO(thr
);
333 *OMPT_CUR_TEAM_INFO(thr
) = tmp_team
;
343 //----------------------------------------------------------
345 //----------------------------------------------------------
347 ompt_data_t
*__ompt_get_task_data() {
348 kmp_info_t
*thr
= ompt_get_thread();
349 ompt_data_t
*task_data
= thr
? OMPT_CUR_TASK_DATA(thr
) : NULL
;
353 ompt_data_t
*__ompt_get_target_task_data() {
354 return &__kmp_threads
[__kmp_get_gtid()]->th
.ompt_thread_info
.target_task_data
;
357 int __ompt_get_task_info_internal(int ancestor_level
, int *type
,
358 ompt_data_t
**task_data
,
359 ompt_frame_t
**task_frame
,
360 ompt_data_t
**parallel_data
,
362 if (__kmp_get_gtid() < 0)
365 if (ancestor_level
< 0)
368 // copied from __ompt_get_scheduling_taskinfo
369 ompt_task_info_t
*info
= NULL
;
370 ompt_team_info_t
*team_info
= NULL
;
371 kmp_info_t
*thr
= ompt_get_thread();
372 int level
= ancestor_level
;
375 kmp_taskdata_t
*taskdata
= thr
->th
.th_current_task
;
376 if (taskdata
== NULL
)
378 kmp_team
*team
= thr
->th
.th_team
, *prev_team
= NULL
;
381 ompt_lw_taskteam_t
*lwt
= NULL
,
382 *next_lwt
= LWT_FROM_TEAM(taskdata
->td_team
);
384 while (ancestor_level
> 0) {
385 // next lightweight team (if any)
389 // next heavyweight team (if any) after
390 // lightweight teams are exhausted
391 if (!lwt
&& taskdata
) {
392 // first try scheduling parent (for explicit task scheduling)
393 if (taskdata
->ompt_task_info
.scheduling_parent
) {
394 taskdata
= taskdata
->ompt_task_info
.scheduling_parent
;
395 } else if (next_lwt
) {
399 // then go for implicit tasks
400 taskdata
= taskdata
->td_parent
;
404 team
= team
->t
.t_parent
;
406 next_lwt
= LWT_FROM_TEAM(taskdata
->td_team
);
414 info
= &lwt
->ompt_task_info
;
415 team_info
= &lwt
->ompt_team_info
;
417 *type
= ompt_task_implicit
;
419 } else if (taskdata
) {
420 info
= &taskdata
->ompt_task_info
;
421 team_info
= &team
->t
.ompt_team_info
;
423 if (taskdata
->td_parent
) {
424 *type
= TASK_TYPE_DETAILS_FORMAT(taskdata
);
426 *type
= ompt_task_initial
;
431 *task_data
= info
? &info
->task_data
: NULL
;
434 // OpenMP spec asks for the scheduling task to be returned.
435 *task_frame
= info
? &info
->frame
: NULL
;
438 *parallel_data
= team_info
? &(team_info
->parallel_data
) : NULL
;
442 *thread_num
= __kmp_get_tid();
445 else if (!prev_team
) {
446 // The innermost parallel region contains at least one explicit task.
447 // The task at level > 0 is either an implicit task that
448 // corresponds to the mentioned region or one of the explicit tasks
449 // nested inside the same region. Note that the task isn't the
450 // innermost explicit tasks (because of condition level > 0).
451 // Since the task at this level still belongs to the innermost parallel
452 // region, thread_num is determined the same way as for level==0.
453 *thread_num
= __kmp_get_tid();
455 *thread_num
= prev_team
->t
.t_master_tid
;
456 // *thread_num = team->t.t_master_tid;
463 int __ompt_get_task_memory_internal(void **addr
, size_t *size
, int blocknum
) {
466 return 0; // support only a single block
468 kmp_info_t
*thr
= ompt_get_thread();
472 kmp_taskdata_t
*taskdata
= thr
->th
.th_current_task
;
474 if (taskdata
->td_flags
.tasktype
!= TASK_EXPLICIT
)
475 return 0; // support only explicit task
478 *size
= taskdata
->td_size_alloc
;
482 //----------------------------------------------------------
484 //----------------------------------------------------------
486 void __ompt_team_assign_id(kmp_team_t
*team
, ompt_data_t ompt_pid
) {
487 team
->t
.ompt_team_info
.parallel_data
= ompt_pid
;
490 //----------------------------------------------------------
492 //----------------------------------------------------------
494 static uint64_t __ompt_get_unique_id_internal() {
495 static uint64_t thread
= 1;
496 static THREAD_LOCAL
uint64_t ID
= 0;
498 uint64_t new_thread
= KMP_TEST_THEN_INC64((kmp_int64
*)&thread
);
499 ID
= new_thread
<< (sizeof(uint64_t) * 8 - OMPT_THREAD_ID_BITS
);
504 ompt_sync_region_t
__ompt_get_barrier_kind(enum barrier_type bt
,
506 if (bt
== bs_forkjoin_barrier
) {
507 if (thr
->th
.ompt_thread_info
.parallel_flags
& ompt_parallel_league
)
508 return ompt_sync_region_barrier_teams
;
510 return ompt_sync_region_barrier_implicit_parallel
;
513 if (bt
!= bs_plain_barrier
|| !thr
->th
.th_ident
)
514 return ompt_sync_region_barrier_implementation
;
516 kmp_int32 flags
= thr
->th
.th_ident
->flags
;
518 if ((flags
& KMP_IDENT_BARRIER_EXPL
) != 0)
519 return ompt_sync_region_barrier_explicit
;
521 if ((flags
& KMP_IDENT_BARRIER_IMPL
) != 0)
522 return ompt_sync_region_barrier_implicit_workshare
;
524 return ompt_sync_region_barrier_implementation
;