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