/* * 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 #include #include #include #include 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 // =\n=\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(*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; }