| 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 | |