| /* | |
| * ompd-specific.cpp -- OpenMP debug support | |
| */ | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // 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 "ompd-specific.h" | |
| #if OMPD_SUPPORT | |
| /** | |
| * Declaration of symbols to hold struct size and member offset information | |
| */ | |
| #define ompd_declare_access(t, m) uint64_t ompd_access__##t##__##m; | |
| OMPD_FOREACH_ACCESS(ompd_declare_access) | |
| #undef ompd_declare_access | |
| #define ompd_declare_sizeof_member(t, m) uint64_t ompd_sizeof__##t##__##m; | |
| OMPD_FOREACH_ACCESS(ompd_declare_sizeof_member) | |
| #undef ompd_declare_sizeof_member | |
| #define ompd_declare_bitfield(t, m) uint64_t ompd_bitfield__##t##__##m; | |
| OMPD_FOREACH_BITFIELD(ompd_declare_bitfield) | |
| #undef ompd_declare_bitfield | |
| #define ompd_declare_sizeof(t) uint64_t ompd_sizeof__##t; | |
| OMPD_FOREACH_SIZEOF(ompd_declare_sizeof) | |
| #undef ompd_declare_sizeof | |
| volatile const char **ompd_dll_locations = NULL; | |
| uint64_t ompd_state = 0; | |
| char *ompd_env_block = NULL; | |
| ompd_size_t ompd_env_block_size = 0; | |
| void ompd_init() { | |
| static int ompd_initialized = 0; | |
| if (ompd_initialized) | |
| return; | |
| /** | |
| * Calculate member offsets for structs and unions | |
| */ | |
| #define ompd_init_access(t, m) \ | |
| ompd_access__##t##__##m = (uint64_t) & (((t *)0)->m); | |
| OMPD_FOREACH_ACCESS(ompd_init_access) | |
| #undef ompd_init_access | |
| /** | |
| * Create bit mask for bitfield access | |
| */ | |
| #define ompd_init_bitfield(t, m) \ | |
| ompd_bitfield__##t##__##m = 0; \ | |
| ((t *)(&ompd_bitfield__##t##__##m))->m = 1; | |
| OMPD_FOREACH_BITFIELD(ompd_init_bitfield) | |
| #undef ompd_init_bitfield | |
| /** | |
| * Calculate type size information | |
| */ | |
| #define ompd_init_sizeof_member(t, m) \ | |
| ompd_sizeof__##t##__##m = sizeof(((t *)0)->m); | |
| OMPD_FOREACH_ACCESS(ompd_init_sizeof_member) | |
| #undef ompd_init_sizeof_member | |
| #define ompd_init_sizeof(t) ompd_sizeof__##t = sizeof(t); | |
| OMPD_FOREACH_SIZEOF(ompd_init_sizeof) | |
| #undef ompd_init_sizeof | |
| char *libname = NULL; | |
| const char *ompd_env_var = getenv("OMP_DEBUG"); | |
| int ompd_debug = ompd_env_var && !strcmp(ompd_env_var, "enabled"); | |
| #if KMP_OS_UNIX | |
| // Find the location of libomp.so thru dladdr and replace the libomp with | |
| // libompd to get the full path of libompd | |
| Dl_info dl_info; | |
| int ret = dladdr((void *)ompd_init, &dl_info); | |
| if (!ret) { | |
| const char *err = dlerror(); | |
| if (ompd_debug || err) | |
| fprintf(stderr, | |
| "The OpenMP runtime could not determine the location of " | |
| "libompd.so. If the debugger fails to load the library, make " | |
| "sure to add the directory containing a compatible libompd.so " | |
| "to your LD_LIBRARY_PATH%s%s\n", | |
| err ? ": " : "", err ? err : ""); | |
| } else if (dl_info.dli_fname && strrchr(dl_info.dli_fname, '/')) { | |
| int lib_path_length = strrchr(dl_info.dli_fname, '/') - dl_info.dli_fname; | |
| libname = | |
| (char *)malloc(lib_path_length + 12 /*for '/libompd.so' and '\0'*/); | |
| strncpy(libname, dl_info.dli_fname, lib_path_length); | |
| memcpy(libname + lib_path_length, "/libompd.so\0", 12); | |
| } | |
| #endif | |
| if (ompd_debug) { | |
| fprintf(stderr, "OMP_OMPD active\n"); | |
| ompt_enabled.enabled = 1; | |
| ompd_state |= OMPD_ENABLE_BP; | |
| } | |
| ompd_initialized = 1; | |
| ompd_dll_locations = (volatile const char **)malloc(3 * sizeof(const char *)); | |
| ompd_dll_locations[0] = "libompd.so"; | |
| ompd_dll_locations[1] = libname; | |
| ompd_dll_locations[2] = NULL; | |
| ompd_dll_locations_valid(); | |
| } | |
| void __attribute__((noinline)) ompd_dll_locations_valid(void) { | |
| /* naive way of implementing hard to opt-out empty function | |
| we might want to use a separate object file? */ | |
| asm(""); | |
| } | |
| void ompd_bp_parallel_begin(void) { | |
| /* naive way of implementing hard to opt-out empty function | |
| we might want to use a separate object file? */ | |
| asm(""); | |
| } | |
| void ompd_bp_parallel_end(void) { | |
| /* naive way of implementing hard to opt-out empty function | |
| we might want to use a separate object file? */ | |
| asm(""); | |
| } | |
| void ompd_bp_task_begin(void) { | |
| /* naive way of implementing hard to opt-out empty function | |
| we might want to use a separate object file? */ | |
| asm(""); | |
| } | |
| void ompd_bp_task_end(void) { | |
| /* naive way of implementing hard to opt-out empty function | |
| we might want to use a separate object file? */ | |
| asm(""); | |
| } | |
| void ompd_bp_thread_begin(void) { | |
| /* naive way of implementing hard to opt-out empty function | |
| we might want to use a separate object file? */ | |
| asm(""); | |
| } | |
| void ompd_bp_thread_end(void) { | |
| /* naive way of implementing hard to opt-out empty function | |
| we might want to use a separate object file? */ | |
| asm(""); | |
| } | |
| #endif /* OMPD_SUPPORT */ |