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