1/*
2 * omp-debug.cpp
3 *
4 * Created on: Jan 14, 2015
5 * Author: Ignacio Laguna
6 * Joachim Protze
7 * Contact: ilaguna@llnl.gov
8 * protze@llnl.gov
9 */
10/*******************************************************************************
11 * This implements an OMPD DLL for the LLVM OpenMP runtime library.
12 */
13
14//===----------------------------------------------------------------------===//
15//
16// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
17// See https://llvm.org/LICENSE.txt for license information.
18// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
19//
20//===----------------------------------------------------------------------===//
21
22#define NDEBUG 1
23
24#include "omp-debug.h"
25#include "TargetValue.h"
26#include "omp.h"
27#include "ompd-private.h"
28#include <assert.h>
29#include <cstdio>
30#include <inttypes.h>
31#include <pthread.h>
32#include <stdint.h>
33
34ompd_device_type_sizes_t type_sizes;
35uint64_t ompd_state;
36ompd_rc_t ompd_get_num_threads(
37 ompd_parallel_handle_t *parallel_handle, /* IN: OpenMP parallel handle */
38 ompd_word_t *val /* OUT: number of threads */);
39
40/* --- OMPD functions ------------------------------------------------------- */
41
42/* --- Initialization ------------------------------------------------------- */
43
44ompd_rc_t ompd_initialize(ompd_word_t version, const ompd_callbacks_t *table) {
45 ompd_rc_t ret = ompd_rc_ok;
46 ompd_word_t ompd_version;
47
48 if (!table)
49 return ompd_rc_bad_input;
50
51 ompd_get_api_version(version: &ompd_version);
52 if (version != ompd_version)
53 return ompd_rc_unsupported;
54 callbacks = table;
55 TValue::callbacks = table;
56 __ompd_init_icvs(table);
57 __ompd_init_states(table);
58
59 return ret;
60}
61
62ompd_rc_t ompd_finalize(void) { return ompd_rc_ok; }
63
64ompd_rc_t ompd_process_initialize(
65 ompd_address_space_context_t
66 *context, /* IN: debugger handle for the target */
67 ompd_address_space_handle_t **handle /* OUT: ompd handle for the target */
68) {
69 if (!context)
70 return ompd_rc_bad_input;
71 if (!handle)
72 return ompd_rc_bad_input;
73
74 ompd_rc_t ret = initTypeSizes(context);
75 if (ret != ompd_rc_ok)
76 return ret;
77
78 ret = TValue(context, "ompd_state")
79 .castBase(baseType: ompd_type_long_long)
80 .getValue(buf&: ompd_state);
81 if (ret != ompd_rc_ok)
82 return ret;
83 ret = callbacks->alloc_memory(sizeof(ompd_address_space_handle_t),
84 (void **)(handle));
85 if (ret != ompd_rc_ok)
86 return ret;
87 if (!*handle)
88 return ompd_rc_error;
89
90 (*handle)->context = context;
91 (*handle)->kind = OMPD_DEVICE_KIND_HOST;
92
93 return ompd_rc_ok;
94}
95
96ompd_rc_t
97ompd_get_omp_version(ompd_address_space_handle_t
98 *address_space, /* IN: handle for the address space */
99 ompd_word_t *version) {
100 if (!address_space)
101 return ompd_rc_stale_handle;
102 if (!version)
103 return ompd_rc_bad_input;
104
105 ompd_address_space_context_t *context = address_space->context;
106 ompd_rc_t ret;
107
108 if (!context)
109 return ompd_rc_stale_handle;
110
111 if (!callbacks) {
112 return ompd_rc_callback_error;
113 }
114
115 ret = TValue(context, "__kmp_openmp_version")
116 .castBase(baseType: ompd_type_int)
117 .getValue(buf&: *version);
118 return ret;
119}
120
121ompd_rc_t ompd_get_omp_version_string(
122 ompd_address_space_handle_t
123 *address_space, /* IN: handle for the address space */
124 const char **string) {
125 if (!address_space)
126 return ompd_rc_stale_handle;
127 if (!string)
128 return ompd_rc_bad_input;
129 ompd_address_space_context_t *context = address_space->context;
130 ompd_word_t ver;
131 ompd_rc_t ret;
132 char *omp_version;
133 ret = callbacks->alloc_memory(10, /* max digit can be store on int*/
134 (void **)&omp_version);
135
136 if (ret != ompd_rc_ok)
137 return ret;
138
139 ret = TValue(context, "__kmp_openmp_version")
140 .castBase(baseType: ompd_type_int)
141 .getValue(buf&: ver);
142 if (ret != ompd_rc_ok)
143 return ret;
144
145 sprintf(s: omp_version, format: "%ld", ver);
146 *string = omp_version;
147 return ret;
148}
149
150ompd_rc_t ompd_rel_address_space_handle(
151 ompd_address_space_handle_t
152 *addr_handle /* IN: handle for the address space */
153) {
154 if (!addr_handle)
155 return ompd_rc_stale_handle;
156
157 ompd_rc_t ret = callbacks->free_memory((void *)(addr_handle));
158 // delete addr_handle;
159 return ret;
160}
161
162ompd_rc_t ompd_device_initialize(ompd_address_space_handle_t *process_handle,
163 ompd_address_space_context_t *device_context,
164 ompd_device_t kind, ompd_size_t sizeof_id,
165 void *id,
166 ompd_address_space_handle_t **device_handle) {
167 if (!device_context)
168 return ompd_rc_bad_input;
169
170 return ompd_rc_unavailable;
171}
172
173/* --- Thread Handles ------------------------------------------------------- */
174
175/* thread_handle is of type (kmp_base_info_t) */
176
177ompd_rc_t ompd_get_thread_in_parallel(
178 ompd_parallel_handle_t *parallel_handle, /* IN: OpenMP parallel handle */
179 int thread_num, /* IN: Thread num, handle of which is to be returned */
180 ompd_thread_handle_t **thread_handle /* OUT: handle */
181) {
182 if (!parallel_handle)
183 return ompd_rc_stale_handle;
184 if (!parallel_handle->ah)
185 return ompd_rc_stale_handle;
186 ompd_address_space_context_t *context = parallel_handle->ah->context;
187 ompd_rc_t ret;
188
189 if (!context)
190 return ompd_rc_stale_handle;
191
192 if (!callbacks) {
193 return ompd_rc_callback_error;
194 }
195
196 ompd_word_t team_size_var;
197 ret = ompd_get_num_threads(parallel_handle, val: &team_size_var);
198 if (ret != ompd_rc_ok)
199 return ret;
200 if (thread_num < 0 || thread_num >= team_size_var)
201 return ompd_rc_bad_input;
202
203 ompd_address_t taddr = {OMPD_SEGMENT_UNSPECIFIED, .address: 0};
204
205 ret = TValue(context, parallel_handle->th) /* t */
206 .cast(typeName: "kmp_base_team_t", pointerLevel: 0)
207 .access(fieldName: "t_threads") /*t.t_threads*/
208 .cast(typeName: "kmp_info_t", pointerLevel: 2)
209 .getArrayElement(elemNumber: thread_num) /*t.t_threads[nth_handle]*/
210 .access(fieldName: "th") /*t.t_threads[i]->th*/
211 .getAddress(addr: &taddr);
212
213 if (ret != ompd_rc_ok)
214 return ret;
215
216 ret = callbacks->alloc_memory(sizeof(ompd_thread_handle_t),
217 (void **)(thread_handle));
218 if (ret != ompd_rc_ok)
219 return ret;
220
221 (*thread_handle)->th = taddr;
222 (*thread_handle)->ah = parallel_handle->ah;
223 return ret;
224}
225
226ompd_rc_t ompd_rel_thread_handle(
227 ompd_thread_handle_t
228 *thread_handle /* IN: OpenMP thread handle to be released */
229) {
230 if (!thread_handle)
231 return ompd_rc_stale_handle;
232 ompd_rc_t ret = callbacks->free_memory((void *)(thread_handle));
233 if (ret != ompd_rc_ok)
234 return ret;
235 return ompd_rc_ok;
236}
237
238ompd_rc_t ompd_thread_handle_compare(ompd_thread_handle_t *thread_handle_1,
239 ompd_thread_handle_t *thread_handle_2,
240 int *cmp_value) {
241 if (!thread_handle_1)
242 return ompd_rc_stale_handle;
243 if (!thread_handle_2)
244 return ompd_rc_stale_handle;
245 if (!cmp_value)
246 return ompd_rc_bad_input;
247 if (thread_handle_1->ah->kind != thread_handle_2->ah->kind)
248 return ompd_rc_bad_input;
249 *cmp_value = thread_handle_1->th.address - thread_handle_2->th.address;
250
251 return ompd_rc_ok;
252}
253
254/* --- Parallel Region Handles----------------------------------------------- */
255
256/* parallel_handle is of type (kmp_base_team_t)*/
257
258ompd_rc_t ompd_get_curr_parallel_handle(
259 ompd_thread_handle_t *thread_handle, /* IN: OpenMP thread handle*/
260 ompd_parallel_handle_t **parallel_handle /* OUT: OpenMP parallel handle */
261) {
262 if (!thread_handle)
263 return ompd_rc_stale_handle;
264 if (!thread_handle->ah)
265 return ompd_rc_stale_handle;
266 ompd_address_space_context_t *context = thread_handle->ah->context;
267 ompd_thread_context_t *thread_context = thread_handle->thread_context;
268 if (!context || !thread_context)
269 return ompd_rc_stale_handle;
270
271 if (!callbacks) {
272 return ompd_rc_callback_error;
273 }
274
275 ompd_rc_t ret;
276
277 ompd_address_t taddr = {OMPD_SEGMENT_UNSPECIFIED, .address: 0},
278 lwt = {OMPD_SEGMENT_UNSPECIFIED, .address: 0};
279
280 TValue teamdata = TValue(context, thread_handle->th) /*__kmp_threads[t]->th*/
281 .cast(typeName: "kmp_base_info_t")
282 .access(fieldName: "th_team") /*__kmp_threads[t]->th.th_team*/
283 .cast(typeName: "kmp_team_p", pointerLevel: 1)
284 .access(fieldName: "t"); /*__kmp_threads[t]->th.th_team->t*/
285
286 ret = teamdata.getAddress(addr: &taddr);
287 if (ret != ompd_rc_ok)
288 return ret;
289
290 lwt.segment = OMPD_SEGMENT_UNSPECIFIED;
291 ret = teamdata.cast(typeName: "kmp_base_team_t", pointerLevel: 0)
292 .access(fieldName: "ompt_serialized_team_info")
293 .castBase()
294 .getValue(buf&: lwt.address);
295 if (ret != ompd_rc_ok)
296 return ret;
297
298 ret = callbacks->alloc_memory(sizeof(ompd_parallel_handle_t),
299 (void **)(parallel_handle));
300 if (ret != ompd_rc_ok)
301 return ret;
302
303 (*parallel_handle)->ah = thread_handle->ah;
304 (*parallel_handle)->th = taddr;
305 (*parallel_handle)->lwt = lwt;
306 return ompd_rc_ok;
307}
308
309ompd_rc_t ompd_get_enclosing_parallel_handle(
310 ompd_parallel_handle_t *parallel_handle, /* IN: OpenMP parallel handle */
311 ompd_parallel_handle_t *
312 *enclosing_parallel_handle /* OUT: OpenMP parallel handle */
313) {
314 if (!parallel_handle)
315 return ompd_rc_stale_handle;
316 if (!parallel_handle->ah)
317 return ompd_rc_stale_handle;
318 ompd_address_space_context_t *context = parallel_handle->ah->context;
319
320 if (!context)
321 return ompd_rc_stale_handle;
322
323 if (!callbacks) {
324 return ompd_rc_callback_error;
325 }
326
327 ompd_address_t taddr = parallel_handle->th,
328 lwt = {OMPD_SEGMENT_UNSPECIFIED, .address: 0};
329 ompd_rc_t ret;
330
331 ret = ompd_rc_stale_handle;
332 TValue lwtValue = TValue(context, parallel_handle->lwt);
333 if (lwtValue.getError() == ompd_rc_ok) // lwt == 0x0
334 { // if we are in lwt, get parent
335 ret = lwtValue.cast(typeName: "ompt_lw_taskteam_t", pointerLevel: 0)
336 .access(fieldName: "parent")
337 .cast(typeName: "ompt_lw_taskteam_t", pointerLevel: 1)
338 .dereference()
339 .getAddress(addr: &lwt);
340 }
341 if (ret != ompd_rc_ok) { // no lwt or parent==0x0
342
343 TValue teamdata =
344 TValue(context, parallel_handle->th) /*__kmp_threads[t]->th*/
345 .cast(typeName: "kmp_base_team_t", pointerLevel: 0) /*t*/
346 .access(fieldName: "t_parent") /*t.t_parent*/
347 .cast(typeName: "kmp_team_p", pointerLevel: 1)
348 .access(fieldName: "t"); /*t.t_parent->t*/
349
350 ret = teamdata.getAddress(addr: &taddr);
351 if (ret != ompd_rc_ok)
352 return ret;
353
354 lwt.segment = OMPD_SEGMENT_UNSPECIFIED;
355 ret = teamdata.cast(typeName: "kmp_base_team_t", pointerLevel: 0)
356 .access(fieldName: "ompt_serialized_team_info")
357 .castBase()
358 .getValue(buf&: lwt.address);
359 if (ret != ompd_rc_ok)
360 return ret;
361 }
362
363 ret = callbacks->alloc_memory(sizeof(ompd_parallel_handle_t),
364 (void **)(enclosing_parallel_handle));
365 if (ret != ompd_rc_ok)
366 return ret;
367 (*enclosing_parallel_handle)->th = taddr;
368 (*enclosing_parallel_handle)->lwt = lwt;
369 (*enclosing_parallel_handle)->ah = parallel_handle->ah;
370 return ompd_rc_ok;
371}
372
373ompd_rc_t ompd_get_task_parallel_handle(
374 ompd_task_handle_t *task_handle, /* IN: OpenMP task handle */
375 ompd_parallel_handle_t *
376 *task_parallel_handle /* OUT: OpenMP parallel handle */
377) {
378 if (!task_handle)
379 return ompd_rc_stale_handle;
380 if (!task_handle->ah)
381 return ompd_rc_stale_handle;
382 ompd_address_space_context_t *context = task_handle->ah->context;
383
384 if (!context)
385 return ompd_rc_stale_handle;
386
387 if (!callbacks) {
388 return ompd_rc_callback_error;
389 }
390
391 ompd_address_t taddr = {OMPD_SEGMENT_UNSPECIFIED, .address: 0};
392
393 ompd_rc_t ret;
394
395 ret = TValue(context, task_handle->th)
396 .cast(typeName: "kmp_taskdata_t") /*td*/
397 .access(fieldName: "td_team") /*td.td_team*/
398 .cast(typeName: "kmp_team_p", pointerLevel: 1)
399 .access(fieldName: "t") /*td.td_team->t*/
400 .getAddress(addr: &taddr);
401
402 if (ret != ompd_rc_ok)
403 return ret;
404
405 ret = callbacks->alloc_memory(sizeof(ompd_parallel_handle_t),
406 (void **)(task_parallel_handle));
407 if (ret != ompd_rc_ok)
408 return ret;
409
410 (*task_parallel_handle)->ah = task_handle->ah;
411 (*task_parallel_handle)->lwt = task_handle->lwt;
412 (*task_parallel_handle)->th = taddr;
413 return ompd_rc_ok;
414}
415
416ompd_rc_t ompd_rel_parallel_handle(
417 ompd_parallel_handle_t *parallel_handle /* IN: OpenMP parallel handle */
418) {
419 if (!parallel_handle)
420 return ompd_rc_stale_handle;
421 ompd_rc_t ret = callbacks->free_memory((void *)(parallel_handle));
422 if (ret != ompd_rc_ok)
423 return ret;
424 return ompd_rc_ok;
425}
426
427ompd_rc_t
428ompd_parallel_handle_compare(ompd_parallel_handle_t *parallel_handle_1,
429 ompd_parallel_handle_t *parallel_handle_2,
430 int *cmp_value) {
431 if (!parallel_handle_1)
432 return ompd_rc_stale_handle;
433 if (!parallel_handle_2)
434 return ompd_rc_stale_handle;
435 if (!cmp_value)
436 return ompd_rc_bad_input;
437 if (parallel_handle_1->ah->kind != parallel_handle_2->ah->kind)
438 return ompd_rc_bad_input;
439 if (parallel_handle_1->ah->kind == OMPD_DEVICE_KIND_HOST) {
440 if (parallel_handle_1->th.address - parallel_handle_2->th.address)
441 *cmp_value =
442 parallel_handle_1->th.address - parallel_handle_2->th.address;
443 else
444 *cmp_value =
445 parallel_handle_1->lwt.address - parallel_handle_2->lwt.address;
446 } else {
447 *cmp_value = parallel_handle_1->th.address - parallel_handle_2->th.address;
448 }
449 return ompd_rc_ok;
450}
451
452/* ------- Task Handles ----------------------------------------------------- */
453
454/* task_handle is of type (kmp_taskdata_t) */
455
456ompd_rc_t ompd_get_curr_task_handle(
457 ompd_thread_handle_t *thread_handle, /* IN: OpenMP thread handle*/
458 ompd_task_handle_t **task_handle /* OUT: OpenMP task handle */
459) {
460 if (!thread_handle)
461 return ompd_rc_stale_handle;
462 if (!thread_handle->ah)
463 return ompd_rc_stale_handle;
464 ompd_address_space_context_t *context = thread_handle->ah->context;
465 if (!context)
466 return ompd_rc_stale_handle;
467
468 if (!callbacks) {
469 return ompd_rc_callback_error;
470 }
471
472 ompd_address_t taddr = {OMPD_SEGMENT_UNSPECIFIED, .address: 0},
473 lwt = {OMPD_SEGMENT_UNSPECIFIED, .address: 0};
474 ompd_rc_t ret = ompd_rc_ok;
475
476 lwt.segment = OMPD_SEGMENT_UNSPECIFIED;
477
478 TValue taskdata =
479 TValue(context, thread_handle->th) /*__kmp_threads[t]->th*/
480 .cast(typeName: "kmp_base_info_t")
481 .access(fieldName: "th_current_task") /*__kmp_threads[t]->th.th_current_task*/
482 .cast(typeName: "kmp_taskdata_t", pointerLevel: 1);
483
484 ret = taskdata.dereference().getAddress(addr: &taddr);
485 if (ret != ompd_rc_ok)
486 return ret;
487
488 ret = taskdata
489 .access(fieldName: "td_team") /*td.td_team*/
490 .cast(typeName: "kmp_team_p", pointerLevel: 1)
491 .access(fieldName: "t") /*td.td_team->t*/
492 .cast(typeName: "kmp_base_team_t", pointerLevel: 0)
493 .access(fieldName: "ompt_serialized_team_info")
494 .castBase()
495 .getValue(buf&: lwt.address);
496
497 if (ret != ompd_rc_ok)
498 return ret;
499
500 ret = callbacks->alloc_memory(sizeof(ompd_task_handle_t),
501 (void **)(task_handle));
502 if (ret != ompd_rc_ok)
503 return ret;
504
505 (*task_handle)->th = taddr;
506 (*task_handle)->lwt = lwt;
507 (*task_handle)->ah = thread_handle->ah;
508 return ompd_rc_ok;
509}
510
511ompd_rc_t ompd_get_generating_task_handle(
512 ompd_task_handle_t *task_handle, /* IN: OpenMP task handle */
513 ompd_task_handle_t **parent_task_handle /* OUT: OpenMP task handle */
514) {
515 if (!task_handle)
516 return ompd_rc_stale_handle;
517 if (!task_handle->ah)
518 return ompd_rc_stale_handle;
519
520 ompd_address_space_context_t *context = task_handle->ah->context;
521 if (!context)
522 return ompd_rc_stale_handle;
523 if (!callbacks) {
524 return ompd_rc_callback_error;
525 }
526
527 ompd_address_t taddr = task_handle->th, lwt = {OMPD_SEGMENT_UNSPECIFIED, .address: 0};
528
529 ompd_rc_t ret = ompd_rc_stale_handle;
530 TValue lwtValue = TValue(context, task_handle->lwt);
531 if (lwtValue.getError() == ompd_rc_ok) // lwt == 0x0
532 { // if we are in lwt, get parent
533 ret = lwtValue.cast(typeName: "ompt_lw_taskteam_t", pointerLevel: 0)
534 .access(fieldName: "parent")
535 .cast(typeName: "ompt_lw_taskteam_t", pointerLevel: 1)
536 .dereference()
537 .getAddress(addr: &lwt);
538 }
539 if (ret != ompd_rc_ok) { // no lwt or parent==0x0
540
541 TValue taskdata = TValue(context, task_handle->th) /*__kmp_threads[t]->th*/
542 .cast(typeName: "kmp_taskdata_t") /*td*/
543 .access(fieldName: "td_parent") /*td->td_parent*/
544 .cast(typeName: "kmp_taskdata_t", pointerLevel: 1);
545
546 ret = taskdata.dereference().getAddress(addr: &taddr);
547 if (ret != ompd_rc_ok)
548 return ret;
549
550 lwt.segment = OMPD_SEGMENT_UNSPECIFIED;
551 ret = taskdata
552 .access(fieldName: "td_team") /*td.td_team*/
553 .cast(typeName: "kmp_team_p", pointerLevel: 1)
554 .access(fieldName: "t") /*td.td_team->t*/
555 .cast(typeName: "kmp_base_team_t", pointerLevel: 0)
556 .access(fieldName: "ompt_serialized_team_info")
557 .castBase()
558 .getValue(buf&: lwt.address);
559 if (ret != ompd_rc_ok)
560 return ret;
561 }
562
563 ret = callbacks->alloc_memory(sizeof(ompd_task_handle_t),
564 (void **)(parent_task_handle));
565 if (ret != ompd_rc_ok)
566 return ret;
567
568 (*parent_task_handle)->th = taddr;
569 (*parent_task_handle)->lwt = lwt;
570 (*parent_task_handle)->ah = task_handle->ah;
571 return ret;
572}
573
574ompd_rc_t ompd_get_scheduling_task_handle(
575 ompd_task_handle_t *task_handle, /* IN: OpenMP task handle */
576 ompd_task_handle_t **parent_task_handle /* OUT: OpenMP task handle */
577) {
578 if (!task_handle)
579 return ompd_rc_stale_handle;
580 if (!task_handle->ah)
581 return ompd_rc_stale_handle;
582 ompd_address_space_context_t *context = task_handle->ah->context;
583 if (!context)
584 return ompd_rc_stale_handle;
585
586 if (!callbacks) {
587 return ompd_rc_callback_error;
588 }
589
590 ompd_address_t taddr = {OMPD_SEGMENT_UNSPECIFIED, .address: 0};
591 ompd_rc_t ret;
592
593 ret = TValue(context, task_handle->th)
594 .cast(typeName: "kmp_taskdata_t") /*td*/
595 .access(fieldName: "ompt_task_info") // td->ompt_task_info
596 .cast(typeName: "ompt_task_info_t")
597 .access(fieldName: "scheduling_parent") // td->ompd_task_info.scheduling_parent
598 .cast(typeName: "kmp_taskdata_t", pointerLevel: 1)
599 .castBase()
600 .getValue(buf&: taddr.address);
601 if (taddr.address == 0) {
602 return ompd_rc_unavailable;
603 }
604
605 if (ret != ompd_rc_ok)
606 return ret;
607 ret = callbacks->alloc_memory(sizeof(ompd_task_handle_t),
608 (void **)(parent_task_handle));
609 if (ret != ompd_rc_ok)
610 return ret;
611
612 (*parent_task_handle)->th = taddr;
613 (*parent_task_handle)->lwt = {OMPD_SEGMENT_UNSPECIFIED, .address: 0};
614 (*parent_task_handle)->ah = task_handle->ah;
615 return ret;
616}
617
618ompd_rc_t ompd_get_task_in_parallel(
619 ompd_parallel_handle_t *parallel_handle, /* IN: OpenMP parallel handle */
620 int thread_num, /* IN: thread num of implicit task of team */
621 ompd_task_handle_t **task_handle /* OUT: OpenMP task handle */
622) {
623 if (!parallel_handle)
624 return ompd_rc_stale_handle;
625 if (!parallel_handle->ah)
626 return ompd_rc_stale_handle;
627 ompd_address_space_context_t *context = parallel_handle->ah->context;
628 if (!context)
629 return ompd_rc_stale_handle;
630
631 if (!callbacks) {
632 return ompd_rc_callback_error;
633 }
634
635 ompd_rc_t ret;
636 ompd_word_t team_size_var;
637 ret = ompd_get_num_threads(parallel_handle, val: &team_size_var);
638 if (ret != ompd_rc_ok)
639 return ret;
640 if (thread_num < 0 || thread_num >= team_size_var)
641 return ompd_rc_bad_input;
642
643 ompd_address_t taddr = {OMPD_SEGMENT_UNSPECIFIED, .address: 0};
644
645 ret = TValue(context, parallel_handle->th) /* t */
646 .cast(typeName: "kmp_base_team_t", pointerLevel: 0)
647 .access(fieldName: "t_implicit_task_taskdata") /*t.t_implicit_task_taskdata*/
648 .cast(typeName: "kmp_taskdata_t", pointerLevel: 1)
649 .getArrayElement(
650 elemNumber: thread_num) /*t.t_implicit_task_taskdata[nth_handle]*/
651 .getAddress(addr: &taddr);
652
653 if (ret != ompd_rc_ok)
654 return ret;
655 ret = callbacks->alloc_memory(sizeof(ompd_task_handle_t),
656 (void **)(task_handle));
657 if (ret != ompd_rc_ok)
658 return ret;
659
660 (*task_handle)->th = taddr;
661 (*task_handle)->ah = parallel_handle->ah;
662 (*task_handle)->lwt = {OMPD_SEGMENT_UNSPECIFIED, .address: 0};
663 return ret;
664}
665
666ompd_rc_t ompd_rel_task_handle(
667 ompd_task_handle_t *task_handle /* IN: OpenMP task handle */
668) {
669 if (!task_handle)
670 return ompd_rc_stale_handle;
671 ompd_rc_t ret = callbacks->free_memory((void *)(task_handle));
672 if (ret != ompd_rc_ok)
673 return ret;
674 return ompd_rc_ok;
675}
676
677ompd_rc_t ompd_task_handle_compare(ompd_task_handle_t *task_handle_1,
678 ompd_task_handle_t *task_handle_2,
679 int *cmp_value) {
680 if (!task_handle_1)
681 return ompd_rc_stale_handle;
682 if (!task_handle_2)
683 return ompd_rc_stale_handle;
684 if (!cmp_value)
685 return ompd_rc_bad_input;
686 if (task_handle_1->ah->kind != task_handle_2->ah->kind)
687 return ompd_rc_bad_input;
688 if (task_handle_1->th.address - task_handle_2->th.address)
689 *cmp_value = task_handle_1->th.address - task_handle_2->th.address;
690 else
691 *cmp_value = task_handle_1->lwt.address - task_handle_2->lwt.address;
692 return ompd_rc_ok;
693}
694
695ompd_rc_t ompd_get_thread_handle(
696 ompd_address_space_handle_t *handle, /* IN: handle for the address space */
697 ompd_thread_id_t kind, ompd_size_t sizeof_thread_id, const void *thread_id,
698 ompd_thread_handle_t **thread_handle) {
699 if (!handle)
700 return ompd_rc_stale_handle;
701 ompd_address_space_context_t *context = handle->context;
702 ompd_rc_t ret;
703
704 if (!context)
705 return ompd_rc_stale_handle;
706
707 if (!callbacks) {
708 return ompd_rc_callback_error;
709 }
710 ompd_thread_context_t *tcontext;
711 ret = callbacks->get_thread_context_for_thread_id(
712 context, kind, sizeof_thread_id, thread_id, &tcontext);
713 if (ret != ompd_rc_ok)
714 return ret;
715
716 int tId;
717
718 ret = TValue(context, tcontext, "__kmp_gtid")
719 .castBase(varName: "__kmp_gtid")
720 .getValue(buf&: tId);
721 if (ret != ompd_rc_ok)
722 return ret;
723
724 if (tId < 0) // thread is no omp worker
725 return ompd_rc_unavailable;
726
727 TValue th = TValue(context, "__kmp_threads") // __kmp_threads
728 .cast(typeName: "kmp_info_t", pointerLevel: 2)
729 .getArrayElement(elemNumber: tId) /*__kmp_threads[t]*/
730 .access(fieldName: "th"); /*__kmp_threads[t]->th*/
731
732 ompd_address_t taddr = {OMPD_SEGMENT_UNSPECIFIED, .address: 0};
733 ret = th.getAddress(addr: &taddr);
734 if (ret != ompd_rc_ok)
735 return ret;
736 ret = callbacks->alloc_memory(sizeof(ompd_thread_handle_t),
737 (void **)(thread_handle));
738 if (ret != ompd_rc_ok)
739 return ret;
740 (*thread_handle)->ah = handle;
741 (*thread_handle)->th = taddr;
742
743#ifndef NDEBUG
744 if (ret != ompd_rc_ok)
745 return ret;
746
747 pthread_t oshandle;
748 TBaseValue ds_handle =
749 th.cast("kmp_base_info_t")
750 .access("th_info") /*__kmp_threads[t]->th.th_info*/
751 .cast("kmp_desc_t")
752 .access("ds") /*__kmp_threads[t]->th.th_info.ds*/
753 .cast("kmp_desc_base_t")
754 .access("ds_thread") /*__kmp_threads[t]->th.th_info.ds.ds_thread*/
755 .castBase();
756
757 assert(ompd_rc_ok == ds_handle.getValue(oshandle) &&
758 oshandle == *(pthread_t *)(thread_id) &&
759 "Callback table not initialized!");
760#endif
761
762 (*thread_handle)->thread_context = tcontext;
763 return ret;
764}
765
766ompd_rc_t ompd_get_thread_id(
767 ompd_thread_handle_t *thread_handle, /* IN: OpenMP thread handle*/
768 ompd_thread_id_t kind, ompd_size_t sizeof_thread_id, void *thread_id) {
769 if (kind != OMPD_THREAD_ID_PTHREAD)
770 return ompd_rc_unsupported;
771 if (!thread_id)
772 return ompd_rc_bad_input;
773 if (!thread_handle)
774 return ompd_rc_stale_handle;
775 if (!thread_handle->ah)
776 return ompd_rc_stale_handle;
777 ompd_address_space_context_t *context = thread_handle->ah->context;
778 if (!context)
779 return ompd_rc_stale_handle;
780 ompd_rc_t ret;
781
782 ompd_size_t size;
783 ret = tf.getType(context, typName: "kmp_thread_t").getSize(size: &size);
784 if (ret != ompd_rc_ok)
785 return ret;
786 if (sizeof_thread_id != size)
787 return ompd_rc_bad_input;
788
789 if (!callbacks) {
790 return ompd_rc_callback_error;
791 }
792
793 ret = TValue(context, thread_handle->th) /*__kmp_threads[t]->th*/
794 .cast(typeName: "kmp_base_info_t")
795 .access(fieldName: "th_info") /*__kmp_threads[t]->th.th_info*/
796 .cast(typeName: "kmp_desc_t")
797 .access(fieldName: "ds") /*__kmp_threads[t]->th.th_info.ds*/
798 .cast(typeName: "kmp_desc_base_t")
799 .access(fieldName: "ds_thread") /*__kmp_threads[t]->th.th_info.ds.ds_thread*/
800 .cast(typeName: "kmp_thread_t")
801 .getRawValue(buf: thread_id, count: 1);
802
803 return ret;
804}
805
806/* --- OMPT Thread State Inquiry Analogue ----------------------------------- */
807
808ompd_rc_t ompd_get_state(
809 ompd_thread_handle_t *thread_handle, /* IN: OpenMP thread handle*/
810 ompd_word_t *state, /* OUT: State of this thread */
811 ompd_wait_id_t *wait_id /* OUT: Wait ID */
812) {
813 if (!thread_handle)
814 return ompd_rc_stale_handle;
815 if (!thread_handle->ah)
816 return ompd_rc_stale_handle;
817 if (!state)
818 return ompd_rc_bad_input;
819 ompd_address_space_context_t *context = thread_handle->ah->context;
820 if (!context)
821 return ompd_rc_stale_handle;
822 if (!ompd_state)
823 return ompd_rc_needs_state_tracking;
824
825 if (!callbacks) {
826 return ompd_rc_callback_error;
827 }
828 ompd_rc_t ret;
829
830 TValue ompt_thread_info =
831 TValue(context, thread_handle->th) /*__kmp_threads[t]->th*/
832 .cast(typeName: "kmp_base_info_t")
833 .access(fieldName: "ompt_thread_info") /*__kmp_threads[t]->th.ompt_thread_info*/
834 .cast(typeName: "ompt_thread_info_t");
835 if (ompt_thread_info.gotError())
836 return ompt_thread_info.getError();
837 ret = ompt_thread_info
838 .access(fieldName: "state") /*__kmp_threads[t]->th.ompt_thread_info.state*/
839 .castBase()
840 .getValue(buf&: *state);
841 if (ret != ompd_rc_ok)
842 return ret;
843 if (wait_id)
844 ret = ompt_thread_info
845 .access(fieldName: "wait_id") /*__kmp_threads[t]->th.ompt_thread_info.state*/
846 .castBase()
847 .getValue(buf&: *wait_id);
848
849 return ret;
850}
851
852/* --- Task Inquiry -------------------------------------------------------- */
853
854/* --- Task Settings ------------------------------------------------------- */
855
856/* --- OMPT Task Inquiry Analogues ----------------------------------------- */
857
858ompd_rc_t
859ompd_get_task_frame(ompd_task_handle_t *task_handle, /* IN: OpenMP task handle*/
860 ompd_frame_info_t *exit_frame,
861 ompd_frame_info_t *enter_frame) {
862 if (!task_handle)
863 return ompd_rc_stale_handle;
864 if (!task_handle->ah)
865 return ompd_rc_stale_handle;
866 if (!exit_frame || !enter_frame)
867 return ompd_rc_bad_input;
868 ompd_address_space_context_t *context = task_handle->ah->context;
869 if (!context)
870 return ompd_rc_stale_handle;
871 if (!ompd_state)
872 return ompd_rc_needs_state_tracking;
873
874 if (!callbacks) {
875 return ompd_rc_callback_error;
876 }
877
878 ompd_rc_t ret;
879
880 TValue taskInfo;
881 if (task_handle->lwt.address != 0)
882 taskInfo =
883 TValue(context, task_handle->lwt).cast(typeName: "ompt_lw_taskteam_t", pointerLevel: 0); /*lwt*/
884 else
885 taskInfo = TValue(context, task_handle->th).cast(typeName: "kmp_taskdata_t", pointerLevel: 0); /*t*/
886 TValue frame = taskInfo
887 .access(fieldName: "ompt_task_info") // td->ompt_task_info
888 .cast(typeName: "ompt_task_info_t")
889 .access(fieldName: "frame") // td->ompd_task_info.frame
890 .cast(typeName: "ompt_frame_t", pointerLevel: 0);
891 enter_frame->frame_address.segment = OMPD_SEGMENT_UNSPECIFIED;
892 ret = frame
893 .access(fieldName: "enter_frame") // td->ompt_task_info.frame.enter_frame
894 .castBase()
895 .getValue(buf&: enter_frame->frame_address.address);
896
897 if (ret != ompd_rc_ok)
898 return ret;
899
900 exit_frame->frame_address.segment = OMPD_SEGMENT_UNSPECIFIED;
901 ret = frame
902 .access(fieldName: "exit_frame") // td->ompt_task_info.frame.exit_frame
903 .castBase()
904 .getValue(buf&: exit_frame->frame_address.address);
905
906 return ret;
907}
908
909ompd_rc_t ompd_get_task_function(
910 ompd_task_handle_t *task_handle, /* IN: OpenMP task handle */
911 ompd_address_t *task_addr /* OUT: first instruction in the task region */
912) {
913 if (!task_handle)
914 return ompd_rc_stale_handle;
915 if (!task_handle->ah)
916 return ompd_rc_stale_handle;
917 if (!task_addr)
918 return ompd_rc_bad_input;
919 ompd_address_space_context_t *context = task_handle->ah->context;
920 if (!context)
921 return ompd_rc_stale_handle;
922 if (!ompd_state)
923 return ompd_rc_needs_state_tracking;
924 if (!callbacks) {
925 return ompd_rc_callback_error;
926 }
927
928 ompd_rc_t ret;
929
930 task_addr->segment = OMPD_SEGMENT_UNSPECIFIED;
931 TValue taskInfo;
932 if (task_handle->lwt.address != 0)
933 return ompd_rc_bad_input; // We need to decide what we do here.
934 else {
935 ompd_word_t val;
936 ret = TValue(context, task_handle->th)
937 .cast(typeName: "kmp_taskdata_t") // td
938 .access(fieldName: "td_flags") // td->td_flags
939 .cast(typeName: "kmp_tasking_flags_t")
940 .check(bitfieldName: "tasktype", isSet: &val); // td->td_flags.tasktype
941
942 if (ret != ompd_rc_ok)
943 return ret;
944
945 if (val == 1) { // tasktype: explicit = 1, implicit = 0
946
947 ret = TValue(context, task_handle->th)
948 .cast(typeName: "kmp_taskdata_t", pointerLevel: 0) /*t*/
949 .getArrayElement(
950 elemNumber: 1) /* see kmp.h: #define KMP_TASKDATA_TO_TASK(taskdata)
951 (kmp_task_t *)(taskdata + 1) */
952 .cast(typeName: "kmp_task_t", pointerLevel: 0) /* (kmp_task_t *) */
953 .access(fieldName: "routine") /*td->ompt_task_info*/
954 .castBase()
955 .getValue(buf&: task_addr->address);
956
957 } else {
958
959 ret = TValue(context, task_handle->th)
960 .cast(typeName: "kmp_taskdata_t") /*td*/
961 .access(fieldName: "td_team") /*td.td_team*/
962 .cast(typeName: "kmp_team_p", pointerLevel: 1)
963 .access(fieldName: "t") /*td.td_team->t*/
964 .cast(typeName: "kmp_base_team_t", pointerLevel: 0)
965 .access(fieldName: "t_pkfn") /*td.td_team->t.t_pkfn*/
966 .castBase()
967 .getValue(buf&: task_addr->address);
968 }
969 }
970
971 return ret;
972}
973
974/* ------- OMPD Version and Compatibility Information ----------------------- */
975
976ompd_rc_t ompd_get_api_version(ompd_word_t *version) {
977 if (!version)
978 return ompd_rc_bad_input;
979
980 *version = OMPD_VERSION;
981 return ompd_rc_ok;
982}
983
984ompd_rc_t
985ompd_get_version_string(const char **string /* OUT: OMPD version string */
986) {
987 if (!string)
988 return ompd_rc_bad_input;
989
990 static const char version_string[] =
991 "LLVM OpenMP " STR(OMPD_IMPLEMENTS_OPENMP) "." STR(
992 OMPD_IMPLEMENTS_OPENMP_SUBVERSION) " Debugging Library implmenting "
993 "TR " STR(OMPD_TR_VERSION) "" STR(
994 OMPD_TR_SUBVERSION);
995 *string = version_string;
996 return ompd_rc_ok;
997}
998
999/* ------ Display Control Variables ----------------------------------------- */
1000
1001ompd_rc_t ompd_get_display_control_vars(ompd_address_space_handle_t *handle,
1002 const char *const **control_vars) {
1003 if (!handle)
1004 return ompd_rc_stale_handle;
1005 if (!control_vars)
1006 return ompd_rc_bad_input;
1007
1008 ompd_address_space_context_t *context = handle->context;
1009 if (!context)
1010 return ompd_rc_stale_handle;
1011
1012 // runtime keeps a full dump of OMP/KMP definitions in this format
1013 // <var1 name>=<var1 value>\n<var2 name>=<var2 value>\n...
1014 ompd_address_t block_addr = {ompd_segment_none, .address: 0};
1015 OMPD_GET_VALUE(context, NULL, "ompd_env_block", type_sizes.sizeof_pointer,
1016 &block_addr.address);
1017
1018 // query size of the block
1019 ompd_size_t block_size;
1020 OMPD_GET_VALUE(context, NULL, "ompd_env_block_size", sizeof(ompd_size_t),
1021 &block_size);
1022
1023 // copy raw data from the address space
1024 char *block;
1025 OMPD_CALLBACK(alloc_memory, block_size, (void **)&block);
1026 OMPD_CALLBACK(read_memory, context, NULL, &block_addr, block_size, block);
1027
1028 // count number of items, replace new line to zero.
1029 int block_items = 1; // also count the last "NULL" item
1030 for (ompd_size_t i = 0; i < block_size; i++) {
1031 if (block[i] == '\n') {
1032 block_items++;
1033 block[i] = '\0';
1034 }
1035 }
1036
1037 // create vector of char*
1038 const char **ctl_vars;
1039 OMPD_CALLBACK(alloc_memory, block_items * sizeof(char *),
1040 (void **)(&ctl_vars));
1041 char *pos = block;
1042 ctl_vars[0] = block;
1043
1044 // ctl_vars[0] points to the entire block, ctl_vars[1]... points to the
1045 // smaller subsets of the block, and ctl_vars[block_items-2] points to the
1046 // last string in the block.
1047 for (int i = 1; i < block_items - 1; i++) {
1048 while (*pos++ != '\0')
1049 ;
1050 if (pos > block + block_size)
1051 return ompd_rc_error;
1052 ctl_vars[i] = pos;
1053 }
1054 // last item must be NULL
1055 ctl_vars[block_items - 1] = NULL;
1056
1057 *control_vars = ctl_vars;
1058
1059 return ompd_rc_ok;
1060}
1061
1062ompd_rc_t ompd_rel_display_control_vars(const char *const **control_vars) {
1063 if (!control_vars)
1064 return ompd_rc_bad_input;
1065
1066 char **ctl_vars = const_cast<char **>(*control_vars);
1067
1068 // remove the raw block first
1069 OMPD_CALLBACK(free_memory, (void *)ctl_vars[0]);
1070 // remove the vector
1071 OMPD_CALLBACK(free_memory, (void *)ctl_vars);
1072
1073 return ompd_rc_ok;
1074}
1075
1076/* --- Helper functions ----------------------------------------------------- */
1077
1078ompd_rc_t initTypeSizes(ompd_address_space_context_t *context) {
1079 static int inited = 0;
1080 static ompd_rc_t ret;
1081 if (inited)
1082 return ret;
1083 ret = callbacks->sizeof_type(context, &type_sizes);
1084 if (ret != ompd_rc_ok)
1085 return ret;
1086 if (!(type_sizes.sizeof_pointer > 0))
1087 return ompd_rc_error;
1088 ret = callbacks->sizeof_type(context, &TValue::type_sizes);
1089 if (ret != ompd_rc_ok)
1090 return ret;
1091 inited = 1;
1092 return ret;
1093}
1094

source code of openmp/libompd/src/omp-debug.cpp