xref: /llvm-project/openmp/libompd/src/omp-debug.cpp (revision 62fddd5ff5cdd5d66a58a01c46dc58c8ca9cd62e)
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 
34 ompd_device_type_sizes_t type_sizes;
35 uint64_t ompd_state;
36 ompd_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 
ompd_initialize(ompd_word_t version,const ompd_callbacks_t * table)44 ompd_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(&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 
ompd_finalize(void)62 ompd_rc_t ompd_finalize(void) { return ompd_rc_ok; }
63 
ompd_process_initialize(ompd_address_space_context_t * context,ompd_address_space_handle_t ** handle)64 ompd_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(ompd_type_long_long)
80             .getValue(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 
96 ompd_rc_t
ompd_get_omp_version(ompd_address_space_handle_t * address_space,ompd_word_t * version)97 ompd_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(ompd_type_int)
117             .getValue(*version);
118   return ret;
119 }
120 
ompd_get_omp_version_string(ompd_address_space_handle_t * address_space,const char ** string)121 ompd_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(ompd_type_int)
141             .getValue(ver);
142   if (ret != ompd_rc_ok)
143     return ret;
144 
145   sprintf(omp_version, "%ld", ver);
146   *string = omp_version;
147   return ret;
148 }
149 
ompd_rel_address_space_handle(ompd_address_space_handle_t * addr_handle)150 ompd_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 
ompd_device_initialize(ompd_address_space_handle_t * process_handle,ompd_address_space_context_t * device_context,ompd_device_t kind,ompd_size_t sizeof_id,void * id,ompd_address_space_handle_t ** device_handle)162 ompd_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 
ompd_get_thread_in_parallel(ompd_parallel_handle_t * parallel_handle,int thread_num,ompd_thread_handle_t ** thread_handle)177 ompd_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, &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, 0};
204 
205   ret = TValue(context, parallel_handle->th) /* t */
206             .cast("kmp_base_team_t", 0)
207             .access("t_threads") /*t.t_threads*/
208             .cast("kmp_info_t", 2)
209             .getArrayElement(thread_num) /*t.t_threads[nth_handle]*/
210             .access("th")                /*t.t_threads[i]->th*/
211             .getAddress(&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 
ompd_rel_thread_handle(ompd_thread_handle_t * thread_handle)226 ompd_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 
ompd_thread_handle_compare(ompd_thread_handle_t * thread_handle_1,ompd_thread_handle_t * thread_handle_2,int * cmp_value)238 ompd_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 
ompd_get_curr_parallel_handle(ompd_thread_handle_t * thread_handle,ompd_parallel_handle_t ** parallel_handle)258 ompd_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, 0},
278                  lwt = {OMPD_SEGMENT_UNSPECIFIED, 0};
279 
280   TValue teamdata = TValue(context, thread_handle->th) /*__kmp_threads[t]->th*/
281                         .cast("kmp_base_info_t")
282                         .access("th_team") /*__kmp_threads[t]->th.th_team*/
283                         .cast("kmp_team_p", 1)
284                         .access("t"); /*__kmp_threads[t]->th.th_team->t*/
285 
286   ret = teamdata.getAddress(&taddr);
287   if (ret != ompd_rc_ok)
288     return ret;
289 
290   lwt.segment = OMPD_SEGMENT_UNSPECIFIED;
291   ret = teamdata.cast("kmp_base_team_t", 0)
292             .access("ompt_serialized_team_info")
293             .castBase()
294             .getValue(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 
ompd_get_enclosing_parallel_handle(ompd_parallel_handle_t * parallel_handle,ompd_parallel_handle_t ** enclosing_parallel_handle)309 ompd_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, 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("ompt_lw_taskteam_t", 0)
336               .access("parent")
337               .cast("ompt_lw_taskteam_t", 1)
338               .dereference()
339               .getAddress(&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("kmp_base_team_t", 0)      /*t*/
346             .access("t_parent")              /*t.t_parent*/
347             .cast("kmp_team_p", 1)
348             .access("t"); /*t.t_parent->t*/
349 
350     ret = teamdata.getAddress(&taddr);
351     if (ret != ompd_rc_ok)
352       return ret;
353 
354     lwt.segment = OMPD_SEGMENT_UNSPECIFIED;
355     ret = teamdata.cast("kmp_base_team_t", 0)
356               .access("ompt_serialized_team_info")
357               .castBase()
358               .getValue(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 
ompd_get_task_parallel_handle(ompd_task_handle_t * task_handle,ompd_parallel_handle_t ** task_parallel_handle)373 ompd_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, 0};
392 
393   ompd_rc_t ret;
394 
395   ret = TValue(context, task_handle->th)
396             .cast("kmp_taskdata_t") /*td*/
397             .access("td_team")      /*td.td_team*/
398             .cast("kmp_team_p", 1)
399             .access("t") /*td.td_team->t*/
400             .getAddress(&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 
ompd_rel_parallel_handle(ompd_parallel_handle_t * parallel_handle)416 ompd_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 
427 ompd_rc_t
ompd_parallel_handle_compare(ompd_parallel_handle_t * parallel_handle_1,ompd_parallel_handle_t * parallel_handle_2,int * cmp_value)428 ompd_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 
ompd_get_curr_task_handle(ompd_thread_handle_t * thread_handle,ompd_task_handle_t ** task_handle)456 ompd_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, 0},
473                  lwt = {OMPD_SEGMENT_UNSPECIFIED, 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("kmp_base_info_t")
481           .access("th_current_task") /*__kmp_threads[t]->th.th_current_task*/
482           .cast("kmp_taskdata_t", 1);
483 
484   ret = taskdata.dereference().getAddress(&taddr);
485   if (ret != ompd_rc_ok)
486     return ret;
487 
488   ret = taskdata
489             .access("td_team") /*td.td_team*/
490             .cast("kmp_team_p", 1)
491             .access("t") /*td.td_team->t*/
492             .cast("kmp_base_team_t", 0)
493             .access("ompt_serialized_team_info")
494             .castBase()
495             .getValue(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 
ompd_get_generating_task_handle(ompd_task_handle_t * task_handle,ompd_task_handle_t ** parent_task_handle)511 ompd_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, 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("ompt_lw_taskteam_t", 0)
534               .access("parent")
535               .cast("ompt_lw_taskteam_t", 1)
536               .dereference()
537               .getAddress(&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("kmp_taskdata_t")      /*td*/
543                           .access("td_parent")         /*td->td_parent*/
544                           .cast("kmp_taskdata_t", 1);
545 
546     ret = taskdata.dereference().getAddress(&taddr);
547     if (ret != ompd_rc_ok)
548       return ret;
549 
550     lwt.segment = OMPD_SEGMENT_UNSPECIFIED;
551     ret = taskdata
552               .access("td_team") /*td.td_team*/
553               .cast("kmp_team_p", 1)
554               .access("t") /*td.td_team->t*/
555               .cast("kmp_base_team_t", 0)
556               .access("ompt_serialized_team_info")
557               .castBase()
558               .getValue(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 
ompd_get_scheduling_task_handle(ompd_task_handle_t * task_handle,ompd_task_handle_t ** parent_task_handle)574 ompd_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, 0};
591   ompd_rc_t ret;
592 
593   ret = TValue(context, task_handle->th)
594             .cast("kmp_taskdata_t")   /*td*/
595             .access("ompt_task_info") // td->ompt_task_info
596             .cast("ompt_task_info_t")
597             .access("scheduling_parent") // td->ompd_task_info.scheduling_parent
598             .cast("kmp_taskdata_t", 1)
599             .castBase()
600             .getValue(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, 0};
614   (*parent_task_handle)->ah = task_handle->ah;
615   return ret;
616 }
617 
ompd_get_task_in_parallel(ompd_parallel_handle_t * parallel_handle,int thread_num,ompd_task_handle_t ** task_handle)618 ompd_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, &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, 0};
644 
645   ret = TValue(context, parallel_handle->th) /* t */
646             .cast("kmp_base_team_t", 0)
647             .access("t_implicit_task_taskdata") /*t.t_implicit_task_taskdata*/
648             .cast("kmp_taskdata_t", 1)
649             .getArrayElement(
650                 thread_num) /*t.t_implicit_task_taskdata[nth_handle]*/
651             .getAddress(&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, 0};
663   return ret;
664 }
665 
ompd_rel_task_handle(ompd_task_handle_t * task_handle)666 ompd_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 
ompd_task_handle_compare(ompd_task_handle_t * task_handle_1,ompd_task_handle_t * task_handle_2,int * cmp_value)677 ompd_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 
ompd_get_thread_handle(ompd_address_space_handle_t * handle,ompd_thread_id_t kind,ompd_size_t sizeof_thread_id,const void * thread_id,ompd_thread_handle_t ** thread_handle)695 ompd_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("__kmp_gtid")
720             .getValue(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("kmp_info_t", 2)
729                   .getArrayElement(tId) /*__kmp_threads[t]*/
730                   .access("th");        /*__kmp_threads[t]->th*/
731 
732   ompd_address_t taddr = {OMPD_SEGMENT_UNSPECIFIED, 0};
733   ret = th.getAddress(&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 
ompd_get_thread_id(ompd_thread_handle_t * thread_handle,ompd_thread_id_t kind,ompd_size_t sizeof_thread_id,void * thread_id)766 ompd_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, "kmp_thread_t").getSize(&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("kmp_base_info_t")
795             .access("th_info") /*__kmp_threads[t]->th.th_info*/
796             .cast("kmp_desc_t")
797             .access("ds") /*__kmp_threads[t]->th.th_info.ds*/
798             .cast("kmp_desc_base_t")
799             .access("ds_thread") /*__kmp_threads[t]->th.th_info.ds.ds_thread*/
800             .cast("kmp_thread_t")
801             .getRawValue(thread_id, 1);
802 
803   return ret;
804 }
805 
806 /* --- OMPT Thread State Inquiry Analogue ----------------------------------- */
807 
ompd_get_state(ompd_thread_handle_t * thread_handle,ompd_word_t * state,ompd_wait_id_t * wait_id)808 ompd_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("kmp_base_info_t")
833           .access("ompt_thread_info") /*__kmp_threads[t]->th.ompt_thread_info*/
834           .cast("ompt_thread_info_t");
835   if (ompt_thread_info.gotError())
836     return ompt_thread_info.getError();
837   ret = ompt_thread_info
838             .access("state") /*__kmp_threads[t]->th.ompt_thread_info.state*/
839             .castBase()
840             .getValue(*state);
841   if (ret != ompd_rc_ok)
842     return ret;
843   if (wait_id)
844     ret = ompt_thread_info
845               .access("wait_id") /*__kmp_threads[t]->th.ompt_thread_info.state*/
846               .castBase()
847               .getValue(*wait_id);
848 
849   return ret;
850 }
851 
852 /* ---  Task Inquiry -------------------------------------------------------- */
853 
854 /* ---  Task Settings ------------------------------------------------------- */
855 
856 /* ---  OMPT Task Inquiry Analogues ----------------------------------------- */
857 
858 ompd_rc_t
ompd_get_task_frame(ompd_task_handle_t * task_handle,ompd_frame_info_t * exit_frame,ompd_frame_info_t * enter_frame)859 ompd_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("ompt_lw_taskteam_t", 0); /*lwt*/
884   else
885     taskInfo = TValue(context, task_handle->th).cast("kmp_taskdata_t", 0); /*t*/
886   TValue frame = taskInfo
887                      .access("ompt_task_info") // td->ompt_task_info
888                      .cast("ompt_task_info_t")
889                      .access("frame") // td->ompd_task_info.frame
890                      .cast("ompt_frame_t", 0);
891   enter_frame->frame_address.segment = OMPD_SEGMENT_UNSPECIFIED;
892   ret = frame
893             .access("enter_frame") // td->ompt_task_info.frame.enter_frame
894             .castBase()
895             .getValue(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("exit_frame") // td->ompt_task_info.frame.exit_frame
903             .castBase()
904             .getValue(exit_frame->frame_address.address);
905 
906   return ret;
907 }
908 
ompd_get_task_function(ompd_task_handle_t * task_handle,ompd_address_t * task_addr)909 ompd_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("kmp_taskdata_t") // td
938               .access("td_flags")     // td->td_flags
939               .cast("kmp_tasking_flags_t")
940               .check("tasktype", &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("kmp_taskdata_t", 0) /*t*/
949                 .getArrayElement(
950                     1) /* see kmp.h: #define KMP_TASKDATA_TO_TASK(taskdata)
951                           (kmp_task_t *)(taskdata + 1) */
952                 .cast("kmp_task_t", 0) /* (kmp_task_t *) */
953                 .access("routine")     /*td->ompt_task_info*/
954                 .castBase()
955                 .getValue(task_addr->address);
956 
957     } else {
958 
959       ret = TValue(context, task_handle->th)
960                 .cast("kmp_taskdata_t") /*td*/
961                 .access("td_team")      /*td.td_team*/
962                 .cast("kmp_team_p", 1)
963                 .access("t") /*td.td_team->t*/
964                 .cast("kmp_base_team_t", 0)
965                 .access("t_pkfn") /*td.td_team->t.t_pkfn*/
966                 .castBase()
967                 .getValue(task_addr->address);
968     }
969   }
970 
971   return ret;
972 }
973 
974 /* ------- OMPD Version and Compatibility Information ----------------------- */
975 
ompd_get_api_version(ompd_word_t * version)976 ompd_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 
984 ompd_rc_t
ompd_get_version_string(const char ** string)985 ompd_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 
ompd_get_display_control_vars(ompd_address_space_handle_t * handle,const char * const ** control_vars)1001 ompd_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, 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 
ompd_rel_display_control_vars(const char * const ** control_vars)1062 ompd_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 
initTypeSizes(ompd_address_space_context_t * context)1078 ompd_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