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 | |
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(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 | |
62 | ompd_rc_t ompd_finalize(void) { return ompd_rc_ok; } |
63 | |
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(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 | |
96 | ompd_rc_t |
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(baseType: ompd_type_int) |
117 | .getValue(buf&: *version); |
118 | return ret; |
119 | } |
120 | |
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(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 | |
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 | |
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 | |
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, 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 | |
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 | |
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 | |
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, .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 | |
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, .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 | |
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, .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 | |
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 |
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 | |
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, .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 | |
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, .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 | |
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, .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 | |
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, 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 | |
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 | |
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 | |
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(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 | |
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, 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 | |
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(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 | |
858 | ompd_rc_t |
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(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 | |
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(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 | |
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 |
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 | |
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, .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 | |
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 | |
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 | |