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