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