ompt-specific.cpp 15 KB

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