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 /***************************************************************************** 14 * system include files 15 ****************************************************************************/ 16 17 #include <assert.h> 18 19 #include <stdint.h> 20 #include <stdio.h> 21 #include <stdlib.h> 22 #include <string.h> 23 #if KMP_OS_UNIX 24 #include <dlfcn.h> 25 #endif 26 27 /***************************************************************************** 28 * ompt include files 29 ****************************************************************************/ 30 31 #include "ompt-specific.cpp" 32 33 /***************************************************************************** 34 * macros 35 ****************************************************************************/ 36 37 #define ompt_get_callback_success 1 38 #define ompt_get_callback_failure 0 39 40 #define no_tool_present 0 41 42 #define OMPT_API_ROUTINE static 43 44 #ifndef OMPT_STR_MATCH 45 #define OMPT_STR_MATCH(haystack, needle) (!strcasecmp(haystack, needle)) 46 #endif 47 48 // prints for an enabled OMP_TOOL_VERBOSE_INIT. 49 // In the future a prefix could be added in the first define, the second define 50 // omits the prefix to allow for continued lines. Example: "PREFIX: Start 51 // tool... Success." instead of "PREFIX: Start tool... PREFIX: Success." 52 #define OMPT_VERBOSE_INIT_PRINT(...) \ 53 if (verbose_init) \ 54 fprintf(verbose_file, __VA_ARGS__) 55 #define OMPT_VERBOSE_INIT_CONTINUED_PRINT(...) \ 56 if (verbose_init) \ 57 fprintf(verbose_file, __VA_ARGS__) 58 59 static FILE *verbose_file; 60 static int verbose_init; 61 62 /***************************************************************************** 63 * types 64 ****************************************************************************/ 65 66 typedef struct { 67 const char *state_name; 68 ompt_state_t state_id; 69 } ompt_state_info_t; 70 71 typedef struct { 72 const char *name; 73 kmp_mutex_impl_t id; 74 } kmp_mutex_impl_info_t; 75 76 enum tool_setting_e { 77 omp_tool_error, 78 omp_tool_unset, 79 omp_tool_disabled, 80 omp_tool_enabled 81 }; 82 83 /***************************************************************************** 84 * global variables 85 ****************************************************************************/ 86 87 ompt_callbacks_active_t ompt_enabled; 88 89 ompt_state_info_t ompt_state_info[] = { 90 #define ompt_state_macro(state, code) {#state, state}, 91 FOREACH_OMPT_STATE(ompt_state_macro) 92 #undef ompt_state_macro 93 }; 94 95 kmp_mutex_impl_info_t kmp_mutex_impl_info[] = { 96 #define kmp_mutex_impl_macro(name, id) {#name, name}, 97 FOREACH_KMP_MUTEX_IMPL(kmp_mutex_impl_macro) 98 #undef kmp_mutex_impl_macro 99 }; 100 101 ompt_callbacks_internal_t ompt_callbacks; 102 103 static ompt_start_tool_result_t *ompt_start_tool_result = NULL; 104 105 #if KMP_OS_WINDOWS 106 static HMODULE ompt_tool_module = NULL; 107 #define OMPT_DLCLOSE(Lib) FreeLibrary(Lib) 108 #else 109 static void *ompt_tool_module = NULL; 110 #define OMPT_DLCLOSE(Lib) dlclose(Lib) 111 #endif 112 113 /***************************************************************************** 114 * forward declarations 115 ****************************************************************************/ 116 117 static ompt_interface_fn_t ompt_fn_lookup(const char *s); 118 119 OMPT_API_ROUTINE ompt_data_t *ompt_get_thread_data(void); 120 121 /***************************************************************************** 122 * initialization and finalization (private operations) 123 ****************************************************************************/ 124 125 typedef ompt_start_tool_result_t *(*ompt_start_tool_t)(unsigned int, 126 const char *); 127 128 #if KMP_OS_DARWIN 129 130 // While Darwin supports weak symbols, the library that wishes to provide a new 131 // implementation has to link against this runtime which defeats the purpose 132 // of having tools that are agnostic of the underlying runtime implementation. 133 // 134 // Fortunately, the linker includes all symbols of an executable in the global 135 // symbol table by default so dlsym() even finds static implementations of 136 // ompt_start_tool. For this to work on Linux, -Wl,--export-dynamic needs to be 137 // passed when building the application which we don't want to rely on. 138 139 static ompt_start_tool_result_t *ompt_tool_darwin(unsigned int omp_version, 140 const char *runtime_version) { 141 ompt_start_tool_result_t *ret = NULL; 142 // Search symbol in the current address space. 143 ompt_start_tool_t start_tool = 144 (ompt_start_tool_t)dlsym(RTLD_DEFAULT, "ompt_start_tool"); 145 if (start_tool) { 146 ret = start_tool(omp_version, runtime_version); 147 } 148 return ret; 149 } 150 151 #elif OMPT_HAVE_WEAK_ATTRIBUTE 152 153 // On Unix-like systems that support weak symbols the following implementation 154 // of ompt_start_tool() will be used in case no tool-supplied implementation of 155 // this function is present in the address space of a process. 156 157 _OMP_EXTERN OMPT_WEAK_ATTRIBUTE ompt_start_tool_result_t * 158 ompt_start_tool(unsigned int omp_version, const char *runtime_version) { 159 ompt_start_tool_result_t *ret = NULL; 160 // Search next symbol in the current address space. This can happen if the 161 // runtime library is linked before the tool. Since glibc 2.2 strong symbols 162 // don't override weak symbols that have been found before unless the user 163 // sets the environment variable LD_DYNAMIC_WEAK. 164 ompt_start_tool_t next_tool = 165 (ompt_start_tool_t)dlsym(RTLD_NEXT, "ompt_start_tool"); 166 if (next_tool) { 167 ret = next_tool(omp_version, runtime_version); 168 } 169 return ret; 170 } 171 172 #elif OMPT_HAVE_PSAPI 173 174 // On Windows, the ompt_tool_windows function is used to find the 175 // ompt_start_tool symbol across all modules loaded by a process. If 176 // ompt_start_tool is found, ompt_start_tool's return value is used to 177 // initialize the tool. Otherwise, NULL is returned and OMPT won't be enabled. 178 179 #include <psapi.h> 180 #pragma comment(lib, "psapi.lib") 181 182 // The number of loaded modules to start enumeration with EnumProcessModules() 183 #define NUM_MODULES 128 184 185 static ompt_start_tool_result_t * 186 ompt_tool_windows(unsigned int omp_version, const char *runtime_version) { 187 int i; 188 DWORD needed, new_size; 189 HMODULE *modules; 190 HANDLE process = GetCurrentProcess(); 191 modules = (HMODULE *)malloc(NUM_MODULES * sizeof(HMODULE)); 192 ompt_start_tool_t ompt_tool_p = NULL; 193 194 #if OMPT_DEBUG 195 printf("ompt_tool_windows(): looking for ompt_start_tool\n"); 196 #endif 197 if (!EnumProcessModules(process, modules, NUM_MODULES * sizeof(HMODULE), 198 &needed)) { 199 // Regardless of the error reason use the stub initialization function 200 free(modules); 201 return NULL; 202 } 203 // Check if NUM_MODULES is enough to list all modules 204 new_size = needed / sizeof(HMODULE); 205 if (new_size > NUM_MODULES) { 206 #if OMPT_DEBUG 207 printf("ompt_tool_windows(): resize buffer to %d bytes\n", needed); 208 #endif 209 modules = (HMODULE *)realloc(modules, needed); 210 // If resizing failed use the stub function. 211 if (!EnumProcessModules(process, modules, needed, &needed)) { 212 free(modules); 213 return NULL; 214 } 215 } 216 for (i = 0; i < new_size; ++i) { 217 (FARPROC &)ompt_tool_p = GetProcAddress(modules[i], "ompt_start_tool"); 218 if (ompt_tool_p) { 219 #if OMPT_DEBUG 220 TCHAR modName[MAX_PATH]; 221 if (GetModuleFileName(modules[i], modName, MAX_PATH)) 222 printf("ompt_tool_windows(): ompt_start_tool found in module %s\n", 223 modName); 224 #endif 225 free(modules); 226 return (*ompt_tool_p)(omp_version, runtime_version); 227 } 228 #if OMPT_DEBUG 229 else { 230 TCHAR modName[MAX_PATH]; 231 if (GetModuleFileName(modules[i], modName, MAX_PATH)) 232 printf("ompt_tool_windows(): ompt_start_tool not found in module %s\n", 233 modName); 234 } 235 #endif 236 } 237 free(modules); 238 return NULL; 239 } 240 #else 241 #error Activation of OMPT is not supported on this platform. 242 #endif 243 244 static ompt_start_tool_result_t * 245 ompt_try_start_tool(unsigned int omp_version, const char *runtime_version) { 246 ompt_start_tool_result_t *ret = NULL; 247 ompt_start_tool_t start_tool = NULL; 248 #if KMP_OS_WINDOWS 249 // Cannot use colon to describe a list of absolute paths on Windows 250 const char *sep = ";"; 251 #else 252 const char *sep = ":"; 253 #endif 254 255 OMPT_VERBOSE_INIT_PRINT("----- START LOGGING OF TOOL REGISTRATION -----\n"); 256 OMPT_VERBOSE_INIT_PRINT("Search for OMP tool in current address space... "); 257 258 #if KMP_OS_DARWIN 259 // Try in the current address space 260 ret = ompt_tool_darwin(omp_version, runtime_version); 261 #elif OMPT_HAVE_WEAK_ATTRIBUTE 262 ret = ompt_start_tool(omp_version, runtime_version); 263 #elif OMPT_HAVE_PSAPI 264 ret = ompt_tool_windows(omp_version, runtime_version); 265 #else 266 #error Activation of OMPT is not supported on this platform. 267 #endif 268 if (ret) { 269 OMPT_VERBOSE_INIT_CONTINUED_PRINT("Success.\n"); 270 OMPT_VERBOSE_INIT_PRINT( 271 "Tool was started and is using the OMPT interface.\n"); 272 OMPT_VERBOSE_INIT_PRINT("----- END LOGGING OF TOOL REGISTRATION -----\n"); 273 return ret; 274 } 275 276 // Try tool-libraries-var ICV 277 OMPT_VERBOSE_INIT_CONTINUED_PRINT("Failed.\n"); 278 const char *tool_libs = getenv("OMP_TOOL_LIBRARIES"); 279 if (tool_libs) { 280 OMPT_VERBOSE_INIT_PRINT("Searching tool libraries...\n"); 281 OMPT_VERBOSE_INIT_PRINT("OMP_TOOL_LIBRARIES = %s\n", tool_libs); 282 char *libs = __kmp_str_format("%s", tool_libs); 283 char *buf; 284 char *fname = __kmp_str_token(libs, sep, &buf); 285 // Reset dl-error 286 dlerror(); 287 288 while (fname) { 289 #if KMP_OS_UNIX 290 OMPT_VERBOSE_INIT_PRINT("Opening %s... ", fname); 291 void *h = dlopen(fname, RTLD_LAZY); 292 if (!h) { 293 OMPT_VERBOSE_INIT_CONTINUED_PRINT("Failed: %s\n", dlerror()); 294 } else { 295 OMPT_VERBOSE_INIT_CONTINUED_PRINT("Success. \n"); 296 OMPT_VERBOSE_INIT_PRINT("Searching for ompt_start_tool in %s... ", 297 fname); 298 dlerror(); // Clear any existing error 299 start_tool = (ompt_start_tool_t)dlsym(h, "ompt_start_tool"); 300 if (!start_tool) { 301 char *error = dlerror(); 302 if (error != NULL) { 303 OMPT_VERBOSE_INIT_CONTINUED_PRINT("Failed: %s\n", error); 304 } else { 305 OMPT_VERBOSE_INIT_CONTINUED_PRINT("Failed: %s\n", 306 "ompt_start_tool = NULL"); 307 } 308 } else 309 #elif KMP_OS_WINDOWS 310 OMPT_VERBOSE_INIT_PRINT("Opening %s... ", fname); 311 HMODULE h = LoadLibrary(fname); 312 if (!h) { 313 OMPT_VERBOSE_INIT_CONTINUED_PRINT("Failed: Error %u\n", 314 (unsigned)GetLastError()); 315 } else { 316 OMPT_VERBOSE_INIT_CONTINUED_PRINT("Success. \n"); 317 OMPT_VERBOSE_INIT_PRINT("Searching for ompt_start_tool in %s... ", 318 fname); 319 start_tool = (ompt_start_tool_t)GetProcAddress(h, "ompt_start_tool"); 320 if (!start_tool) { 321 OMPT_VERBOSE_INIT_CONTINUED_PRINT("Failed: Error %u\n", 322 (unsigned)GetLastError()); 323 } else 324 #else 325 #error Activation of OMPT is not supported on this platform. 326 #endif 327 { // if (start_tool) 328 ret = (*start_tool)(omp_version, runtime_version); 329 if (ret) { 330 OMPT_VERBOSE_INIT_CONTINUED_PRINT("Success.\n"); 331 OMPT_VERBOSE_INIT_PRINT( 332 "Tool was started and is using the OMPT interface.\n"); 333 ompt_tool_module = h; 334 break; 335 } 336 OMPT_VERBOSE_INIT_CONTINUED_PRINT( 337 "Found but not using the OMPT interface.\n"); 338 OMPT_VERBOSE_INIT_PRINT("Continuing search...\n"); 339 } 340 OMPT_DLCLOSE(h); 341 } 342 fname = __kmp_str_token(NULL, sep, &buf); 343 } 344 __kmp_str_free(&libs); 345 } else { 346 OMPT_VERBOSE_INIT_PRINT("No OMP_TOOL_LIBRARIES defined.\n"); 347 } 348 349 // usable tool found in tool-libraries 350 if (ret) { 351 OMPT_VERBOSE_INIT_PRINT("----- END LOGGING OF TOOL REGISTRATION -----\n"); 352 return ret; 353 } 354 355 #if KMP_OS_UNIX 356 { // Non-standard: load archer tool if application is built with TSan 357 const char *fname = "libarcher.so"; 358 OMPT_VERBOSE_INIT_PRINT( 359 "...searching tool libraries failed. Using archer tool.\n"); 360 OMPT_VERBOSE_INIT_PRINT("Opening %s... ", fname); 361 void *h = dlopen(fname, RTLD_LAZY); 362 if (h) { 363 OMPT_VERBOSE_INIT_CONTINUED_PRINT("Success.\n"); 364 OMPT_VERBOSE_INIT_PRINT("Searching for ompt_start_tool in %s... ", fname); 365 start_tool = (ompt_start_tool_t)dlsym(h, "ompt_start_tool"); 366 if (start_tool) { 367 ret = (*start_tool)(omp_version, runtime_version); 368 if (ret) { 369 OMPT_VERBOSE_INIT_CONTINUED_PRINT("Success.\n"); 370 OMPT_VERBOSE_INIT_PRINT( 371 "Tool was started and is using the OMPT interface.\n"); 372 OMPT_VERBOSE_INIT_PRINT( 373 "----- END LOGGING OF TOOL REGISTRATION -----\n"); 374 return ret; 375 } 376 OMPT_VERBOSE_INIT_CONTINUED_PRINT( 377 "Found but not using the OMPT interface.\n"); 378 } else { 379 OMPT_VERBOSE_INIT_CONTINUED_PRINT("Failed: %s\n", dlerror()); 380 } 381 } 382 } 383 #endif 384 OMPT_VERBOSE_INIT_PRINT("No OMP tool loaded.\n"); 385 OMPT_VERBOSE_INIT_PRINT("----- END LOGGING OF TOOL REGISTRATION -----\n"); 386 return ret; 387 } 388 389 void ompt_pre_init() { 390 //-------------------------------------------------- 391 // Execute the pre-initialization logic only once. 392 //-------------------------------------------------- 393 static int ompt_pre_initialized = 0; 394 395 if (ompt_pre_initialized) 396 return; 397 398 ompt_pre_initialized = 1; 399 400 //-------------------------------------------------- 401 // Use a tool iff a tool is enabled and available. 402 //-------------------------------------------------- 403 const char *ompt_env_var = getenv("OMP_TOOL"); 404 tool_setting_e tool_setting = omp_tool_error; 405 406 if (!ompt_env_var || !strcmp(ompt_env_var, "")) 407 tool_setting = omp_tool_unset; 408 else if (OMPT_STR_MATCH(ompt_env_var, "disabled")) 409 tool_setting = omp_tool_disabled; 410 else if (OMPT_STR_MATCH(ompt_env_var, "enabled")) 411 tool_setting = omp_tool_enabled; 412 413 const char *ompt_env_verbose_init = getenv("OMP_TOOL_VERBOSE_INIT"); 414 // possible options: disabled | stdout | stderr | <filename> 415 // if set, not empty and not disabled -> prepare for logging 416 if (ompt_env_verbose_init && strcmp(ompt_env_verbose_init, "") && 417 !OMPT_STR_MATCH(ompt_env_verbose_init, "disabled")) { 418 verbose_init = 1; 419 if (OMPT_STR_MATCH(ompt_env_verbose_init, "STDERR")) 420 verbose_file = stderr; 421 else if (OMPT_STR_MATCH(ompt_env_verbose_init, "STDOUT")) 422 verbose_file = stdout; 423 else 424 verbose_file = fopen(ompt_env_verbose_init, "w"); 425 } else 426 verbose_init = 0; 427 428 #if OMPT_DEBUG 429 printf("ompt_pre_init(): tool_setting = %d\n", tool_setting); 430 #endif 431 switch (tool_setting) { 432 case omp_tool_disabled: 433 OMPT_VERBOSE_INIT_PRINT("OMP tool disabled. \n"); 434 break; 435 436 case omp_tool_unset: 437 case omp_tool_enabled: 438 439 //-------------------------------------------------- 440 // Load tool iff specified in environment variable 441 //-------------------------------------------------- 442 ompt_start_tool_result = 443 ompt_try_start_tool(__kmp_openmp_version, ompt_get_runtime_version()); 444 445 memset(&ompt_enabled, 0, sizeof(ompt_enabled)); 446 break; 447 448 case omp_tool_error: 449 fprintf(stderr, 450 "Warning: OMP_TOOL has invalid value \"%s\".\n" 451 " legal values are (NULL,\"\",\"disabled\"," 452 "\"enabled\").\n", 453 ompt_env_var); 454 break; 455 } 456 if (verbose_init && verbose_file != stderr && verbose_file != stdout) 457 fclose(verbose_file); 458 #if OMPT_DEBUG 459 printf("ompt_pre_init(): ompt_enabled = %d\n", ompt_enabled); 460 #endif 461 } 462 463 extern "C" int omp_get_initial_device(void); 464 465 void ompt_post_init() { 466 //-------------------------------------------------- 467 // Execute the post-initialization logic only once. 468 //-------------------------------------------------- 469 static int ompt_post_initialized = 0; 470 471 if (ompt_post_initialized) 472 return; 473 474 ompt_post_initialized = 1; 475 476 //-------------------------------------------------- 477 // Initialize the tool if so indicated. 478 //-------------------------------------------------- 479 if (ompt_start_tool_result) { 480 ompt_enabled.enabled = !!ompt_start_tool_result->initialize( 481 ompt_fn_lookup, omp_get_initial_device(), 482 &(ompt_start_tool_result->tool_data)); 483 484 if (!ompt_enabled.enabled) { 485 // tool not enabled, zero out the bitmap, and done 486 memset(&ompt_enabled, 0, sizeof(ompt_enabled)); 487 return; 488 } 489 490 kmp_info_t *root_thread = ompt_get_thread(); 491 492 ompt_set_thread_state(root_thread, ompt_state_overhead); 493 494 if (ompt_enabled.ompt_callback_thread_begin) { 495 ompt_callbacks.ompt_callback(ompt_callback_thread_begin)( 496 ompt_thread_initial, __ompt_get_thread_data_internal()); 497 } 498 ompt_data_t *task_data; 499 ompt_data_t *parallel_data; 500 __ompt_get_task_info_internal(0, NULL, &task_data, NULL, ¶llel_data, 501 NULL); 502 if (ompt_enabled.ompt_callback_implicit_task) { 503 ompt_callbacks.ompt_callback(ompt_callback_implicit_task)( 504 ompt_scope_begin, parallel_data, task_data, 1, 1, ompt_task_initial); 505 } 506 507 ompt_set_thread_state(root_thread, ompt_state_work_serial); 508 } 509 } 510 511 void ompt_fini() { 512 if (ompt_enabled.enabled 513 #if OMPD_SUPPORT 514 && ompt_start_tool_result && ompt_start_tool_result->finalize 515 #endif 516 ) { 517 ompt_start_tool_result->finalize(&(ompt_start_tool_result->tool_data)); 518 } 519 520 if (ompt_tool_module) 521 OMPT_DLCLOSE(ompt_tool_module); 522 memset(&ompt_enabled, 0, sizeof(ompt_enabled)); 523 } 524 525 /***************************************************************************** 526 * interface operations 527 ****************************************************************************/ 528 529 /***************************************************************************** 530 * state 531 ****************************************************************************/ 532 533 OMPT_API_ROUTINE int ompt_enumerate_states(int current_state, int *next_state, 534 const char **next_state_name) { 535 const static int len = sizeof(ompt_state_info) / sizeof(ompt_state_info_t); 536 int i = 0; 537 538 for (i = 0; i < len - 1; i++) { 539 if (ompt_state_info[i].state_id == current_state) { 540 *next_state = ompt_state_info[i + 1].state_id; 541 *next_state_name = ompt_state_info[i + 1].state_name; 542 return 1; 543 } 544 } 545 546 return 0; 547 } 548 549 OMPT_API_ROUTINE int ompt_enumerate_mutex_impls(int current_impl, 550 int *next_impl, 551 const char **next_impl_name) { 552 const static int len = 553 sizeof(kmp_mutex_impl_info) / sizeof(kmp_mutex_impl_info_t); 554 int i = 0; 555 for (i = 0; i < len - 1; i++) { 556 if (kmp_mutex_impl_info[i].id != current_impl) 557 continue; 558 *next_impl = kmp_mutex_impl_info[i + 1].id; 559 *next_impl_name = kmp_mutex_impl_info[i + 1].name; 560 return 1; 561 } 562 return 0; 563 } 564 565 /***************************************************************************** 566 * callbacks 567 ****************************************************************************/ 568 569 OMPT_API_ROUTINE ompt_set_result_t ompt_set_callback(ompt_callbacks_t which, 570 ompt_callback_t callback) { 571 switch (which) { 572 573 #define ompt_event_macro(event_name, callback_type, event_id) \ 574 case event_name: \ 575 ompt_callbacks.ompt_callback(event_name) = (callback_type)callback; \ 576 ompt_enabled.event_name = (callback != 0); \ 577 if (callback) \ 578 return ompt_event_implementation_status(event_name); \ 579 else \ 580 return ompt_set_always; 581 582 FOREACH_OMPT_EVENT(ompt_event_macro) 583 584 #undef ompt_event_macro 585 586 default: 587 return ompt_set_error; 588 } 589 } 590 591 OMPT_API_ROUTINE int ompt_get_callback(ompt_callbacks_t which, 592 ompt_callback_t *callback) { 593 if (!ompt_enabled.enabled) 594 return ompt_get_callback_failure; 595 596 switch (which) { 597 598 #define ompt_event_macro(event_name, callback_type, event_id) \ 599 case event_name: { \ 600 ompt_callback_t mycb = \ 601 (ompt_callback_t)ompt_callbacks.ompt_callback(event_name); \ 602 if (ompt_enabled.event_name && mycb) { \ 603 *callback = mycb; \ 604 return ompt_get_callback_success; \ 605 } \ 606 return ompt_get_callback_failure; \ 607 } 608 609 FOREACH_OMPT_EVENT(ompt_event_macro) 610 611 #undef ompt_event_macro 612 613 default: 614 return ompt_get_callback_failure; 615 } 616 } 617 618 /***************************************************************************** 619 * parallel regions 620 ****************************************************************************/ 621 622 OMPT_API_ROUTINE int ompt_get_parallel_info(int ancestor_level, 623 ompt_data_t **parallel_data, 624 int *team_size) { 625 if (!ompt_enabled.enabled) 626 return 0; 627 return __ompt_get_parallel_info_internal(ancestor_level, parallel_data, 628 team_size); 629 } 630 631 OMPT_API_ROUTINE int ompt_get_state(ompt_wait_id_t *wait_id) { 632 if (!ompt_enabled.enabled) 633 return ompt_state_work_serial; 634 int thread_state = __ompt_get_state_internal(wait_id); 635 636 if (thread_state == ompt_state_undefined) { 637 thread_state = ompt_state_work_serial; 638 } 639 640 return thread_state; 641 } 642 643 /***************************************************************************** 644 * tasks 645 ****************************************************************************/ 646 647 OMPT_API_ROUTINE ompt_data_t *ompt_get_thread_data(void) { 648 if (!ompt_enabled.enabled) 649 return NULL; 650 return __ompt_get_thread_data_internal(); 651 } 652 653 OMPT_API_ROUTINE int ompt_get_task_info(int ancestor_level, int *type, 654 ompt_data_t **task_data, 655 ompt_frame_t **task_frame, 656 ompt_data_t **parallel_data, 657 int *thread_num) { 658 if (!ompt_enabled.enabled) 659 return 0; 660 return __ompt_get_task_info_internal(ancestor_level, type, task_data, 661 task_frame, parallel_data, thread_num); 662 } 663 664 OMPT_API_ROUTINE int ompt_get_task_memory(void **addr, size_t *size, 665 int block) { 666 return __ompt_get_task_memory_internal(addr, size, block); 667 } 668 669 /***************************************************************************** 670 * num_procs 671 ****************************************************************************/ 672 673 OMPT_API_ROUTINE int ompt_get_num_procs(void) { 674 // copied from kmp_ftn_entry.h (but modified: OMPT can only be called when 675 // runtime is initialized) 676 return __kmp_avail_proc; 677 } 678 679 /***************************************************************************** 680 * places 681 ****************************************************************************/ 682 683 OMPT_API_ROUTINE int ompt_get_num_places(void) { 684 // copied from kmp_ftn_entry.h (but modified) 685 #if !KMP_AFFINITY_SUPPORTED 686 return 0; 687 #else 688 if (!KMP_AFFINITY_CAPABLE()) 689 return 0; 690 return __kmp_affinity_num_masks; 691 #endif 692 } 693 694 OMPT_API_ROUTINE int ompt_get_place_proc_ids(int place_num, int ids_size, 695 int *ids) { 696 // copied from kmp_ftn_entry.h (but modified) 697 #if !KMP_AFFINITY_SUPPORTED 698 return 0; 699 #else 700 int i, count; 701 int tmp_ids[ids_size]; 702 for (int j = 0; j < ids_size; j++) 703 tmp_ids[j] = 0; 704 if (!KMP_AFFINITY_CAPABLE()) 705 return 0; 706 if (place_num < 0 || place_num >= (int)__kmp_affinity_num_masks) 707 return 0; 708 /* TODO: Is this safe for asynchronous call from signal handler during runtime 709 * shutdown? */ 710 kmp_affin_mask_t *mask = KMP_CPU_INDEX(__kmp_affinity_masks, place_num); 711 count = 0; 712 KMP_CPU_SET_ITERATE(i, mask) { 713 if ((!KMP_CPU_ISSET(i, __kmp_affin_fullMask)) || 714 (!KMP_CPU_ISSET(i, mask))) { 715 continue; 716 } 717 if (count < ids_size) 718 tmp_ids[count] = i; 719 count++; 720 } 721 if (ids_size >= count) { 722 for (i = 0; i < count; i++) { 723 ids[i] = tmp_ids[i]; 724 } 725 } 726 return count; 727 #endif 728 } 729 730 OMPT_API_ROUTINE int ompt_get_place_num(void) { 731 // copied from kmp_ftn_entry.h (but modified) 732 #if !KMP_AFFINITY_SUPPORTED 733 return -1; 734 #else 735 if (!ompt_enabled.enabled || __kmp_get_gtid() < 0) 736 return -1; 737 738 int gtid; 739 kmp_info_t *thread; 740 if (!KMP_AFFINITY_CAPABLE()) 741 return -1; 742 gtid = __kmp_entry_gtid(); 743 thread = __kmp_thread_from_gtid(gtid); 744 if (thread == NULL || thread->th.th_current_place < 0) 745 return -1; 746 return thread->th.th_current_place; 747 #endif 748 } 749 750 OMPT_API_ROUTINE int ompt_get_partition_place_nums(int place_nums_size, 751 int *place_nums) { 752 // copied from kmp_ftn_entry.h (but modified) 753 #if !KMP_AFFINITY_SUPPORTED 754 return 0; 755 #else 756 if (!ompt_enabled.enabled || __kmp_get_gtid() < 0) 757 return 0; 758 759 int i, gtid, place_num, first_place, last_place, start, end; 760 kmp_info_t *thread; 761 if (!KMP_AFFINITY_CAPABLE()) 762 return 0; 763 gtid = __kmp_entry_gtid(); 764 thread = __kmp_thread_from_gtid(gtid); 765 if (thread == NULL) 766 return 0; 767 first_place = thread->th.th_first_place; 768 last_place = thread->th.th_last_place; 769 if (first_place < 0 || last_place < 0) 770 return 0; 771 if (first_place <= last_place) { 772 start = first_place; 773 end = last_place; 774 } else { 775 start = last_place; 776 end = first_place; 777 } 778 if (end - start <= place_nums_size) 779 for (i = 0, place_num = start; place_num <= end; ++place_num, ++i) { 780 place_nums[i] = place_num; 781 } 782 return end - start + 1; 783 #endif 784 } 785 786 /***************************************************************************** 787 * places 788 ****************************************************************************/ 789 790 OMPT_API_ROUTINE int ompt_get_proc_id(void) { 791 if (!ompt_enabled.enabled || __kmp_get_gtid() < 0) 792 return -1; 793 #if KMP_HAVE_SCHED_GETCPU 794 return sched_getcpu(); 795 #elif KMP_OS_WINDOWS 796 PROCESSOR_NUMBER pn; 797 GetCurrentProcessorNumberEx(&pn); 798 return 64 * pn.Group + pn.Number; 799 #else 800 return -1; 801 #endif 802 } 803 804 /***************************************************************************** 805 * compatability 806 ****************************************************************************/ 807 808 /* 809 * Currently unused function 810 OMPT_API_ROUTINE int ompt_get_ompt_version() { return OMPT_VERSION; } 811 */ 812 813 /***************************************************************************** 814 * application-facing API 815 ****************************************************************************/ 816 817 /*---------------------------------------------------------------------------- 818 | control 819 ---------------------------------------------------------------------------*/ 820 821 int __kmp_control_tool(uint64_t command, uint64_t modifier, void *arg) { 822 823 if (ompt_enabled.enabled) { 824 if (ompt_enabled.ompt_callback_control_tool) { 825 return ompt_callbacks.ompt_callback(ompt_callback_control_tool)( 826 command, modifier, arg, OMPT_LOAD_RETURN_ADDRESS(__kmp_entry_gtid())); 827 } else { 828 return -1; 829 } 830 } else { 831 return -2; 832 } 833 } 834 835 /***************************************************************************** 836 * misc 837 ****************************************************************************/ 838 839 OMPT_API_ROUTINE uint64_t ompt_get_unique_id(void) { 840 return __ompt_get_unique_id_internal(); 841 } 842 843 OMPT_API_ROUTINE void ompt_finalize_tool(void) { __kmp_internal_end_atexit(); } 844 845 /***************************************************************************** 846 * Target 847 ****************************************************************************/ 848 849 OMPT_API_ROUTINE int ompt_get_target_info(uint64_t *device_num, 850 ompt_id_t *target_id, 851 ompt_id_t *host_op_id) { 852 return 0; // thread is not in a target region 853 } 854 855 OMPT_API_ROUTINE int ompt_get_num_devices(void) { 856 return 1; // only one device (the current device) is available 857 } 858 859 /***************************************************************************** 860 * API inquiry for tool 861 ****************************************************************************/ 862 863 static ompt_interface_fn_t ompt_fn_lookup(const char *s) { 864 865 #define ompt_interface_fn(fn) \ 866 fn##_t fn##_f = fn; \ 867 if (strcmp(s, #fn) == 0) \ 868 return (ompt_interface_fn_t)fn##_f; 869 870 FOREACH_OMPT_INQUIRY_FN(ompt_interface_fn) 871 872 return NULL; 873 } 874