1 /* 2 * ompt-specific.cpp -- OMPT internal functions 3 */ 4 5 //===----------------------------------------------------------------------===// 6 // 7 // The LLVM Compiler Infrastructure 8 // 9 // This file is dual licensed under the MIT and the University of Illinois Open 10 // Source Licenses. See LICENSE.txt for details. 11 // 12 //===----------------------------------------------------------------------===// 13 14 //****************************************************************************** 15 // include files 16 //****************************************************************************** 17 18 #include "kmp.h" 19 #include "ompt-specific.h" 20 21 #if KMP_OS_UNIX 22 #include <dlfcn.h> 23 #endif 24 25 #if KMP_OS_WINDOWS 26 #define THREAD_LOCAL __declspec(thread) 27 #else 28 #define THREAD_LOCAL __thread 29 #endif 30 31 #define OMPT_WEAK_ATTRIBUTE KMP_WEAK_ATTRIBUTE 32 33 //****************************************************************************** 34 // macros 35 //****************************************************************************** 36 37 #define LWT_FROM_TEAM(team) (team)->t.ompt_serialized_team_info 38 39 #define OMPT_THREAD_ID_BITS 16 40 41 //****************************************************************************** 42 // private operations 43 //****************************************************************************** 44 45 //---------------------------------------------------------- 46 // traverse the team and task hierarchy 47 // note: __ompt_get_teaminfo and __ompt_get_task_info_object 48 // traverse the hierarchy similarly and need to be 49 // kept consistent 50 //---------------------------------------------------------- 51 52 ompt_team_info_t *__ompt_get_teaminfo(int depth, int *size) { 53 kmp_info_t *thr = ompt_get_thread(); 54 55 if (thr) { 56 kmp_team *team = thr->th.th_team; 57 if (team == NULL) 58 return NULL; 59 60 ompt_lw_taskteam_t *next_lwt = LWT_FROM_TEAM(team), *lwt = NULL; 61 62 while (depth > 0) { 63 // next lightweight team (if any) 64 if (lwt) 65 lwt = lwt->parent; 66 67 // next heavyweight team (if any) after 68 // lightweight teams are exhausted 69 if (!lwt && team) { 70 if (next_lwt) { 71 lwt = next_lwt; 72 next_lwt = NULL; 73 } else { 74 team = team->t.t_parent; 75 if (team) { 76 next_lwt = LWT_FROM_TEAM(team); 77 } 78 } 79 } 80 81 depth--; 82 } 83 84 if (lwt) { 85 // lightweight teams have one task 86 if (size) 87 *size = 1; 88 89 // return team info for lightweight team 90 return &lwt->ompt_team_info; 91 } else if (team) { 92 // extract size from heavyweight team 93 if (size) 94 *size = team->t.t_nproc; 95 96 // return team info for heavyweight team 97 return &team->t.ompt_team_info; 98 } 99 } 100 101 return NULL; 102 } 103 104 ompt_task_info_t *__ompt_get_task_info_object(int depth) { 105 ompt_task_info_t *info = NULL; 106 kmp_info_t *thr = ompt_get_thread(); 107 108 if (thr) { 109 kmp_taskdata_t *taskdata = thr->th.th_current_task; 110 ompt_lw_taskteam_t *lwt = NULL, 111 *next_lwt = LWT_FROM_TEAM(taskdata->td_team); 112 113 while (depth > 0) { 114 // next lightweight team (if any) 115 if (lwt) 116 lwt = lwt->parent; 117 118 // next heavyweight team (if any) after 119 // lightweight teams are exhausted 120 if (!lwt && taskdata) { 121 if (next_lwt) { 122 lwt = next_lwt; 123 next_lwt = NULL; 124 } else { 125 taskdata = taskdata->td_parent; 126 if (taskdata) { 127 next_lwt = LWT_FROM_TEAM(taskdata->td_team); 128 } 129 } 130 } 131 depth--; 132 } 133 134 if (lwt) { 135 info = &lwt->ompt_task_info; 136 } else if (taskdata) { 137 info = &taskdata->ompt_task_info; 138 } 139 } 140 141 return info; 142 } 143 144 ompt_task_info_t *__ompt_get_scheduling_taskinfo(int depth) { 145 ompt_task_info_t *info = NULL; 146 kmp_info_t *thr = ompt_get_thread(); 147 148 if (thr) { 149 kmp_taskdata_t *taskdata = thr->th.th_current_task; 150 151 ompt_lw_taskteam_t *lwt = NULL, 152 *next_lwt = LWT_FROM_TEAM(taskdata->td_team); 153 154 while (depth > 0) { 155 // next lightweight team (if any) 156 if (lwt) 157 lwt = lwt->parent; 158 159 // next heavyweight team (if any) after 160 // lightweight teams are exhausted 161 if (!lwt && taskdata) { 162 // first try scheduling parent (for explicit task scheduling) 163 if (taskdata->ompt_task_info.scheduling_parent) { 164 taskdata = taskdata->ompt_task_info.scheduling_parent; 165 } else if (next_lwt) { 166 lwt = next_lwt; 167 next_lwt = NULL; 168 } else { 169 // then go for implicit tasks 170 taskdata = taskdata->td_parent; 171 if (taskdata) { 172 next_lwt = LWT_FROM_TEAM(taskdata->td_team); 173 } 174 } 175 } 176 depth--; 177 } 178 179 if (lwt) { 180 info = &lwt->ompt_task_info; 181 } else if (taskdata) { 182 info = &taskdata->ompt_task_info; 183 } 184 } 185 186 return info; 187 } 188 189 //****************************************************************************** 190 // interface operations 191 //****************************************************************************** 192 193 //---------------------------------------------------------- 194 // thread support 195 //---------------------------------------------------------- 196 197 ompt_data_t *__ompt_get_thread_data_internal() { 198 if (__kmp_get_gtid() >= 0) { 199 kmp_info_t *thread = ompt_get_thread(); 200 if (thread == NULL) 201 return NULL; 202 return &(thread->th.ompt_thread_info.thread_data); 203 } 204 return NULL; 205 } 206 207 //---------------------------------------------------------- 208 // state support 209 //---------------------------------------------------------- 210 211 void __ompt_thread_assign_wait_id(void *variable) { 212 kmp_info_t *ti = ompt_get_thread(); 213 214 ti->th.ompt_thread_info.wait_id = (omp_wait_id_t)variable; 215 } 216 217 omp_state_t __ompt_get_state_internal(omp_wait_id_t *omp_wait_id) { 218 kmp_info_t *ti = ompt_get_thread(); 219 220 if (ti) { 221 if (omp_wait_id) 222 *omp_wait_id = ti->th.ompt_thread_info.wait_id; 223 return ti->th.ompt_thread_info.state; 224 } 225 return omp_state_undefined; 226 } 227 228 //---------------------------------------------------------- 229 // parallel region support 230 //---------------------------------------------------------- 231 232 int __ompt_get_parallel_info_internal(int ancestor_level, 233 ompt_data_t **parallel_data, 234 int *team_size) { 235 if (__kmp_get_gtid() >= 0) { 236 ompt_team_info_t *info; 237 if (team_size) { 238 info = __ompt_get_teaminfo(ancestor_level, team_size); 239 } else { 240 info = __ompt_get_teaminfo(ancestor_level, NULL); 241 } 242 if (parallel_data) { 243 *parallel_data = info ? &(info->parallel_data) : NULL; 244 } 245 return info ? 2 : 0; 246 } else { 247 return 0; 248 } 249 } 250 251 //---------------------------------------------------------- 252 // lightweight task team support 253 //---------------------------------------------------------- 254 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 258 // exit 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 = NULL; 263 lwt->ompt_task_info.frame.exit_frame = NULL; 264 lwt->ompt_task_info.scheduling_parent = NULL; 265 lwt->ompt_task_info.deps = NULL; 266 lwt->ompt_task_info.ndeps = 0; 267 lwt->heap = 0; 268 lwt->parent = 0; 269 } 270 271 void __ompt_lw_taskteam_link(ompt_lw_taskteam_t *lwt, kmp_info_t *thr, 272 int on_heap) { 273 ompt_lw_taskteam_t *link_lwt = lwt; 274 if (thr->th.th_team->t.t_serialized > 275 1) { // we already have a team, so link the new team and swap values 276 if (on_heap) { // the lw_taskteam cannot stay on stack, allocate it on heap 277 link_lwt = 278 (ompt_lw_taskteam_t *)__kmp_allocate(sizeof(ompt_lw_taskteam_t)); 279 } 280 link_lwt->heap = on_heap; 281 282 // would be swap in the (on_stack) case. 283 ompt_team_info_t tmp_team = lwt->ompt_team_info; 284 link_lwt->ompt_team_info = *OMPT_CUR_TEAM_INFO(thr); 285 *OMPT_CUR_TEAM_INFO(thr) = tmp_team; 286 287 ompt_task_info_t tmp_task = lwt->ompt_task_info; 288 link_lwt->ompt_task_info = *OMPT_CUR_TASK_INFO(thr); 289 *OMPT_CUR_TASK_INFO(thr) = tmp_task; 290 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; 296 } else { 297 // this is the first serialized team, so we just store the values in the 298 // team and drop the taskteam-object 299 *OMPT_CUR_TEAM_INFO(thr) = lwt->ompt_team_info; 300 *OMPT_CUR_TASK_INFO(thr) = lwt->ompt_task_info; 301 } 302 } 303 304 void __ompt_lw_taskteam_unlink(kmp_info_t *thr) { 305 ompt_lw_taskteam_t *lwtask = thr->th.th_team->t.ompt_serialized_team_info; 306 if (lwtask) { 307 thr->th.th_team->t.ompt_serialized_team_info = lwtask->parent; 308 309 ompt_team_info_t tmp_team = lwtask->ompt_team_info; 310 lwtask->ompt_team_info = *OMPT_CUR_TEAM_INFO(thr); 311 *OMPT_CUR_TEAM_INFO(thr) = tmp_team; 312 313 ompt_task_info_t tmp_task = lwtask->ompt_task_info; 314 lwtask->ompt_task_info = *OMPT_CUR_TASK_INFO(thr); 315 *OMPT_CUR_TASK_INFO(thr) = tmp_task; 316 317 if (lwtask->heap) { 318 __kmp_free(lwtask); 319 lwtask = NULL; 320 } 321 } 322 // return lwtask; 323 } 324 325 //---------------------------------------------------------- 326 // task support 327 //---------------------------------------------------------- 328 329 int __ompt_get_task_info_internal(int ancestor_level, int *type, 330 ompt_data_t **task_data, 331 omp_frame_t **task_frame, 332 ompt_data_t **parallel_data, 333 int *thread_num) { 334 if (__kmp_get_gtid() < 0) 335 return 0; 336 337 if (ancestor_level < 0) 338 return 0; 339 340 // copied from __ompt_get_scheduling_taskinfo 341 ompt_task_info_t *info = NULL; 342 ompt_team_info_t *team_info = NULL; 343 kmp_info_t *thr = ompt_get_thread(); 344 int level = ancestor_level; 345 346 if (thr) { 347 kmp_taskdata_t *taskdata = thr->th.th_current_task; 348 if (taskdata == NULL) 349 return 0; 350 kmp_team *team = thr->th.th_team, *prev_team = NULL; 351 if (team == NULL) 352 return 0; 353 ompt_lw_taskteam_t *lwt = NULL, 354 *next_lwt = LWT_FROM_TEAM(taskdata->td_team), 355 *prev_lwt = NULL; 356 357 while (ancestor_level > 0) { 358 // needed for thread_num 359 prev_team = team; 360 prev_lwt = lwt; 361 // next lightweight team (if any) 362 if (lwt) 363 lwt = lwt->parent; 364 365 // next heavyweight team (if any) after 366 // lightweight teams are exhausted 367 if (!lwt && taskdata) { 368 // first try scheduling parent (for explicit task scheduling) 369 if (taskdata->ompt_task_info.scheduling_parent) { 370 taskdata = taskdata->ompt_task_info.scheduling_parent; 371 } else if (next_lwt) { 372 lwt = next_lwt; 373 next_lwt = NULL; 374 } else { 375 // then go for implicit tasks 376 taskdata = taskdata->td_parent; 377 if (team == NULL) 378 return 0; 379 team = team->t.t_parent; 380 if (taskdata) { 381 next_lwt = LWT_FROM_TEAM(taskdata->td_team); 382 } 383 } 384 } 385 ancestor_level--; 386 } 387 388 if (lwt) { 389 info = &lwt->ompt_task_info; 390 team_info = &lwt->ompt_team_info; 391 if (type) { 392 *type = ompt_task_implicit; 393 } 394 } else if (taskdata) { 395 info = &taskdata->ompt_task_info; 396 team_info = &team->t.ompt_team_info; 397 if (type) { 398 if (taskdata->td_parent) { 399 *type = (taskdata->td_flags.tasktype ? ompt_task_explicit 400 : ompt_task_implicit) | 401 TASK_TYPE_DETAILS_FORMAT(taskdata); 402 } else { 403 *type = ompt_task_initial; 404 } 405 } 406 } 407 if (task_data) { 408 *task_data = info ? &info->task_data : NULL; 409 } 410 if (task_frame) { 411 // OpenMP spec asks for the scheduling task to be returned. 412 *task_frame = info ? &info->frame : NULL; 413 } 414 if (parallel_data) { 415 *parallel_data = team_info ? &(team_info->parallel_data) : NULL; 416 } 417 if (thread_num) { 418 if (level == 0) 419 *thread_num = __kmp_get_tid(); 420 else if (prev_lwt) 421 *thread_num = 0; 422 else 423 *thread_num = prev_team->t.t_master_tid; 424 // *thread_num = team->t.t_master_tid; 425 } 426 return info ? 2 : 0; 427 } 428 return 0; 429 } 430 431 //---------------------------------------------------------- 432 // team support 433 //---------------------------------------------------------- 434 435 void __ompt_team_assign_id(kmp_team_t *team, ompt_data_t ompt_pid) { 436 team->t.ompt_team_info.parallel_data = ompt_pid; 437 } 438 439 //---------------------------------------------------------- 440 // misc 441 //---------------------------------------------------------- 442 443 static uint64_t __ompt_get_unique_id_internal() { 444 static uint64_t thread = 1; 445 static THREAD_LOCAL uint64_t ID = 0; 446 if (ID == 0) { 447 uint64_t new_thread = KMP_TEST_THEN_INC64((kmp_int64 *)&thread); 448 ID = new_thread << (sizeof(uint64_t) * 8 - OMPT_THREAD_ID_BITS); 449 } 450 return ++ID; 451 } 452