brintos

brintos / llvm-project-archived public Read only

0
0
Text · 42.0 KiB · 0288e96 Raw
1279 lines · cpp
1/*2 * omp-icv.cpp -- OMPD Internal Control Variable handling3 */4 5//===----------------------------------------------------------------------===//6//7// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.8// See https://llvm.org/LICENSE.txt for license information.9// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception10//11//===----------------------------------------------------------------------===//12// clang-format off13/* clang-format expect kmp.h before omp.h which results in build break14 * due to a few redeclarations.15 */16#include "omp-debug.h"17// NOLINTNEXTLINE "to avoid clang tidy warning for the same reason as above."18#include "omp.h"19#include "ompd-private.h"20#include "TargetValue.h"21#define OMPD_SKIP_HWLOC 122#include "kmp.h"23#undef OMPD_SKIP_HWLOC24#include <cstring>25 26/* The ICVs ompd-final-var and ompd-implicit-var below are for backward27 * compatibility with 5.0.28 */29 30#define FOREACH_OMPD_ICV(macro)                                                     \31  macro(dyn_var, "dyn-var", ompd_scope_thread, 0)                                   \32  macro(run_sched_var, "run-sched-var", ompd_scope_task, 0)                         \33  macro(stacksize_var, "stacksize-var", ompd_scope_address_space, 0)                \34  macro(cancel_var, "cancel-var", ompd_scope_address_space, 0)                      \35  macro(max_task_priority_var, "max-task-priority-var", ompd_scope_address_space, 0)\36  macro(debug_var, "debug-var", ompd_scope_address_space, 0)                        \37  macro(nthreads_var, "nthreads-var", ompd_scope_thread, 0)                         \38  macro(display_affinity_var, "display-affinity-var", ompd_scope_address_space, 0)  \39  macro(affinity_format_var, "affinity-format-var", ompd_scope_address_space, 0)    \40  macro(default_device_var, "default-device-var", ompd_scope_thread, 0)             \41  macro(tool_var, "tool-var", ompd_scope_address_space, 0)                          \42  macro(tool_libraries_var, "tool-libraries-var", ompd_scope_address_space, 0)      \43  macro(tool_verbose_init_var, "tool-verbose-init-var", ompd_scope_address_space, 0)\44  macro(levels_var, "levels-var", ompd_scope_parallel, 1)                           \45  macro(active_levels_var, "active-levels-var", ompd_scope_parallel, 0)             \46  macro(thread_limit_var, "thread-limit-var", ompd_scope_task, 0)                   \47  macro(max_active_levels_var, "max-active-levels-var", ompd_scope_task, 0)         \48  macro(bind_var, "bind-var", ompd_scope_task, 0)                                   \49  macro(num_procs_var, "num-procs-var", ompd_scope_address_space, 0)                \50  macro(ompd_num_procs_var, "ompd-num-procs-var", ompd_scope_address_space, 0)      \51  macro(thread_num_var, "thread-num-var", ompd_scope_thread, 1)                     \52  macro(ompd_thread_num_var, "ompd-thread-num-var", ompd_scope_thread, 1)           \53  macro(final_var, "final-task-var", ompd_scope_task, 0)                            \54  macro(ompd_final_var, "ompd-final-var", ompd_scope_task, 0)                       \55  macro(ompd_final_task_var, "ompd-final-task-var", ompd_scope_task, 0)             \56  macro(implicit_var, "implicit-task-var", ompd_scope_task, 0)                      \57  macro(ompd_implicit_var, "ompd-implicit-var", ompd_scope_task, 0)                 \58  macro(ompd_implicit_task_var, "ompd-implicit-task-var", ompd_scope_task, 0)       \59  macro(team_size_var, "team-size-var", ompd_scope_parallel, 1)                     \60  macro(ompd_team_size_var, "ompd-team-size-var", ompd_scope_parallel, 1)61 62void __ompd_init_icvs(const ompd_callbacks_t *table) { callbacks = table; }63 64enum ompd_icv {65  ompd_icv_undefined_marker =66      0, // ompd_icv_undefined is already defined in ompd.h67#define ompd_icv_macro(v, n, s, d) ompd_icv_##v,68  FOREACH_OMPD_ICV(ompd_icv_macro)69#undef ompd_icv_macro70      ompd_icv_after_last_icv71};72 73static const char *ompd_icv_string_values[] = {"undefined",74#define ompd_icv_macro(v, n, s, d) n,75  FOREACH_OMPD_ICV(ompd_icv_macro)76#undef ompd_icv_macro77};78 79static const ompd_scope_t ompd_icv_scope_values[] = {80    ompd_scope_global, // undefined marker81#define ompd_icv_macro(v, n, s, d) s,82    FOREACH_OMPD_ICV(ompd_icv_macro)83#undef ompd_icv_macro84};85 86// clang-format on87ompd_rc_t ompd_enumerate_icvs(ompd_address_space_handle_t *handle,88                              ompd_icv_id_t current, ompd_icv_id_t *next_id,89                              const char **next_icv_name,90                              ompd_scope_t *next_scope, int *more) {91  if (!handle) {92    return ompd_rc_stale_handle;93  }94  if (!next_id || !next_icv_name || !next_scope || !more) {95    return ompd_rc_bad_input;96  }97  if (current + 1 >= ompd_icv_after_last_icv) {98    return ompd_rc_bad_input;99  }100 101  *next_id = current + 1;102 103  char *icv_name = NULL;104  ompd_rc_t ret = callbacks->alloc_memory(105      std::strlen(ompd_icv_string_values[*next_id]) + 1, (void **)&icv_name);106  *next_icv_name = icv_name;107  if (ret != ompd_rc_ok) {108    return ret;109  }110  std::strcpy(icv_name, ompd_icv_string_values[*next_id]);111 112  *next_scope = ompd_icv_scope_values[*next_id];113 114  if ((*next_id) + 1 >= ompd_icv_after_last_icv) {115    *more = 0;116  } else {117    *more = 1;118  }119 120  return ompd_rc_ok;121}122 123static ompd_rc_t create_empty_string(const char **empty_string_ptr) {124  char *empty_str;125  ompd_rc_t ret;126 127  if (!callbacks) {128    return ompd_rc_callback_error;129  }130  ret = callbacks->alloc_memory(1, (void **)&empty_str);131  if (ret != ompd_rc_ok) {132    return ret;133  }134  empty_str[0] = '\0';135  *empty_string_ptr = empty_str;136  return ompd_rc_ok;137}138 139static ompd_rc_t ompd_get_dynamic(140    ompd_thread_handle_t *thread_handle, /* IN: OpenMP thread handle */141    ompd_word_t *dyn_val /* OUT: Dynamic adjustment of threads */142) {143  if (!thread_handle)144    return ompd_rc_stale_handle;145  if (!thread_handle->ah)146    return ompd_rc_stale_handle;147  ompd_address_space_context_t *context = thread_handle->ah->context;148  if (!context)149    return ompd_rc_stale_handle;150  if (!callbacks) {151    return ompd_rc_callback_error;152  }153 154  int8_t dynamic;155  ompd_rc_t ret =156      TValue(context, thread_handle->th) /*__kmp_threads[t]->th*/157          .cast("kmp_base_info_t")158          .access("th_current_task") /*__kmp_threads[t]->th.th_current_task*/159          .cast("kmp_taskdata_t", 1)160          .access("td_icvs") /*__kmp_threads[t]->th.th_current_task->td_icvs*/161          .cast("kmp_internal_control_t", 0)162          .access(163              "dynamic") /*__kmp_threads[t]->th.th_current_task->td_icvs.dynamic*/164          .castBase()165          .getValue(dynamic);166  *dyn_val = dynamic;167  return ret;168}169 170static ompd_rc_t171ompd_get_stacksize(ompd_address_space_handle_t172                       *addr_handle, /* IN: handle for the address space */173                   ompd_word_t *stacksize_val /* OUT: per thread stack size */174) {175  ompd_address_space_context_t *context = addr_handle->context;176  if (!context)177    return ompd_rc_stale_handle;178  ompd_rc_t ret;179  if (!callbacks) {180    return ompd_rc_callback_error;181  }182 183  size_t stacksize;184  ret = TValue(context, "__kmp_stksize")185            .castBase("__kmp_stksize")186            .getValue(stacksize);187  *stacksize_val = stacksize;188  return ret;189}190 191static ompd_rc_t ompd_get_cancellation(192    ompd_address_space_handle_t193        *addr_handle,             /* IN: handle for the address space */194    ompd_word_t *cancellation_val /* OUT: cancellation value */195) {196  ompd_address_space_context_t *context = addr_handle->context;197  if (!context)198    return ompd_rc_stale_handle;199  if (!callbacks) {200    return ompd_rc_callback_error;201  }202  ompd_rc_t ret;203 204  int omp_cancellation;205  ret = TValue(context, "__kmp_omp_cancellation")206            .castBase("__kmp_omp_cancellation")207            .getValue(omp_cancellation);208  *cancellation_val = omp_cancellation;209  return ret;210}211 212static ompd_rc_t ompd_get_max_task_priority(213    ompd_address_space_handle_t214        *addr_handle,                  /* IN: handle for the address space */215    ompd_word_t *max_task_priority_val /* OUT: max task priority value */216) {217  ompd_address_space_context_t *context = addr_handle->context;218  if (!context)219    return ompd_rc_stale_handle;220  if (!callbacks) {221    return ompd_rc_callback_error;222  }223  ompd_rc_t ret;224 225  int max_task_priority;226  ret = TValue(context, "__kmp_max_task_priority")227            .castBase("__kmp_max_task_priority")228            .getValue(max_task_priority);229  *max_task_priority_val = max_task_priority;230  return ret;231}232 233static ompd_rc_t234ompd_get_debug(ompd_address_space_handle_t235                   *addr_handle,      /* IN: handle for the address space */236               ompd_word_t *debug_val /* OUT: debug value */237) {238  ompd_address_space_context_t *context = addr_handle->context;239  if (!context)240    return ompd_rc_stale_handle;241  if (!callbacks) {242    return ompd_rc_callback_error;243  }244  ompd_rc_t ret;245 246  uint64_t ompd_state_val;247  ret = TValue(context, "ompd_state")248            .castBase("ompd_state")249            .getValue(ompd_state_val);250  if (ompd_state_val > 0) {251    *debug_val = 1;252  } else {253    *debug_val = 0;254  }255  return ret;256}257 258/* Helper routine for the ompd_get_nthreads routines */259static ompd_rc_t ompd_get_nthreads_aux(ompd_thread_handle_t *thread_handle,260                                       uint32_t *used,261                                       uint32_t *current_nesting_level,262                                       uint32_t *nproc) {263  if (!thread_handle)264    return ompd_rc_stale_handle;265  if (!thread_handle->ah)266    return ompd_rc_stale_handle;267  ompd_address_space_context_t *context = thread_handle->ah->context;268  if (!context)269    return ompd_rc_stale_handle;270  if (!callbacks) {271    return ompd_rc_callback_error;272  }273 274  ompd_rc_t ret = TValue(context, "__kmp_nested_nth")275                      .cast("kmp_nested_nthreads_t")276                      .access("used")277                      .castBase(ompd_type_int)278                      .getValue(*used);279  if (ret != ompd_rc_ok)280    return ret;281 282  TValue taskdata =283      TValue(context, thread_handle->th) /*__kmp_threads[t]->th*/284          .cast("kmp_base_info_t")285          .access("th_current_task") /*__kmp_threads[t]->th.th_current_task*/286          .cast("kmp_taskdata_t", 1);287 288  ret = taskdata289            .access("td_team") /*__kmp_threads[t]->th.th_current_task.td_team*/290            .cast("kmp_team_p", 1)291            .access("t") /*__kmp_threads[t]->th.th_current_task.td_team->t*/292            .cast("kmp_base_team_t", 0) /*t*/293            .access("t_level")          /*t.t_level*/294            .castBase(ompd_type_int)295            .getValue(*current_nesting_level);296  if (ret != ompd_rc_ok)297    return ret;298 299  ret = taskdata.cast("kmp_taskdata_t", 1)300            .access("td_icvs") /*__kmp_threads[t]->th.th_current_task->td_icvs*/301            .cast("kmp_internal_control_t", 0)302            .access(303                "nproc") /*__kmp_threads[t]->th.th_current_task->td_icvs.nproc*/304            .castBase(ompd_type_int)305            .getValue(*nproc);306  if (ret != ompd_rc_ok)307    return ret;308 309  return ompd_rc_ok;310}311 312static ompd_rc_t ompd_get_nthreads(313    ompd_thread_handle_t *thread_handle, /* IN: handle for the thread */314    ompd_word_t *nthreads_var_val        /* OUT: nthreads-var (of integer type)315                                            value */316) {317  uint32_t used;318  uint32_t nproc;319  uint32_t current_nesting_level;320 321  ompd_rc_t ret;322  ret = ompd_get_nthreads_aux(thread_handle, &used, &current_nesting_level,323                              &nproc);324  if (ret != ompd_rc_ok)325    return ret;326 327  /*__kmp_threads[t]->th.th_current_task->td_icvs.nproc*/328  *nthreads_var_val = nproc;329  /* If the nthreads-var is a list with more than one element, then the value of330     this ICV cannot be represented by an integer type. In this case,331     ompd_rc_incomplete is returned. The tool can check the return value and332     can choose to invoke ompd_get_icv_string_from_scope() if needed. */333  if (current_nesting_level < used - 1) {334    return ompd_rc_incomplete;335  }336  return ompd_rc_ok;337}338 339static ompd_rc_t ompd_get_nthreads(340    ompd_thread_handle_t *thread_handle, /* IN: handle for the thread */341    const char **nthreads_list_string    /* OUT: string list of comma separated342                                            nthreads values */343) {344  uint32_t used;345  uint32_t nproc;346  uint32_t current_nesting_level;347 348  ompd_rc_t ret;349  ret = ompd_get_nthreads_aux(thread_handle, &used, &current_nesting_level,350                              &nproc);351  if (ret != ompd_rc_ok)352    return ret;353 354  uint32_t num_list_elems;355  if (used == 0 || current_nesting_level >= used) {356    num_list_elems = 1;357  } else {358    num_list_elems = used - current_nesting_level;359  }360  size_t buffer_size = 16 /* digits per element including the comma separator */361                           * num_list_elems +362                       1; /* string terminator NULL */363  char *nthreads_list_str;364  ret = callbacks->alloc_memory(buffer_size, (void **)&nthreads_list_str);365  if (ret != ompd_rc_ok)366    return ret;367 368  /* The nthreads-var list would be:369  [__kmp_threads[t]->th.th_current_task->td_icvs.nproc,370   __kmp_nested_nth.nth[current_nesting_level + 1],371   __kmp_nested_nth.nth[current_nesting_level + 2],372    …,373   __kmp_nested_nth.nth[used - 1]]*/374 375  sprintf(nthreads_list_str, "%d", nproc);376  *nthreads_list_string = nthreads_list_str;377  if (num_list_elems == 1) {378    return ompd_rc_ok;379  }380 381  char temp_value[16];382  uint32_t nth_value;383 384  for (current_nesting_level++; /* the list element for this nesting385                                 * level has already been accounted for386                                   by nproc */387       current_nesting_level < used; current_nesting_level++) {388 389    ret = TValue(thread_handle->ah->context, "__kmp_nested_nth")390              .cast("kmp_nested_nthreads_t")391              .access("nth")392              .cast("int", 1)393              .getArrayElement(current_nesting_level)394              .castBase(ompd_type_int)395              .getValue(nth_value);396 397    if (ret != ompd_rc_ok)398      return ret;399 400    sprintf(temp_value, ",%d", nth_value);401    strcat(nthreads_list_str, temp_value);402  }403 404  return ompd_rc_ok;405}406 407static ompd_rc_t ompd_get_display_affinity(408    ompd_address_space_handle_t409        *addr_handle,                 /* IN: handle for the address space */410    ompd_word_t *display_affinity_val /* OUT: display affinity value */411) {412  ompd_address_space_context_t *context = addr_handle->context;413  if (!context)414    return ompd_rc_stale_handle;415  ompd_rc_t ret;416 417  if (!callbacks) {418    return ompd_rc_callback_error;419  }420  ret = TValue(context, "__kmp_display_affinity")421            .castBase("__kmp_display_affinity")422            .getValue(*display_affinity_val);423  return ret;424}425 426static ompd_rc_t ompd_get_affinity_format(427    ompd_address_space_handle_t *addr_handle, /* IN: address space handle*/428    const char **affinity_format_string       /* OUT: affinity format string */429) {430  ompd_address_space_context_t *context = addr_handle->context;431  if (!context)432    return ompd_rc_stale_handle;433 434  if (!callbacks) {435    return ompd_rc_callback_error;436  }437  ompd_rc_t ret;438  ret = TValue(context, "__kmp_affinity_format")439            .cast("char", 1)440            .getString(affinity_format_string);441  return ret;442}443 444static ompd_rc_t ompd_get_tool_libraries(445    ompd_address_space_handle_t *addr_handle, /* IN: address space handle*/446    const char **tool_libraries_string        /* OUT: tool libraries string */447) {448  if (!tool_libraries_string)449    return ompd_rc_bad_input;450 451  ompd_address_space_context_t *context = addr_handle->context;452  if (!context)453    return ompd_rc_stale_handle;454 455  if (!callbacks) {456    return ompd_rc_callback_error;457  }458  ompd_rc_t ret;459  ret = TValue(context, "__kmp_tool_libraries")460            .cast("char", 1)461            .getString(tool_libraries_string);462  if (ret == ompd_rc_unsupported) {463    ret = create_empty_string(tool_libraries_string);464  }465  return ret;466}467 468static ompd_rc_t ompd_get_default_device(469    ompd_thread_handle_t *thread_handle, /* IN: handle for the thread */470    ompd_word_t *default_device_val      /* OUT: default device value */471) {472  if (!thread_handle)473    return ompd_rc_stale_handle;474  if (!thread_handle->ah)475    return ompd_rc_stale_handle;476  ompd_address_space_context_t *context = thread_handle->ah->context;477  if (!context)478    return ompd_rc_stale_handle;479  if (!callbacks)480    return ompd_rc_callback_error;481 482  ompd_rc_t ret =483      TValue(context, thread_handle->th) /*__kmp_threads[t]->th*/484          .cast("kmp_base_info_t")485          .access("th_current_task") /*__kmp_threads[t]->th.th_current_task*/486          .cast("kmp_taskdata_t", 1)487          .access("td_icvs") /*__kmp_threads[t]->th.th_current_task->td_icvs*/488          .cast("kmp_internal_control_t", 0)489          /*__kmp_threads[t]->th.th_current_task->td_icvs.default_device*/490          .access("default_device")491          .castBase()492          .getValue(*default_device_val);493  return ret;494}495 496static ompd_rc_t497ompd_get_tool(ompd_address_space_handle_t498                  *addr_handle,     /* IN: handle for the address space */499              ompd_word_t *tool_val /* OUT: tool value */500) {501  ompd_address_space_context_t *context = addr_handle->context;502  if (!context)503    return ompd_rc_stale_handle;504  if (!callbacks) {505    return ompd_rc_callback_error;506  }507  ompd_rc_t ret;508 509  ret =510      TValue(context, "__kmp_tool").castBase("__kmp_tool").getValue(*tool_val);511  return ret;512}513 514static ompd_rc_t ompd_get_tool_verbose_init(515    ompd_address_space_handle_t *addr_handle, /* IN: address space handle*/516    const char **tool_verbose_init_string /* OUT: tool verbose init string */517) {518  ompd_address_space_context_t *context = addr_handle->context;519  if (!context)520    return ompd_rc_stale_handle;521 522  if (!callbacks) {523    return ompd_rc_callback_error;524  }525  ompd_rc_t ret;526  ret = TValue(context, "__kmp_tool_verbose_init")527            .cast("char", 1)528            .getString(tool_verbose_init_string);529  if (ret == ompd_rc_unsupported) {530    ret = create_empty_string(tool_verbose_init_string);531  }532  return ret;533}534 535static ompd_rc_t ompd_get_level(536    ompd_parallel_handle_t *parallel_handle, /* IN: OpenMP parallel handle */537    ompd_word_t *val                         /* OUT: nesting level */538) {539  if (!parallel_handle->ah)540    return ompd_rc_stale_handle;541  ompd_address_space_context_t *context = parallel_handle->ah->context;542  if (!context)543    return ompd_rc_stale_handle;544 545  if (!callbacks) {546    return ompd_rc_callback_error;547  }548 549  uint32_t res;550 551  ompd_rc_t ret = TValue(context, parallel_handle->th)552                      .cast("kmp_base_team_t", 0) /*t*/553                      .access("t_level")          /*t.t_level*/554                      .castBase()555                      .getValue(res);556  *val = res;557  return ret;558}559 560static ompd_rc_t ompd_get_active_level(561    ompd_parallel_handle_t *parallel_handle, /* IN: OpenMP parallel handle */562    ompd_word_t *val                         /* OUT: active nesting level */563) {564  if (!parallel_handle->ah)565    return ompd_rc_stale_handle;566  ompd_address_space_context_t *context = parallel_handle->ah->context;567  if (!context)568    return ompd_rc_stale_handle;569  if (!callbacks) {570    return ompd_rc_callback_error;571  }572 573  uint32_t res;574 575  ompd_rc_t ret = TValue(context, parallel_handle->th)576                      .cast("kmp_base_team_t", 0) /*t*/577                      .access("t_active_level")   /*t.t_active_level*/578                      .castBase()579                      .getValue(res);580  *val = res;581  return ret;582}583 584static ompd_rc_t585ompd_get_num_procs(ompd_address_space_handle_t586                       *addr_handle, /* IN: handle for the address space */587                   ompd_word_t *val  /* OUT: number of processes */588) {589  ompd_address_space_context_t *context = addr_handle->context;590  if (!context)591    return ompd_rc_stale_handle;592  if (!callbacks) {593    return ompd_rc_callback_error;594  }595 596  if (!val)597    return ompd_rc_bad_input;598  ompd_rc_t ret;599 600  int nth;601  ret = TValue(context, "__kmp_avail_proc")602            .castBase("__kmp_avail_proc")603            .getValue(nth);604  *val = nth;605  return ret;606}607 608static ompd_rc_t ompd_get_thread_limit(609    ompd_task_handle_t *task_handle, /* IN: OpenMP task handle*/610    ompd_word_t *val                 /* OUT: max number of threads */611) {612  if (!task_handle->ah)613    return ompd_rc_stale_handle;614  ompd_address_space_context_t *context = task_handle->ah->context;615  if (!context)616    return ompd_rc_stale_handle;617  if (!callbacks) {618    return ompd_rc_callback_error;619  }620 621  ompd_rc_t ret = TValue(context, task_handle->th)622                      .cast("kmp_taskdata_t") // td623                      .access("td_icvs")      // td->td_icvs624                      .cast("kmp_internal_control_t", 0)625                      .access("thread_limit") // td->td_icvs.thread_limit626                      .castBase()627                      .getValue(*val);628 629  return ret;630}631 632static ompd_rc_t ompd_get_thread_num(633    ompd_thread_handle_t *thread_handle, /* IN: OpenMP thread handle*/634    ompd_word_t *val /* OUT: number of the thread within the team */635) {636  if (!thread_handle)637    return ompd_rc_stale_handle;638  if (!thread_handle->ah)639    return ompd_rc_stale_handle;640  ompd_address_space_context_t *context = thread_handle->ah->context;641  if (!context)642    return ompd_rc_stale_handle;643  if (!callbacks) {644    return ompd_rc_callback_error;645  }646 647  ompd_rc_t ret =648      TValue(context, thread_handle->th) /*__kmp_threads[t]->th*/649          .cast("kmp_base_info_t")650          .access("th_info") /*__kmp_threads[t]->th.th_info*/651          .cast("kmp_desc_t")652          .access("ds") /*__kmp_threads[t]->th.th_info.ds*/653          .cast("kmp_desc_base_t")654          .access("ds_tid") /*__kmp_threads[t]->th.th_info.ds.ds_tid*/655          .castBase()656          .getValue(*val);657  return ret;658}659 660static ompd_rc_t661ompd_in_final(ompd_task_handle_t *task_handle, /* IN: OpenMP task handle*/662              ompd_word_t *val                 /* OUT: max number of threads */663) {664  if (!task_handle->ah)665    return ompd_rc_stale_handle;666  ompd_address_space_context_t *context = task_handle->ah->context;667  if (!context)668    return ompd_rc_stale_handle;669  if (!callbacks) {670    return ompd_rc_callback_error;671  }672 673  ompd_rc_t ret = TValue(context, task_handle->th)674                      .cast("kmp_taskdata_t") // td675                      .access("td_flags")     // td->td_flags676                      .cast("kmp_tasking_flags_t")677                      .check("final", val); // td->td_flags.tasktype678 679  return ret;680}681 682static ompd_rc_t ompd_get_max_active_levels(683    ompd_task_handle_t *task_handle, /* IN: OpenMP task handle*/684    ompd_word_t *val                 /* OUT: max number of threads */685) {686  if (!task_handle->ah)687    return ompd_rc_stale_handle;688  ompd_address_space_context_t *context = task_handle->ah->context;689  if (!context)690    return ompd_rc_stale_handle;691  if (!callbacks) {692    return ompd_rc_callback_error;693  }694 695  ompd_rc_t ret =696      TValue(context, task_handle->th)697          .cast("kmp_taskdata_t") // td698          .access("td_icvs")      // td->td_icvs699          .cast("kmp_internal_control_t", 0)700          .access("max_active_levels") // td->td_icvs.max_active_levels701          .castBase()702          .getValue(*val);703 704  return ret;705}706 707static ompd_rc_t ompd_get_run_schedule(708    ompd_task_handle_t *task_handle, /* IN: OpenMP task handle*/709    const char **run_sched_string    /* OUT: Run Schedule String710                                        consisting of kind and modifier */711) {712  if (!task_handle->ah)713    return ompd_rc_stale_handle;714  ompd_address_space_context_t *context = task_handle->ah->context;715  if (!context)716    return ompd_rc_stale_handle;717  if (!callbacks) {718    return ompd_rc_callback_error;719  }720 721  int kind;722 723  TValue sched = TValue(context, task_handle->th)724                     .cast("kmp_taskdata_t") // td725                     .access("td_icvs")      // td->td_icvs726                     .cast("kmp_internal_control_t", 0)727                     .access("sched") // td->td_icvs.sched728                     .cast("kmp_r_sched_t", 0);729 730  ompd_rc_t ret = sched731                      .access("r_sched_type") // td->td_icvs.sched.r_sched_type732                      .castBase()733                      .getValue(kind);734  if (ret != ompd_rc_ok) {735    return ret;736  }737  int chunk = 0;738  ret = sched739            .access("chunk") // td->td_icvs.sched.chunk740            .castBase()741            .getValue(chunk);742  if (ret != ompd_rc_ok) {743    return ret;744  }745  char *run_sched_var_string;746  ret = callbacks->alloc_memory(100, (void **)&run_sched_var_string);747  if (ret != ompd_rc_ok) {748    return ret;749  }750  run_sched_var_string[0] = '\0';751  if (SCHEDULE_HAS_MONOTONIC(kind)) {752    strcpy(run_sched_var_string, "monotonic:");753  } else if (SCHEDULE_HAS_NONMONOTONIC(kind)) {754    strcpy(run_sched_var_string, "nonmonotonic:");755  }756 757  bool static_unchunked = false;758  switch (SCHEDULE_WITHOUT_MODIFIERS(kind)) {759  case kmp_sch_static:760  case kmp_sch_static_greedy:761  case kmp_sch_static_balanced:762    static_unchunked = true;763    strcat(run_sched_var_string, "static");764    break;765  case kmp_sch_static_chunked:766    strcat(run_sched_var_string, "static");767    break;768  case kmp_sch_dynamic_chunked:769    strcat(run_sched_var_string, "dynamic");770    break;771  case kmp_sch_guided_chunked:772  case kmp_sch_guided_iterative_chunked:773  case kmp_sch_guided_analytical_chunked:774    strcat(run_sched_var_string, "guided");775    break;776  case kmp_sch_auto:777    strcat(run_sched_var_string, "auto");778    break;779  case kmp_sch_trapezoidal:780    strcat(run_sched_var_string, "trapezoidal");781    break;782  case kmp_sch_static_steal:783    strcat(run_sched_var_string, "static_steal");784    break;785  default:786    ret = callbacks->free_memory((void *)(run_sched_var_string));787    if (ret != ompd_rc_ok) {788      return ret;789    }790    ret = create_empty_string(run_sched_string);791    return ret;792  }793 794  if (static_unchunked == true) {795    // To be in sync with what OMPT returns.796    // Chunk was not set. Shown with a zero value.797    chunk = 0;798  }799 800  char temp_str[16];801  sprintf(temp_str, ",%d", chunk);802  strcat(run_sched_var_string, temp_str);803  *run_sched_string = run_sched_var_string;804  return ret;805}806 807/* Helper routine for the ompd_get_proc_bind routines */808static ompd_rc_t ompd_get_proc_bind_aux(ompd_task_handle_t *task_handle,809                                        uint32_t *used,810                                        uint32_t *current_nesting_level,811                                        uint32_t *proc_bind) {812  if (!task_handle->ah)813    return ompd_rc_stale_handle;814  ompd_address_space_context_t *context = task_handle->ah->context;815  if (!context)816    return ompd_rc_stale_handle;817  if (!callbacks) {818    return ompd_rc_callback_error;819  }820 821  ompd_rc_t ret = TValue(context, "__kmp_nested_proc_bind")822                      .cast("kmp_nested_proc_bind_t")823                      .access("used")824                      .castBase(ompd_type_int)825                      .getValue(*used);826  if (ret != ompd_rc_ok)827    return ret;828 829  TValue taskdata = TValue(context, task_handle->th) /* td */830                        .cast("kmp_taskdata_t");831 832  ret = taskdata833            .access("td_team") /* td->td_team*/834            .cast("kmp_team_p", 1)835            .access("t")                /* td->td_team->t*/836            .cast("kmp_base_team_t", 0) /*t*/837            .access("t_level")          /*t.t_level*/838            .castBase(ompd_type_int)839            .getValue(*current_nesting_level);840  if (ret != ompd_rc_ok)841    return ret;842 843  ret = taskdata844            .access("td_icvs") /* td->td_icvs */845            .cast("kmp_internal_control_t", 0)846            .access("proc_bind") /* td->td_icvs.proc_bind */847            .castBase()848            .getValue(*proc_bind);849  return ret;850}851 852static ompd_rc_t853ompd_get_proc_bind(ompd_task_handle_t *task_handle, /* IN: OpenMP task handle */854                   ompd_word_t *bind /* OUT: Kind of proc-binding */855) {856  uint32_t used;857  uint32_t proc_bind;858  uint32_t current_nesting_level;859 860  ompd_rc_t ret;861  ret = ompd_get_proc_bind_aux(task_handle, &used, &current_nesting_level,862                               &proc_bind);863  if (ret != ompd_rc_ok)864    return ret;865 866  *bind = proc_bind;867  /* If bind-var is a list with more than one element, then the value of868     this ICV cannot be represented by an integer type. In this case,869     ompd_rc_incomplete is returned. The tool can check the return value and870     can choose to invoke ompd_get_icv_string_from_scope() if needed. */871  if (current_nesting_level < used - 1) {872    return ompd_rc_incomplete;873  }874  return ompd_rc_ok;875}876 877static ompd_rc_t ompd_get_proc_bind(878    ompd_task_handle_t *task_handle,   /* IN: OpenMP task handle */879    const char **proc_bind_list_string /* OUT: string list of comma separated880                                          bind-var values */881) {882  uint32_t used;883  uint32_t proc_bind;884  uint32_t current_nesting_level;885 886  ompd_rc_t ret;887  ret = ompd_get_proc_bind_aux(task_handle, &used, &current_nesting_level,888                               &proc_bind);889  if (ret != ompd_rc_ok)890    return ret;891 892  uint32_t num_list_elems;893  if (used == 0 || current_nesting_level >= used) {894    num_list_elems = 1;895  } else {896    num_list_elems = used - current_nesting_level;897  }898  size_t buffer_size = 16 /* digits per element including the comma separator */899                           * num_list_elems +900                       1; /* string terminator NULL */901  char *proc_bind_list_str;902  ret = callbacks->alloc_memory(buffer_size, (void **)&proc_bind_list_str);903  if (ret != ompd_rc_ok)904    return ret;905 906  /* The bind-var list would be:907  [td->td_icvs.proc_bind,908   __kmp_nested_proc_bind.bind_types[current_nesting_level + 1],909   __kmp_nested_proc_bind.bind_types[current_nesting_level + 2],910    …,911   __kmp_nested_proc_bind.bind_types[used - 1]]*/912 913  sprintf(proc_bind_list_str, "%d", proc_bind);914  *proc_bind_list_string = proc_bind_list_str;915  if (num_list_elems == 1) {916    return ompd_rc_ok;917  }918 919  char temp_value[16];920  uint32_t bind_types_value;921 922  for (current_nesting_level++; /* the list element for this nesting923                                   level has already been accounted for924                                   by proc_bind */925       current_nesting_level < used; current_nesting_level++) {926 927    ret = TValue(task_handle->ah->context, "__kmp_nested_proc_bind")928              .cast("kmp_nested_proc_bind_t")929              .access("bind_types")930              .cast("int", 1)931              .getArrayElement(current_nesting_level)932              .castBase(ompd_type_int)933              .getValue(bind_types_value);934 935    if (ret != ompd_rc_ok)936      return ret;937 938    sprintf(temp_value, ",%d", bind_types_value);939    strcat(proc_bind_list_str, temp_value);940  }941 942  return ompd_rc_ok;943}944 945static ompd_rc_t946ompd_is_implicit(ompd_task_handle_t *task_handle, /* IN: OpenMP task handle*/947                 ompd_word_t *val /* OUT: max number of threads */948) {949  if (!task_handle)950    return ompd_rc_stale_handle;951  if (!task_handle->ah)952    return ompd_rc_stale_handle;953  ompd_address_space_context_t *context = task_handle->ah->context;954  if (!context)955    return ompd_rc_stale_handle;956  if (!callbacks) {957    return ompd_rc_callback_error;958  }959 960  ompd_rc_t ret = TValue(context, task_handle->th)961                      .cast("kmp_taskdata_t") // td962                      .access("td_flags")     // td->td_flags963                      .cast("kmp_tasking_flags_t")964                      .check("tasktype", val); // td->td_flags.tasktype965  *val ^= 1; // tasktype: explicit = 1, implicit = 0 => invert the value966  return ret;967}968 969ompd_rc_t ompd_get_num_threads(970    ompd_parallel_handle_t *parallel_handle, /* IN: OpenMP parallel handle */971    ompd_word_t *val                         /* OUT: number of threads */972) {973  if (!parallel_handle->ah)974    return ompd_rc_stale_handle;975  ompd_address_space_context_t *context = parallel_handle->ah->context;976  if (!context)977    return ompd_rc_stale_handle;978  if (!callbacks) {979    return ompd_rc_callback_error;980  }981 982  ompd_rc_t ret = ompd_rc_ok;983  if (parallel_handle->lwt.address != 0) {984    *val = 1;985  } else {986    uint32_t res;987    ret = TValue(context, parallel_handle->th)988              .cast("kmp_base_team_t", 0) /*t*/989              .access("t_nproc")          /*t.t_nproc*/990              .castBase()991              .getValue(res);992    *val = res;993  }994  return ret;995}996 997ompd_rc_t ompd_get_icv_from_scope(void *handle, ompd_scope_t scope,998                                  ompd_icv_id_t icv_id,999                                  ompd_word_t *icv_value) {1000  if (!handle) {1001    return ompd_rc_stale_handle;1002  }1003  if (icv_id >= ompd_icv_after_last_icv || icv_id == 0) {1004    return ompd_rc_bad_input;1005  }1006  if (scope != ompd_icv_scope_values[icv_id]) {1007    return ompd_rc_bad_input;1008  }1009 1010  ompd_device_t device_kind;1011 1012  switch (scope) {1013  case ompd_scope_thread:1014    device_kind = ((ompd_thread_handle_t *)handle)->ah->kind;1015    break;1016  case ompd_scope_parallel:1017    device_kind = ((ompd_parallel_handle_t *)handle)->ah->kind;1018    break;1019  case ompd_scope_address_space:1020    device_kind = ((ompd_address_space_handle_t *)handle)->kind;1021    break;1022  case ompd_scope_task:1023    device_kind = ((ompd_task_handle_t *)handle)->ah->kind;1024    break;1025  default:1026    return ompd_rc_bad_input;1027  }1028 1029  if (device_kind == OMPD_DEVICE_KIND_HOST) {1030    switch (icv_id) {1031    case ompd_icv_dyn_var:1032      return ompd_get_dynamic((ompd_thread_handle_t *)handle, icv_value);1033    case ompd_icv_run_sched_var:1034      return ompd_rc_incompatible;1035    case ompd_icv_stacksize_var:1036      return ompd_get_stacksize((ompd_address_space_handle_t *)handle,1037                                icv_value);1038    case ompd_icv_cancel_var:1039      return ompd_get_cancellation((ompd_address_space_handle_t *)handle,1040                                   icv_value);1041    case ompd_icv_max_task_priority_var:1042      return ompd_get_max_task_priority((ompd_address_space_handle_t *)handle,1043                                        icv_value);1044    case ompd_icv_debug_var:1045      return ompd_get_debug((ompd_address_space_handle_t *)handle, icv_value);1046    case ompd_icv_nthreads_var:1047      return ompd_get_nthreads((ompd_thread_handle_t *)handle, icv_value);1048    case ompd_icv_display_affinity_var:1049      return ompd_get_display_affinity((ompd_address_space_handle_t *)handle,1050                                       icv_value);1051    case ompd_icv_affinity_format_var:1052      return ompd_rc_incompatible;1053    case ompd_icv_tool_libraries_var:1054      return ompd_rc_incompatible;1055    case ompd_icv_default_device_var:1056      return ompd_get_default_device((ompd_thread_handle_t *)handle, icv_value);1057    case ompd_icv_tool_var:1058      return ompd_get_tool((ompd_address_space_handle_t *)handle, icv_value);1059    case ompd_icv_tool_verbose_init_var:1060      return ompd_rc_incompatible;1061    case ompd_icv_levels_var:1062      return ompd_get_level((ompd_parallel_handle_t *)handle, icv_value);1063    case ompd_icv_active_levels_var:1064      return ompd_get_active_level((ompd_parallel_handle_t *)handle, icv_value);1065    case ompd_icv_thread_limit_var:1066      return ompd_get_thread_limit((ompd_task_handle_t *)handle, icv_value);1067    case ompd_icv_max_active_levels_var:1068      return ompd_get_max_active_levels((ompd_task_handle_t *)handle,1069                                        icv_value);1070    case ompd_icv_bind_var:1071      return ompd_get_proc_bind((ompd_task_handle_t *)handle, icv_value);1072    case ompd_icv_num_procs_var:1073    case ompd_icv_ompd_num_procs_var:1074      return ompd_get_num_procs((ompd_address_space_handle_t *)handle,1075                                icv_value);1076    case ompd_icv_thread_num_var:1077    case ompd_icv_ompd_thread_num_var:1078      return ompd_get_thread_num((ompd_thread_handle_t *)handle, icv_value);1079    case ompd_icv_final_var:1080    case ompd_icv_ompd_final_var:1081    case ompd_icv_ompd_final_task_var:1082      return ompd_in_final((ompd_task_handle_t *)handle, icv_value);1083    case ompd_icv_implicit_var:1084    case ompd_icv_ompd_implicit_var:1085    case ompd_icv_ompd_implicit_task_var:1086      return ompd_is_implicit((ompd_task_handle_t *)handle, icv_value);1087    case ompd_icv_team_size_var:1088    case ompd_icv_ompd_team_size_var:1089      return ompd_get_num_threads((ompd_parallel_handle_t *)handle, icv_value);1090    default:1091      return ompd_rc_unsupported;1092    }1093  }1094  return ompd_rc_unsupported;1095}1096 1097ompd_rc_t ompd_get_icv_string_from_scope(void *handle, ompd_scope_t scope,1098                                         ompd_icv_id_t icv_id,1099                                         const char **icv_string) {1100  if (!handle) {1101    return ompd_rc_stale_handle;1102  }1103  if (icv_id >= ompd_icv_after_last_icv || icv_id == 0) {1104    return ompd_rc_bad_input;1105  }1106  if (scope != ompd_icv_scope_values[icv_id]) {1107    return ompd_rc_bad_input;1108  }1109 1110  ompd_device_t device_kind;1111 1112  switch (scope) {1113  case ompd_scope_thread:1114    device_kind = ((ompd_thread_handle_t *)handle)->ah->kind;1115    break;1116  case ompd_scope_parallel:1117    device_kind = ((ompd_parallel_handle_t *)handle)->ah->kind;1118    break;1119  case ompd_scope_address_space:1120    device_kind = ((ompd_address_space_handle_t *)handle)->kind;1121    break;1122  case ompd_scope_task:1123    device_kind = ((ompd_task_handle_t *)handle)->ah->kind;1124    break;1125  default:1126    return ompd_rc_bad_input;1127  }1128 1129  if (device_kind == OMPD_DEVICE_KIND_HOST) {1130    switch (icv_id) {1131    case ompd_icv_run_sched_var:1132      return ompd_get_run_schedule((ompd_task_handle_t *)handle, icv_string);1133    case ompd_icv_nthreads_var:1134      return ompd_get_nthreads((ompd_thread_handle_t *)handle, icv_string);1135    case ompd_icv_bind_var:1136      return ompd_get_proc_bind((ompd_task_handle_t *)handle, icv_string);1137    case ompd_icv_affinity_format_var:1138      return ompd_get_affinity_format((ompd_address_space_handle_t *)handle,1139                                      icv_string);1140    case ompd_icv_tool_libraries_var:1141      return ompd_get_tool_libraries((ompd_address_space_handle_t *)handle,1142                                     icv_string);1143    case ompd_icv_tool_verbose_init_var:1144      return ompd_get_tool_verbose_init((ompd_address_space_handle_t *)handle,1145                                        icv_string);1146    default:1147      return ompd_rc_unsupported;1148    }1149  }1150  return ompd_rc_unsupported;1151}1152 1153static ompd_rc_t __ompd_get_tool_data(TValue &dataValue, ompd_word_t *value,1154                                      ompd_address_t *ptr) {1155  ompd_rc_t ret = dataValue.getError();1156  if (ret != ompd_rc_ok)1157    return ret;1158  ret = dataValue.access("value").castBase().getValue(*value);1159  if (ret != ompd_rc_ok)1160    return ret;1161  ptr->segment = OMPD_SEGMENT_UNSPECIFIED;1162  ret = dataValue.access("ptr").castBase().getValue(ptr->address);1163  return ret;1164}1165 1166ompd_rc_t ompd_get_task_data(ompd_task_handle_t *task_handle,1167                             ompd_word_t *value, ompd_address_t *ptr) {1168  ompd_address_space_context_t *context = task_handle->ah->context;1169  if (!context)1170    return ompd_rc_stale_handle;1171  if (!callbacks) {1172    return ompd_rc_callback_error;1173  }1174 1175  TValue dataValue;1176  if (task_handle->lwt.address) {1177    dataValue = TValue(context, task_handle->lwt)1178                    .cast("ompt_lw_taskteam_t") /*lwt*/1179                    .access("ompt_task_info")   // lwt->ompt_task_info1180                    .cast("ompt_task_info_t")1181                    .access("task_data") // lwt->ompd_task_info.task_data1182                    .cast("ompt_data_t");1183  } else {1184    dataValue = TValue(context, task_handle->th)1185                    .cast("kmp_taskdata_t")   /*td*/1186                    .access("ompt_task_info") // td->ompt_task_info1187                    .cast("ompt_task_info_t")1188                    .access("task_data") // td->ompd_task_info.task_data1189                    .cast("ompt_data_t");1190  }1191  return __ompd_get_tool_data(dataValue, value, ptr);1192}1193 1194ompd_rc_t ompd_get_parallel_data(ompd_parallel_handle_t *parallel_handle,1195                                 ompd_word_t *value, ompd_address_t *ptr) {1196  ompd_address_space_context_t *context = parallel_handle->ah->context;1197  if (!context)1198    return ompd_rc_stale_handle;1199  if (!callbacks) {1200    return ompd_rc_callback_error;1201  }1202 1203  TValue dataValue;1204  if (parallel_handle->lwt.address) {1205    dataValue =1206        TValue(context, parallel_handle->lwt)1207            .cast("ompt_lw_taskteam_t") /*lwt*/1208            .access("ompt_team_info")   // lwt->ompt_team_info1209            .cast("ompt_team_info_t")1210            .access("parallel_data") // lwt->ompt_team_info.parallel_data1211            .cast("ompt_data_t");1212  } else {1213    dataValue = TValue(context, parallel_handle->th)1214                    .cast("kmp_base_team_t")  /*t*/1215                    .access("ompt_team_info") // t->ompt_team_info1216                    .cast("ompt_team_info_t")1217                    .access("parallel_data") // t->ompt_team_info.parallel_data1218                    .cast("ompt_data_t");1219  }1220  return __ompd_get_tool_data(dataValue, value, ptr);1221}1222 1223ompd_rc_t ompd_get_thread_data(ompd_thread_handle_t *thread_handle,1224                               ompd_word_t *value, ompd_address_t *ptr) {1225  ompd_address_space_context_t *context = thread_handle->ah->context;1226  if (!context)1227    return ompd_rc_stale_handle;1228  if (!callbacks) {1229    return ompd_rc_callback_error;1230  }1231 1232  TValue dataValue =1233      TValue(context, thread_handle->th)1234          .cast("kmp_base_info_t")    /*th*/1235          .access("ompt_thread_info") // th->ompt_thread_info1236          .cast("ompt_thread_info_t")1237          .access("thread_data") // th->ompt_thread_info.thread_data1238          .cast("ompt_data_t");1239  return __ompd_get_tool_data(dataValue, value, ptr);1240}1241 1242ompd_rc_t ompd_get_tool_data(void *handle, ompd_scope_t scope,1243                             ompd_word_t *value, ompd_address_t *ptr) {1244  if (!handle) {1245    return ompd_rc_stale_handle;1246  }1247 1248  ompd_device_t device_kind;1249 1250  switch (scope) {1251  case ompd_scope_thread:1252    device_kind = ((ompd_thread_handle_t *)handle)->ah->kind;1253    break;1254  case ompd_scope_parallel:1255    device_kind = ((ompd_parallel_handle_t *)handle)->ah->kind;1256    break;1257  case ompd_scope_task:1258    device_kind = ((ompd_task_handle_t *)handle)->ah->kind;1259    break;1260  default:1261    return ompd_rc_bad_input;1262  }1263 1264  if (device_kind == OMPD_DEVICE_KIND_HOST) {1265    switch (scope) {1266    case ompd_scope_thread:1267      return ompd_get_thread_data((ompd_thread_handle_t *)handle, value, ptr);1268    case ompd_scope_parallel:1269      return ompd_get_parallel_data((ompd_parallel_handle_t *)handle, value,1270                                    ptr);1271    case ompd_scope_task:1272      return ompd_get_task_data((ompd_task_handle_t *)handle, value, ptr);1273    default:1274      return ompd_rc_unsupported;1275    }1276  }1277  return ompd_rc_unsupported;1278}1279