brintos

brintos / llvm-project-archived public Read only

0
0
Text · 31.6 KiB · 1a778e4 Raw
939 lines · cpp
1/*2 * ompt-general.cpp -- OMPT implementation of interface functions3 */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 13#include "kmp_utils.h"14 15/*****************************************************************************16 * system include files17 ****************************************************************************/18#include <assert.h>19 20#include <stdint.h>21#include <stdio.h>22#include <stdlib.h>23#include <string.h>24#if KMP_OS_UNIX25#include <dlfcn.h>26#endif27 28/*****************************************************************************29 * ompt include files30 ****************************************************************************/31 32#include "ompt-specific.cpp"33 34/*****************************************************************************35 * macros36 ****************************************************************************/37 38#define ompt_get_callback_success 139#define ompt_get_callback_failure 040 41#define no_tool_present 042 43#define OMPT_API_ROUTINE static44 45#ifndef OMPT_STR_MATCH46#define OMPT_STR_MATCH(haystack, needle) (!strcasecmp(haystack, needle))47#endif48 49// prints for an enabled OMP_TOOL_VERBOSE_INIT.50// In the future a prefix could be added in the first define, the second define51// omits the prefix to allow for continued lines. Example: "PREFIX: Start52// tool... Success." instead of "PREFIX: Start tool... PREFIX: Success."53#define OMPT_VERBOSE_INIT_PRINT(...)                                           \54  if (verbose_init)                                                            \55  fprintf(verbose_file, __VA_ARGS__)56#define OMPT_VERBOSE_INIT_CONTINUED_PRINT(...)                                 \57  if (verbose_init)                                                            \58  fprintf(verbose_file, __VA_ARGS__)59 60static FILE *verbose_file;61static int verbose_init;62 63/*****************************************************************************64 * types65 ****************************************************************************/66 67typedef struct {68  const char *state_name;69  ompt_state_t state_id;70} ompt_state_info_t;71 72typedef struct {73  const char *name;74  kmp_mutex_impl_t id;75} kmp_mutex_impl_info_t;76 77enum tool_setting_e {78  omp_tool_error,79  omp_tool_unset,80  omp_tool_disabled,81  omp_tool_enabled82};83 84/*****************************************************************************85 * global variables86 ****************************************************************************/87 88ompt_callbacks_active_t ompt_enabled;89 90ompt_state_info_t ompt_state_info[] = {91#define ompt_state_macro(state, code) {#state, state},92    FOREACH_OMPT_STATE(ompt_state_macro)93#undef ompt_state_macro94};95 96kmp_mutex_impl_info_t kmp_mutex_impl_info[] = {97#define kmp_mutex_impl_macro(name, id) {#name, name},98    FOREACH_KMP_MUTEX_IMPL(kmp_mutex_impl_macro)99#undef kmp_mutex_impl_macro100};101 102ompt_callbacks_internal_t ompt_callbacks;103 104static ompt_start_tool_result_t *ompt_start_tool_result = NULL;105 106#if KMP_OS_WINDOWS107static HMODULE ompt_tool_module = NULL;108static HMODULE ompt_archer_module = NULL;109#define OMPT_DLCLOSE(Lib) FreeLibrary(Lib)110#else111static void *ompt_tool_module = NULL;112static void *ompt_archer_module = NULL;113#define OMPT_DLCLOSE(Lib) dlclose(Lib)114#endif115 116/// Used to track the initializer and the finalizer provided by libomptarget117static ompt_start_tool_result_t *libomptarget_ompt_result = NULL;118 119/*****************************************************************************120 * forward declarations121 ****************************************************************************/122 123static ompt_interface_fn_t ompt_fn_lookup(const char *s);124 125OMPT_API_ROUTINE ompt_data_t *ompt_get_thread_data(void);126 127/*****************************************************************************128 * initialization and finalization (private operations)129 ****************************************************************************/130 131typedef ompt_start_tool_result_t *(*ompt_start_tool_t)(unsigned int,132                                                       const char *);133 134#if KMP_OS_DARWIN135 136// While Darwin supports weak symbols, the library that wishes to provide a new137// implementation has to link against this runtime which defeats the purpose138// of having tools that are agnostic of the underlying runtime implementation.139//140// Fortunately, the linker includes all symbols of an executable in the global141// symbol table by default so dlsym() even finds static implementations of142// ompt_start_tool. For this to work on Linux, -Wl,--export-dynamic needs to be143// passed when building the application which we don't want to rely on.144 145static ompt_start_tool_result_t *ompt_tool_darwin(unsigned int omp_version,146                                                  const char *runtime_version) {147  ompt_start_tool_result_t *ret = NULL;148  // Search symbol in the current address space.149  ompt_start_tool_t start_tool =150      (ompt_start_tool_t)dlsym(RTLD_DEFAULT, "ompt_start_tool");151  if (start_tool) {152    ret = start_tool(omp_version, runtime_version);153  }154  return ret;155}156 157#elif OMPT_HAVE_WEAK_ATTRIBUTE158 159// On Unix-like systems that support weak symbols the following implementation160// of ompt_start_tool() will be used in case no tool-supplied implementation of161// this function is present in the address space of a process.162 163_OMP_EXTERN OMPT_WEAK_ATTRIBUTE ompt_start_tool_result_t *164ompt_start_tool(unsigned int omp_version, const char *runtime_version) {165  ompt_start_tool_result_t *ret = NULL;166  // Search next symbol in the current address space. This can happen if the167  // runtime library is linked before the tool. Since glibc 2.2 strong symbols168  // don't override weak symbols that have been found before unless the user169  // sets the environment variable LD_DYNAMIC_WEAK.170  ompt_start_tool_t next_tool =171      (ompt_start_tool_t)dlsym(RTLD_NEXT, "ompt_start_tool");172  if (next_tool) {173    ret = next_tool(omp_version, runtime_version);174  }175  return ret;176}177 178#elif OMPT_HAVE_PSAPI179 180// On Windows, the ompt_tool_windows function is used to find the181// ompt_start_tool symbol across all modules loaded by a process. If182// ompt_start_tool is found, ompt_start_tool's return value is used to183// initialize the tool. Otherwise, NULL is returned and OMPT won't be enabled.184 185#include <psapi.h>186#pragma comment(lib, "psapi.lib")187 188// The number of loaded modules to start enumeration with EnumProcessModules()189#define NUM_MODULES 128190 191static ompt_start_tool_result_t *192ompt_tool_windows(unsigned int omp_version, const char *runtime_version) {193  int i;194  DWORD needed, new_size;195  HMODULE *modules;196  HANDLE process = GetCurrentProcess();197  modules = (HMODULE *)malloc(NUM_MODULES * sizeof(HMODULE));198  ompt_start_tool_t ompt_tool_p = NULL;199 200#if OMPT_DEBUG201  printf("ompt_tool_windows(): looking for ompt_start_tool\n");202#endif203  if (!EnumProcessModules(process, modules, NUM_MODULES * sizeof(HMODULE),204                          &needed)) {205    // Regardless of the error reason use the stub initialization function206    free(modules);207    return NULL;208  }209  // Check if NUM_MODULES is enough to list all modules210  new_size = needed / sizeof(HMODULE);211  if (new_size > NUM_MODULES) {212#if OMPT_DEBUG213    printf("ompt_tool_windows(): resize buffer to %d bytes\n", needed);214#endif215    modules = (HMODULE *)realloc(modules, needed);216    // If resizing failed use the stub function.217    if (!EnumProcessModules(process, modules, needed, &needed)) {218      free(modules);219      return NULL;220    }221  }222  for (i = 0; i < new_size; ++i) {223    (FARPROC &)ompt_tool_p = GetProcAddress(modules[i], "ompt_start_tool");224    if (ompt_tool_p) {225#if OMPT_DEBUG226      TCHAR modName[MAX_PATH];227      if (GetModuleFileName(modules[i], modName, MAX_PATH))228        printf("ompt_tool_windows(): ompt_start_tool found in module %s\n",229               modName);230#endif231      free(modules);232      return (*ompt_tool_p)(omp_version, runtime_version);233    }234#if OMPT_DEBUG235    else {236      TCHAR modName[MAX_PATH];237      if (GetModuleFileName(modules[i], modName, MAX_PATH))238        printf("ompt_tool_windows(): ompt_start_tool not found in module %s\n",239               modName);240    }241#endif242  }243  free(modules);244  return NULL;245}246#else247#error Activation of OMPT is not supported on this platform.248#endif249 250static ompt_start_tool_result_t *251ompt_try_start_tool(unsigned int omp_version, const char *runtime_version) {252  ompt_start_tool_result_t *ret = NULL;253  ompt_start_tool_t start_tool = NULL;254#if KMP_OS_WINDOWS255  // Cannot use colon to describe a list of absolute paths on Windows256  const char *sep = ";";257#else258  const char *sep = ":";259#endif260 261  OMPT_VERBOSE_INIT_PRINT("----- START LOGGING OF TOOL REGISTRATION -----\n");262  OMPT_VERBOSE_INIT_PRINT("Search for OMP tool in current address space... ");263 264#if KMP_OS_DARWIN265  // Try in the current address space266  ret = ompt_tool_darwin(omp_version, runtime_version);267#elif OMPT_HAVE_WEAK_ATTRIBUTE268  ret = ompt_start_tool(omp_version, runtime_version);269#elif OMPT_HAVE_PSAPI270  ret = ompt_tool_windows(omp_version, runtime_version);271#else272#error Activation of OMPT is not supported on this platform.273#endif274  if (ret) {275    OMPT_VERBOSE_INIT_CONTINUED_PRINT("Success.\n");276    OMPT_VERBOSE_INIT_PRINT(277        "Tool was started and is using the OMPT interface.\n");278    OMPT_VERBOSE_INIT_PRINT("----- END LOGGING OF TOOL REGISTRATION -----\n");279    return ret;280  }281 282  // Try tool-libraries-var ICV283  OMPT_VERBOSE_INIT_CONTINUED_PRINT("Failed.\n");284  const char *tool_libs = getenv("OMP_TOOL_LIBRARIES");285  if (tool_libs) {286    OMPT_VERBOSE_INIT_PRINT("Searching tool libraries...\n");287    OMPT_VERBOSE_INIT_PRINT("OMP_TOOL_LIBRARIES = %s\n", tool_libs);288    char *libs = __kmp_str_format("%s", tool_libs);289    char *buf;290    char *fname = __kmp_str_token(libs, sep, &buf);291    // Reset dl-error292    dlerror();293 294    while (fname) {295#if KMP_OS_UNIX296      OMPT_VERBOSE_INIT_PRINT("Opening %s... ", fname);297      void *h = dlopen(fname, RTLD_LAZY);298      if (!h) {299        OMPT_VERBOSE_INIT_CONTINUED_PRINT("Failed: %s\n", dlerror());300      } else {301        OMPT_VERBOSE_INIT_CONTINUED_PRINT("Success. \n");302        OMPT_VERBOSE_INIT_PRINT("Searching for ompt_start_tool in %s... ",303                                fname);304        dlerror(); // Clear any existing error305        start_tool = (ompt_start_tool_t)dlsym(h, "ompt_start_tool");306        if (!start_tool) {307          char *error = dlerror();308          if (error != NULL) {309            OMPT_VERBOSE_INIT_CONTINUED_PRINT("Failed: %s\n", error);310          } else {311            OMPT_VERBOSE_INIT_CONTINUED_PRINT("Failed: %s\n",312                                              "ompt_start_tool = NULL");313          }314        } else315#elif KMP_OS_WINDOWS316      OMPT_VERBOSE_INIT_PRINT("Opening %s... ", fname);317      HMODULE h = LoadLibrary(fname);318      if (!h) {319        OMPT_VERBOSE_INIT_CONTINUED_PRINT("Failed: Error %u\n",320                                          (unsigned)GetLastError());321      } else {322        OMPT_VERBOSE_INIT_CONTINUED_PRINT("Success. \n");323        OMPT_VERBOSE_INIT_PRINT("Searching for ompt_start_tool in %s... ",324                                fname);325        start_tool = (ompt_start_tool_t)GetProcAddress(h, "ompt_start_tool");326        if (!start_tool) {327          OMPT_VERBOSE_INIT_CONTINUED_PRINT("Failed: Error %u\n",328                                            (unsigned)GetLastError());329        } else330#else331#error Activation of OMPT is not supported on this platform.332#endif333        { // if (start_tool)334          ret = (*start_tool)(omp_version, runtime_version);335          if (ret) {336            OMPT_VERBOSE_INIT_CONTINUED_PRINT("Success.\n");337            OMPT_VERBOSE_INIT_PRINT(338                "Tool was started and is using the OMPT interface.\n");339            ompt_tool_module = h;340            break;341          }342          OMPT_VERBOSE_INIT_CONTINUED_PRINT(343              "Found but not using the OMPT interface.\n");344          OMPT_VERBOSE_INIT_PRINT("Continuing search...\n");345        }346        OMPT_DLCLOSE(h);347      }348      fname = __kmp_str_token(NULL, sep, &buf);349    }350    __kmp_str_free(&libs);351  } else {352    OMPT_VERBOSE_INIT_PRINT("No OMP_TOOL_LIBRARIES defined.\n");353  }354 355  // usable tool found in tool-libraries356  if (ret) {357    OMPT_VERBOSE_INIT_PRINT("----- END LOGGING OF TOOL REGISTRATION -----\n");358    return ret;359  }360 361#if KMP_OS_UNIX362  { // Non-standard: load archer tool if application is built with TSan363    const char *fname = "libarcher.so";364    OMPT_VERBOSE_INIT_PRINT(365        "...searching tool libraries failed. Using archer tool.\n");366    OMPT_VERBOSE_INIT_PRINT("Opening %s... ", fname);367    void *h = dlopen(fname, RTLD_LAZY);368    if (h) {369      OMPT_VERBOSE_INIT_CONTINUED_PRINT("Success.\n");370      OMPT_VERBOSE_INIT_PRINT("Searching for ompt_start_tool in %s... ", fname);371      start_tool = (ompt_start_tool_t)dlsym(h, "ompt_start_tool");372      if (start_tool) {373        ret = (*start_tool)(omp_version, runtime_version);374        if (ret) {375          OMPT_VERBOSE_INIT_CONTINUED_PRINT("Success.\n");376          OMPT_VERBOSE_INIT_PRINT(377              "Tool was started and is using the OMPT interface.\n");378          OMPT_VERBOSE_INIT_PRINT(379              "----- END LOGGING OF TOOL REGISTRATION -----\n");380          ompt_archer_module = h;381          return ret;382        }383        OMPT_VERBOSE_INIT_CONTINUED_PRINT(384            "Found but not using the OMPT interface.\n");385      } else {386        OMPT_VERBOSE_INIT_CONTINUED_PRINT("Failed: %s\n", dlerror());387      }388      OMPT_DLCLOSE(h);389    }390  }391#endif392  OMPT_VERBOSE_INIT_PRINT("No OMP tool loaded.\n");393  OMPT_VERBOSE_INIT_PRINT("----- END LOGGING OF TOOL REGISTRATION -----\n");394  return ret;395}396 397void ompt_pre_init() {398  //--------------------------------------------------399  // Execute the pre-initialization logic only once.400  //--------------------------------------------------401  static int ompt_pre_initialized = 0;402 403  if (ompt_pre_initialized)404    return;405 406  ompt_pre_initialized = 1;407 408  //--------------------------------------------------409  // Use a tool iff a tool is enabled and available.410  //--------------------------------------------------411  const char *ompt_env_var = getenv("OMP_TOOL");412  tool_setting_e tool_setting = omp_tool_error;413 414  if (!ompt_env_var || !strcmp(ompt_env_var, ""))415    tool_setting = omp_tool_unset;416  else if (OMPT_STR_MATCH(ompt_env_var, "disabled"))417    tool_setting = omp_tool_disabled;418  else if (OMPT_STR_MATCH(ompt_env_var, "enabled"))419    tool_setting = omp_tool_enabled;420 421  const char *ompt_env_verbose_init = getenv("OMP_TOOL_VERBOSE_INIT");422  // possible options: disabled | stdout | stderr | <filename>423  // if set, not empty and not disabled -> prepare for logging424  if (ompt_env_verbose_init && strcmp(ompt_env_verbose_init, "") &&425      !OMPT_STR_MATCH(ompt_env_verbose_init, "disabled")) {426    verbose_init = 1;427    if (OMPT_STR_MATCH(ompt_env_verbose_init, "STDERR"))428      verbose_file = stderr;429    else if (OMPT_STR_MATCH(ompt_env_verbose_init, "STDOUT"))430      verbose_file = stdout;431    else432      verbose_file = fopen(ompt_env_verbose_init, "w");433  } else434    verbose_init = 0;435 436#if OMPT_DEBUG437  printf("ompt_pre_init(): tool_setting = %d\n", tool_setting);438#endif439  switch (tool_setting) {440  case omp_tool_disabled:441    OMPT_VERBOSE_INIT_PRINT("OMP tool disabled. \n");442    break;443 444  case omp_tool_unset:445  case omp_tool_enabled:446 447    //--------------------------------------------------448    // Load tool iff specified in environment variable449    //--------------------------------------------------450    ompt_start_tool_result =451        ompt_try_start_tool(__kmp_openmp_version, ompt_get_runtime_version());452 453    memset(&ompt_enabled, 0, sizeof(ompt_enabled));454    break;455 456  case omp_tool_error:457    fprintf(stderr,458            "Warning: OMP_TOOL has invalid value \"%s\".\n"459            "  legal values are (NULL,\"\",\"disabled\","460            "\"enabled\").\n",461            ompt_env_var);462    break;463  }464  if (verbose_init && verbose_file != stderr && verbose_file != stdout)465    fclose(verbose_file);466#if OMPT_DEBUG467  printf("ompt_pre_init(): ompt_enabled = %d\n", ompt_enabled.enabled);468#endif469}470 471extern "C" int omp_get_initial_device(void);472 473void ompt_post_init() {474  //--------------------------------------------------475  // Execute the post-initialization logic only once.476  //--------------------------------------------------477  static int ompt_post_initialized = 0;478 479  if (ompt_post_initialized)480    return;481 482  ompt_post_initialized = 1;483 484  //--------------------------------------------------485  // Initialize the tool if so indicated.486  //--------------------------------------------------487  if (ompt_start_tool_result) {488    ompt_enabled.enabled = !!ompt_start_tool_result->initialize(489        ompt_fn_lookup, omp_get_initial_device(),490        &(ompt_start_tool_result->tool_data));491 492    if (!ompt_enabled.enabled) {493      // tool not enabled, zero out the bitmap, and done494      memset(&ompt_enabled, 0, sizeof(ompt_enabled));495      return;496    }497 498    kmp_info_t *root_thread = ompt_get_thread();499 500    ompt_set_thread_state(root_thread, ompt_state_overhead);501    __ompt_task_init(root_thread->th.th_current_task, 0);502 503    if (ompt_enabled.ompt_callback_thread_begin) {504      ompt_callbacks.ompt_callback(ompt_callback_thread_begin)(505          ompt_thread_initial, __ompt_get_thread_data_internal());506    }507    ompt_data_t *task_data = nullptr;508    ompt_data_t *parallel_data = nullptr;509    __ompt_get_task_info_internal(0, NULL, &task_data, NULL, &parallel_data,510                                  NULL);511    if (ompt_enabled.ompt_callback_implicit_task) {512      ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(513          ompt_scope_begin, parallel_data, task_data, 1, 1, ompt_task_initial);514    }515 516    ompt_set_thread_state(root_thread, ompt_state_work_serial);517  }518}519 520void ompt_fini() {521  if (ompt_enabled.enabled) {522    if (ompt_start_tool_result && ompt_start_tool_result->finalize) {523      ompt_start_tool_result->finalize(&(ompt_start_tool_result->tool_data));524    }525    if (libomptarget_ompt_result && libomptarget_ompt_result->finalize) {526      libomptarget_ompt_result->finalize(NULL);527    }528  }529 530  if (ompt_archer_module)531    OMPT_DLCLOSE(ompt_archer_module);532  if (ompt_tool_module)533    OMPT_DLCLOSE(ompt_tool_module);534  memset(&ompt_enabled, 0, sizeof(ompt_enabled));535}536 537/*****************************************************************************538 * interface operations539 ****************************************************************************/540 541/*****************************************************************************542 * state543 ****************************************************************************/544 545OMPT_API_ROUTINE int ompt_enumerate_states(int current_state, int *next_state,546                                           const char **next_state_name) {547  const static int len = sizeof(ompt_state_info) / sizeof(ompt_state_info_t);548  int i = 0;549 550  for (i = 0; i < len - 1; i++) {551    if (ompt_state_info[i].state_id == current_state) {552      *next_state = ompt_state_info[i + 1].state_id;553      *next_state_name = ompt_state_info[i + 1].state_name;554      return 1;555    }556  }557 558  return 0;559}560 561OMPT_API_ROUTINE int ompt_enumerate_mutex_impls(int current_impl,562                                                int *next_impl,563                                                const char **next_impl_name) {564  const static int len =565      sizeof(kmp_mutex_impl_info) / sizeof(kmp_mutex_impl_info_t);566  int i = 0;567  for (i = 0; i < len - 1; i++) {568    if (kmp_mutex_impl_info[i].id != current_impl)569      continue;570    *next_impl = kmp_mutex_impl_info[i + 1].id;571    *next_impl_name = kmp_mutex_impl_info[i + 1].name;572    return 1;573  }574  return 0;575}576 577/*****************************************************************************578 * callbacks579 ****************************************************************************/580 581OMPT_API_ROUTINE ompt_set_result_t ompt_set_callback(ompt_callbacks_t which,582                                                     ompt_callback_t callback) {583  switch (which) {584 585#define ompt_event_macro(event_name, callback_type, event_id)                  \586  case event_name:                                                             \587    ompt_callbacks.ompt_callback(event_name) = (callback_type)callback;        \588    ompt_enabled.event_name = (callback != 0);                                 \589    if (callback)                                                              \590      return ompt_event_implementation_status(event_name);                     \591    else                                                                       \592      return ompt_set_always;593 594    FOREACH_OMPT_EVENT(ompt_event_macro)595 596#undef ompt_event_macro597 598  default:599    return ompt_set_error;600  }601}602 603OMPT_API_ROUTINE int ompt_get_callback(ompt_callbacks_t which,604                                       ompt_callback_t *callback) {605  if (!ompt_enabled.enabled)606    return ompt_get_callback_failure;607 608  switch (which) {609 610#define ompt_event_macro(event_name, callback_type, event_id)                  \611  case event_name: {                                                           \612    ompt_callback_t mycb =                                                     \613        (ompt_callback_t)ompt_callbacks.ompt_callback(event_name);             \614    if (ompt_enabled.event_name && mycb) {                                     \615      *callback = mycb;                                                        \616      return ompt_get_callback_success;                                        \617    }                                                                          \618    return ompt_get_callback_failure;                                          \619  }620 621    FOREACH_OMPT_EVENT(ompt_event_macro)622 623#undef ompt_event_macro624 625  default:626    return ompt_get_callback_failure;627  }628}629 630/*****************************************************************************631 * parallel regions632 ****************************************************************************/633 634OMPT_API_ROUTINE int ompt_get_parallel_info(int ancestor_level,635                                            ompt_data_t **parallel_data,636                                            int *team_size) {637  if (!ompt_enabled.enabled)638    return 0;639  return __ompt_get_parallel_info_internal(ancestor_level, parallel_data,640                                           team_size);641}642 643OMPT_API_ROUTINE int ompt_get_state(ompt_wait_id_t *wait_id) {644  if (!ompt_enabled.enabled)645    return ompt_state_work_serial;646  int thread_state = __ompt_get_state_internal(wait_id);647 648  if (thread_state == ompt_state_undefined) {649    thread_state = ompt_state_work_serial;650  }651 652  return thread_state;653}654 655/*****************************************************************************656 * tasks657 ****************************************************************************/658 659OMPT_API_ROUTINE ompt_data_t *ompt_get_thread_data(void) {660  if (!ompt_enabled.enabled)661    return NULL;662  return __ompt_get_thread_data_internal();663}664 665OMPT_API_ROUTINE int ompt_get_task_info(int ancestor_level, int *type,666                                        ompt_data_t **task_data,667                                        ompt_frame_t **task_frame,668                                        ompt_data_t **parallel_data,669                                        int *thread_num) {670  if (!ompt_enabled.enabled)671    return 0;672  return __ompt_get_task_info_internal(ancestor_level, type, task_data,673                                       task_frame, parallel_data, thread_num);674}675 676OMPT_API_ROUTINE int ompt_get_task_memory(void **addr, size_t *size,677                                          int block) {678  return __ompt_get_task_memory_internal(addr, size, block);679}680 681/*****************************************************************************682 * num_procs683 ****************************************************************************/684 685OMPT_API_ROUTINE int ompt_get_num_procs(void) {686  // copied from kmp_ftn_entry.h (but modified: OMPT can only be called when687  // runtime is initialized)688  return __kmp_avail_proc;689}690 691/*****************************************************************************692 * places693 ****************************************************************************/694 695OMPT_API_ROUTINE int ompt_get_num_places(void) {696// copied from kmp_ftn_entry.h (but modified)697#if !KMP_AFFINITY_SUPPORTED698  return 0;699#else700  if (!KMP_AFFINITY_CAPABLE())701    return 0;702  return __kmp_affinity.num_masks;703#endif704}705 706OMPT_API_ROUTINE int ompt_get_place_proc_ids(int place_num, int ids_size,707                                             int *ids) {708// copied from kmp_ftn_entry.h (but modified)709#if !KMP_AFFINITY_SUPPORTED710  return 0;711#else712  int i, count;713  SimpleVLA<int> tmp_ids(ids_size);714  for (int j = 0; j < ids_size; j++)715    tmp_ids[j] = 0;716  if (!KMP_AFFINITY_CAPABLE())717    return 0;718  if (place_num < 0 || place_num >= (int)__kmp_affinity.num_masks)719    return 0;720  /* TODO: Is this safe for asynchronous call from signal handler during runtime721   * shutdown? */722  kmp_affin_mask_t *mask = KMP_CPU_INDEX(__kmp_affinity.masks, place_num);723  count = 0;724  KMP_CPU_SET_ITERATE(i, mask) {725    if ((!KMP_CPU_ISSET(i, __kmp_affin_fullMask)) ||726        (!KMP_CPU_ISSET(i, mask))) {727      continue;728    }729    if (count < ids_size)730      tmp_ids[count] = i;731    count++;732  }733  if (ids_size >= count) {734    for (i = 0; i < count; i++) {735      ids[i] = tmp_ids[i];736    }737  }738  return count;739#endif740}741 742OMPT_API_ROUTINE int ompt_get_place_num(void) {743// copied from kmp_ftn_entry.h (but modified)744#if !KMP_AFFINITY_SUPPORTED745  return -1;746#else747  if (!ompt_enabled.enabled || __kmp_get_gtid() < 0)748    return -1;749 750  int gtid;751  kmp_info_t *thread;752  if (!KMP_AFFINITY_CAPABLE())753    return -1;754  gtid = __kmp_entry_gtid();755  thread = __kmp_thread_from_gtid(gtid);756  if (thread == NULL || thread->th.th_current_place < 0)757    return -1;758  return thread->th.th_current_place;759#endif760}761 762OMPT_API_ROUTINE int ompt_get_partition_place_nums(int place_nums_size,763                                                   int *place_nums) {764// copied from kmp_ftn_entry.h (but modified)765#if !KMP_AFFINITY_SUPPORTED766  return 0;767#else768  if (!ompt_enabled.enabled || __kmp_get_gtid() < 0)769    return 0;770 771  int i, gtid, place_num, first_place, last_place, start, end;772  kmp_info_t *thread;773  if (!KMP_AFFINITY_CAPABLE())774    return 0;775  gtid = __kmp_entry_gtid();776  thread = __kmp_thread_from_gtid(gtid);777  if (thread == NULL)778    return 0;779  first_place = thread->th.th_first_place;780  last_place = thread->th.th_last_place;781  if (first_place < 0 || last_place < 0)782    return 0;783  if (first_place <= last_place) {784    start = first_place;785    end = last_place;786  } else {787    start = last_place;788    end = first_place;789  }790  if (end - start <= place_nums_size)791    for (i = 0, place_num = start; place_num <= end; ++place_num, ++i) {792      place_nums[i] = place_num;793    }794  return end - start + 1;795#endif796}797 798/*****************************************************************************799 * places800 ****************************************************************************/801 802OMPT_API_ROUTINE int ompt_get_proc_id(void) {803  if (!ompt_enabled.enabled || __kmp_get_gtid() < 0)804    return -1;805#if KMP_HAVE_SCHED_GETCPU806  return sched_getcpu();807#elif KMP_OS_WINDOWS808  PROCESSOR_NUMBER pn;809  GetCurrentProcessorNumberEx(&pn);810  return 64 * pn.Group + pn.Number;811#else812  return -1;813#endif814}815 816/*****************************************************************************817 * compatability818 ****************************************************************************/819 820/*821 * Currently unused function822OMPT_API_ROUTINE int ompt_get_ompt_version() { return OMPT_VERSION; }823*/824 825/*****************************************************************************826 * application-facing API827 ****************************************************************************/828 829/*----------------------------------------------------------------------------830 | control831 ---------------------------------------------------------------------------*/832 833int __kmp_control_tool(uint64_t command, uint64_t modifier, void *arg) {834 835  if (ompt_enabled.enabled) {836    if (ompt_enabled.ompt_callback_control_tool) {837      return ompt_callbacks.ompt_callback(ompt_callback_control_tool)(838          command, modifier, arg, OMPT_LOAD_RETURN_ADDRESS(__kmp_entry_gtid()));839    } else {840      return -1;841    }842  } else {843    return -2;844  }845}846 847/*****************************************************************************848 * misc849 ****************************************************************************/850 851OMPT_API_ROUTINE uint64_t ompt_get_unique_id(void) {852  return __ompt_get_unique_id_internal();853}854 855OMPT_API_ROUTINE void ompt_finalize_tool(void) { __kmp_internal_end_atexit(); }856 857/*****************************************************************************858 * Target859 ****************************************************************************/860 861OMPT_API_ROUTINE int ompt_get_target_info(uint64_t *device_num,862                                          ompt_id_t *target_id,863                                          ompt_id_t *host_op_id) {864  return 0; // thread is not in a target region865}866 867OMPT_API_ROUTINE int ompt_get_num_devices(void) {868  return 1; // only one device (the current device) is available869}870 871/*****************************************************************************872 * API inquiry for tool873 ****************************************************************************/874 875static ompt_interface_fn_t ompt_fn_lookup(const char *s) {876 877#define ompt_interface_fn(fn)                                                  \878  fn##_t fn##_f = fn;                                                          \879  if (strcmp(s, #fn) == 0)                                                     \880    return (ompt_interface_fn_t)fn##_f;881 882  FOREACH_OMPT_INQUIRY_FN(ompt_interface_fn)883 884#undef ompt_interface_fn885 886  return NULL;887}888 889static ompt_data_t *ompt_get_task_data() { return __ompt_get_task_data(); }890 891static ompt_data_t *ompt_get_target_task_data() {892  return __ompt_get_target_task_data();893}894 895/// Lookup function to query libomp callbacks registered by the tool896static ompt_interface_fn_t ompt_libomp_target_fn_lookup(const char *s) {897#define provide_fn(fn)                                                         \898  if (strcmp(s, #fn) == 0)                                                     \899    return (ompt_interface_fn_t)fn;900 901  provide_fn(ompt_get_callback);902  provide_fn(ompt_get_task_data);903  provide_fn(ompt_get_target_task_data);904#undef provide_fn905 906#define ompt_interface_fn(fn, type, code)                                      \907  if (strcmp(s, #fn) == 0)                                                     \908    return (ompt_interface_fn_t)ompt_callbacks.ompt_callback(fn);909 910  FOREACH_OMPT_DEVICE_EVENT(ompt_interface_fn)911  FOREACH_OMPT_EMI_EVENT(ompt_interface_fn)912  FOREACH_OMPT_NOEMI_EVENT(ompt_interface_fn)913#undef ompt_interface_fn914 915  return (ompt_interface_fn_t)0;916}917 918/// This function is called by the libomptarget connector to assign919/// callbacks already registered with libomp.920_OMP_EXTERN void ompt_libomp_connect(ompt_start_tool_result_t *result) {921  OMPT_VERBOSE_INIT_PRINT("libomp --> OMPT: Enter ompt_libomp_connect\n");922 923  // Ensure libomp callbacks have been added if not already924  __ompt_force_initialization();925 926  if (ompt_enabled.enabled && result) {927    OMPT_VERBOSE_INIT_PRINT("libomp --> OMPT: Connecting with libomptarget\n");928    // Pass in the libomp lookup function so that the already registered929    // functions can be extracted and assigned to the callbacks in930    // libomptarget931    result->initialize(ompt_libomp_target_fn_lookup,932                       /* initial_device_num */ 0, /* tool_data */ nullptr);933    // Track the object provided by libomptarget so that the finalizer can be934    // called during OMPT finalization935    libomptarget_ompt_result = result;936  }937  OMPT_VERBOSE_INIT_PRINT("libomp --> OMPT: Exit ompt_libomp_connect\n");938}939