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