1 /* 2 * ompd-specific.cpp -- OpenMP debug support 3 */ 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-exception 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "ompd-specific.h" 14 15 #if OMPD_SUPPORT 16 17 /** 18 * Declaration of symbols to hold struct size and member offset information 19 */ 20 21 #define ompd_declare_access(t, m) uint64_t ompd_access__##t##__##m; 22 OMPD_FOREACH_ACCESS(ompd_declare_access) 23 #undef ompd_declare_access 24 25 #define ompd_declare_sizeof_member(t, m) uint64_t ompd_sizeof__##t##__##m; 26 OMPD_FOREACH_ACCESS(ompd_declare_sizeof_member) 27 #undef ompd_declare_sizeof_member 28 29 #define ompd_declare_bitfield(t, m) uint64_t ompd_bitfield__##t##__##m; 30 OMPD_FOREACH_BITFIELD(ompd_declare_bitfield) 31 #undef ompd_declare_bitfield 32 33 #define ompd_declare_sizeof(t) uint64_t ompd_sizeof__##t; 34 OMPD_FOREACH_SIZEOF(ompd_declare_sizeof) 35 #undef ompd_declare_sizeof 36 37 volatile const char **ompd_dll_locations = NULL; 38 uint64_t ompd_state = 0; 39 40 char *ompd_env_block = NULL; 41 ompd_size_t ompd_env_block_size = 0; 42 43 void ompd_init() { 44 45 static int ompd_initialized = 0; 46 47 if (ompd_initialized) 48 return; 49 50 /** 51 * Calculate member offsets for structs and unions 52 */ 53 54 #define ompd_init_access(t, m) \ 55 ompd_access__##t##__##m = (uint64_t) & (((t *)0)->m); 56 OMPD_FOREACH_ACCESS(ompd_init_access) 57 #undef ompd_init_access 58 59 /** 60 * Create bit mask for bitfield access 61 */ 62 63 #define ompd_init_bitfield(t, m) \ 64 ompd_bitfield__##t##__##m = 0; \ 65 ((t *)(&ompd_bitfield__##t##__##m))->m = 1; 66 OMPD_FOREACH_BITFIELD(ompd_init_bitfield) 67 #undef ompd_init_bitfield 68 69 /** 70 * Calculate type size information 71 */ 72 73 #define ompd_init_sizeof_member(t, m) \ 74 ompd_sizeof__##t##__##m = sizeof(((t *)0)->m); 75 OMPD_FOREACH_ACCESS(ompd_init_sizeof_member) 76 #undef ompd_init_sizeof_member 77 78 #define ompd_init_sizeof(t) ompd_sizeof__##t = sizeof(t); 79 OMPD_FOREACH_SIZEOF(ompd_init_sizeof) 80 #undef ompd_init_sizeof 81 82 char *libname = NULL; 83 84 #if KMP_OS_UNIX 85 // Find the location of libomp.so thru dladdr and replace the libomp with 86 // libompd to get the full path of libompd 87 Dl_info dl_info; 88 int ret = dladdr((void *)ompd_init, &dl_info); 89 if (!ret) { 90 fprintf(stderr, "%s\n", dlerror()); 91 } 92 int lib_path_length; 93 if (strrchr(dl_info.dli_fname, '/')) { 94 lib_path_length = strrchr(dl_info.dli_fname, '/') - dl_info.dli_fname; 95 libname = 96 (char *)malloc(lib_path_length + 12 /*for '/libompd.so' and '\0'*/); 97 strncpy(libname, dl_info.dli_fname, lib_path_length); 98 memcpy(libname + lib_path_length, "/libompd.so\0", 12); 99 } 100 #endif 101 102 const char *ompd_env_var = getenv("OMP_DEBUG"); 103 if (ompd_env_var && !strcmp(ompd_env_var, "enabled")) { 104 fprintf(stderr, "OMP_OMPD active\n"); 105 ompt_enabled.enabled = 1; 106 ompd_state |= OMPD_ENABLE_BP; 107 } 108 109 ompd_initialized = 1; 110 ompd_dll_locations = (volatile const char **)malloc(3 * sizeof(const char *)); 111 ompd_dll_locations[0] = "libompd.so"; 112 ompd_dll_locations[1] = libname; 113 ompd_dll_locations[2] = NULL; 114 ompd_dll_locations_valid(); 115 } 116 117 void __attribute__((noinline)) ompd_dll_locations_valid(void) { 118 /* naive way of implementing hard to opt-out empty function 119 we might want to use a separate object file? */ 120 asm(""); 121 } 122 123 void ompd_bp_parallel_begin(void) { 124 /* naive way of implementing hard to opt-out empty function 125 we might want to use a separate object file? */ 126 asm(""); 127 } 128 void ompd_bp_parallel_end(void) { 129 /* naive way of implementing hard to opt-out empty function 130 we might want to use a separate object file? */ 131 asm(""); 132 } 133 void ompd_bp_task_begin(void) { 134 /* naive way of implementing hard to opt-out empty function 135 we might want to use a separate object file? */ 136 asm(""); 137 } 138 void ompd_bp_task_end(void) { 139 /* naive way of implementing hard to opt-out empty function 140 we might want to use a separate object file? */ 141 asm(""); 142 } 143 void ompd_bp_thread_begin(void) { 144 /* naive way of implementing hard to opt-out empty function 145 we might want to use a separate object file? */ 146 asm(""); 147 } 148 void ompd_bp_thread_end(void) { 149 /* naive way of implementing hard to opt-out empty function 150 we might want to use a separate object file? */ 151 asm(""); 152 } 153 154 #endif /* OMPD_SUPPORT */ 155