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 ompt_team_info_t *info; 223 if (team_size) { 224 info = __ompt_get_teaminfo(ancestor_level, team_size); 225 } else { 226 info = __ompt_get_teaminfo(ancestor_level, NULL); 227 } 228 if (parallel_data) { 229 *parallel_data = info ? &(info->parallel_data) : NULL; 230 } 231 return info ? 2 : 0; 232 } 233 234 //---------------------------------------------------------- 235 // lightweight task team support 236 //---------------------------------------------------------- 237 238 void __ompt_lw_taskteam_init(ompt_lw_taskteam_t *lwt, kmp_info_t *thr, int gtid, 239 ompt_data_t *ompt_pid, void *codeptr) { 240 // initialize parallel_data with input, return address to parallel_data on 241 // exit 242 lwt->ompt_team_info.parallel_data = *ompt_pid; 243 lwt->ompt_team_info.master_return_address = codeptr; 244 lwt->ompt_task_info.task_data.value = 0; 245 lwt->ompt_task_info.frame.enter_frame = NULL; 246 lwt->ompt_task_info.frame.exit_frame = NULL; 247 lwt->ompt_task_info.scheduling_parent = NULL; 248 lwt->ompt_task_info.deps = NULL; 249 lwt->ompt_task_info.ndeps = 0; 250 lwt->heap = 0; 251 lwt->parent = 0; 252 } 253 254 void __ompt_lw_taskteam_link(ompt_lw_taskteam_t *lwt, kmp_info_t *thr, 255 int on_heap) { 256 ompt_lw_taskteam_t *link_lwt = lwt; 257 if (thr->th.th_team->t.t_serialized > 258 1) { // we already have a team, so link the new team and swap values 259 if (on_heap) { // the lw_taskteam cannot stay on stack, allocate it on heap 260 link_lwt = 261 (ompt_lw_taskteam_t *)__kmp_allocate(sizeof(ompt_lw_taskteam_t)); 262 } 263 link_lwt->heap = on_heap; 264 265 // would be swap in the (on_stack) case. 266 ompt_team_info_t tmp_team = lwt->ompt_team_info; 267 link_lwt->ompt_team_info = *OMPT_CUR_TEAM_INFO(thr); 268 *OMPT_CUR_TEAM_INFO(thr) = tmp_team; 269 270 ompt_task_info_t tmp_task = lwt->ompt_task_info; 271 link_lwt->ompt_task_info = *OMPT_CUR_TASK_INFO(thr); 272 *OMPT_CUR_TASK_INFO(thr) = tmp_task; 273 274 // link the taskteam into the list of taskteams: 275 ompt_lw_taskteam_t *my_parent = 276 thr->th.th_team->t.ompt_serialized_team_info; 277 link_lwt->parent = my_parent; 278 thr->th.th_team->t.ompt_serialized_team_info = link_lwt; 279 } else { 280 // this is the first serialized team, so we just store the values in the 281 // team and drop the taskteam-object 282 *OMPT_CUR_TEAM_INFO(thr) = lwt->ompt_team_info; 283 *OMPT_CUR_TASK_INFO(thr) = lwt->ompt_task_info; 284 } 285 } 286 287 void __ompt_lw_taskteam_unlink(kmp_info_t *thr) { 288 ompt_lw_taskteam_t *lwtask = thr->th.th_team->t.ompt_serialized_team_info; 289 if (lwtask) { 290 thr->th.th_team->t.ompt_serialized_team_info = lwtask->parent; 291 292 ompt_team_info_t tmp_team = lwtask->ompt_team_info; 293 lwtask->ompt_team_info = *OMPT_CUR_TEAM_INFO(thr); 294 *OMPT_CUR_TEAM_INFO(thr) = tmp_team; 295 296 ompt_task_info_t tmp_task = lwtask->ompt_task_info; 297 lwtask->ompt_task_info = *OMPT_CUR_TASK_INFO(thr); 298 *OMPT_CUR_TASK_INFO(thr) = tmp_task; 299 300 if (lwtask->heap) { 301 __kmp_free(lwtask); 302 lwtask = NULL; 303 } 304 } 305 // return lwtask; 306 } 307 308 //---------------------------------------------------------- 309 // task support 310 //---------------------------------------------------------- 311 312 int __ompt_get_task_info_internal(int ancestor_level, int *type, 313 ompt_data_t **task_data, 314 ompt_frame_t **task_frame, 315 ompt_data_t **parallel_data, 316 int *thread_num) { 317 if (ancestor_level < 0) 318 return 0; 319 320 // copied from __ompt_get_scheduling_taskinfo 321 ompt_task_info_t *info = NULL; 322 ompt_team_info_t *team_info = NULL; 323 kmp_info_t *thr = ompt_get_thread(); 324 325 if (thr) { 326 kmp_taskdata_t *taskdata = thr->th.th_current_task; 327 if (taskdata == NULL) 328 return 0; 329 kmp_team *team = thr->th.th_team; 330 if (team == NULL) 331 return 0; 332 ompt_lw_taskteam_t *lwt = NULL, 333 *next_lwt = LWT_FROM_TEAM(taskdata->td_team); 334 335 while (ancestor_level > 0) { 336 // next lightweight team (if any) 337 if (lwt) 338 lwt = lwt->parent; 339 340 // next heavyweight team (if any) after 341 // lightweight teams are exhausted 342 if (!lwt && taskdata) { 343 // first try scheduling parent (for explicit task scheduling) 344 if (taskdata->ompt_task_info.scheduling_parent) { 345 taskdata = taskdata->ompt_task_info.scheduling_parent; 346 } else if (next_lwt) { 347 lwt = next_lwt; 348 next_lwt = NULL; 349 } else { 350 // then go for implicit tasks 351 taskdata = taskdata->td_parent; 352 if (team == NULL) 353 return 0; 354 team = team->t.t_parent; 355 if (taskdata) { 356 next_lwt = LWT_FROM_TEAM(taskdata->td_team); 357 } 358 } 359 } 360 ancestor_level--; 361 } 362 363 if (lwt) { 364 info = &lwt->ompt_task_info; 365 team_info = &lwt->ompt_team_info; 366 if (type) { 367 *type = ompt_task_implicit; 368 } 369 } else if (taskdata) { 370 info = &taskdata->ompt_task_info; 371 team_info = &team->t.ompt_team_info; 372 if (type) { 373 if (taskdata->td_parent) { 374 *type = (taskdata->td_flags.tasktype ? ompt_task_explicit 375 : ompt_task_implicit) | 376 TASK_TYPE_DETAILS_FORMAT(taskdata); 377 } else { 378 *type = ompt_task_initial; 379 } 380 } 381 } 382 if (task_data) { 383 *task_data = info ? &info->task_data : NULL; 384 } 385 if (task_frame) { 386 // OpenMP spec asks for the scheduling task to be returned. 387 *task_frame = info ? &info->frame : NULL; 388 } 389 if (parallel_data) { 390 *parallel_data = team_info ? &(team_info->parallel_data) : NULL; 391 } 392 return info ? 2 : 0; 393 } 394 return 0; 395 } 396 397 //---------------------------------------------------------- 398 // team support 399 //---------------------------------------------------------- 400 401 void __ompt_team_assign_id(kmp_team_t *team, ompt_data_t ompt_pid) { 402 team->t.ompt_team_info.parallel_data = ompt_pid; 403 } 404 405 //---------------------------------------------------------- 406 // misc 407 //---------------------------------------------------------- 408 409 static uint64_t __ompt_get_unique_id_internal() { 410 static uint64_t thread = 1; 411 static THREAD_LOCAL uint64_t ID = 0; 412 if (ID == 0) { 413 uint64_t new_thread = KMP_TEST_THEN_INC64((kmp_int64 *)&thread); 414 ID = new_thread << (sizeof(uint64_t) * 8 - OMPT_THREAD_ID_BITS); 415 } 416 return ++ID; 417 } 418