1 /* 2 * ompt-general.cpp -- OMPT implementation of interface functions 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 "kmp_utils.h" 14 15 /***************************************************************************** 16 * system include files 17 ****************************************************************************/ 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_UNIX 25 #include <dlfcn.h> 26 #endif 27 28 /***************************************************************************** 29 * ompt include files 30 ****************************************************************************/ 31 32 #include "ompt-specific.cpp" 33 34 /***************************************************************************** 35 * macros 36 ****************************************************************************/ 37 38 #define ompt_get_callback_success 1 39 #define ompt_get_callback_failure 0 40 41 #define no_tool_present 0 42 43 #define OMPT_API_ROUTINE static 44 45 #ifndef OMPT_STR_MATCH 46 #define OMPT_STR_MATCH(haystack, needle) (!strcasecmp(haystack, needle)) 47 #endif 48 49 // prints for an enabled OMP_TOOL_VERBOSE_INIT. 50 // In the future a prefix could be added in the first define, the second define 51 // omits the prefix to allow for continued lines. Example: "PREFIX: Start 52 // 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 60 static FILE *verbose_file; 61 static int verbose_init; 62 63 /***************************************************************************** 64 * types 65 ****************************************************************************/ 66 67 typedef struct { 68 const char *state_name; 69 ompt_state_t state_id; 70 } ompt_state_info_t; 71 72 typedef struct { 73 const char *name; 74 kmp_mutex_impl_t id; 75 } kmp_mutex_impl_info_t; 76 77 enum tool_setting_e { 78 omp_tool_error, 79 omp_tool_unset, 80 omp_tool_disabled, 81 omp_tool_enabled 82 }; 83 84 /***************************************************************************** 85 * global variables 86 ****************************************************************************/ 87 88 ompt_callbacks_active_t ompt_enabled; 89 90 ompt_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_macro 94 }; 95 96 kmp_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_macro 100 }; 101 102 ompt_callbacks_internal_t ompt_callbacks; 103 104 static ompt_start_tool_result_t *ompt_start_tool_result = NULL; 105 106 #if KMP_OS_WINDOWS 107 static HMODULE ompt_tool_module = NULL; 108 static HMODULE ompt_archer_module = NULL; 109 #define OMPT_DLCLOSE(Lib) FreeLibrary(Lib) 110 #else 111 static void *ompt_tool_module = NULL; 112 static void *ompt_archer_module = NULL; 113 #define OMPT_DLCLOSE(Lib) dlclose(Lib) 114 #endif 115 116 /// Used to track the initializer and the finalizer provided by libomptarget 117 static ompt_start_tool_result_t *libomptarget_ompt_result = NULL; 118 119 /***************************************************************************** 120 * forward declarations 121 ****************************************************************************/ 122 123 static ompt_interface_fn_t ompt_fn_lookup(const char *s); 124 125 OMPT_API_ROUTINE ompt_data_t *ompt_get_thread_data(void); 126 127 /***************************************************************************** 128 * initialization and finalization (private operations) 129 ****************************************************************************/ 130 131 typedef ompt_start_tool_result_t *(*ompt_start_tool_t)(unsigned int, 132 const char *); 133 134 #if KMP_OS_DARWIN 135 136 // While Darwin supports weak symbols, the library that wishes to provide a new 137 // implementation has to link against this runtime which defeats the purpose 138 // of having tools that are agnostic of the underlying runtime implementation. 139 // 140 // Fortunately, the linker includes all symbols of an executable in the global 141 // symbol table by default so dlsym() even finds static implementations of 142 // ompt_start_tool. For this to work on Linux, -Wl,--export-dynamic needs to be 143 // passed when building the application which we don't want to rely on. 144 145 static 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_ATTRIBUTE 158 159 // On Unix-like systems that support weak symbols the following implementation 160 // of ompt_start_tool() will be used in case no tool-supplied implementation of 161 // this function is present in the address space of a process. 162 163 _OMP_EXTERN OMPT_WEAK_ATTRIBUTE ompt_start_tool_result_t * 164 ompt_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 the 167 // runtime library is linked before the tool. Since glibc 2.2 strong symbols 168 // don't override weak symbols that have been found before unless the user 169 // 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_PSAPI 179 180 // On Windows, the ompt_tool_windows function is used to find the 181 // ompt_start_tool symbol across all modules loaded by a process. If 182 // ompt_start_tool is found, ompt_start_tool's return value is used to 183 // 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 128 190 191 static ompt_start_tool_result_t * 192 ompt_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_DEBUG 201 printf("ompt_tool_windows(): looking for ompt_start_tool\n"); 202 #endif 203 if (!EnumProcessModules(process, modules, NUM_MODULES * sizeof(HMODULE), 204 &needed)) { 205 // Regardless of the error reason use the stub initialization function 206 free(modules); 207 return NULL; 208 } 209 // Check if NUM_MODULES is enough to list all modules 210 new_size = needed / sizeof(HMODULE); 211 if (new_size > NUM_MODULES) { 212 #if OMPT_DEBUG 213 printf("ompt_tool_windows(): resize buffer to %d bytes\n", needed); 214 #endif 215 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_DEBUG 226 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 #endif 231 free(modules); 232 return (*ompt_tool_p)(omp_version, runtime_version); 233 } 234 #if OMPT_DEBUG 235 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 #endif 242 } 243 free(modules); 244 return NULL; 245 } 246 #else 247 #error Activation of OMPT is not supported on this platform. 248 #endif 249 250 static ompt_start_tool_result_t * 251 ompt_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_WINDOWS 255 // Cannot use colon to describe a list of absolute paths on Windows 256 const char *sep = ";"; 257 #else 258 const char *sep = ":"; 259 #endif 260 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_DARWIN 265 // Try in the current address space 266 ret = ompt_tool_darwin(omp_version, runtime_version); 267 #elif OMPT_HAVE_WEAK_ATTRIBUTE 268 ret = ompt_start_tool(omp_version, runtime_version); 269 #elif OMPT_HAVE_PSAPI 270 ret = ompt_tool_windows(omp_version, runtime_version); 271 #else 272 #error Activation of OMPT is not supported on this platform. 273 #endif 274 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 ICV 283 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-error 292 dlerror(); 293 294 while (fname) { 295 #if KMP_OS_UNIX 296 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 error 305 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 } else 315 #elif KMP_OS_WINDOWS 316 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 } else 330 #else 331 #error Activation of OMPT is not supported on this platform. 332 #endif 333 { // 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-libraries 356 if (ret) { 357 OMPT_VERBOSE_INIT_PRINT("----- END LOGGING OF TOOL REGISTRATION -----\n"); 358 return ret; 359 } 360 361 #if KMP_OS_UNIX 362 { // Non-standard: load archer tool if application is built with TSan 363 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 #endif 392 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 397 void 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 logging 424 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 else 432 verbose_file = fopen(ompt_env_verbose_init, "w"); 433 } else 434 verbose_init = 0; 435 436 #if OMPT_DEBUG 437 printf("ompt_pre_init(): tool_setting = %d\n", tool_setting); 438 #endif 439 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 variable 449 //-------------------------------------------------- 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_DEBUG 467 printf("ompt_pre_init(): ompt_enabled = %d\n", ompt_enabled.enabled); 468 #endif 469 } 470 471 extern "C" int omp_get_initial_device(void); 472 473 void 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 done 494 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 502 if (ompt_enabled.ompt_callback_thread_begin) { 503 ompt_callbacks.ompt_callback(ompt_callback_thread_begin)( 504 ompt_thread_initial, __ompt_get_thread_data_internal()); 505 } 506 ompt_data_t *task_data = nullptr; 507 ompt_data_t *parallel_data = nullptr; 508 __ompt_get_task_info_internal(0, NULL, &task_data, NULL, ¶llel_data, 509 NULL); 510 if (ompt_enabled.ompt_callback_implicit_task) { 511 ompt_callbacks.ompt_callback(ompt_callback_implicit_task)( 512 ompt_scope_begin, parallel_data, task_data, 1, 1, ompt_task_initial); 513 } 514 515 ompt_set_thread_state(root_thread, ompt_state_work_serial); 516 } 517 } 518 519 void ompt_fini() { 520 if (ompt_enabled.enabled) { 521 if (ompt_start_tool_result && ompt_start_tool_result->finalize) { 522 ompt_start_tool_result->finalize(&(ompt_start_tool_result->tool_data)); 523 } 524 if (libomptarget_ompt_result && libomptarget_ompt_result->finalize) { 525 libomptarget_ompt_result->finalize(NULL); 526 } 527 } 528 529 if (ompt_archer_module) 530 OMPT_DLCLOSE(ompt_archer_module); 531 if (ompt_tool_module) 532 OMPT_DLCLOSE(ompt_tool_module); 533 memset(&ompt_enabled, 0, sizeof(ompt_enabled)); 534 } 535 536 /***************************************************************************** 537 * interface operations 538 ****************************************************************************/ 539 540 /***************************************************************************** 541 * state 542 ****************************************************************************/ 543 544 OMPT_API_ROUTINE int ompt_enumerate_states(int current_state, int *next_state, 545 const char **next_state_name) { 546 const static int len = sizeof(ompt_state_info) / sizeof(ompt_state_info_t); 547 int i = 0; 548 549 for (i = 0; i < len - 1; i++) { 550 if (ompt_state_info[i].state_id == current_state) { 551 *next_state = ompt_state_info[i + 1].state_id; 552 *next_state_name = ompt_state_info[i + 1].state_name; 553 return 1; 554 } 555 } 556 557 return 0; 558 } 559 560 OMPT_API_ROUTINE int ompt_enumerate_mutex_impls(int current_impl, 561 int *next_impl, 562 const char **next_impl_name) { 563 const static int len = 564 sizeof(kmp_mutex_impl_info) / sizeof(kmp_mutex_impl_info_t); 565 int i = 0; 566 for (i = 0; i < len - 1; i++) { 567 if (kmp_mutex_impl_info[i].id != current_impl) 568 continue; 569 *next_impl = kmp_mutex_impl_info[i + 1].id; 570 *next_impl_name = kmp_mutex_impl_info[i + 1].name; 571 return 1; 572 } 573 return 0; 574 } 575 576 /***************************************************************************** 577 * callbacks 578 ****************************************************************************/ 579 580 OMPT_API_ROUTINE ompt_set_result_t ompt_set_callback(ompt_callbacks_t which, 581 ompt_callback_t callback) { 582 switch (which) { 583 584 #define ompt_event_macro(event_name, callback_type, event_id) \ 585 case event_name: \ 586 ompt_callbacks.ompt_callback(event_name) = (callback_type)callback; \ 587 ompt_enabled.event_name = (callback != 0); \ 588 if (callback) \ 589 return ompt_event_implementation_status(event_name); \ 590 else \ 591 return ompt_set_always; 592 593 FOREACH_OMPT_EVENT(ompt_event_macro) 594 595 #undef ompt_event_macro 596 597 default: 598 return ompt_set_error; 599 } 600 } 601 602 OMPT_API_ROUTINE int ompt_get_callback(ompt_callbacks_t which, 603 ompt_callback_t *callback) { 604 if (!ompt_enabled.enabled) 605 return ompt_get_callback_failure; 606 607 switch (which) { 608 609 #define ompt_event_macro(event_name, callback_type, event_id) \ 610 case event_name: { \ 611 ompt_callback_t mycb = \ 612 (ompt_callback_t)ompt_callbacks.ompt_callback(event_name); \ 613 if (ompt_enabled.event_name && mycb) { \ 614 *callback = mycb; \ 615 return ompt_get_callback_success; \ 616 } \ 617 return ompt_get_callback_failure; \ 618 } 619 620 FOREACH_OMPT_EVENT(ompt_event_macro) 621 622 #undef ompt_event_macro 623 624 default: 625 return ompt_get_callback_failure; 626 } 627 } 628 629 /***************************************************************************** 630 * parallel regions 631 ****************************************************************************/ 632 633 OMPT_API_ROUTINE int ompt_get_parallel_info(int ancestor_level, 634 ompt_data_t **parallel_data, 635 int *team_size) { 636 if (!ompt_enabled.enabled) 637 return 0; 638 return __ompt_get_parallel_info_internal(ancestor_level, parallel_data, 639 team_size); 640 } 641 642 OMPT_API_ROUTINE int ompt_get_state(ompt_wait_id_t *wait_id) { 643 if (!ompt_enabled.enabled) 644 return ompt_state_work_serial; 645 int thread_state = __ompt_get_state_internal(wait_id); 646 647 if (thread_state == ompt_state_undefined) { 648 thread_state = ompt_state_work_serial; 649 } 650 651 return thread_state; 652 } 653 654 /***************************************************************************** 655 * tasks 656 ****************************************************************************/ 657 658 OMPT_API_ROUTINE ompt_data_t *ompt_get_thread_data(void) { 659 if (!ompt_enabled.enabled) 660 return NULL; 661 return __ompt_get_thread_data_internal(); 662 } 663 664 OMPT_API_ROUTINE int ompt_get_task_info(int ancestor_level, int *type, 665 ompt_data_t **task_data, 666 ompt_frame_t **task_frame, 667 ompt_data_t **parallel_data, 668 int *thread_num) { 669 if (!ompt_enabled.enabled) 670 return 0; 671 return __ompt_get_task_info_internal(ancestor_level, type, task_data, 672 task_frame, parallel_data, thread_num); 673 } 674 675 OMPT_API_ROUTINE int ompt_get_task_memory(void **addr, size_t *size, 676 int block) { 677 return __ompt_get_task_memory_internal(addr, size, block); 678 } 679 680 /***************************************************************************** 681 * num_procs 682 ****************************************************************************/ 683 684 OMPT_API_ROUTINE int ompt_get_num_procs(void) { 685 // copied from kmp_ftn_entry.h (but modified: OMPT can only be called when 686 // runtime is initialized) 687 return __kmp_avail_proc; 688 } 689 690 /***************************************************************************** 691 * places 692 ****************************************************************************/ 693 694 OMPT_API_ROUTINE int ompt_get_num_places(void) { 695 // copied from kmp_ftn_entry.h (but modified) 696 #if !KMP_AFFINITY_SUPPORTED 697 return 0; 698 #else 699 if (!KMP_AFFINITY_CAPABLE()) 700 return 0; 701 return __kmp_affinity.num_masks; 702 #endif 703 } 704 705 OMPT_API_ROUTINE int ompt_get_place_proc_ids(int place_num, int ids_size, 706 int *ids) { 707 // copied from kmp_ftn_entry.h (but modified) 708 #if !KMP_AFFINITY_SUPPORTED 709 return 0; 710 #else 711 int i, count; 712 SimpleVLA<int> tmp_ids(ids_size); 713 for (int j = 0; j < ids_size; j++) 714 tmp_ids[j] = 0; 715 if (!KMP_AFFINITY_CAPABLE()) 716 return 0; 717 if (place_num < 0 || place_num >= (int)__kmp_affinity.num_masks) 718 return 0; 719 /* TODO: Is this safe for asynchronous call from signal handler during runtime 720 * shutdown? */ 721 kmp_affin_mask_t *mask = KMP_CPU_INDEX(__kmp_affinity.masks, place_num); 722 count = 0; 723 KMP_CPU_SET_ITERATE(i, mask) { 724 if ((!KMP_CPU_ISSET(i, __kmp_affin_fullMask)) || 725 (!KMP_CPU_ISSET(i, mask))) { 726 continue; 727 } 728 if (count < ids_size) 729 tmp_ids[count] = i; 730 count++; 731 } 732 if (ids_size >= count) { 733 for (i = 0; i < count; i++) { 734 ids[i] = tmp_ids[i]; 735 } 736 } 737 return count; 738 #endif 739 } 740 741 OMPT_API_ROUTINE int ompt_get_place_num(void) { 742 // copied from kmp_ftn_entry.h (but modified) 743 #if !KMP_AFFINITY_SUPPORTED 744 return -1; 745 #else 746 if (!ompt_enabled.enabled || __kmp_get_gtid() < 0) 747 return -1; 748 749 int gtid; 750 kmp_info_t *thread; 751 if (!KMP_AFFINITY_CAPABLE()) 752 return -1; 753 gtid = __kmp_entry_gtid(); 754 thread = __kmp_thread_from_gtid(gtid); 755 if (thread == NULL || thread->th.th_current_place < 0) 756 return -1; 757 return thread->th.th_current_place; 758 #endif 759 } 760 761 OMPT_API_ROUTINE int ompt_get_partition_place_nums(int place_nums_size, 762 int *place_nums) { 763 // copied from kmp_ftn_entry.h (but modified) 764 #if !KMP_AFFINITY_SUPPORTED 765 return 0; 766 #else 767 if (!ompt_enabled.enabled || __kmp_get_gtid() < 0) 768 return 0; 769 770 int i, gtid, place_num, first_place, last_place, start, end; 771 kmp_info_t *thread; 772 if (!KMP_AFFINITY_CAPABLE()) 773 return 0; 774 gtid = __kmp_entry_gtid(); 775 thread = __kmp_thread_from_gtid(gtid); 776 if (thread == NULL) 777 return 0; 778 first_place = thread->th.th_first_place; 779 last_place = thread->th.th_last_place; 780 if (first_place < 0 || last_place < 0) 781 return 0; 782 if (first_place <= last_place) { 783 start = first_place; 784 end = last_place; 785 } else { 786 start = last_place; 787 end = first_place; 788 } 789 if (end - start <= place_nums_size) 790 for (i = 0, place_num = start; place_num <= end; ++place_num, ++i) { 791 place_nums[i] = place_num; 792 } 793 return end - start + 1; 794 #endif 795 } 796 797 /***************************************************************************** 798 * places 799 ****************************************************************************/ 800 801 OMPT_API_ROUTINE int ompt_get_proc_id(void) { 802 if (!ompt_enabled.enabled || __kmp_get_gtid() < 0) 803 return -1; 804 #if KMP_HAVE_SCHED_GETCPU 805 return sched_getcpu(); 806 #elif KMP_OS_WINDOWS 807 PROCESSOR_NUMBER pn; 808 GetCurrentProcessorNumberEx(&pn); 809 return 64 * pn.Group + pn.Number; 810 #else 811 return -1; 812 #endif 813 } 814 815 /***************************************************************************** 816 * compatability 817 ****************************************************************************/ 818 819 /* 820 * Currently unused function 821 OMPT_API_ROUTINE int ompt_get_ompt_version() { return OMPT_VERSION; } 822 */ 823 824 /***************************************************************************** 825 * application-facing API 826 ****************************************************************************/ 827 828 /*---------------------------------------------------------------------------- 829 | control 830 ---------------------------------------------------------------------------*/ 831 832 int __kmp_control_tool(uint64_t command, uint64_t modifier, void *arg) { 833 834 if (ompt_enabled.enabled) { 835 if (ompt_enabled.ompt_callback_control_tool) { 836 return ompt_callbacks.ompt_callback(ompt_callback_control_tool)( 837 command, modifier, arg, OMPT_LOAD_RETURN_ADDRESS(__kmp_entry_gtid())); 838 } else { 839 return -1; 840 } 841 } else { 842 return -2; 843 } 844 } 845 846 /***************************************************************************** 847 * misc 848 ****************************************************************************/ 849 850 OMPT_API_ROUTINE uint64_t ompt_get_unique_id(void) { 851 return __ompt_get_unique_id_internal(); 852 } 853 854 OMPT_API_ROUTINE void ompt_finalize_tool(void) { __kmp_internal_end_atexit(); } 855 856 /***************************************************************************** 857 * Target 858 ****************************************************************************/ 859 860 OMPT_API_ROUTINE int ompt_get_target_info(uint64_t *device_num, 861 ompt_id_t *target_id, 862 ompt_id_t *host_op_id) { 863 return 0; // thread is not in a target region 864 } 865 866 OMPT_API_ROUTINE int ompt_get_num_devices(void) { 867 return 1; // only one device (the current device) is available 868 } 869 870 /***************************************************************************** 871 * API inquiry for tool 872 ****************************************************************************/ 873 874 static ompt_interface_fn_t ompt_fn_lookup(const char *s) { 875 876 #define ompt_interface_fn(fn) \ 877 fn##_t fn##_f = fn; \ 878 if (strcmp(s, #fn) == 0) \ 879 return (ompt_interface_fn_t)fn##_f; 880 881 FOREACH_OMPT_INQUIRY_FN(ompt_interface_fn) 882 883 #undef ompt_interface_fn 884 885 return NULL; 886 } 887 888 static ompt_data_t *ompt_get_task_data() { return __ompt_get_task_data(); } 889 890 static ompt_data_t *ompt_get_target_task_data() { 891 return __ompt_get_target_task_data(); 892 } 893 894 /// Lookup function to query libomp callbacks registered by the tool 895 static ompt_interface_fn_t ompt_libomp_target_fn_lookup(const char *s) { 896 #define provide_fn(fn) \ 897 if (strcmp(s, #fn) == 0) \ 898 return (ompt_interface_fn_t)fn; 899 900 provide_fn(ompt_get_callback); 901 provide_fn(ompt_get_task_data); 902 provide_fn(ompt_get_target_task_data); 903 #undef provide_fn 904 905 #define ompt_interface_fn(fn, type, code) \ 906 if (strcmp(s, #fn) == 0) \ 907 return (ompt_interface_fn_t)ompt_callbacks.ompt_callback(fn); 908 909 FOREACH_OMPT_DEVICE_EVENT(ompt_interface_fn) 910 FOREACH_OMPT_EMI_EVENT(ompt_interface_fn) 911 FOREACH_OMPT_NOEMI_EVENT(ompt_interface_fn) 912 #undef ompt_interface_fn 913 914 return (ompt_interface_fn_t)0; 915 } 916 917 /// This function is called by the libomptarget connector to assign 918 /// callbacks already registered with libomp. 919 _OMP_EXTERN void ompt_libomp_connect(ompt_start_tool_result_t *result) { 920 OMPT_VERBOSE_INIT_PRINT("libomp --> OMPT: Enter ompt_libomp_connect\n"); 921 922 // Ensure libomp callbacks have been added if not already 923 __ompt_force_initialization(); 924 925 if (ompt_enabled.enabled && result) { 926 OMPT_VERBOSE_INIT_PRINT("libomp --> OMPT: Connecting with libomptarget\n"); 927 // Pass in the libomp lookup function so that the already registered 928 // functions can be extracted and assigned to the callbacks in 929 // libomptarget 930 result->initialize(ompt_libomp_target_fn_lookup, 931 /* initial_device_num */ 0, /* tool_data */ nullptr); 932 // Track the object provided by libomptarget so that the finalizer can be 933 // called during OMPT finalization 934 libomptarget_ompt_result = result; 935 } 936 OMPT_VERBOSE_INIT_PRINT("libomp --> OMPT: Exit ompt_libomp_connect\n"); 937 } 938