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