summaryrefslogtreecommitdiff
path: root/openmp/libompd
diff options
context:
space:
mode:
authorVignesh Balasubramanian <Vignesh.Balasubrmanian@amd.com>2021-10-27 16:19:07 +0530
committerVignesh Balasubramanian <Vignesh.Balasubrmanian@amd.com>2021-10-27 16:31:19 +0530
commitb0277bef9739d5e3a3feb89ff9c1aaa90a801ee0 (patch)
treeafced1fbf72d517378453a67bb182265216c85c1 /openmp/libompd
parent560221ac7f5ca3d5dcae405587db066f4c4c8a7c (diff)
downloadllvm-b0277bef9739d5e3a3feb89ff9c1aaa90a801ee0.tar.gz
[OpenMP][OMPD] Implementation of OMPD debugging library - libompd.
This is a continuation of the review: https://reviews.llvm.org/D100183 It contains routines that retrieve OpenMP ICV values for OMPD. Reviewed By: @hbae Differential Revision: https://reviews.llvm.org/D100184
Diffstat (limited to 'openmp/libompd')
-rw-r--r--openmp/libompd/src/CMakeLists.txt5
-rw-r--r--openmp/libompd/src/omp-icv.cpp1276
-rw-r--r--openmp/libompd/src/omp-state.cpp64
3 files changed, 1341 insertions, 4 deletions
diff --git a/openmp/libompd/src/CMakeLists.txt b/openmp/libompd/src/CMakeLists.txt
index d5958a4e4d8d..9c203bdd6b4f 100644
--- a/openmp/libompd/src/CMakeLists.txt
+++ b/openmp/libompd/src/CMakeLists.txt
@@ -11,7 +11,7 @@
project (libompd)
cmake_minimum_required(VERSION 3.13.4)
-add_library (ompd SHARED TargetValue.cpp omp-debug.cpp)
+add_library (ompd SHARED TargetValue.cpp omp-debug.cpp omp-state.cpp omp-icv.cpp)
add_dependencies(ompd omp) # ensure generated import library is created first
@@ -38,9 +38,6 @@ if(${LIBOMPD_LD_STD_FLAGS})
endif()
endif()
-#TODO: Required temporarily for lib to build as during patch submission.
-#when lld used, it expects every symbol to be defined, whereas a few function defined as a part of the next patch
-string(REPLACE "-Wl,-z,defs" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
include_directories (
${CMAKE_CURRENT_SOURCE_DIR}
${LIBOMP_INCLUDE_DIR}
diff --git a/openmp/libompd/src/omp-icv.cpp b/openmp/libompd/src/omp-icv.cpp
new file mode 100644
index 000000000000..4a2c2b6e8bc6
--- /dev/null
+++ b/openmp/libompd/src/omp-icv.cpp
@@ -0,0 +1,1276 @@
+/*
+ * omp-icv.cpp -- OMPD Internal Control Variable handling
+ */
+
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// clang-format off
+/* clang-format expect kmp.h before omp.h which results in build break
+ * due to a few redeclarations.
+ */
+#include "omp-debug.h"
+// NOLINTNEXTLINE "to avoid clang tidy warning for the same reason as above."
+#include "omp.h"
+#include "ompd-private.h"
+#include "TargetValue.h"
+#include "kmp.h"
+#include <cstring>
+
+/* The ICVs ompd-final-var and ompd-implicit-var below are for backward
+ * compatibility with 5.0.
+ */
+
+#define FOREACH_OMPD_ICV(macro) \
+ macro(dyn_var, "dyn-var", ompd_scope_thread, 0) \
+ macro(run_sched_var, "run-sched-var", ompd_scope_task, 0) \
+ macro(stacksize_var, "stacksize-var", ompd_scope_address_space, 0) \
+ macro(cancel_var, "cancel-var", ompd_scope_address_space, 0) \
+ macro(max_task_priority_var, "max-task-priority-var", ompd_scope_address_space, 0)\
+ macro(debug_var, "debug-var", ompd_scope_address_space, 0) \
+ macro(nthreads_var, "nthreads-var", ompd_scope_thread, 0) \
+ macro(display_affinity_var, "display-affinity-var", ompd_scope_address_space, 0) \
+ macro(affinity_format_var, "affinity-format-var", ompd_scope_address_space, 0) \
+ macro(default_device_var, "default-device-var", ompd_scope_thread, 0) \
+ macro(tool_var, "tool-var", ompd_scope_address_space, 0) \
+ macro(tool_libraries_var, "tool-libraries-var", ompd_scope_address_space, 0) \
+ macro(tool_verbose_init_var, "tool-verbose-init-var", ompd_scope_address_space, 0)\
+ macro(levels_var, "levels-var", ompd_scope_parallel, 1) \
+ macro(active_levels_var, "active-levels-var", ompd_scope_parallel, 0) \
+ macro(thread_limit_var, "thread-limit-var", ompd_scope_task, 0) \
+ macro(max_active_levels_var, "max-active-levels-var", ompd_scope_task, 0) \
+ macro(bind_var, "bind-var", ompd_scope_task, 0) \
+ macro(num_procs_var, "num-procs-var", ompd_scope_address_space, 0) \
+ macro(ompd_num_procs_var, "ompd-num-procs-var", ompd_scope_address_space, 0) \
+ macro(thread_num_var, "thread-num-var", ompd_scope_thread, 1) \
+ macro(ompd_thread_num_var, "ompd-thread-num-var", ompd_scope_thread, 1) \
+ macro(final_var, "final-task-var", ompd_scope_task, 0) \
+ macro(ompd_final_var, "ompd-final-var", ompd_scope_task, 0) \
+ macro(ompd_final_task_var, "ompd-final-task-var", ompd_scope_task, 0) \
+ macro(implicit_var, "implicit-task-var", ompd_scope_task, 0) \
+ macro(ompd_implicit_var, "ompd-implicit-var", ompd_scope_task, 0) \
+ macro(ompd_implicit_task_var, "ompd-implicit-task-var", ompd_scope_task, 0) \
+ macro(team_size_var, "team-size-var", ompd_scope_parallel, 1) \
+ macro(ompd_team_size_var, "ompd-team-size-var", ompd_scope_parallel, 1)
+
+void __ompd_init_icvs(const ompd_callbacks_t *table) { callbacks = table; }
+
+enum ompd_icv {
+ ompd_icv_undefined_marker =
+ 0, // ompd_icv_undefined is already defined in ompd.h
+#define ompd_icv_macro(v, n, s, d) ompd_icv_##v,
+ FOREACH_OMPD_ICV(ompd_icv_macro)
+#undef ompd_icv_macro
+ ompd_icv_after_last_icv
+};
+
+static const char *ompd_icv_string_values[] = {"undefined",
+#define ompd_icv_macro(v, n, s, d) n,
+ FOREACH_OMPD_ICV(ompd_icv_macro)
+#undef ompd_icv_macro
+};
+
+static const ompd_scope_t ompd_icv_scope_values[] = {
+ ompd_scope_global, // undefined marker
+#define ompd_icv_macro(v, n, s, d) s,
+ FOREACH_OMPD_ICV(ompd_icv_macro)
+#undef ompd_icv_macro
+};
+
+// clang-format on
+ompd_rc_t ompd_enumerate_icvs(ompd_address_space_handle_t *handle,
+ ompd_icv_id_t current, ompd_icv_id_t *next_id,
+ const char **next_icv_name,
+ ompd_scope_t *next_scope, int *more) {
+ if (!handle) {
+ return ompd_rc_stale_handle;
+ }
+ if (!next_id || !next_icv_name || !next_scope || !more) {
+ return ompd_rc_bad_input;
+ }
+ if (current + 1 >= ompd_icv_after_last_icv) {
+ return ompd_rc_bad_input;
+ }
+
+ *next_id = current + 1;
+
+ char *icv_name = NULL;
+ ompd_rc_t ret = callbacks->alloc_memory(
+ std::strlen(ompd_icv_string_values[*next_id]) + 1, (void **)&icv_name);
+ *next_icv_name = icv_name;
+ if (ret != ompd_rc_ok) {
+ return ret;
+ }
+ std::strcpy(icv_name, ompd_icv_string_values[*next_id]);
+
+ *next_scope = ompd_icv_scope_values[*next_id];
+
+ if ((*next_id) + 1 >= ompd_icv_after_last_icv) {
+ *more = 0;
+ } else {
+ *more = 1;
+ }
+
+ return ompd_rc_ok;
+}
+
+static ompd_rc_t create_empty_string(const char **empty_string_ptr) {
+ char *empty_str;
+ ompd_rc_t ret;
+
+ if (!callbacks) {
+ return ompd_rc_callback_error;
+ }
+ ret = callbacks->alloc_memory(1, (void **)&empty_str);
+ if (ret != ompd_rc_ok) {
+ return ret;
+ }
+ empty_str[0] = '\0';
+ *empty_string_ptr = empty_str;
+ return ompd_rc_ok;
+}
+
+static ompd_rc_t ompd_get_dynamic(
+ ompd_thread_handle_t *thread_handle, /* IN: OpenMP thread handle */
+ ompd_word_t *dyn_val /* OUT: Dynamic adjustment of threads */
+) {
+ 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;
+ }
+
+ int8_t dynamic;
+ ompd_rc_t ret =
+ 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)
+ .access("td_icvs") /*__kmp_threads[t]->th.th_current_task->td_icvs*/
+ .cast("kmp_internal_control_t", 0)
+ .access(
+ "dynamic") /*__kmp_threads[t]->th.th_current_task->td_icvs.dynamic*/
+ .castBase()
+ .getValue(dynamic);
+ *dyn_val = dynamic;
+ return ret;
+}
+
+static ompd_rc_t
+ompd_get_stacksize(ompd_address_space_handle_t
+ *addr_handle, /* IN: handle for the address space */
+ ompd_word_t *stacksize_val /* OUT: per thread stack size */
+) {
+ ompd_address_space_context_t *context = addr_handle->context;
+ if (!context)
+ return ompd_rc_stale_handle;
+ ompd_rc_t ret;
+ if (!callbacks) {
+ return ompd_rc_callback_error;
+ }
+
+ size_t stacksize;
+ ret = TValue(context, "__kmp_stksize")
+ .castBase("__kmp_stksize")
+ .getValue(stacksize);
+ *stacksize_val = stacksize;
+ return ret;
+}
+
+static ompd_rc_t ompd_get_cancellation(
+ ompd_address_space_handle_t
+ *addr_handle, /* IN: handle for the address space */
+ ompd_word_t *cancellation_val /* OUT: cancellation value */
+) {
+ ompd_address_space_context_t *context = addr_handle->context;
+ if (!context)
+ return ompd_rc_stale_handle;
+ if (!callbacks) {
+ return ompd_rc_callback_error;
+ }
+ ompd_rc_t ret;
+
+ int omp_cancellation;
+ ret = TValue(context, "__kmp_omp_cancellation")
+ .castBase("__kmp_omp_cancellation")
+ .getValue(omp_cancellation);
+ *cancellation_val = omp_cancellation;
+ return ret;
+}
+
+static ompd_rc_t ompd_get_max_task_priority(
+ ompd_address_space_handle_t
+ *addr_handle, /* IN: handle for the address space */
+ ompd_word_t *max_task_priority_val /* OUT: max task priority value */
+) {
+ ompd_address_space_context_t *context = addr_handle->context;
+ if (!context)
+ return ompd_rc_stale_handle;
+ if (!callbacks) {
+ return ompd_rc_callback_error;
+ }
+ ompd_rc_t ret;
+
+ int max_task_priority;
+ ret = TValue(context, "__kmp_max_task_priority")
+ .castBase("__kmp_max_task_priority")
+ .getValue(max_task_priority);
+ *max_task_priority_val = max_task_priority;
+ return ret;
+}
+
+static ompd_rc_t
+ompd_get_debug(ompd_address_space_handle_t
+ *addr_handle, /* IN: handle for the address space */
+ ompd_word_t *debug_val /* OUT: debug value */
+) {
+ ompd_address_space_context_t *context = addr_handle->context;
+ if (!context)
+ return ompd_rc_stale_handle;
+ if (!callbacks) {
+ return ompd_rc_callback_error;
+ }
+ ompd_rc_t ret;
+
+ uint64_t ompd_state_val;
+ ret = TValue(context, "ompd_state")
+ .castBase("ompd_state")
+ .getValue(ompd_state_val);
+ if (ompd_state_val > 0) {
+ *debug_val = 1;
+ } else {
+ *debug_val = 0;
+ }
+ return ret;
+}
+
+/* Helper routine for the ompd_get_nthreads routines */
+static ompd_rc_t ompd_get_nthreads_aux(ompd_thread_handle_t *thread_handle,
+ uint32_t *used,
+ uint32_t *current_nesting_level,
+ uint32_t *nproc) {
+ 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_rc_t ret = TValue(context, "__kmp_nested_nth")
+ .cast("kmp_nested_nthreads_t")
+ .access("used")
+ .castBase(ompd_type_int)
+ .getValue(*used);
+ if (ret != ompd_rc_ok)
+ return ret;
+
+ 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
+ .access("td_team") /*__kmp_threads[t]->th.th_current_task.td_team*/
+ .cast("kmp_team_p", 1)
+ .access("t") /*__kmp_threads[t]->th.th_current_task.td_team->t*/
+ .cast("kmp_base_team_t", 0) /*t*/
+ .access("t_level") /*t.t_level*/
+ .castBase(ompd_type_int)
+ .getValue(*current_nesting_level);
+ if (ret != ompd_rc_ok)
+ return ret;
+
+ ret = taskdata.cast("kmp_taskdata_t", 1)
+ .access("td_icvs") /*__kmp_threads[t]->th.th_current_task->td_icvs*/
+ .cast("kmp_internal_control_t", 0)
+ .access(
+ "nproc") /*__kmp_threads[t]->th.th_current_task->td_icvs.nproc*/
+ .castBase(ompd_type_int)
+ .getValue(*nproc);
+ if (ret != ompd_rc_ok)
+ return ret;
+
+ return ompd_rc_ok;
+}
+
+static ompd_rc_t ompd_get_nthreads(
+ ompd_thread_handle_t *thread_handle, /* IN: handle for the thread */
+ ompd_word_t *nthreads_var_val /* OUT: nthreads-var (of integer type)
+ value */
+) {
+ uint32_t used;
+ uint32_t nproc;
+ uint32_t current_nesting_level;
+
+ ompd_rc_t ret;
+ ret = ompd_get_nthreads_aux(thread_handle, &used, &current_nesting_level,
+ &nproc);
+ if (ret != ompd_rc_ok)
+ return ret;
+
+ /*__kmp_threads[t]->th.th_current_task->td_icvs.nproc*/
+ *nthreads_var_val = nproc;
+ /* If the nthreads-var is a list with more than one element, then the value of
+ this ICV cannot be represented by an integer type. In this case,
+ ompd_rc_incomplete is returned. The tool can check the return value and
+ can choose to invoke ompd_get_icv_string_from_scope() if needed. */
+ if (current_nesting_level < used - 1) {
+ return ompd_rc_incomplete;
+ }
+ return ompd_rc_ok;
+}
+
+static ompd_rc_t ompd_get_nthreads(
+ ompd_thread_handle_t *thread_handle, /* IN: handle for the thread */
+ const char **nthreads_list_string /* OUT: string list of comma separated
+ nthreads values */
+) {
+ uint32_t used;
+ uint32_t nproc;
+ uint32_t current_nesting_level;
+
+ ompd_rc_t ret;
+ ret = ompd_get_nthreads_aux(thread_handle, &used, &current_nesting_level,
+ &nproc);
+ if (ret != ompd_rc_ok)
+ return ret;
+
+ uint32_t num_list_elems;
+ if (used == 0 || current_nesting_level >= used) {
+ num_list_elems = 1;
+ } else {
+ num_list_elems = used - current_nesting_level;
+ }
+ size_t buffer_size = 16 /* digits per element including the comma separator */
+ * num_list_elems +
+ 1; /* string terminator NULL */
+ char *nthreads_list_str;
+ ret = callbacks->alloc_memory(buffer_size, (void **)&nthreads_list_str);
+ if (ret != ompd_rc_ok)
+ return ret;
+
+ /* The nthreads-var list would be:
+ [__kmp_threads[t]->th.th_current_task->td_icvs.nproc,
+ __kmp_nested_nth.nth[current_nesting_level + 1],
+ __kmp_nested_nth.nth[current_nesting_level + 2],
+ …,
+ __kmp_nested_nth.nth[used - 1]]*/
+
+ sprintf(nthreads_list_str, "%d", nproc);
+ *nthreads_list_string = nthreads_list_str;
+ if (num_list_elems == 1) {
+ return ompd_rc_ok;
+ }
+
+ char temp_value[16];
+ uint32_t nth_value;
+
+ for (current_nesting_level++; /* the list element for this nesting
+ * level has already been accounted for
+ by nproc */
+ current_nesting_level < used; current_nesting_level++) {
+
+ ret = TValue(thread_handle->ah->context, "__kmp_nested_nth")
+ .cast("kmp_nested_nthreads_t")
+ .access("nth")
+ .cast("int", 1)
+ .getArrayElement(current_nesting_level)
+ .castBase(ompd_type_int)
+ .getValue(nth_value);
+
+ if (ret != ompd_rc_ok)
+ return ret;
+
+ sprintf(temp_value, ",%d", nth_value);
+ strcat(nthreads_list_str, temp_value);
+ }
+
+ return ompd_rc_ok;
+}
+
+static ompd_rc_t ompd_get_display_affinity(
+ ompd_address_space_handle_t
+ *addr_handle, /* IN: handle for the address space */
+ ompd_word_t *display_affinity_val /* OUT: display affinity value */
+) {
+ ompd_address_space_context_t *context = addr_handle->context;
+ if (!context)
+ return ompd_rc_stale_handle;
+ ompd_rc_t ret;
+
+ if (!callbacks) {
+ return ompd_rc_callback_error;
+ }
+ ret = TValue(context, "__kmp_display_affinity")
+ .castBase("__kmp_display_affinity")
+ .getValue(*display_affinity_val);
+ return ret;
+}
+
+static ompd_rc_t ompd_get_affinity_format(
+ ompd_address_space_handle_t *addr_handle, /* IN: address space handle*/
+ const char **affinity_format_string /* OUT: affinity format string */
+) {
+ ompd_address_space_context_t *context = addr_handle->context;
+ if (!context)
+ return ompd_rc_stale_handle;
+
+ if (!callbacks) {
+ return ompd_rc_callback_error;
+ }
+ ompd_rc_t ret;
+ ret = TValue(context, "__kmp_affinity_format")
+ .cast("char", 1)
+ .getString(affinity_format_string);
+ return ret;
+}
+
+static ompd_rc_t ompd_get_tool_libraries(
+ ompd_address_space_handle_t *addr_handle, /* IN: address space handle*/
+ const char **tool_libraries_string /* OUT: tool libraries string */
+) {
+ if (!tool_libraries_string)
+ return ompd_rc_bad_input;
+
+ ompd_address_space_context_t *context = addr_handle->context;
+ if (!context)
+ return ompd_rc_stale_handle;
+
+ if (!callbacks) {
+ return ompd_rc_callback_error;
+ }
+ ompd_rc_t ret;
+ ret = TValue(context, "__kmp_tool_libraries")
+ .cast("char", 1)
+ .getString(tool_libraries_string);
+ if (ret == ompd_rc_unsupported) {
+ ret = create_empty_string(tool_libraries_string);
+ }
+ return ret;
+}
+
+static ompd_rc_t ompd_get_default_device(
+ ompd_thread_handle_t *thread_handle, /* IN: handle for the thread */
+ ompd_word_t *default_device_val /* OUT: default device value */
+) {
+ 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_rc_t ret =
+ 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)
+ .access("td_icvs") /*__kmp_threads[t]->th.th_current_task->td_icvs*/
+ .cast("kmp_internal_control_t", 0)
+ /*__kmp_threads[t]->th.th_current_task->td_icvs.default_device*/
+ .access("default_device")
+ .castBase()
+ .getValue(*default_device_val);
+ return ret;
+}
+
+static ompd_rc_t
+ompd_get_tool(ompd_address_space_handle_t
+ *addr_handle, /* IN: handle for the address space */
+ ompd_word_t *tool_val /* OUT: tool value */
+) {
+ ompd_address_space_context_t *context = addr_handle->context;
+ if (!context)
+ return ompd_rc_stale_handle;
+ if (!callbacks) {
+ return ompd_rc_callback_error;
+ }
+ ompd_rc_t ret;
+
+ ret =
+ TValue(context, "__kmp_tool").castBase("__kmp_tool").getValue(*tool_val);
+ return ret;
+}
+
+static ompd_rc_t ompd_get_tool_verbose_init(
+ ompd_address_space_handle_t *addr_handle, /* IN: address space handle*/
+ const char **tool_verbose_init_string /* OUT: tool verbose init string */
+) {
+ ompd_address_space_context_t *context = addr_handle->context;
+ if (!context)
+ return ompd_rc_stale_handle;
+
+ if (!callbacks) {
+ return ompd_rc_callback_error;
+ }
+ ompd_rc_t ret;
+ ret = TValue(context, "__kmp_tool_verbose_init")
+ .cast("char", 1)
+ .getString(tool_verbose_init_string);
+ if (ret == ompd_rc_unsupported) {
+ ret = create_empty_string(tool_verbose_init_string);
+ }
+ return ret;
+}
+
+static ompd_rc_t ompd_get_level(
+ ompd_parallel_handle_t *parallel_handle, /* IN: OpenMP parallel handle */
+ ompd_word_t *val /* OUT: nesting level */
+) {
+ 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;
+ }
+
+ uint32_t res;
+
+ ompd_rc_t ret = TValue(context, parallel_handle->th)
+ .cast("kmp_base_team_t", 0) /*t*/
+ .access("t_level") /*t.t_level*/
+ .castBase()
+ .getValue(res);
+ *val = res;
+ return ret;
+}
+
+static ompd_rc_t ompd_get_active_level(
+ ompd_parallel_handle_t *parallel_handle, /* IN: OpenMP parallel handle */
+ ompd_word_t *val /* OUT: active nesting level */
+) {
+ 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;
+ }
+
+ uint32_t res;
+
+ ompd_rc_t ret = TValue(context, parallel_handle->th)
+ .cast("kmp_base_team_t", 0) /*t*/
+ .access("t_active_level") /*t.t_active_level*/
+ .castBase()
+ .getValue(res);
+ *val = res;
+ return ret;
+}
+
+static ompd_rc_t
+ompd_get_num_procs(ompd_address_space_handle_t
+ *addr_handle, /* IN: handle for the address space */
+ ompd_word_t *val /* OUT: number of processes */
+) {
+ ompd_address_space_context_t *context = addr_handle->context;
+ if (!context)
+ return ompd_rc_stale_handle;
+ if (!callbacks) {
+ return ompd_rc_callback_error;
+ }
+
+ if (!val)
+ return ompd_rc_bad_input;
+ ompd_rc_t ret;
+
+ int nth;
+ ret = TValue(context, "__kmp_avail_proc")
+ .castBase("__kmp_avail_proc")
+ .getValue(nth);
+ *val = nth;
+ return ret;
+}
+
+static ompd_rc_t ompd_get_thread_limit(
+ ompd_task_handle_t *task_handle, /* IN: OpenMP task handle*/
+ ompd_word_t *val /* OUT: max number of threads */
+) {
+ 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_rc_t ret = TValue(context, task_handle->th)
+ .cast("kmp_taskdata_t") // td
+ .access("td_icvs") // td->td_icvs
+ .cast("kmp_internal_control_t", 0)
+ .access("thread_limit") // td->td_icvs.thread_limit
+ .castBase()
+ .getValue(*val);
+
+ return ret;
+}
+
+static ompd_rc_t ompd_get_thread_num(
+ ompd_thread_handle_t *thread_handle, /* IN: OpenMP thread handle*/
+ ompd_word_t *val /* OUT: number of the thread within the team */
+) {
+ 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_rc_t 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_tid") /*__kmp_threads[t]->th.th_info.ds.ds_tid*/
+ .castBase()
+ .getValue(*val);
+ return ret;
+}
+
+static ompd_rc_t
+ompd_in_final(ompd_task_handle_t *task_handle, /* IN: OpenMP task handle*/
+ ompd_word_t *val /* OUT: max number of threads */
+) {
+ 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_rc_t ret = TValue(context, task_handle->th)
+ .cast("kmp_taskdata_t") // td
+ .access("td_flags") // td->td_flags
+ .cast("kmp_tasking_flags_t")
+ .check("final", val); // td->td_flags.tasktype
+
+ return ret;
+}
+
+static ompd_rc_t ompd_get_max_active_levels(
+ ompd_task_handle_t *task_handle, /* IN: OpenMP task handle*/
+ ompd_word_t *val /* OUT: max number of threads */
+) {
+ 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_rc_t ret =
+ TValue(context, task_handle->th)
+ .cast("kmp_taskdata_t") // td
+ .access("td_icvs") // td->td_icvs
+ .cast("kmp_internal_control_t", 0)
+ .access("max_active_levels") // td->td_icvs.max_active_levels
+ .castBase()
+ .getValue(*val);
+
+ return ret;
+}
+
+static ompd_rc_t ompd_get_run_schedule(
+ ompd_task_handle_t *task_handle, /* IN: OpenMP task handle*/
+ const char **run_sched_string /* OUT: Run Schedule String
+ consisting of kind and modifier */
+) {
+ 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;
+ }
+
+ int kind;
+
+ TValue sched = TValue(context, task_handle->th)
+ .cast("kmp_taskdata_t") // td
+ .access("td_icvs") // td->td_icvs
+ .cast("kmp_internal_control_t", 0)
+ .access("sched") // td->td_icvs.sched
+ .cast("kmp_r_sched_t", 0);
+
+ ompd_rc_t ret = sched
+ .access("r_sched_type") // td->td_icvs.sched.r_sched_type
+ .castBase()
+ .getValue(kind);
+ if (ret != ompd_rc_ok) {
+ return ret;
+ }
+ int chunk = 0;
+ ret = sched
+ .access("chunk") // td->td_icvs.sched.chunk
+ .castBase()
+ .getValue(chunk);
+ if (ret != ompd_rc_ok) {
+ return ret;
+ }
+ char *run_sched_var_string;
+ ret = callbacks->alloc_memory(100, (void **)&run_sched_var_string);
+ if (ret != ompd_rc_ok) {
+ return ret;
+ }
+ run_sched_var_string[0] = '\0';
+ if (SCHEDULE_HAS_MONOTONIC(kind)) {
+ strcpy(run_sched_var_string, "monotonic:");
+ } else if (SCHEDULE_HAS_NONMONOTONIC(kind)) {
+ strcpy(run_sched_var_string, "nonmonotonic:");
+ }
+
+ bool static_unchunked = false;
+ switch (SCHEDULE_WITHOUT_MODIFIERS(kind)) {
+ case kmp_sch_static:
+ case kmp_sch_static_greedy:
+ case kmp_sch_static_balanced:
+ static_unchunked = true;
+ strcat(run_sched_var_string, "static");
+ break;
+ case kmp_sch_static_chunked:
+ strcat(run_sched_var_string, "static");
+ break;
+ case kmp_sch_dynamic_chunked:
+ strcat(run_sched_var_string, "dynamic");
+ break;
+ case kmp_sch_guided_chunked:
+ case kmp_sch_guided_iterative_chunked:
+ case kmp_sch_guided_analytical_chunked:
+ strcat(run_sched_var_string, "guided");
+ break;
+ case kmp_sch_auto:
+ strcat(run_sched_var_string, "auto");
+ break;
+ case kmp_sch_trapezoidal:
+ strcat(run_sched_var_string, "trapezoidal");
+ break;
+ case kmp_sch_static_steal:
+ strcat(run_sched_var_string, "static_steal");
+ break;
+ default:
+ ret = callbacks->free_memory((void *)(run_sched_var_string));
+ if (ret != ompd_rc_ok) {
+ return ret;
+ }
+ ret = create_empty_string(run_sched_string);
+ return ret;
+ }
+
+ if (static_unchunked == true) {
+ // To be in sync with what OMPT returns.
+ // Chunk was not set. Shown with a zero value.
+ chunk = 0;
+ }
+
+ char temp_str[16];
+ sprintf(temp_str, ",%d", chunk);
+ strcat(run_sched_var_string, temp_str);
+ *run_sched_string = run_sched_var_string;
+ return ret;
+}
+
+/* Helper routine for the ompd_get_proc_bind routines */
+static ompd_rc_t ompd_get_proc_bind_aux(ompd_task_handle_t *task_handle,
+ uint32_t *used,
+ uint32_t *current_nesting_level,
+ uint32_t *proc_bind) {
+ 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_rc_t ret = TValue(context, "__kmp_nested_proc_bind")
+ .cast("kmp_nested_proc_bind_t")
+ .access("used")
+ .castBase(ompd_type_int)
+ .getValue(*used);
+ if (ret != ompd_rc_ok)
+ return ret;
+
+ TValue taskdata = TValue(context, task_handle->th) /* td */
+ .cast("kmp_taskdata_t");
+
+ 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) /*t*/
+ .access("t_level") /*t.t_level*/
+ .castBase(ompd_type_int)
+ .getValue(*current_nesting_level);
+ if (ret != ompd_rc_ok)
+ return ret;
+
+ ret = taskdata
+ .access("td_icvs") /* td->td_icvs */
+ .cast("kmp_internal_control_t", 0)
+ .access("proc_bind") /* td->td_icvs.proc_bind */
+ .castBase()
+ .getValue(*proc_bind);
+ return ret;
+}
+
+static ompd_rc_t
+ompd_get_proc_bind(ompd_task_handle_t *task_handle, /* IN: OpenMP task handle */
+ ompd_word_t *bind /* OUT: Kind of proc-binding */
+) {
+ uint32_t used;
+ uint32_t proc_bind;
+ uint32_t current_nesting_level;
+
+ ompd_rc_t ret;
+ ret = ompd_get_proc_bind_aux(task_handle, &used, &current_nesting_level,
+ &proc_bind);
+ if (ret != ompd_rc_ok)
+ return ret;
+
+ *bind = proc_bind;
+ /* If bind-var is a list with more than one element, then the value of
+ this ICV cannot be represented by an integer type. In this case,
+ ompd_rc_incomplete is returned. The tool can check the return value and
+ can choose to invoke ompd_get_icv_string_from_scope() if needed. */
+ if (current_nesting_level < used - 1) {
+ return ompd_rc_incomplete;
+ }
+ return ompd_rc_ok;
+}
+
+static ompd_rc_t ompd_get_proc_bind(
+ ompd_task_handle_t *task_handle, /* IN: OpenMP task handle */
+ const char **proc_bind_list_string /* OUT: string list of comma separated
+ bind-var values */
+) {
+ uint32_t used;
+ uint32_t proc_bind;
+ uint32_t current_nesting_level;
+
+ ompd_rc_t ret;
+ ret = ompd_get_proc_bind_aux(task_handle, &used, &current_nesting_level,
+ &proc_bind);
+ if (ret != ompd_rc_ok)
+ return ret;
+
+ uint32_t num_list_elems;
+ if (used == 0 || current_nesting_level >= used) {
+ num_list_elems = 1;
+ } else {
+ num_list_elems = used - current_nesting_level;
+ }
+ size_t buffer_size = 16 /* digits per element including the comma separator */
+ * num_list_elems +
+ 1; /* string terminator NULL */
+ char *proc_bind_list_str;
+ ret = callbacks->alloc_memory(buffer_size, (void **)&proc_bind_list_str);
+ if (ret != ompd_rc_ok)
+ return ret;
+
+ /* The bind-var list would be:
+ [td->td_icvs.proc_bind,
+ __kmp_nested_proc_bind.bind_types[current_nesting_level + 1],
+ __kmp_nested_proc_bind.bind_types[current_nesting_level + 2],
+ …,
+ __kmp_nested_proc_bind.bind_types[used - 1]]*/
+
+ sprintf(proc_bind_list_str, "%d", proc_bind);
+ *proc_bind_list_string = proc_bind_list_str;
+ if (num_list_elems == 1) {
+ return ompd_rc_ok;
+ }
+
+ char temp_value[16];
+ uint32_t bind_types_value;
+
+ for (current_nesting_level++; /* the list element for this nesting
+ level has already been accounted for
+ by proc_bind */
+ current_nesting_level < used; current_nesting_level++) {
+
+ ret = TValue(task_handle->ah->context, "__kmp_nested_proc_bind")
+ .cast("kmp_nested_proc_bind_t")
+ .access("bind_types")
+ .cast("int", 1)
+ .getArrayElement(current_nesting_level)
+ .castBase(ompd_type_int)
+ .getValue(bind_types_value);
+
+ if (ret != ompd_rc_ok)
+ return ret;
+
+ sprintf(temp_value, ",%d", bind_types_value);
+ strcat(proc_bind_list_str, temp_value);
+ }
+
+ return ompd_rc_ok;
+}
+
+static ompd_rc_t
+ompd_is_implicit(ompd_task_handle_t *task_handle, /* IN: OpenMP task handle*/
+ ompd_word_t *val /* OUT: max number of threads */
+) {
+ 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_rc_t 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
+ *val ^= 1; // tasktype: explicit = 1, implicit = 0 => invert the value
+ return ret;
+}
+
+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 */
+) {
+ 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_rc_ok;
+ if (parallel_handle->lwt.address != 0) {
+ *val = 1;
+ } else {
+ uint32_t res;
+ ret = TValue(context, parallel_handle->th)
+ .cast("kmp_base_team_t", 0) /*t*/
+ .access("t_nproc") /*t.t_nproc*/
+ .castBase()
+ .getValue(res);
+ *val = res;
+ }
+ return ret;
+}
+
+ompd_rc_t ompd_get_icv_from_scope(void *handle, ompd_scope_t scope,
+ ompd_icv_id_t icv_id,
+ ompd_word_t *icv_value) {
+ if (!handle) {
+ return ompd_rc_stale_handle;
+ }
+ if (icv_id >= ompd_icv_after_last_icv || icv_id == 0) {
+ return ompd_rc_bad_input;
+ }
+ if (scope != ompd_icv_scope_values[icv_id]) {
+ return ompd_rc_bad_input;
+ }
+
+ ompd_device_t device_kind;
+
+ switch (scope) {
+ case ompd_scope_thread:
+ device_kind = ((ompd_thread_handle_t *)handle)->ah->kind;
+ break;
+ case ompd_scope_parallel:
+ device_kind = ((ompd_parallel_handle_t *)handle)->ah->kind;
+ break;
+ case ompd_scope_address_space:
+ device_kind = ((ompd_address_space_handle_t *)handle)->kind;
+ break;
+ case ompd_scope_task:
+ device_kind = ((ompd_task_handle_t *)handle)->ah->kind;
+ break;
+ default:
+ return ompd_rc_bad_input;
+ }
+
+ if (device_kind == OMPD_DEVICE_KIND_HOST) {
+ switch (icv_id) {
+ case ompd_icv_dyn_var:
+ return ompd_get_dynamic((ompd_thread_handle_t *)handle, icv_value);
+ case ompd_icv_run_sched_var:
+ return ompd_rc_incompatible;
+ case ompd_icv_stacksize_var:
+ return ompd_get_stacksize((ompd_address_space_handle_t *)handle,
+ icv_value);
+ case ompd_icv_cancel_var:
+ return ompd_get_cancellation((ompd_address_space_handle_t *)handle,
+ icv_value);
+ case ompd_icv_max_task_priority_var:
+ return ompd_get_max_task_priority((ompd_address_space_handle_t *)handle,
+ icv_value);
+ case ompd_icv_debug_var:
+ return ompd_get_debug((ompd_address_space_handle_t *)handle, icv_value);
+ case ompd_icv_nthreads_var:
+ return ompd_get_nthreads((ompd_thread_handle_t *)handle, icv_value);
+ case ompd_icv_display_affinity_var:
+ return ompd_get_display_affinity((ompd_address_space_handle_t *)handle,
+ icv_value);
+ case ompd_icv_affinity_format_var:
+ return ompd_rc_incompatible;
+ case ompd_icv_tool_libraries_var:
+ return ompd_rc_incompatible;
+ case ompd_icv_default_device_var:
+ return ompd_get_default_device((ompd_thread_handle_t *)handle, icv_value);
+ case ompd_icv_tool_var:
+ return ompd_get_tool((ompd_address_space_handle_t *)handle, icv_value);
+ case ompd_icv_tool_verbose_init_var:
+ return ompd_rc_incompatible;
+ case ompd_icv_levels_var:
+ return ompd_get_level((ompd_parallel_handle_t *)handle, icv_value);
+ case ompd_icv_active_levels_var:
+ return ompd_get_active_level((ompd_parallel_handle_t *)handle, icv_value);
+ case ompd_icv_thread_limit_var:
+ return ompd_get_thread_limit((ompd_task_handle_t *)handle, icv_value);
+ case ompd_icv_max_active_levels_var:
+ return ompd_get_max_active_levels((ompd_task_handle_t *)handle,
+ icv_value);
+ case ompd_icv_bind_var:
+ return ompd_get_proc_bind((ompd_task_handle_t *)handle, icv_value);
+ case ompd_icv_num_procs_var:
+ case ompd_icv_ompd_num_procs_var:
+ return ompd_get_num_procs((ompd_address_space_handle_t *)handle,
+ icv_value);
+ case ompd_icv_thread_num_var:
+ case ompd_icv_ompd_thread_num_var:
+ return ompd_get_thread_num((ompd_thread_handle_t *)handle, icv_value);
+ case ompd_icv_final_var:
+ case ompd_icv_ompd_final_var:
+ case ompd_icv_ompd_final_task_var:
+ return ompd_in_final((ompd_task_handle_t *)handle, icv_value);
+ case ompd_icv_implicit_var:
+ case ompd_icv_ompd_implicit_var:
+ case ompd_icv_ompd_implicit_task_var:
+ return ompd_is_implicit((ompd_task_handle_t *)handle, icv_value);
+ case ompd_icv_team_size_var:
+ case ompd_icv_ompd_team_size_var:
+ return ompd_get_num_threads((ompd_parallel_handle_t *)handle, icv_value);
+ default:
+ return ompd_rc_unsupported;
+ }
+ }
+ return ompd_rc_unsupported;
+}
+
+ompd_rc_t ompd_get_icv_string_from_scope(void *handle, ompd_scope_t scope,
+ ompd_icv_id_t icv_id,
+ const char **icv_string) {
+ if (!handle) {
+ return ompd_rc_stale_handle;
+ }
+ if (icv_id >= ompd_icv_after_last_icv || icv_id == 0) {
+ return ompd_rc_bad_input;
+ }
+ if (scope != ompd_icv_scope_values[icv_id]) {
+ return ompd_rc_bad_input;
+ }
+
+ ompd_device_t device_kind;
+
+ switch (scope) {
+ case ompd_scope_thread:
+ device_kind = ((ompd_thread_handle_t *)handle)->ah->kind;
+ break;
+ case ompd_scope_parallel:
+ device_kind = ((ompd_parallel_handle_t *)handle)->ah->kind;
+ break;
+ case ompd_scope_address_space:
+ device_kind = ((ompd_address_space_handle_t *)handle)->kind;
+ break;
+ case ompd_scope_task:
+ device_kind = ((ompd_task_handle_t *)handle)->ah->kind;
+ break;
+ default:
+ return ompd_rc_bad_input;
+ }
+
+ if (device_kind == OMPD_DEVICE_KIND_HOST) {
+ switch (icv_id) {
+ case ompd_icv_run_sched_var:
+ return ompd_get_run_schedule((ompd_task_handle_t *)handle, icv_string);
+ case ompd_icv_nthreads_var:
+ return ompd_get_nthreads((ompd_thread_handle_t *)handle, icv_string);
+ case ompd_icv_bind_var:
+ return ompd_get_proc_bind((ompd_task_handle_t *)handle, icv_string);
+ case ompd_icv_affinity_format_var:
+ return ompd_get_affinity_format((ompd_address_space_handle_t *)handle,
+ icv_string);
+ case ompd_icv_tool_libraries_var:
+ return ompd_get_tool_libraries((ompd_address_space_handle_t *)handle,
+ icv_string);
+ case ompd_icv_tool_verbose_init_var:
+ return ompd_get_tool_verbose_init((ompd_address_space_handle_t *)handle,
+ icv_string);
+ default:
+ return ompd_rc_unsupported;
+ }
+ }
+ return ompd_rc_unsupported;
+}
+
+static ompd_rc_t __ompd_get_tool_data(TValue &dataValue, ompd_word_t *value,
+ ompd_address_t *ptr) {
+ ompd_rc_t ret = dataValue.getError();
+ if (ret != ompd_rc_ok)
+ return ret;
+ ret = dataValue.access("value").castBase().getValue(*value);
+ if (ret != ompd_rc_ok)
+ return ret;
+ ptr->segment = OMPD_SEGMENT_UNSPECIFIED;
+ ret = dataValue.access("ptr").castBase().getValue(ptr->address);
+ return ret;
+}
+
+ompd_rc_t ompd_get_task_data(ompd_task_handle_t *task_handle,
+ ompd_word_t *value, ompd_address_t *ptr) {
+ ompd_address_space_context_t *context = task_handle->ah->context;
+ if (!context)
+ return ompd_rc_stale_handle;
+ if (!callbacks) {
+ return ompd_rc_callback_error;
+ }
+
+ TValue dataValue;
+ if (task_handle->lwt.address) {
+ dataValue = TValue(context, task_handle->lwt)
+ .cast("ompt_lw_taskteam_t") /*lwt*/
+ .access("ompt_task_info") // lwt->ompt_task_info
+ .cast("ompt_task_info_t")
+ .access("task_data") // lwt->ompd_task_info.task_data
+ .cast("ompt_data_t");
+ } else {
+ dataValue = TValue(context, task_handle->th)
+ .cast("kmp_taskdata_t") /*td*/
+ .access("ompt_task_info") // td->ompt_task_info
+ .cast("ompt_task_info_t")
+ .access("task_data") // td->ompd_task_info.task_data
+ .cast("ompt_data_t");
+ }
+ return __ompd_get_tool_data(dataValue, value, ptr);
+}
+
+ompd_rc_t ompd_get_parallel_data(ompd_parallel_handle_t *parallel_handle,
+ ompd_word_t *value, ompd_address_t *ptr) {
+ ompd_address_space_context_t *context = parallel_handle->ah->context;
+ if (!context)
+ return ompd_rc_stale_handle;
+ if (!callbacks) {
+ return ompd_rc_callback_error;
+ }
+
+ TValue dataValue;
+ if (parallel_handle->lwt.address) {
+ dataValue =
+ TValue(context, parallel_handle->lwt)
+ .cast("ompt_lw_taskteam_t") /*lwt*/
+ .access("ompt_team_info") // lwt->ompt_team_info
+ .cast("ompt_team_info_t")
+ .access("parallel_data") // lwt->ompt_team_info.parallel_data
+ .cast("ompt_data_t");
+ } else {
+ dataValue = TValue(context, parallel_handle->th)
+ .cast("kmp_base_team_t") /*t*/
+ .access("ompt_team_info") // t->ompt_team_info
+ .cast("ompt_team_info_t")
+ .access("parallel_data") // t->ompt_team_info.parallel_data
+ .cast("ompt_data_t");
+ }
+ return __ompd_get_tool_data(dataValue, value, ptr);
+}
+
+ompd_rc_t ompd_get_thread_data(ompd_thread_handle_t *thread_handle,
+ ompd_word_t *value, ompd_address_t *ptr) {
+ ompd_address_space_context_t *context = thread_handle->ah->context;
+ if (!context)
+ return ompd_rc_stale_handle;
+ if (!callbacks) {
+ return ompd_rc_callback_error;
+ }
+
+ TValue dataValue =
+ TValue(context, thread_handle->th)
+ .cast("kmp_base_info_t") /*th*/
+ .access("ompt_thread_info") // th->ompt_thread_info
+ .cast("ompt_thread_info_t")
+ .access("thread_data") // th->ompt_thread_info.thread_data
+ .cast("ompt_data_t");
+ return __ompd_get_tool_data(dataValue, value, ptr);
+}
+
+ompd_rc_t ompd_get_tool_data(void *handle, ompd_scope_t scope,
+ ompd_word_t *value, ompd_address_t *ptr) {
+ if (!handle) {
+ return ompd_rc_stale_handle;
+ }
+
+ ompd_device_t device_kind;
+
+ switch (scope) {
+ case ompd_scope_thread:
+ device_kind = ((ompd_thread_handle_t *)handle)->ah->kind;
+ break;
+ case ompd_scope_parallel:
+ device_kind = ((ompd_parallel_handle_t *)handle)->ah->kind;
+ break;
+ case ompd_scope_task:
+ device_kind = ((ompd_task_handle_t *)handle)->ah->kind;
+ break;
+ default:
+ return ompd_rc_bad_input;
+ }
+
+ if (device_kind == OMPD_DEVICE_KIND_HOST) {
+ switch (scope) {
+ case ompd_scope_thread:
+ return ompd_get_thread_data((ompd_thread_handle_t *)handle, value, ptr);
+ case ompd_scope_parallel:
+ return ompd_get_parallel_data((ompd_parallel_handle_t *)handle, value,
+ ptr);
+ case ompd_scope_task:
+ return ompd_get_task_data((ompd_task_handle_t *)handle, value, ptr);
+ default:
+ return ompd_rc_unsupported;
+ }
+ }
+ return ompd_rc_unsupported;
+}
diff --git a/openmp/libompd/src/omp-state.cpp b/openmp/libompd/src/omp-state.cpp
new file mode 100644
index 000000000000..ca87907aa6b2
--- /dev/null
+++ b/openmp/libompd/src/omp-state.cpp
@@ -0,0 +1,64 @@
+/*
+ * omp-state.cpp -- OMPD states
+ */
+
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "omp-debug.h"
+#include "ompd-private.h"
+#include <cstring>
+
+void __ompd_init_states(const ompd_callbacks_t *table) { callbacks = table; }
+
+static const char *get_ompd_state_name(ompd_word_t state) {
+ switch (state) {
+#define ompd_state_macro(state, code) \
+ case code: \
+ return #state;
+ FOREACH_OMPD_STATE(ompd_state_macro)
+#undef ompd_state_macro
+ default:
+ return NULL;
+ }
+}
+
+ompd_rc_t
+ompd_enumerate_states(ompd_address_space_handle_t *address_space_handle,
+ ompd_word_t current_state, ompd_word_t *next_state,
+ const char **next_state_name, ompd_word_t *more_enums) {
+ ompd_rc_t ret;
+ if (current_state > ompt_state_undefined &&
+ current_state >= OMPD_LAST_OMP_STATE) {
+ return ompd_rc_bad_input;
+ }
+ const char *find_next_state_name;
+ *next_state = (current_state == ompt_state_undefined ? ompt_state_work_serial
+ : current_state + 1);
+ while (!(find_next_state_name = get_ompd_state_name(*next_state))) {
+ ++(*next_state);
+ }
+
+ char *next_state_name_cpy;
+ ret = callbacks->alloc_memory(strlen(find_next_state_name) + 1,
+ (void **)&next_state_name_cpy);
+ if (ret != ompd_rc_ok) {
+ return ret;
+ }
+ strcpy(next_state_name_cpy, find_next_state_name);
+
+ *next_state_name = next_state_name_cpy;
+
+ if (*next_state == OMPD_LAST_OMP_STATE) {
+ *more_enums = 0;
+ } else {
+ *more_enums = 1;
+ }
+
+ return ompd_rc_ok;
+}