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