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
60static FILE *verbose_file;
61static int verbose_init;
62
63/*****************************************************************************
64 * types
65 ****************************************************************************/
66
67typedef struct {
68 const char *state_name;
69 ompt_state_t state_id;
70} ompt_state_info_t;
71
72typedef struct {
73 const char *name;
74 kmp_mutex_impl_t id;
75} kmp_mutex_impl_info_t;
76
77enum 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
88ompt_callbacks_active_t ompt_enabled;
89
90ompt_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
96kmp_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
102ompt_callbacks_internal_t ompt_callbacks;
103
104static ompt_start_tool_result_t *ompt_start_tool_result = NULL;
105
106#if KMP_OS_WINDOWS
107static HMODULE ompt_tool_module = NULL;
108static HMODULE ompt_archer_module = NULL;
109#define OMPT_DLCLOSE(Lib) FreeLibrary(Lib)
110#else
111static void *ompt_tool_module = NULL;
112static 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
117static ompt_start_tool_result_t *libomptarget_ompt_result = NULL;
118
119/*****************************************************************************
120 * forward declarations
121 ****************************************************************************/
122
123static ompt_interface_fn_t ompt_fn_lookup(const char *s);
124
125OMPT_API_ROUTINE ompt_data_t *ompt_get_thread_data(void);
126
127/*****************************************************************************
128 * initialization and finalization (private operations)
129 ****************************************************************************/
130
131typedef 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
145static 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 *
164ompt_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, name: "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
191static ompt_start_tool_result_t *
192ompt_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
250static ompt_start_tool_result_t *
251ompt_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(name: "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(format: "%s", tool_libs);
289 char *buf;
290 char *fname = __kmp_str_token(str: libs, delim: sep, buf: &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(file: 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(handle: h, name: "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, delim: sep, buf: &buf);
349 }
350 __kmp_str_free(str: &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(file: 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(handle: h, name: "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
397void 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(name: "OMP_TOOL");
412 tool_setting_e tool_setting = omp_tool_error;
413
414 if (!ompt_env_var || !strcmp(s1: ompt_env_var, s2: ""))
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(name: "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(s1: ompt_env_verbose_init, s2: "") &&
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(filename: ompt_env_verbose_init, modes: "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(omp_version: __kmp_openmp_version, runtime_version: ompt_get_runtime_version());
452
453 memset(s: &ompt_enabled, c: 0, n: sizeof(ompt_enabled));
454 break;
455
456 case omp_tool_error:
457 fprintf(stderr,
458 format: "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(stream: verbose_file);
466#if OMPT_DEBUG
467 printf("ompt_pre_init(): ompt_enabled = %d\n", ompt_enabled.enabled);
468#endif
469}
470
471extern "C" int omp_get_initial_device(void);
472
473void 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(s: &ompt_enabled, c: 0, n: sizeof(ompt_enabled));
495 return;
496 }
497
498 kmp_info_t *root_thread = ompt_get_thread();
499
500 ompt_set_thread_state(thread: root_thread, state: ompt_state_overhead);
501 __ompt_task_init(task: root_thread->th.th_current_task, tid: 0);
502
503 if (ompt_enabled.ompt_callback_thread_begin) {
504 ompt_callbacks.ompt_callback(ompt_callback_thread_begin)(
505 ompt_thread_initial, __ompt_get_thread_data_internal());
506 }
507 ompt_data_t *task_data = nullptr;
508 ompt_data_t *parallel_data = nullptr;
509 __ompt_get_task_info_internal(ancestor_level: 0, NULL, task_data: &task_data, NULL, parallel_data: &parallel_data,
510 NULL);
511 if (ompt_enabled.ompt_callback_implicit_task) {
512 ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
513 ompt_scope_begin, parallel_data, task_data, 1, 1, ompt_task_initial);
514 }
515
516 ompt_set_thread_state(thread: root_thread, state: ompt_state_work_serial);
517 }
518}
519
520void ompt_fini() {
521 if (ompt_enabled.enabled) {
522 if (ompt_start_tool_result && ompt_start_tool_result->finalize) {
523 ompt_start_tool_result->finalize(&(ompt_start_tool_result->tool_data));
524 }
525 if (libomptarget_ompt_result && libomptarget_ompt_result->finalize) {
526 libomptarget_ompt_result->finalize(NULL);
527 }
528 }
529
530 if (ompt_archer_module)
531 OMPT_DLCLOSE(ompt_archer_module);
532 if (ompt_tool_module)
533 OMPT_DLCLOSE(ompt_tool_module);
534 memset(s: &ompt_enabled, c: 0, n: sizeof(ompt_enabled));
535}
536
537/*****************************************************************************
538 * interface operations
539 ****************************************************************************/
540
541/*****************************************************************************
542 * state
543 ****************************************************************************/
544
545OMPT_API_ROUTINE int ompt_enumerate_states(int current_state, int *next_state,
546 const char **next_state_name) {
547 const static int len = sizeof(ompt_state_info) / sizeof(ompt_state_info_t);
548 int i = 0;
549
550 for (i = 0; i < len - 1; i++) {
551 if (ompt_state_info[i].state_id == current_state) {
552 *next_state = ompt_state_info[i + 1].state_id;
553 *next_state_name = ompt_state_info[i + 1].state_name;
554 return 1;
555 }
556 }
557
558 return 0;
559}
560
561OMPT_API_ROUTINE int ompt_enumerate_mutex_impls(int current_impl,
562 int *next_impl,
563 const char **next_impl_name) {
564 const static int len =
565 sizeof(kmp_mutex_impl_info) / sizeof(kmp_mutex_impl_info_t);
566 int i = 0;
567 for (i = 0; i < len - 1; i++) {
568 if (kmp_mutex_impl_info[i].id != current_impl)
569 continue;
570 *next_impl = kmp_mutex_impl_info[i + 1].id;
571 *next_impl_name = kmp_mutex_impl_info[i + 1].name;
572 return 1;
573 }
574 return 0;
575}
576
577/*****************************************************************************
578 * callbacks
579 ****************************************************************************/
580
581OMPT_API_ROUTINE ompt_set_result_t ompt_set_callback(ompt_callbacks_t which,
582 ompt_callback_t callback) {
583 switch (which) {
584
585#define ompt_event_macro(event_name, callback_type, event_id) \
586 case event_name: \
587 ompt_callbacks.ompt_callback(event_name) = (callback_type)callback; \
588 ompt_enabled.event_name = (callback != 0); \
589 if (callback) \
590 return ompt_event_implementation_status(event_name); \
591 else \
592 return ompt_set_always;
593
594 FOREACH_OMPT_EVENT(ompt_event_macro)
595
596#undef ompt_event_macro
597
598 default:
599 return ompt_set_error;
600 }
601}
602
603OMPT_API_ROUTINE int ompt_get_callback(ompt_callbacks_t which,
604 ompt_callback_t *callback) {
605 if (!ompt_enabled.enabled)
606 return ompt_get_callback_failure;
607
608 switch (which) {
609
610#define ompt_event_macro(event_name, callback_type, event_id) \
611 case event_name: { \
612 ompt_callback_t mycb = \
613 (ompt_callback_t)ompt_callbacks.ompt_callback(event_name); \
614 if (ompt_enabled.event_name && mycb) { \
615 *callback = mycb; \
616 return ompt_get_callback_success; \
617 } \
618 return ompt_get_callback_failure; \
619 }
620
621 FOREACH_OMPT_EVENT(ompt_event_macro)
622
623#undef ompt_event_macro
624
625 default:
626 return ompt_get_callback_failure;
627 }
628}
629
630/*****************************************************************************
631 * parallel regions
632 ****************************************************************************/
633
634OMPT_API_ROUTINE int ompt_get_parallel_info(int ancestor_level,
635 ompt_data_t **parallel_data,
636 int *team_size) {
637 if (!ompt_enabled.enabled)
638 return 0;
639 return __ompt_get_parallel_info_internal(ancestor_level, parallel_data,
640 team_size);
641}
642
643OMPT_API_ROUTINE int ompt_get_state(ompt_wait_id_t *wait_id) {
644 if (!ompt_enabled.enabled)
645 return ompt_state_work_serial;
646 int thread_state = __ompt_get_state_internal(omp_wait_id: wait_id);
647
648 if (thread_state == ompt_state_undefined) {
649 thread_state = ompt_state_work_serial;
650 }
651
652 return thread_state;
653}
654
655/*****************************************************************************
656 * tasks
657 ****************************************************************************/
658
659OMPT_API_ROUTINE ompt_data_t *ompt_get_thread_data(void) {
660 if (!ompt_enabled.enabled)
661 return NULL;
662 return __ompt_get_thread_data_internal();
663}
664
665OMPT_API_ROUTINE int ompt_get_task_info(int ancestor_level, int *type,
666 ompt_data_t **task_data,
667 ompt_frame_t **task_frame,
668 ompt_data_t **parallel_data,
669 int *thread_num) {
670 if (!ompt_enabled.enabled)
671 return 0;
672 return __ompt_get_task_info_internal(ancestor_level, type, task_data,
673 task_frame, parallel_data, thread_num);
674}
675
676OMPT_API_ROUTINE int ompt_get_task_memory(void **addr, size_t *size,
677 int block) {
678 return __ompt_get_task_memory_internal(addr, size, blocknum: block);
679}
680
681/*****************************************************************************
682 * num_procs
683 ****************************************************************************/
684
685OMPT_API_ROUTINE int ompt_get_num_procs(void) {
686 // copied from kmp_ftn_entry.h (but modified: OMPT can only be called when
687 // runtime is initialized)
688 return __kmp_avail_proc;
689}
690
691/*****************************************************************************
692 * places
693 ****************************************************************************/
694
695OMPT_API_ROUTINE int ompt_get_num_places(void) {
696// copied from kmp_ftn_entry.h (but modified)
697#if !KMP_AFFINITY_SUPPORTED
698 return 0;
699#else
700 if (!KMP_AFFINITY_CAPABLE())
701 return 0;
702 return __kmp_affinity.num_masks;
703#endif
704}
705
706OMPT_API_ROUTINE int ompt_get_place_proc_ids(int place_num, int ids_size,
707 int *ids) {
708// copied from kmp_ftn_entry.h (but modified)
709#if !KMP_AFFINITY_SUPPORTED
710 return 0;
711#else
712 int i, count;
713 SimpleVLA<int> tmp_ids(ids_size);
714 for (int j = 0; j < ids_size; j++)
715 tmp_ids[j] = 0;
716 if (!KMP_AFFINITY_CAPABLE())
717 return 0;
718 if (place_num < 0 || place_num >= (int)__kmp_affinity.num_masks)
719 return 0;
720 /* TODO: Is this safe for asynchronous call from signal handler during runtime
721 * shutdown? */
722 kmp_affin_mask_t *mask = KMP_CPU_INDEX(__kmp_affinity.masks, place_num);
723 count = 0;
724 KMP_CPU_SET_ITERATE(i, mask) {
725 if ((!KMP_CPU_ISSET(i, __kmp_affin_fullMask)) ||
726 (!KMP_CPU_ISSET(i, mask))) {
727 continue;
728 }
729 if (count < ids_size)
730 tmp_ids[count] = i;
731 count++;
732 }
733 if (ids_size >= count) {
734 for (i = 0; i < count; i++) {
735 ids[i] = tmp_ids[i];
736 }
737 }
738 return count;
739#endif
740}
741
742OMPT_API_ROUTINE int ompt_get_place_num(void) {
743// copied from kmp_ftn_entry.h (but modified)
744#if !KMP_AFFINITY_SUPPORTED
745 return -1;
746#else
747 if (!ompt_enabled.enabled || __kmp_get_gtid() < 0)
748 return -1;
749
750 int gtid;
751 kmp_info_t *thread;
752 if (!KMP_AFFINITY_CAPABLE())
753 return -1;
754 gtid = __kmp_entry_gtid();
755 thread = __kmp_thread_from_gtid(gtid);
756 if (thread == NULL || thread->th.th_current_place < 0)
757 return -1;
758 return thread->th.th_current_place;
759#endif
760}
761
762OMPT_API_ROUTINE int ompt_get_partition_place_nums(int place_nums_size,
763 int *place_nums) {
764// copied from kmp_ftn_entry.h (but modified)
765#if !KMP_AFFINITY_SUPPORTED
766 return 0;
767#else
768 if (!ompt_enabled.enabled || __kmp_get_gtid() < 0)
769 return 0;
770
771 int i, gtid, place_num, first_place, last_place, start, end;
772 kmp_info_t *thread;
773 if (!KMP_AFFINITY_CAPABLE())
774 return 0;
775 gtid = __kmp_entry_gtid();
776 thread = __kmp_thread_from_gtid(gtid);
777 if (thread == NULL)
778 return 0;
779 first_place = thread->th.th_first_place;
780 last_place = thread->th.th_last_place;
781 if (first_place < 0 || last_place < 0)
782 return 0;
783 if (first_place <= last_place) {
784 start = first_place;
785 end = last_place;
786 } else {
787 start = last_place;
788 end = first_place;
789 }
790 if (end - start <= place_nums_size)
791 for (i = 0, place_num = start; place_num <= end; ++place_num, ++i) {
792 place_nums[i] = place_num;
793 }
794 return end - start + 1;
795#endif
796}
797
798/*****************************************************************************
799 * places
800 ****************************************************************************/
801
802OMPT_API_ROUTINE int ompt_get_proc_id(void) {
803 if (!ompt_enabled.enabled || __kmp_get_gtid() < 0)
804 return -1;
805#if KMP_HAVE_SCHED_GETCPU
806 return sched_getcpu();
807#elif KMP_OS_WINDOWS
808 PROCESSOR_NUMBER pn;
809 GetCurrentProcessorNumberEx(&pn);
810 return 64 * pn.Group + pn.Number;
811#else
812 return -1;
813#endif
814}
815
816/*****************************************************************************
817 * compatability
818 ****************************************************************************/
819
820/*
821 * Currently unused function
822OMPT_API_ROUTINE int ompt_get_ompt_version() { return OMPT_VERSION; }
823*/
824
825/*****************************************************************************
826 * application-facing API
827 ****************************************************************************/
828
829/*----------------------------------------------------------------------------
830 | control
831 ---------------------------------------------------------------------------*/
832
833int __kmp_control_tool(uint64_t command, uint64_t modifier, void *arg) {
834
835 if (ompt_enabled.enabled) {
836 if (ompt_enabled.ompt_callback_control_tool) {
837 return ompt_callbacks.ompt_callback(ompt_callback_control_tool)(
838 command, modifier, arg, OMPT_LOAD_RETURN_ADDRESS(__kmp_entry_gtid()));
839 } else {
840 return -1;
841 }
842 } else {
843 return -2;
844 }
845}
846
847/*****************************************************************************
848 * misc
849 ****************************************************************************/
850
851OMPT_API_ROUTINE uint64_t ompt_get_unique_id(void) {
852 return __ompt_get_unique_id_internal();
853}
854
855OMPT_API_ROUTINE void ompt_finalize_tool(void) { __kmp_internal_end_atexit(); }
856
857/*****************************************************************************
858 * Target
859 ****************************************************************************/
860
861OMPT_API_ROUTINE int ompt_get_target_info(uint64_t *device_num,
862 ompt_id_t *target_id,
863 ompt_id_t *host_op_id) {
864 return 0; // thread is not in a target region
865}
866
867OMPT_API_ROUTINE int ompt_get_num_devices(void) {
868 return 1; // only one device (the current device) is available
869}
870
871/*****************************************************************************
872 * API inquiry for tool
873 ****************************************************************************/
874
875static ompt_interface_fn_t ompt_fn_lookup(const char *s) {
876
877#define ompt_interface_fn(fn) \
878 fn##_t fn##_f = fn; \
879 if (strcmp(s, #fn) == 0) \
880 return (ompt_interface_fn_t)fn##_f;
881
882 FOREACH_OMPT_INQUIRY_FN(ompt_interface_fn)
883
884#undef ompt_interface_fn
885
886 return NULL;
887}
888
889static ompt_data_t *ompt_get_task_data() { return __ompt_get_task_data(); }
890
891static ompt_data_t *ompt_get_target_task_data() {
892 return __ompt_get_target_task_data();
893}
894
895/// Lookup function to query libomp callbacks registered by the tool
896static ompt_interface_fn_t ompt_libomp_target_fn_lookup(const char *s) {
897#define provide_fn(fn) \
898 if (strcmp(s, #fn) == 0) \
899 return (ompt_interface_fn_t)fn;
900
901 provide_fn(ompt_get_callback);
902 provide_fn(ompt_get_task_data);
903 provide_fn(ompt_get_target_task_data);
904#undef provide_fn
905
906#define ompt_interface_fn(fn, type, code) \
907 if (strcmp(s, #fn) == 0) \
908 return (ompt_interface_fn_t)ompt_callbacks.ompt_callback(fn);
909
910 FOREACH_OMPT_DEVICE_EVENT(ompt_interface_fn)
911 FOREACH_OMPT_EMI_EVENT(ompt_interface_fn)
912 FOREACH_OMPT_NOEMI_EVENT(ompt_interface_fn)
913#undef ompt_interface_fn
914
915 return (ompt_interface_fn_t)0;
916}
917
918/// This function is called by the libomptarget connector to assign
919/// callbacks already registered with libomp.
920_OMP_EXTERN void ompt_libomp_connect(ompt_start_tool_result_t *result) {
921 OMPT_VERBOSE_INIT_PRINT("libomp --> OMPT: Enter ompt_libomp_connect\n");
922
923 // Ensure libomp callbacks have been added if not already
924 __ompt_force_initialization();
925
926 if (ompt_enabled.enabled && result) {
927 OMPT_VERBOSE_INIT_PRINT("libomp --> OMPT: Connecting with libomptarget\n");
928 // Pass in the libomp lookup function so that the already registered
929 // functions can be extracted and assigned to the callbacks in
930 // libomptarget
931 result->initialize(ompt_libomp_target_fn_lookup,
932 /* initial_device_num */ 0, /* tool_data */ nullptr);
933 // Track the object provided by libomptarget so that the finalizer can be
934 // called during OMPT finalization
935 libomptarget_ompt_result = result;
936 }
937 OMPT_VERBOSE_INIT_PRINT("libomp --> OMPT: Exit ompt_libomp_connect\n");
938}
939

source code of openmp/runtime/src/ompt-general.cpp