1 /***************************************************************************** 2 * system include files 3 ****************************************************************************/ 4 5 #include <assert.h> 6 7 #include <stdint.h> 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <string.h> 11 12 /***************************************************************************** 13 * ompt include files 14 ****************************************************************************/ 15 16 #include "ompt-specific.cpp" 17 18 /***************************************************************************** 19 * macros 20 ****************************************************************************/ 21 22 #define ompt_get_callback_success 1 23 #define ompt_get_callback_failure 0 24 25 #define no_tool_present 0 26 27 #define OMPT_API_ROUTINE static 28 29 #ifndef OMPT_STR_MATCH 30 #define OMPT_STR_MATCH(haystack, needle) (!strcasecmp(haystack, needle)) 31 #endif 32 33 /***************************************************************************** 34 * types 35 ****************************************************************************/ 36 37 typedef struct { 38 const char *state_name; 39 ompt_state_t state_id; 40 } ompt_state_info_t; 41 42 enum tool_setting_e { 43 omp_tool_error, 44 omp_tool_unset, 45 omp_tool_disabled, 46 omp_tool_enabled 47 }; 48 49 typedef void (*ompt_initialize_t)(ompt_function_lookup_t ompt_fn_lookup, 50 const char *version, 51 unsigned int ompt_version); 52 53 /***************************************************************************** 54 * global variables 55 ****************************************************************************/ 56 57 int ompt_enabled = 0; 58 59 ompt_state_info_t ompt_state_info[] = { 60 #define ompt_state_macro(state, code) {#state, state}, 61 FOREACH_OMPT_STATE(ompt_state_macro) 62 #undef ompt_state_macro 63 }; 64 65 ompt_callbacks_t ompt_callbacks; 66 67 static ompt_initialize_t ompt_initialize_fn = NULL; 68 69 /***************************************************************************** 70 * forward declarations 71 ****************************************************************************/ 72 73 static ompt_interface_fn_t ompt_fn_lookup(const char *s); 74 75 OMPT_API_ROUTINE ompt_thread_id_t ompt_get_thread_id(void); 76 77 /***************************************************************************** 78 * initialization and finalization (private operations) 79 ****************************************************************************/ 80 81 /* On Unix-like systems that support weak symbols the following implementation 82 * of ompt_tool() will be used in case no tool-supplied implementation of 83 * this function is present in the address space of a process. 84 * 85 * On Windows, the ompt_tool_windows function is used to find the 86 * ompt_tool symbol across all modules loaded by a process. If ompt_tool is 87 * found, ompt_tool's return value is used to initialize the tool. Otherwise, 88 * NULL is returned and OMPT won't be enabled */ 89 #if OMPT_HAVE_WEAK_ATTRIBUTE 90 _OMP_EXTERN 91 __attribute__((weak)) ompt_initialize_t ompt_tool() { 92 #if OMPT_DEBUG 93 printf("ompt_tool() is called from the RTL\n"); 94 #endif 95 return NULL; 96 } 97 98 #elif OMPT_HAVE_PSAPI 99 100 #include <psapi.h> 101 #pragma comment(lib, "psapi.lib") 102 #define ompt_tool ompt_tool_windows 103 104 // The number of loaded modules to start enumeration with EnumProcessModules() 105 #define NUM_MODULES 128 106 107 static ompt_initialize_t ompt_tool_windows() { 108 int i; 109 DWORD needed, new_size; 110 HMODULE *modules; 111 HANDLE process = GetCurrentProcess(); 112 modules = (HMODULE *)malloc(NUM_MODULES * sizeof(HMODULE)); 113 ompt_initialize_t (*ompt_tool_p)() = NULL; 114 115 #if OMPT_DEBUG 116 printf("ompt_tool_windows(): looking for ompt_tool\n"); 117 #endif 118 if (!EnumProcessModules(process, modules, NUM_MODULES * sizeof(HMODULE), 119 &needed)) { 120 // Regardless of the error reason use the stub initialization function 121 free(modules); 122 return NULL; 123 } 124 // Check if NUM_MODULES is enough to list all modules 125 new_size = needed / sizeof(HMODULE); 126 if (new_size > NUM_MODULES) { 127 #if OMPT_DEBUG 128 printf("ompt_tool_windows(): resize buffer to %d bytes\n", needed); 129 #endif 130 modules = (HMODULE *)realloc(modules, needed); 131 // If resizing failed use the stub function. 132 if (!EnumProcessModules(process, modules, needed, &needed)) { 133 free(modules); 134 return NULL; 135 } 136 } 137 for (i = 0; i < new_size; ++i) { 138 (FARPROC &)ompt_tool_p = GetProcAddress(modules[i], "ompt_tool"); 139 if (ompt_tool_p) { 140 #if OMPT_DEBUG 141 TCHAR modName[MAX_PATH]; 142 if (GetModuleFileName(modules[i], modName, MAX_PATH)) 143 printf("ompt_tool_windows(): ompt_tool found in module %s\n", modName); 144 #endif 145 free(modules); 146 return ompt_tool_p(); 147 } 148 #if OMPT_DEBUG 149 else { 150 TCHAR modName[MAX_PATH]; 151 if (GetModuleFileName(modules[i], modName, MAX_PATH)) 152 printf("ompt_tool_windows(): ompt_tool not found in module %s\n", 153 modName); 154 } 155 #endif 156 } 157 free(modules); 158 return NULL; 159 } 160 #else 161 #error Either __attribute__((weak)) or psapi.dll are required for OMPT support 162 #endif // OMPT_HAVE_WEAK_ATTRIBUTE 163 164 void ompt_pre_init() { 165 //-------------------------------------------------- 166 // Execute the pre-initialization logic only once. 167 //-------------------------------------------------- 168 static int ompt_pre_initialized = 0; 169 170 if (ompt_pre_initialized) 171 return; 172 173 ompt_pre_initialized = 1; 174 175 //-------------------------------------------------- 176 // Use a tool iff a tool is enabled and available. 177 //-------------------------------------------------- 178 const char *ompt_env_var = getenv("OMP_TOOL"); 179 tool_setting_e tool_setting = omp_tool_error; 180 181 if (!ompt_env_var || !strcmp(ompt_env_var, "")) 182 tool_setting = omp_tool_unset; 183 else if (OMPT_STR_MATCH(ompt_env_var, "disabled")) 184 tool_setting = omp_tool_disabled; 185 else if (OMPT_STR_MATCH(ompt_env_var, "enabled")) 186 tool_setting = omp_tool_enabled; 187 188 #if OMPT_DEBUG 189 printf("ompt_pre_init(): tool_setting = %d\n", tool_setting); 190 #endif 191 switch (tool_setting) { 192 case omp_tool_disabled: 193 break; 194 195 case omp_tool_unset: 196 case omp_tool_enabled: 197 ompt_initialize_fn = ompt_tool(); 198 if (ompt_initialize_fn) { 199 ompt_enabled = 1; 200 } 201 break; 202 203 case omp_tool_error: 204 fprintf(stderr, "Warning: OMP_TOOL has invalid value \"%s\".\n" 205 " legal values are (NULL,\"\",\"disabled\"," 206 "\"enabled\").\n", 207 ompt_env_var); 208 break; 209 } 210 #if OMPT_DEBUG 211 printf("ompt_pre_init(): ompt_enabled = %d\n", ompt_enabled); 212 #endif 213 } 214 215 void ompt_post_init() { 216 //-------------------------------------------------- 217 // Execute the post-initialization logic only once. 218 //-------------------------------------------------- 219 static int ompt_post_initialized = 0; 220 221 if (ompt_post_initialized) 222 return; 223 224 ompt_post_initialized = 1; 225 226 //-------------------------------------------------- 227 // Initialize the tool if so indicated. 228 //-------------------------------------------------- 229 if (ompt_enabled) { 230 ompt_initialize_fn(ompt_fn_lookup, ompt_get_runtime_version(), 231 OMPT_VERSION); 232 233 ompt_thread_t *root_thread = ompt_get_thread(); 234 235 ompt_set_thread_state(root_thread, ompt_state_overhead); 236 237 if (ompt_callbacks.ompt_callback(ompt_event_thread_begin)) { 238 ompt_callbacks.ompt_callback(ompt_event_thread_begin)( 239 ompt_thread_initial, ompt_get_thread_id()); 240 } 241 242 ompt_set_thread_state(root_thread, ompt_state_work_serial); 243 } 244 } 245 246 void ompt_fini() { 247 if (ompt_enabled) { 248 if (ompt_callbacks.ompt_callback(ompt_event_runtime_shutdown)) { 249 ompt_callbacks.ompt_callback(ompt_event_runtime_shutdown)(); 250 } 251 } 252 253 ompt_enabled = 0; 254 } 255 256 /***************************************************************************** 257 * interface operations 258 ****************************************************************************/ 259 260 /***************************************************************************** 261 * state 262 ****************************************************************************/ 263 264 OMPT_API_ROUTINE int ompt_enumerate_state(int current_state, int *next_state, 265 const char **next_state_name) { 266 const static int len = sizeof(ompt_state_info) / sizeof(ompt_state_info_t); 267 int i = 0; 268 269 for (i = 0; i < len - 1; i++) { 270 if (ompt_state_info[i].state_id == current_state) { 271 *next_state = ompt_state_info[i + 1].state_id; 272 *next_state_name = ompt_state_info[i + 1].state_name; 273 return 1; 274 } 275 } 276 277 return 0; 278 } 279 280 /***************************************************************************** 281 * callbacks 282 ****************************************************************************/ 283 284 OMPT_API_ROUTINE int ompt_set_callback(ompt_event_t evid, ompt_callback_t cb) { 285 switch (evid) { 286 287 #define ompt_event_macro(event_name, callback_type, event_id) \ 288 case event_name: \ 289 if (ompt_event_implementation_status(event_name)) { \ 290 ompt_callbacks.ompt_callback(event_name) = (callback_type)cb; \ 291 } \ 292 return ompt_event_implementation_status(event_name); 293 294 FOREACH_OMPT_EVENT(ompt_event_macro) 295 296 #undef ompt_event_macro 297 298 default: 299 return ompt_set_result_registration_error; 300 } 301 } 302 303 OMPT_API_ROUTINE int ompt_get_callback(ompt_event_t evid, ompt_callback_t *cb) { 304 switch (evid) { 305 306 #define ompt_event_macro(event_name, callback_type, event_id) \ 307 case event_name: \ 308 if (ompt_event_implementation_status(event_name)) { \ 309 ompt_callback_t mycb = \ 310 (ompt_callback_t)ompt_callbacks.ompt_callback(event_name); \ 311 if (mycb) { \ 312 *cb = mycb; \ 313 return ompt_get_callback_success; \ 314 } \ 315 } \ 316 return ompt_get_callback_failure; 317 318 FOREACH_OMPT_EVENT(ompt_event_macro) 319 320 #undef ompt_event_macro 321 322 default: 323 return ompt_get_callback_failure; 324 } 325 } 326 327 /***************************************************************************** 328 * parallel regions 329 ****************************************************************************/ 330 331 OMPT_API_ROUTINE ompt_parallel_id_t ompt_get_parallel_id(int ancestor_level) { 332 return __ompt_get_parallel_id_internal(ancestor_level); 333 } 334 335 OMPT_API_ROUTINE int ompt_get_parallel_team_size(int ancestor_level) { 336 return __ompt_get_parallel_team_size_internal(ancestor_level); 337 } 338 339 OMPT_API_ROUTINE void *ompt_get_parallel_function(int ancestor_level) { 340 return __ompt_get_parallel_function_internal(ancestor_level); 341 } 342 343 OMPT_API_ROUTINE ompt_state_t ompt_get_state(ompt_wait_id_t *ompt_wait_id) { 344 ompt_state_t thread_state = __ompt_get_state_internal(ompt_wait_id); 345 346 if (thread_state == ompt_state_undefined) { 347 thread_state = ompt_state_work_serial; 348 } 349 350 return thread_state; 351 } 352 353 /***************************************************************************** 354 * threads 355 ****************************************************************************/ 356 357 OMPT_API_ROUTINE void *ompt_get_idle_frame() { 358 return __ompt_get_idle_frame_internal(); 359 } 360 361 /***************************************************************************** 362 * tasks 363 ****************************************************************************/ 364 365 OMPT_API_ROUTINE ompt_thread_id_t ompt_get_thread_id(void) { 366 return __ompt_get_thread_id_internal(); 367 } 368 369 OMPT_API_ROUTINE ompt_task_id_t ompt_get_task_id(int depth) { 370 return __ompt_get_task_id_internal(depth); 371 } 372 373 OMPT_API_ROUTINE ompt_frame_t *ompt_get_task_frame(int depth) { 374 return __ompt_get_task_frame_internal(depth); 375 } 376 377 OMPT_API_ROUTINE void *ompt_get_task_function(int depth) { 378 return __ompt_get_task_function_internal(depth); 379 } 380 381 /***************************************************************************** 382 * placeholders 383 ****************************************************************************/ 384 385 // Don't define this as static. The loader may choose to eliminate the symbol 386 // even though it is needed by tools. 387 #define OMPT_API_PLACEHOLDER 388 389 // Ensure that placeholders don't have mangled names in the symbol table. 390 #ifdef __cplusplus 391 extern "C" { 392 #endif 393 394 OMPT_API_PLACEHOLDER void ompt_idle(void) { 395 // This function is a placeholder used to represent the calling context of 396 // idle OpenMP worker threads. It is not meant to be invoked. 397 assert(0); 398 } 399 400 OMPT_API_PLACEHOLDER void ompt_overhead(void) { 401 // This function is a placeholder used to represent the OpenMP context of 402 // threads working in the OpenMP runtime. It is not meant to be invoked. 403 assert(0); 404 } 405 406 OMPT_API_PLACEHOLDER void ompt_barrier_wait(void) { 407 // This function is a placeholder used to represent the OpenMP context of 408 // threads waiting for a barrier in the OpenMP runtime. It is not meant 409 // to be invoked. 410 assert(0); 411 } 412 413 OMPT_API_PLACEHOLDER void ompt_task_wait(void) { 414 // This function is a placeholder used to represent the OpenMP context of 415 // threads waiting for a task in the OpenMP runtime. It is not meant 416 // to be invoked. 417 assert(0); 418 } 419 420 OMPT_API_PLACEHOLDER void ompt_mutex_wait(void) { 421 // This function is a placeholder used to represent the OpenMP context of 422 // threads waiting for a mutex in the OpenMP runtime. It is not meant 423 // to be invoked. 424 assert(0); 425 } 426 427 #ifdef __cplusplus 428 }; 429 #endif 430 431 /***************************************************************************** 432 * compatability 433 ****************************************************************************/ 434 435 OMPT_API_ROUTINE int ompt_get_ompt_version() { return OMPT_VERSION; } 436 437 /***************************************************************************** 438 * application-facing API 439 ****************************************************************************/ 440 441 /*---------------------------------------------------------------------------- 442 | control 443 ---------------------------------------------------------------------------*/ 444 445 _OMP_EXTERN void ompt_control(uint64_t command, uint64_t modifier) { 446 if (ompt_enabled && ompt_callbacks.ompt_callback(ompt_event_control)) { 447 ompt_callbacks.ompt_callback(ompt_event_control)(command, modifier); 448 } 449 } 450 451 /***************************************************************************** 452 * API inquiry for tool 453 ****************************************************************************/ 454 455 static ompt_interface_fn_t ompt_fn_lookup(const char *s) { 456 457 #define ompt_interface_fn(fn) \ 458 if (strcmp(s, #fn) == 0) \ 459 return (ompt_interface_fn_t)fn; 460 461 FOREACH_OMPT_INQUIRY_FN(ompt_interface_fn) 462 463 FOREACH_OMPT_PLACEHOLDER_FN(ompt_interface_fn) 464 465 return (ompt_interface_fn_t)0; 466 } 467