| /* |
| * 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; |
| } |