LLVM OpenMP* Runtime Library
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  omp_state_t state_id;
56 } omp_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 omp_state_info_t omp_state_info[] = {
77 #define omp_state_macro(state, code) {#state, state},
78  FOREACH_OMP_STATE(omp_state_macro)
79 #undef omp_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 void ompt_post_init() {
331  //--------------------------------------------------
332  // Execute the post-initialization logic only once.
333  //--------------------------------------------------
334  static int ompt_post_initialized = 0;
335 
336  if (ompt_post_initialized)
337  return;
338 
339  ompt_post_initialized = 1;
340 
341  //--------------------------------------------------
342  // Initialize the tool if so indicated.
343  //--------------------------------------------------
344  if (ompt_start_tool_result) {
345  ompt_enabled.enabled = !!ompt_start_tool_result->initialize(
346  ompt_fn_lookup, &(ompt_start_tool_result->tool_data));
347 
348  if (!ompt_enabled.enabled) {
349  // tool not enabled, zero out the bitmap, and done
350  memset(&ompt_enabled, 0, sizeof(ompt_enabled));
351  return;
352  }
353 
354  kmp_info_t *root_thread = ompt_get_thread();
355 
356  ompt_set_thread_state(root_thread, omp_state_overhead);
357 
358  if (ompt_enabled.ompt_callback_thread_begin) {
359  ompt_callbacks.ompt_callback(ompt_callback_thread_begin)(
360  ompt_thread_initial, __ompt_get_thread_data_internal());
361  }
362  ompt_data_t *task_data;
363  __ompt_get_task_info_internal(0, NULL, &task_data, NULL, NULL, NULL);
364  if (ompt_enabled.ompt_callback_task_create) {
365  ompt_callbacks.ompt_callback(ompt_callback_task_create)(
366  NULL, NULL, task_data, ompt_task_initial, 0, NULL);
367  }
368 
369  ompt_set_thread_state(root_thread, omp_state_work_serial);
370  }
371 }
372 
373 void ompt_fini() {
374  if (ompt_enabled.enabled) {
375  ompt_start_tool_result->finalize(&(ompt_start_tool_result->tool_data));
376  }
377 
378  memset(&ompt_enabled, 0, sizeof(ompt_enabled));
379 }
380 
381 /*****************************************************************************
382  * interface operations
383  ****************************************************************************/
384 
385 /*****************************************************************************
386  * state
387  ****************************************************************************/
388 
389 OMPT_API_ROUTINE int ompt_enumerate_states(int current_state, int *next_state,
390  const char **next_state_name) {
391  const static int len = sizeof(omp_state_info) / sizeof(omp_state_info_t);
392  int i = 0;
393 
394  for (i = 0; i < len - 1; i++) {
395  if (omp_state_info[i].state_id == current_state) {
396  *next_state = omp_state_info[i + 1].state_id;
397  *next_state_name = omp_state_info[i + 1].state_name;
398  return 1;
399  }
400  }
401 
402  return 0;
403 }
404 
405 OMPT_API_ROUTINE int ompt_enumerate_mutex_impls(int current_impl,
406  int *next_impl,
407  const char **next_impl_name) {
408  const static int len =
409  sizeof(kmp_mutex_impl_info) / sizeof(kmp_mutex_impl_info_t);
410  int i = 0;
411  for (i = 0; i < len - 1; i++) {
412  if (kmp_mutex_impl_info[i].id != current_impl)
413  continue;
414  *next_impl = kmp_mutex_impl_info[i + 1].id;
415  *next_impl_name = kmp_mutex_impl_info[i + 1].name;
416  return 1;
417  }
418  return 0;
419 }
420 
421 /*****************************************************************************
422  * callbacks
423  ****************************************************************************/
424 
425 OMPT_API_ROUTINE int ompt_set_callback(ompt_callbacks_t which,
426  ompt_callback_t callback) {
427  switch (which) {
428 
429 #define ompt_event_macro(event_name, callback_type, event_id) \
430  case event_name: \
431  if (ompt_event_implementation_status(event_name)) { \
432  ompt_callbacks.ompt_callback(event_name) = (callback_type)callback; \
433  ompt_enabled.event_name = (callback != 0); \
434  } \
435  if (callback) \
436  return ompt_event_implementation_status(event_name); \
437  else \
438  return ompt_set_always;
439 
440  FOREACH_OMPT_EVENT(ompt_event_macro)
441 
442 #undef ompt_event_macro
443 
444  default:
445  return ompt_set_error;
446  }
447 }
448 
449 OMPT_API_ROUTINE int ompt_get_callback(ompt_callbacks_t which,
450  ompt_callback_t *callback) {
451  switch (which) {
452 
453 #define ompt_event_macro(event_name, callback_type, event_id) \
454  case event_name: \
455  if (ompt_event_implementation_status(event_name)) { \
456  ompt_callback_t mycb = \
457  (ompt_callback_t)ompt_callbacks.ompt_callback(event_name); \
458  if (mycb) { \
459  *callback = mycb; \
460  return ompt_get_callback_success; \
461  } \
462  } \
463  return ompt_get_callback_failure;
464 
465  FOREACH_OMPT_EVENT(ompt_event_macro)
466 
467 #undef ompt_event_macro
468 
469  default:
470  return ompt_get_callback_failure;
471  }
472 }
473 
474 /*****************************************************************************
475  * parallel regions
476  ****************************************************************************/
477 
478 OMPT_API_ROUTINE int ompt_get_parallel_info(int ancestor_level,
479  ompt_data_t **parallel_data,
480  int *team_size) {
481  return __ompt_get_parallel_info_internal(ancestor_level, parallel_data,
482  team_size);
483 }
484 
485 OMPT_API_ROUTINE omp_state_t ompt_get_state(omp_wait_id_t *wait_id) {
486  omp_state_t thread_state = __ompt_get_state_internal(wait_id);
487 
488  if (thread_state == omp_state_undefined) {
489  thread_state = omp_state_work_serial;
490  }
491 
492  return thread_state;
493 }
494 
495 /*****************************************************************************
496  * tasks
497  ****************************************************************************/
498 
499 OMPT_API_ROUTINE ompt_data_t *ompt_get_thread_data(void) {
500  return __ompt_get_thread_data_internal();
501 }
502 
503 OMPT_API_ROUTINE int ompt_get_task_info(int ancestor_level, int *type,
504  ompt_data_t **task_data,
505  omp_frame_t **task_frame,
506  ompt_data_t **parallel_data,
507  int *thread_num) {
508  return __ompt_get_task_info_internal(ancestor_level, type, task_data,
509  task_frame, parallel_data, thread_num);
510 }
511 
512 OMPT_API_ROUTINE int ompt_get_task_memory(void **addr, size_t *size,
513  int block) {
514  // stub
515  return 0;
516 }
517 
518 /*****************************************************************************
519  * num_procs
520  ****************************************************************************/
521 
522 OMPT_API_ROUTINE int ompt_get_num_procs(void) {
523  // copied from kmp_ftn_entry.h (but modified: OMPT can only be called when
524  // runtime is initialized)
525  return __kmp_avail_proc;
526 }
527 
528 /*****************************************************************************
529  * places
530  ****************************************************************************/
531 
532 OMPT_API_ROUTINE int ompt_get_num_places(void) {
533 // copied from kmp_ftn_entry.h (but modified)
534 #if !KMP_AFFINITY_SUPPORTED
535  return 0;
536 #else
537  if (!KMP_AFFINITY_CAPABLE())
538  return 0;
539  return __kmp_affinity_num_masks;
540 #endif
541 }
542 
543 OMPT_API_ROUTINE int ompt_get_place_proc_ids(int place_num, int ids_size,
544  int *ids) {
545 // copied from kmp_ftn_entry.h (but modified)
546 #if !KMP_AFFINITY_SUPPORTED
547  return 0;
548 #else
549  int i, count;
550  int tmp_ids[ids_size];
551  if (!KMP_AFFINITY_CAPABLE())
552  return 0;
553  if (place_num < 0 || place_num >= (int)__kmp_affinity_num_masks)
554  return 0;
555  /* TODO: Is this safe for asynchronous call from signal handler during runtime
556  * shutdown? */
557  kmp_affin_mask_t *mask = KMP_CPU_INDEX(__kmp_affinity_masks, place_num);
558  count = 0;
559  KMP_CPU_SET_ITERATE(i, mask) {
560  if ((!KMP_CPU_ISSET(i, __kmp_affin_fullMask)) ||
561  (!KMP_CPU_ISSET(i, mask))) {
562  continue;
563  }
564  if (count < ids_size)
565  tmp_ids[count] = i;
566  count++;
567  }
568  if (ids_size >= count) {
569  for (i = 0; i < count; i++) {
570  ids[i] = tmp_ids[i];
571  }
572  }
573  return count;
574 #endif
575 }
576 
577 OMPT_API_ROUTINE int ompt_get_place_num(void) {
578 // copied from kmp_ftn_entry.h (but modified)
579 #if !KMP_AFFINITY_SUPPORTED
580  return -1;
581 #else
582  if (__kmp_get_gtid() < 0)
583  return -1;
584 
585  int gtid;
586  kmp_info_t *thread;
587  if (!KMP_AFFINITY_CAPABLE())
588  return -1;
589  gtid = __kmp_entry_gtid();
590  thread = __kmp_thread_from_gtid(gtid);
591  if (thread == NULL || thread->th.th_current_place < 0)
592  return -1;
593  return thread->th.th_current_place;
594 #endif
595 }
596 
597 OMPT_API_ROUTINE int ompt_get_partition_place_nums(int place_nums_size,
598  int *place_nums) {
599 // copied from kmp_ftn_entry.h (but modified)
600 #if !KMP_AFFINITY_SUPPORTED
601  return 0;
602 #else
603  if (__kmp_get_gtid() < 0)
604  return 0;
605 
606  int i, gtid, place_num, first_place, last_place, start, end;
607  kmp_info_t *thread;
608  if (!KMP_AFFINITY_CAPABLE())
609  return 0;
610  gtid = __kmp_entry_gtid();
611  thread = __kmp_thread_from_gtid(gtid);
612  if (thread == NULL)
613  return 0;
614  first_place = thread->th.th_first_place;
615  last_place = thread->th.th_last_place;
616  if (first_place < 0 || last_place < 0)
617  return 0;
618  if (first_place <= last_place) {
619  start = first_place;
620  end = last_place;
621  } else {
622  start = last_place;
623  end = first_place;
624  }
625  if (end - start <= place_nums_size)
626  for (i = 0, place_num = start; place_num <= end; ++place_num, ++i) {
627  place_nums[i] = place_num;
628  }
629  return end - start + 1;
630 #endif
631 }
632 
633 /*****************************************************************************
634  * places
635  ****************************************************************************/
636 
637 OMPT_API_ROUTINE int ompt_get_proc_id(void) {
638  if (__kmp_get_gtid() < 0)
639  return -1;
640 #if KMP_OS_LINUX
641  return sched_getcpu();
642 #elif KMP_OS_WINDOWS
643  PROCESSOR_NUMBER pn;
644  GetCurrentProcessorNumberEx(&pn);
645  return 64 * pn.Group + pn.Number;
646 #else
647  return -1;
648 #endif
649 }
650 
651 /*****************************************************************************
652  * compatability
653  ****************************************************************************/
654 
655 /*
656  * Currently unused function
657 OMPT_API_ROUTINE int ompt_get_ompt_version() { return OMPT_VERSION; }
658 */
659 
660 /*****************************************************************************
661 * application-facing API
662  ****************************************************************************/
663 
664 /*----------------------------------------------------------------------------
665  | control
666  ---------------------------------------------------------------------------*/
667 
668 int __kmp_control_tool(uint64_t command, uint64_t modifier, void *arg) {
669 
670  if (ompt_enabled.enabled) {
671  if (ompt_enabled.ompt_callback_control_tool) {
672  return ompt_callbacks.ompt_callback(ompt_callback_control_tool)(
673  command, modifier, arg, OMPT_LOAD_RETURN_ADDRESS(__kmp_entry_gtid()));
674  } else {
675  return -1;
676  }
677  } else {
678  return -2;
679  }
680 }
681 
682 /*****************************************************************************
683  * misc
684  ****************************************************************************/
685 
686 OMPT_API_ROUTINE uint64_t ompt_get_unique_id(void) {
687  return __ompt_get_unique_id_internal();
688 }
689 
690 OMPT_API_ROUTINE void ompt_finalize_tool(void) {
691  // stub
692 }
693 
694 /*****************************************************************************
695  * Target
696  ****************************************************************************/
697 
698 OMPT_API_ROUTINE int ompt_get_target_info(uint64_t *device_num,
699  ompt_id_t *target_id,
700  ompt_id_t *host_op_id) {
701  return 0; // thread is not in a target region
702 }
703 
704 OMPT_API_ROUTINE int ompt_get_num_devices(void) {
705  return 1; // only one device (the current device) is available
706 }
707 
708 /*****************************************************************************
709  * API inquiry for tool
710  ****************************************************************************/
711 
712 static ompt_interface_fn_t ompt_fn_lookup(const char *s) {
713 
714 #define ompt_interface_fn(fn) \
715  fn##_t fn##_f = fn; \
716  if (strcmp(s, #fn) == 0) \
717  return (ompt_interface_fn_t)fn##_f;
718 
719  FOREACH_OMPT_INQUIRY_FN(ompt_interface_fn)
720 
721  return (ompt_interface_fn_t)0;
722 }