| /* | |
| * omp-debug.cpp | |
| * | |
| * Created on: Jan 14, 2015 | |
| * Author: Ignacio Laguna | |
| * Joachim Protze | |
| * Contact: ilaguna@llnl.gov | |
| * protze@llnl.gov | |
| */ | |
| /******************************************************************************* | |
| * This implements an OMPD DLL for the LLVM OpenMP runtime library. | |
| */ | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #define NDEBUG 1 | |
| #include "omp-debug.h" | |
| #include "TargetValue.h" | |
| #include "omp.h" | |
| #include "ompd-private.h" | |
| #include <assert.h> | |
| #include <cstdio> | |
| #include <inttypes.h> | |
| #include <pthread.h> | |
| #include <stdint.h> | |
| ompd_device_type_sizes_t type_sizes; | |
| uint64_t ompd_state; | |
| ompd_rc_t ompd_get_num_threads( | |
| ompd_parallel_handle_t *parallel_handle, /* IN: OpenMP parallel handle */ | |
| ompd_word_t *val /* OUT: number of threads */); | |
| /* --- OMPD functions ------------------------------------------------------- */ | |
| /* --- Initialization ------------------------------------------------------- */ | |
| ompd_rc_t ompd_initialize(ompd_word_t version, const ompd_callbacks_t *table) { | |
| ompd_rc_t ret = ompd_rc_ok; | |
| ompd_word_t ompd_version; | |
| if (!table) | |
| return ompd_rc_bad_input; | |
| ompd_get_api_version(&ompd_version); | |
| if (version != ompd_version) | |
| return ompd_rc_unsupported; | |
| callbacks = table; | |
| TValue::callbacks = table; | |
| __ompd_init_icvs(table); | |
| __ompd_init_states(table); | |
| return ret; | |
| } | |
| ompd_rc_t ompd_finalize(void) { return ompd_rc_ok; } | |
| ompd_rc_t ompd_process_initialize( | |
| ompd_address_space_context_t | |
| *context, /* IN: debugger handle for the target */ | |
| ompd_address_space_handle_t **handle /* OUT: ompd handle for the target */ | |
| ) { | |
| if (!context) | |
| return ompd_rc_bad_input; | |
| if (!handle) | |
| return ompd_rc_bad_input; | |
| ompd_rc_t ret = initTypeSizes(context); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| ret = TValue(context, "ompd_state") | |
| .castBase(ompd_type_long_long) | |
| .getValue(ompd_state); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| ret = callbacks->alloc_memory(sizeof(ompd_address_space_handle_t), | |
| (void **)(handle)); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| if (!*handle) | |
| return ompd_rc_error; | |
| (*handle)->context = context; | |
| (*handle)->kind = OMPD_DEVICE_KIND_HOST; | |
| return ompd_rc_ok; | |
| } | |
| ompd_rc_t | |
| ompd_get_omp_version(ompd_address_space_handle_t | |
| *address_space, /* IN: handle for the address space */ | |
| ompd_word_t *version) { | |
| if (!address_space) | |
| return ompd_rc_stale_handle; | |
| if (!version) | |
| return ompd_rc_bad_input; | |
| ompd_address_space_context_t *context = address_space->context; | |
| ompd_rc_t ret; | |
| if (!context) | |
| return ompd_rc_stale_handle; | |
| if (!callbacks) { | |
| return ompd_rc_callback_error; | |
| } | |
| ret = TValue(context, "__kmp_openmp_version") | |
| .castBase(ompd_type_int) | |
| .getValue(*version); | |
| return ret; | |
| } | |
| ompd_rc_t ompd_get_omp_version_string( | |
| ompd_address_space_handle_t | |
| *address_space, /* IN: handle for the address space */ | |
| const char **string) { | |
| if (!address_space) | |
| return ompd_rc_stale_handle; | |
| if (!string) | |
| return ompd_rc_bad_input; | |
| ompd_address_space_context_t *context = address_space->context; | |
| ompd_word_t ver; | |
| ompd_rc_t ret; | |
| char *omp_version; | |
| ret = callbacks->alloc_memory(10, /* max digit can be store on int*/ | |
| (void **)&omp_version); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| ret = TValue(context, "__kmp_openmp_version") | |
| .castBase(ompd_type_int) | |
| .getValue(ver); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| sprintf(omp_version, "%ld", ver); | |
| *string = omp_version; | |
| return ret; | |
| } | |
| ompd_rc_t ompd_rel_address_space_handle( | |
| ompd_address_space_handle_t | |
| *addr_handle /* IN: handle for the address space */ | |
| ) { | |
| if (!addr_handle) | |
| return ompd_rc_stale_handle; | |
| ompd_rc_t ret = callbacks->free_memory((void *)(addr_handle)); | |
| // delete addr_handle; | |
| return ret; | |
| } | |
| ompd_rc_t 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) { | |
| if (!device_context) | |
| return ompd_rc_bad_input; | |
| return ompd_rc_unavailable; | |
| } | |
| /* --- Thread Handles ------------------------------------------------------- */ | |
| /* thread_handle is of type (kmp_base_info_t) */ | |
| ompd_rc_t ompd_get_thread_in_parallel( | |
| ompd_parallel_handle_t *parallel_handle, /* IN: OpenMP parallel handle */ | |
| int thread_num, /* IN: Thread num, handle of which is to be returned */ | |
| ompd_thread_handle_t **thread_handle /* OUT: handle */ | |
| ) { | |
| if (!parallel_handle) | |
| return ompd_rc_stale_handle; | |
| if (!parallel_handle->ah) | |
| return ompd_rc_stale_handle; | |
| ompd_address_space_context_t *context = parallel_handle->ah->context; | |
| ompd_rc_t ret; | |
| if (!context) | |
| return ompd_rc_stale_handle; | |
| if (!callbacks) { | |
| return ompd_rc_callback_error; | |
| } | |
| ompd_word_t team_size_var; | |
| ret = ompd_get_num_threads(parallel_handle, &team_size_var); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| if (thread_num < 0 || thread_num >= team_size_var) | |
| return ompd_rc_bad_input; | |
| ompd_address_t taddr = {OMPD_SEGMENT_UNSPECIFIED, 0}; | |
| ret = TValue(context, parallel_handle->th) /* t */ | |
| .cast("kmp_base_team_t", 0) | |
| .access("t_threads") /*t.t_threads*/ | |
| .cast("kmp_info_t", 2) | |
| .getArrayElement(thread_num) /*t.t_threads[nth_handle]*/ | |
| .access("th") /*t.t_threads[i]->th*/ | |
| .getAddress(&taddr); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| ret = callbacks->alloc_memory(sizeof(ompd_thread_handle_t), | |
| (void **)(thread_handle)); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| (*thread_handle)->th = taddr; | |
| (*thread_handle)->ah = parallel_handle->ah; | |
| return ret; | |
| } | |
| ompd_rc_t ompd_rel_thread_handle( | |
| ompd_thread_handle_t | |
| *thread_handle /* IN: OpenMP thread handle to be released */ | |
| ) { | |
| if (!thread_handle) | |
| return ompd_rc_stale_handle; | |
| ompd_rc_t ret = callbacks->free_memory((void *)(thread_handle)); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| return ompd_rc_ok; | |
| } | |
| ompd_rc_t ompd_thread_handle_compare(ompd_thread_handle_t *thread_handle_1, | |
| ompd_thread_handle_t *thread_handle_2, | |
| int *cmp_value) { | |
| if (!thread_handle_1) | |
| return ompd_rc_stale_handle; | |
| if (!thread_handle_2) | |
| return ompd_rc_stale_handle; | |
| if (!cmp_value) | |
| return ompd_rc_bad_input; | |
| if (thread_handle_1->ah->kind != thread_handle_2->ah->kind) | |
| return ompd_rc_bad_input; | |
| *cmp_value = thread_handle_1->th.address - thread_handle_2->th.address; | |
| return ompd_rc_ok; | |
| } | |
| /* --- Parallel Region Handles----------------------------------------------- */ | |
| /* parallel_handle is of type (kmp_base_team_t)*/ | |
| ompd_rc_t ompd_get_curr_parallel_handle( | |
| ompd_thread_handle_t *thread_handle, /* IN: OpenMP thread handle*/ | |
| ompd_parallel_handle_t **parallel_handle /* OUT: OpenMP parallel handle */ | |
| ) { | |
| if (!thread_handle) | |
| return ompd_rc_stale_handle; | |
| if (!thread_handle->ah) | |
| return ompd_rc_stale_handle; | |
| ompd_address_space_context_t *context = thread_handle->ah->context; | |
| ompd_thread_context_t *thread_context = thread_handle->thread_context; | |
| if (!context || !thread_context) | |
| return ompd_rc_stale_handle; | |
| if (!callbacks) { | |
| return ompd_rc_callback_error; | |
| } | |
| ompd_rc_t ret; | |
| ompd_address_t taddr = {OMPD_SEGMENT_UNSPECIFIED, 0}, | |
| lwt = {OMPD_SEGMENT_UNSPECIFIED, 0}; | |
| TValue teamdata = TValue(context, thread_handle->th) /*__kmp_threads[t]->th*/ | |
| .cast("kmp_base_info_t") | |
| .access("th_team") /*__kmp_threads[t]->th.th_team*/ | |
| .cast("kmp_team_p", 1) | |
| .access("t"); /*__kmp_threads[t]->th.th_team->t*/ | |
| ret = teamdata.getAddress(&taddr); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| lwt.segment = OMPD_SEGMENT_UNSPECIFIED; | |
| ret = teamdata.cast("kmp_base_team_t", 0) | |
| .access("ompt_serialized_team_info") | |
| .castBase() | |
| .getValue(lwt.address); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| ret = callbacks->alloc_memory(sizeof(ompd_parallel_handle_t), | |
| (void **)(parallel_handle)); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| (*parallel_handle)->ah = thread_handle->ah; | |
| (*parallel_handle)->th = taddr; | |
| (*parallel_handle)->lwt = lwt; | |
| return ompd_rc_ok; | |
| } | |
| ompd_rc_t ompd_get_enclosing_parallel_handle( | |
| ompd_parallel_handle_t *parallel_handle, /* IN: OpenMP parallel handle */ | |
| ompd_parallel_handle_t * | |
| *enclosing_parallel_handle /* OUT: OpenMP parallel handle */ | |
| ) { | |
| if (!parallel_handle) | |
| return ompd_rc_stale_handle; | |
| if (!parallel_handle->ah) | |
| return ompd_rc_stale_handle; | |
| ompd_address_space_context_t *context = parallel_handle->ah->context; | |
| if (!context) | |
| return ompd_rc_stale_handle; | |
| if (!callbacks) { | |
| return ompd_rc_callback_error; | |
| } | |
| ompd_address_t taddr = parallel_handle->th, | |
| lwt = {OMPD_SEGMENT_UNSPECIFIED, 0}; | |
| ompd_rc_t ret; | |
| ret = ompd_rc_stale_handle; | |
| TValue lwtValue = TValue(context, parallel_handle->lwt); | |
| if (lwtValue.getError() == ompd_rc_ok) // lwt == 0x0 | |
| { // if we are in lwt, get parent | |
| ret = lwtValue.cast("ompt_lw_taskteam_t", 0) | |
| .access("parent") | |
| .cast("ompt_lw_taskteam_t", 1) | |
| .dereference() | |
| .getAddress(&lwt); | |
| } | |
| if (ret != ompd_rc_ok) { // no lwt or parent==0x0 | |
| TValue teamdata = | |
| TValue(context, parallel_handle->th) /*__kmp_threads[t]->th*/ | |
| .cast("kmp_base_team_t", 0) /*t*/ | |
| .access("t_parent") /*t.t_parent*/ | |
| .cast("kmp_team_p", 1) | |
| .access("t"); /*t.t_parent->t*/ | |
| ret = teamdata.getAddress(&taddr); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| lwt.segment = OMPD_SEGMENT_UNSPECIFIED; | |
| ret = teamdata.cast("kmp_base_team_t", 0) | |
| .access("ompt_serialized_team_info") | |
| .castBase() | |
| .getValue(lwt.address); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| } | |
| ret = callbacks->alloc_memory(sizeof(ompd_parallel_handle_t), | |
| (void **)(enclosing_parallel_handle)); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| (*enclosing_parallel_handle)->th = taddr; | |
| (*enclosing_parallel_handle)->lwt = lwt; | |
| (*enclosing_parallel_handle)->ah = parallel_handle->ah; | |
| return ompd_rc_ok; | |
| } | |
| ompd_rc_t ompd_get_task_parallel_handle( | |
| ompd_task_handle_t *task_handle, /* IN: OpenMP task handle */ | |
| ompd_parallel_handle_t * | |
| *task_parallel_handle /* OUT: OpenMP parallel handle */ | |
| ) { | |
| if (!task_handle) | |
| return ompd_rc_stale_handle; | |
| if (!task_handle->ah) | |
| return ompd_rc_stale_handle; | |
| ompd_address_space_context_t *context = task_handle->ah->context; | |
| if (!context) | |
| return ompd_rc_stale_handle; | |
| if (!callbacks) { | |
| return ompd_rc_callback_error; | |
| } | |
| ompd_address_t taddr = {OMPD_SEGMENT_UNSPECIFIED, 0}; | |
| ompd_rc_t ret; | |
| ret = TValue(context, task_handle->th) | |
| .cast("kmp_taskdata_t") /*td*/ | |
| .access("td_team") /*td.td_team*/ | |
| .cast("kmp_team_p", 1) | |
| .access("t") /*td.td_team->t*/ | |
| .getAddress(&taddr); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| ret = callbacks->alloc_memory(sizeof(ompd_parallel_handle_t), | |
| (void **)(task_parallel_handle)); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| (*task_parallel_handle)->ah = task_handle->ah; | |
| (*task_parallel_handle)->lwt = task_handle->lwt; | |
| (*task_parallel_handle)->th = taddr; | |
| return ompd_rc_ok; | |
| } | |
| ompd_rc_t ompd_rel_parallel_handle( | |
| ompd_parallel_handle_t *parallel_handle /* IN: OpenMP parallel handle */ | |
| ) { | |
| if (!parallel_handle) | |
| return ompd_rc_stale_handle; | |
| ompd_rc_t ret = callbacks->free_memory((void *)(parallel_handle)); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| return ompd_rc_ok; | |
| } | |
| ompd_rc_t | |
| ompd_parallel_handle_compare(ompd_parallel_handle_t *parallel_handle_1, | |
| ompd_parallel_handle_t *parallel_handle_2, | |
| int *cmp_value) { | |
| if (!parallel_handle_1) | |
| return ompd_rc_stale_handle; | |
| if (!parallel_handle_2) | |
| return ompd_rc_stale_handle; | |
| if (!cmp_value) | |
| return ompd_rc_bad_input; | |
| if (parallel_handle_1->ah->kind != parallel_handle_2->ah->kind) | |
| return ompd_rc_bad_input; | |
| if (parallel_handle_1->ah->kind == OMPD_DEVICE_KIND_HOST) { | |
| if (parallel_handle_1->th.address - parallel_handle_2->th.address) | |
| *cmp_value = | |
| parallel_handle_1->th.address - parallel_handle_2->th.address; | |
| else | |
| *cmp_value = | |
| parallel_handle_1->lwt.address - parallel_handle_2->lwt.address; | |
| } else { | |
| *cmp_value = parallel_handle_1->th.address - parallel_handle_2->th.address; | |
| } | |
| return ompd_rc_ok; | |
| } | |
| /* ------- Task Handles ----------------------------------------------------- */ | |
| /* task_handle is of type (kmp_taskdata_t) */ | |
| ompd_rc_t ompd_get_curr_task_handle( | |
| ompd_thread_handle_t *thread_handle, /* IN: OpenMP thread handle*/ | |
| ompd_task_handle_t **task_handle /* OUT: OpenMP task handle */ | |
| ) { | |
| if (!thread_handle) | |
| return ompd_rc_stale_handle; | |
| if (!thread_handle->ah) | |
| return ompd_rc_stale_handle; | |
| ompd_address_space_context_t *context = thread_handle->ah->context; | |
| if (!context) | |
| return ompd_rc_stale_handle; | |
| if (!callbacks) { | |
| return ompd_rc_callback_error; | |
| } | |
| ompd_address_t taddr = {OMPD_SEGMENT_UNSPECIFIED, 0}, | |
| lwt = {OMPD_SEGMENT_UNSPECIFIED, 0}; | |
| ompd_rc_t ret = ompd_rc_ok; | |
| lwt.segment = OMPD_SEGMENT_UNSPECIFIED; | |
| TValue taskdata = | |
| TValue(context, thread_handle->th) /*__kmp_threads[t]->th*/ | |
| .cast("kmp_base_info_t") | |
| .access("th_current_task") /*__kmp_threads[t]->th.th_current_task*/ | |
| .cast("kmp_taskdata_t", 1); | |
| ret = taskdata.dereference().getAddress(&taddr); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| ret = taskdata | |
| .access("td_team") /*td.td_team*/ | |
| .cast("kmp_team_p", 1) | |
| .access("t") /*td.td_team->t*/ | |
| .cast("kmp_base_team_t", 0) | |
| .access("ompt_serialized_team_info") | |
| .castBase() | |
| .getValue(lwt.address); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| ret = callbacks->alloc_memory(sizeof(ompd_task_handle_t), | |
| (void **)(task_handle)); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| (*task_handle)->th = taddr; | |
| (*task_handle)->lwt = lwt; | |
| (*task_handle)->ah = thread_handle->ah; | |
| return ompd_rc_ok; | |
| } | |
| ompd_rc_t ompd_get_generating_task_handle( | |
| ompd_task_handle_t *task_handle, /* IN: OpenMP task handle */ | |
| ompd_task_handle_t **parent_task_handle /* OUT: OpenMP task handle */ | |
| ) { | |
| if (!task_handle) | |
| return ompd_rc_stale_handle; | |
| if (!task_handle->ah) | |
| return ompd_rc_stale_handle; | |
| ompd_address_space_context_t *context = task_handle->ah->context; | |
| if (!context) | |
| return ompd_rc_stale_handle; | |
| if (!callbacks) { | |
| return ompd_rc_callback_error; | |
| } | |
| ompd_address_t taddr = task_handle->th, lwt = {OMPD_SEGMENT_UNSPECIFIED, 0}; | |
| ompd_rc_t ret = ompd_rc_stale_handle; | |
| TValue lwtValue = TValue(context, task_handle->lwt); | |
| if (lwtValue.getError() == ompd_rc_ok) // lwt == 0x0 | |
| { // if we are in lwt, get parent | |
| ret = lwtValue.cast("ompt_lw_taskteam_t", 0) | |
| .access("parent") | |
| .cast("ompt_lw_taskteam_t", 1) | |
| .dereference() | |
| .getAddress(&lwt); | |
| } | |
| if (ret != ompd_rc_ok) { // no lwt or parent==0x0 | |
| TValue taskdata = TValue(context, task_handle->th) /*__kmp_threads[t]->th*/ | |
| .cast("kmp_taskdata_t") /*td*/ | |
| .access("td_parent") /*td->td_parent*/ | |
| .cast("kmp_taskdata_t", 1); | |
| ret = taskdata.dereference().getAddress(&taddr); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| lwt.segment = OMPD_SEGMENT_UNSPECIFIED; | |
| ret = taskdata | |
| .access("td_team") /*td.td_team*/ | |
| .cast("kmp_team_p", 1) | |
| .access("t") /*td.td_team->t*/ | |
| .cast("kmp_base_team_t", 0) | |
| .access("ompt_serialized_team_info") | |
| .castBase() | |
| .getValue(lwt.address); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| } | |
| ret = callbacks->alloc_memory(sizeof(ompd_task_handle_t), | |
| (void **)(parent_task_handle)); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| (*parent_task_handle)->th = taddr; | |
| (*parent_task_handle)->lwt = lwt; | |
| (*parent_task_handle)->ah = task_handle->ah; | |
| return ret; | |
| } | |
| ompd_rc_t ompd_get_scheduling_task_handle( | |
| ompd_task_handle_t *task_handle, /* IN: OpenMP task handle */ | |
| ompd_task_handle_t **parent_task_handle /* OUT: OpenMP task handle */ | |
| ) { | |
| if (!task_handle) | |
| return ompd_rc_stale_handle; | |
| if (!task_handle->ah) | |
| return ompd_rc_stale_handle; | |
| ompd_address_space_context_t *context = task_handle->ah->context; | |
| if (!context) | |
| return ompd_rc_stale_handle; | |
| if (!callbacks) { | |
| return ompd_rc_callback_error; | |
| } | |
| ompd_address_t taddr = {OMPD_SEGMENT_UNSPECIFIED, 0}; | |
| ompd_rc_t ret; | |
| ret = TValue(context, task_handle->th) | |
| .cast("kmp_taskdata_t") /*td*/ | |
| .access("ompt_task_info") // td->ompt_task_info | |
| .cast("ompt_task_info_t") | |
| .access("scheduling_parent") // td->ompd_task_info.scheduling_parent | |
| .cast("kmp_taskdata_t", 1) | |
| .castBase() | |
| .getValue(taddr.address); | |
| if (taddr.address == 0) { | |
| return ompd_rc_unavailable; | |
| } | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| ret = callbacks->alloc_memory(sizeof(ompd_task_handle_t), | |
| (void **)(parent_task_handle)); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| (*parent_task_handle)->th = taddr; | |
| (*parent_task_handle)->lwt = {OMPD_SEGMENT_UNSPECIFIED, 0}; | |
| (*parent_task_handle)->ah = task_handle->ah; | |
| return ret; | |
| } | |
| ompd_rc_t ompd_get_task_in_parallel( | |
| ompd_parallel_handle_t *parallel_handle, /* IN: OpenMP parallel handle */ | |
| int thread_num, /* IN: thread num of implicit task of team */ | |
| ompd_task_handle_t **task_handle /* OUT: OpenMP task handle */ | |
| ) { | |
| if (!parallel_handle) | |
| return ompd_rc_stale_handle; | |
| if (!parallel_handle->ah) | |
| return ompd_rc_stale_handle; | |
| ompd_address_space_context_t *context = parallel_handle->ah->context; | |
| if (!context) | |
| return ompd_rc_stale_handle; | |
| if (!callbacks) { | |
| return ompd_rc_callback_error; | |
| } | |
| ompd_rc_t ret; | |
| ompd_word_t team_size_var; | |
| ret = ompd_get_num_threads(parallel_handle, &team_size_var); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| if (thread_num < 0 || thread_num >= team_size_var) | |
| return ompd_rc_bad_input; | |
| ompd_address_t taddr = {OMPD_SEGMENT_UNSPECIFIED, 0}; | |
| ret = TValue(context, parallel_handle->th) /* t */ | |
| .cast("kmp_base_team_t", 0) | |
| .access("t_implicit_task_taskdata") /*t.t_implicit_task_taskdata*/ | |
| .cast("kmp_taskdata_t", 1) | |
| .getArrayElement( | |
| thread_num) /*t.t_implicit_task_taskdata[nth_handle]*/ | |
| .getAddress(&taddr); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| ret = callbacks->alloc_memory(sizeof(ompd_task_handle_t), | |
| (void **)(task_handle)); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| (*task_handle)->th = taddr; | |
| (*task_handle)->ah = parallel_handle->ah; | |
| (*task_handle)->lwt = {OMPD_SEGMENT_UNSPECIFIED, 0}; | |
| return ret; | |
| } | |
| ompd_rc_t ompd_rel_task_handle( | |
| ompd_task_handle_t *task_handle /* IN: OpenMP task handle */ | |
| ) { | |
| if (!task_handle) | |
| return ompd_rc_stale_handle; | |
| ompd_rc_t ret = callbacks->free_memory((void *)(task_handle)); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| return ompd_rc_ok; | |
| } | |
| ompd_rc_t ompd_task_handle_compare(ompd_task_handle_t *task_handle_1, | |
| ompd_task_handle_t *task_handle_2, | |
| int *cmp_value) { | |
| if (!task_handle_1) | |
| return ompd_rc_stale_handle; | |
| if (!task_handle_2) | |
| return ompd_rc_stale_handle; | |
| if (!cmp_value) | |
| return ompd_rc_bad_input; | |
| if (task_handle_1->ah->kind != task_handle_2->ah->kind) | |
| return ompd_rc_bad_input; | |
| if (task_handle_1->th.address - task_handle_2->th.address) | |
| *cmp_value = task_handle_1->th.address - task_handle_2->th.address; | |
| else | |
| *cmp_value = task_handle_1->lwt.address - task_handle_2->lwt.address; | |
| return ompd_rc_ok; | |
| } | |
| ompd_rc_t ompd_get_thread_handle( | |
| ompd_address_space_handle_t *handle, /* IN: handle for the address space */ | |
| ompd_thread_id_t kind, ompd_size_t sizeof_thread_id, const void *thread_id, | |
| ompd_thread_handle_t **thread_handle) { | |
| if (!handle) | |
| return ompd_rc_stale_handle; | |
| ompd_address_space_context_t *context = handle->context; | |
| ompd_rc_t ret; | |
| if (!context) | |
| return ompd_rc_stale_handle; | |
| if (!callbacks) { | |
| return ompd_rc_callback_error; | |
| } | |
| ompd_thread_context_t *tcontext; | |
| ret = callbacks->get_thread_context_for_thread_id( | |
| context, kind, sizeof_thread_id, thread_id, &tcontext); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| int tId; | |
| ret = TValue(context, tcontext, "__kmp_gtid") | |
| .castBase("__kmp_gtid") | |
| .getValue(tId); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| if (tId < 0) // thread is no omp worker | |
| return ompd_rc_unavailable; | |
| TValue th = TValue(context, "__kmp_threads") // __kmp_threads | |
| .cast("kmp_info_t", 2) | |
| .getArrayElement(tId) /*__kmp_threads[t]*/ | |
| .access("th"); /*__kmp_threads[t]->th*/ | |
| ompd_address_t taddr = {OMPD_SEGMENT_UNSPECIFIED, 0}; | |
| ret = th.getAddress(&taddr); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| ret = callbacks->alloc_memory(sizeof(ompd_thread_handle_t), | |
| (void **)(thread_handle)); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| (*thread_handle)->ah = handle; | |
| (*thread_handle)->th = taddr; | |
| #ifndef NDEBUG | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| pthread_t oshandle; | |
| TBaseValue ds_handle = | |
| th.cast("kmp_base_info_t") | |
| .access("th_info") /*__kmp_threads[t]->th.th_info*/ | |
| .cast("kmp_desc_t") | |
| .access("ds") /*__kmp_threads[t]->th.th_info.ds*/ | |
| .cast("kmp_desc_base_t") | |
| .access("ds_thread") /*__kmp_threads[t]->th.th_info.ds.ds_thread*/ | |
| .castBase(); | |
| assert(ompd_rc_ok == ds_handle.getValue(oshandle) && | |
| oshandle == *(pthread_t *)(thread_id) && | |
| "Callback table not initialized!"); | |
| #endif | |
| (*thread_handle)->thread_context = tcontext; | |
| return ret; | |
| } | |
| ompd_rc_t ompd_get_thread_id( | |
| ompd_thread_handle_t *thread_handle, /* IN: OpenMP thread handle*/ | |
| ompd_thread_id_t kind, ompd_size_t sizeof_thread_id, void *thread_id) { | |
| if (kind != OMPD_THREAD_ID_PTHREAD) | |
| return ompd_rc_unsupported; | |
| if (!thread_id) | |
| return ompd_rc_bad_input; | |
| if (!thread_handle) | |
| return ompd_rc_stale_handle; | |
| if (!thread_handle->ah) | |
| return ompd_rc_stale_handle; | |
| ompd_address_space_context_t *context = thread_handle->ah->context; | |
| if (!context) | |
| return ompd_rc_stale_handle; | |
| ompd_rc_t ret; | |
| ompd_size_t size; | |
| ret = tf.getType(context, "kmp_thread_t").getSize(&size); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| if (sizeof_thread_id != size) | |
| return ompd_rc_bad_input; | |
| if (!callbacks) { | |
| return ompd_rc_callback_error; | |
| } | |
| ret = TValue(context, thread_handle->th) /*__kmp_threads[t]->th*/ | |
| .cast("kmp_base_info_t") | |
| .access("th_info") /*__kmp_threads[t]->th.th_info*/ | |
| .cast("kmp_desc_t") | |
| .access("ds") /*__kmp_threads[t]->th.th_info.ds*/ | |
| .cast("kmp_desc_base_t") | |
| .access("ds_thread") /*__kmp_threads[t]->th.th_info.ds.ds_thread*/ | |
| .cast("kmp_thread_t") | |
| .getRawValue(thread_id, 1); | |
| return ret; | |
| } | |
| /* --- OMPT Thread State Inquiry Analogue ----------------------------------- */ | |
| ompd_rc_t ompd_get_state( | |
| ompd_thread_handle_t *thread_handle, /* IN: OpenMP thread handle*/ | |
| ompd_word_t *state, /* OUT: State of this thread */ | |
| ompd_wait_id_t *wait_id /* OUT: Wait ID */ | |
| ) { | |
| if (!thread_handle) | |
| return ompd_rc_stale_handle; | |
| if (!thread_handle->ah) | |
| return ompd_rc_stale_handle; | |
| if (!state) | |
| return ompd_rc_bad_input; | |
| ompd_address_space_context_t *context = thread_handle->ah->context; | |
| if (!context) | |
| return ompd_rc_stale_handle; | |
| if (!ompd_state) | |
| return ompd_rc_needs_state_tracking; | |
| if (!callbacks) { | |
| return ompd_rc_callback_error; | |
| } | |
| ompd_rc_t ret; | |
| TValue ompt_thread_info = | |
| TValue(context, thread_handle->th) /*__kmp_threads[t]->th*/ | |
| .cast("kmp_base_info_t") | |
| .access("ompt_thread_info") /*__kmp_threads[t]->th.ompt_thread_info*/ | |
| .cast("ompt_thread_info_t"); | |
| if (ompt_thread_info.gotError()) | |
| return ompt_thread_info.getError(); | |
| ret = ompt_thread_info | |
| .access("state") /*__kmp_threads[t]->th.ompt_thread_info.state*/ | |
| .castBase() | |
| .getValue(*state); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| if (wait_id) | |
| ret = ompt_thread_info | |
| .access("wait_id") /*__kmp_threads[t]->th.ompt_thread_info.state*/ | |
| .castBase() | |
| .getValue(*wait_id); | |
| return ret; | |
| } | |
| /* --- Task Inquiry -------------------------------------------------------- */ | |
| /* --- Task Settings ------------------------------------------------------- */ | |
| /* --- OMPT Task Inquiry Analogues ----------------------------------------- */ | |
| ompd_rc_t | |
| ompd_get_task_frame(ompd_task_handle_t *task_handle, /* IN: OpenMP task handle*/ | |
| ompd_frame_info_t *exit_frame, | |
| ompd_frame_info_t *enter_frame) { | |
| if (!task_handle) | |
| return ompd_rc_stale_handle; | |
| if (!task_handle->ah) | |
| return ompd_rc_stale_handle; | |
| if (!exit_frame || !enter_frame) | |
| return ompd_rc_bad_input; | |
| ompd_address_space_context_t *context = task_handle->ah->context; | |
| if (!context) | |
| return ompd_rc_stale_handle; | |
| if (!ompd_state) | |
| return ompd_rc_needs_state_tracking; | |
| if (!callbacks) { | |
| return ompd_rc_callback_error; | |
| } | |
| ompd_rc_t ret; | |
| TValue taskInfo; | |
| if (task_handle->lwt.address != 0) | |
| taskInfo = | |
| TValue(context, task_handle->lwt).cast("ompt_lw_taskteam_t", 0); /*lwt*/ | |
| else | |
| taskInfo = TValue(context, task_handle->th).cast("kmp_taskdata_t", 0); /*t*/ | |
| TValue frame = taskInfo | |
| .access("ompt_task_info") // td->ompt_task_info | |
| .cast("ompt_task_info_t") | |
| .access("frame") // td->ompd_task_info.frame | |
| .cast("ompt_frame_t", 0); | |
| enter_frame->frame_address.segment = OMPD_SEGMENT_UNSPECIFIED; | |
| ret = frame | |
| .access("enter_frame") // td->ompt_task_info.frame.enter_frame | |
| .castBase() | |
| .getValue(enter_frame->frame_address.address); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| exit_frame->frame_address.segment = OMPD_SEGMENT_UNSPECIFIED; | |
| ret = frame | |
| .access("exit_frame") // td->ompt_task_info.frame.exit_frame | |
| .castBase() | |
| .getValue(exit_frame->frame_address.address); | |
| return ret; | |
| } | |
| ompd_rc_t ompd_get_task_function( | |
| ompd_task_handle_t *task_handle, /* IN: OpenMP task handle */ | |
| ompd_address_t *task_addr /* OUT: first instruction in the task region */ | |
| ) { | |
| if (!task_handle) | |
| return ompd_rc_stale_handle; | |
| if (!task_handle->ah) | |
| return ompd_rc_stale_handle; | |
| if (!task_addr) | |
| return ompd_rc_bad_input; | |
| ompd_address_space_context_t *context = task_handle->ah->context; | |
| if (!context) | |
| return ompd_rc_stale_handle; | |
| if (!ompd_state) | |
| return ompd_rc_needs_state_tracking; | |
| if (!callbacks) { | |
| return ompd_rc_callback_error; | |
| } | |
| ompd_rc_t ret; | |
| task_addr->segment = OMPD_SEGMENT_UNSPECIFIED; | |
| TValue taskInfo; | |
| if (task_handle->lwt.address != 0) | |
| return ompd_rc_bad_input; // We need to decide what we do here. | |
| else { | |
| ompd_word_t val; | |
| ret = TValue(context, task_handle->th) | |
| .cast("kmp_taskdata_t") // td | |
| .access("td_flags") // td->td_flags | |
| .cast("kmp_tasking_flags_t") | |
| .check("tasktype", &val); // td->td_flags.tasktype | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| if (val == 1) { // tasktype: explicit = 1, implicit = 0 | |
| ret = TValue(context, task_handle->th) | |
| .cast("kmp_taskdata_t", 0) /*t*/ | |
| .getArrayElement( | |
| 1) /* see kmp.h: #define KMP_TASKDATA_TO_TASK(taskdata) | |
| (kmp_task_t *)(taskdata + 1) */ | |
| .cast("kmp_task_t", 0) /* (kmp_task_t *) */ | |
| .access("routine") /*td->ompt_task_info*/ | |
| .castBase() | |
| .getValue(task_addr->address); | |
| } else { | |
| ret = TValue(context, task_handle->th) | |
| .cast("kmp_taskdata_t") /*td*/ | |
| .access("td_team") /*td.td_team*/ | |
| .cast("kmp_team_p", 1) | |
| .access("t") /*td.td_team->t*/ | |
| .cast("kmp_base_team_t", 0) | |
| .access("t_pkfn") /*td.td_team->t.t_pkfn*/ | |
| .castBase() | |
| .getValue(task_addr->address); | |
| } | |
| } | |
| return ret; | |
| } | |
| /* ------- OMPD Version and Compatibility Information ----------------------- */ | |
| ompd_rc_t ompd_get_api_version(ompd_word_t *version) { | |
| if (!version) | |
| return ompd_rc_bad_input; | |
| *version = OMPD_VERSION; | |
| return ompd_rc_ok; | |
| } | |
| ompd_rc_t | |
| ompd_get_version_string(const char **string /* OUT: OMPD version string */ | |
| ) { | |
| if (!string) | |
| return ompd_rc_bad_input; | |
| static const char version_string[] = | |
| "LLVM OpenMP " STR(OMPD_IMPLEMENTS_OPENMP) "." STR( | |
| OMPD_IMPLEMENTS_OPENMP_SUBVERSION) " Debugging Library implmenting " | |
| "TR " STR(OMPD_TR_VERSION) "" STR( | |
| OMPD_TR_SUBVERSION); | |
| *string = version_string; | |
| return ompd_rc_ok; | |
| } | |
| /* ------ Display Control Variables ----------------------------------------- */ | |
| ompd_rc_t ompd_get_display_control_vars(ompd_address_space_handle_t *handle, | |
| const char *const **control_vars) { | |
| if (!handle) | |
| return ompd_rc_stale_handle; | |
| if (!control_vars) | |
| return ompd_rc_bad_input; | |
| ompd_address_space_context_t *context = handle->context; | |
| if (!context) | |
| return ompd_rc_stale_handle; | |
| // runtime keeps a full dump of OMP/KMP definitions in this format | |
| // <var1 name>=<var1 value>\n<var2 name>=<var2 value>\n... | |
| ompd_address_t block_addr = {ompd_segment_none, 0}; | |
| OMPD_GET_VALUE(context, NULL, "ompd_env_block", type_sizes.sizeof_pointer, | |
| &block_addr.address); | |
| // query size of the block | |
| ompd_size_t block_size; | |
| OMPD_GET_VALUE(context, NULL, "ompd_env_block_size", sizeof(ompd_size_t), | |
| &block_size); | |
| // copy raw data from the address space | |
| char *block; | |
| OMPD_CALLBACK(alloc_memory, block_size, (void **)&block); | |
| OMPD_CALLBACK(read_memory, context, NULL, &block_addr, block_size, block); | |
| // count number of items, replace new line to zero. | |
| int block_items = 1; // also count the last "NULL" item | |
| for (ompd_size_t i = 0; i < block_size; i++) { | |
| if (block[i] == '\n') { | |
| block_items++; | |
| block[i] = '\0'; | |
| } | |
| } | |
| // create vector of char* | |
| const char **ctl_vars; | |
| OMPD_CALLBACK(alloc_memory, block_items * sizeof(char *), | |
| (void **)(&ctl_vars)); | |
| char *pos = block; | |
| ctl_vars[0] = block; | |
| // ctl_vars[0] points to the entire block, ctl_vars[1]... points to the | |
| // smaller subsets of the block, and ctl_vars[block_items-2] points to the | |
| // last string in the block. | |
| for (int i = 1; i < block_items - 1; i++) { | |
| while (*pos++ != '\0') | |
| ; | |
| if (pos > block + block_size) | |
| return ompd_rc_error; | |
| ctl_vars[i] = pos; | |
| } | |
| // last item must be NULL | |
| ctl_vars[block_items - 1] = NULL; | |
| *control_vars = ctl_vars; | |
| return ompd_rc_ok; | |
| } | |
| ompd_rc_t ompd_rel_display_control_vars(const char *const **control_vars) { | |
| if (!control_vars) | |
| return ompd_rc_bad_input; | |
| char **ctl_vars = const_cast<char **>(*control_vars); | |
| // remove the raw block first | |
| OMPD_CALLBACK(free_memory, (void *)ctl_vars[0]); | |
| // remove the vector | |
| OMPD_CALLBACK(free_memory, (void *)ctl_vars); | |
| return ompd_rc_ok; | |
| } | |
| /* --- Helper functions ----------------------------------------------------- */ | |
| ompd_rc_t initTypeSizes(ompd_address_space_context_t *context) { | |
| static int inited = 0; | |
| static ompd_rc_t ret; | |
| if (inited) | |
| return ret; | |
| ret = callbacks->sizeof_type(context, &type_sizes); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| if (!(type_sizes.sizeof_pointer > 0)) | |
| return ompd_rc_error; | |
| ret = callbacks->sizeof_type(context, &TValue::type_sizes); | |
| if (ret != ompd_rc_ok) | |
| return ret; | |
| inited = 1; | |
| return ret; | |
| } |