1345153Sdim/*
2345153Sdim * kmp_ftn_entry.h -- Fortran entry linkage support for OpenMP.
3345153Sdim */
4345153Sdim
5345153Sdim//===----------------------------------------------------------------------===//
6345153Sdim//
7353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
8353358Sdim// See https://llvm.org/LICENSE.txt for license information.
9353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
10345153Sdim//
11345153Sdim//===----------------------------------------------------------------------===//
12345153Sdim
13345153Sdim#ifndef FTN_STDCALL
14345153Sdim#error The support file kmp_ftn_entry.h should not be compiled by itself.
15345153Sdim#endif
16345153Sdim
17345153Sdim#ifdef KMP_STUB
18345153Sdim#include "kmp_stub.h"
19345153Sdim#endif
20345153Sdim
21345153Sdim#include "kmp_i18n.h"
22345153Sdim
23345153Sdim// For affinity format functions
24345153Sdim#include "kmp_io.h"
25345153Sdim#include "kmp_str.h"
26345153Sdim
27345153Sdim#if OMPT_SUPPORT
28345153Sdim#include "ompt-specific.h"
29345153Sdim#endif
30345153Sdim
31345153Sdim#ifdef __cplusplus
32345153Sdimextern "C" {
33345153Sdim#endif // __cplusplus
34345153Sdim
35345153Sdim/* For compatibility with the Gnu/MS Open MP codegen, omp_set_num_threads(),
36345153Sdim * omp_set_nested(), and omp_set_dynamic() [in lowercase on MS, and w/o
37345153Sdim * a trailing underscore on Linux* OS] take call by value integer arguments.
38345153Sdim * + omp_set_max_active_levels()
39345153Sdim * + omp_set_schedule()
40345153Sdim *
41345153Sdim * For backward compatibility with 9.1 and previous Intel compiler, these
42345153Sdim * entry points take call by reference integer arguments. */
43345153Sdim#ifdef KMP_GOMP_COMPAT
44345153Sdim#if (KMP_FTN_ENTRIES == KMP_FTN_PLAIN) || (KMP_FTN_ENTRIES == KMP_FTN_UPPER)
45345153Sdim#define PASS_ARGS_BY_VALUE 1
46345153Sdim#endif
47345153Sdim#endif
48345153Sdim#if KMP_OS_WINDOWS
49345153Sdim#if (KMP_FTN_ENTRIES == KMP_FTN_PLAIN) || (KMP_FTN_ENTRIES == KMP_FTN_APPEND)
50345153Sdim#define PASS_ARGS_BY_VALUE 1
51345153Sdim#endif
52345153Sdim#endif
53345153Sdim
54345153Sdim// This macro helps to reduce code duplication.
55345153Sdim#ifdef PASS_ARGS_BY_VALUE
56345153Sdim#define KMP_DEREF
57345153Sdim#else
58345153Sdim#define KMP_DEREF *
59345153Sdim#endif
60345153Sdim
61345153Sdimvoid FTN_STDCALL FTN_SET_STACKSIZE(int KMP_DEREF arg) {
62345153Sdim#ifdef KMP_STUB
63345153Sdim  __kmps_set_stacksize(KMP_DEREF arg);
64345153Sdim#else
65345153Sdim  // __kmp_aux_set_stacksize initializes the library if needed
66345153Sdim  __kmp_aux_set_stacksize((size_t)KMP_DEREF arg);
67345153Sdim#endif
68345153Sdim}
69345153Sdim
70345153Sdimvoid FTN_STDCALL FTN_SET_STACKSIZE_S(size_t KMP_DEREF arg) {
71345153Sdim#ifdef KMP_STUB
72345153Sdim  __kmps_set_stacksize(KMP_DEREF arg);
73345153Sdim#else
74345153Sdim  // __kmp_aux_set_stacksize initializes the library if needed
75345153Sdim  __kmp_aux_set_stacksize(KMP_DEREF arg);
76345153Sdim#endif
77345153Sdim}
78345153Sdim
79345153Sdimint FTN_STDCALL FTN_GET_STACKSIZE(void) {
80345153Sdim#ifdef KMP_STUB
81345153Sdim  return __kmps_get_stacksize();
82345153Sdim#else
83345153Sdim  if (!__kmp_init_serial) {
84345153Sdim    __kmp_serial_initialize();
85345153Sdim  }
86345153Sdim  return (int)__kmp_stksize;
87345153Sdim#endif
88345153Sdim}
89345153Sdim
90345153Sdimsize_t FTN_STDCALL FTN_GET_STACKSIZE_S(void) {
91345153Sdim#ifdef KMP_STUB
92345153Sdim  return __kmps_get_stacksize();
93345153Sdim#else
94345153Sdim  if (!__kmp_init_serial) {
95345153Sdim    __kmp_serial_initialize();
96345153Sdim  }
97345153Sdim  return __kmp_stksize;
98345153Sdim#endif
99345153Sdim}
100345153Sdim
101345153Sdimvoid FTN_STDCALL FTN_SET_BLOCKTIME(int KMP_DEREF arg) {
102345153Sdim#ifdef KMP_STUB
103345153Sdim  __kmps_set_blocktime(KMP_DEREF arg);
104345153Sdim#else
105345153Sdim  int gtid, tid;
106345153Sdim  kmp_info_t *thread;
107345153Sdim
108345153Sdim  gtid = __kmp_entry_gtid();
109345153Sdim  tid = __kmp_tid_from_gtid(gtid);
110345153Sdim  thread = __kmp_thread_from_gtid(gtid);
111345153Sdim
112345153Sdim  __kmp_aux_set_blocktime(KMP_DEREF arg, thread, tid);
113345153Sdim#endif
114345153Sdim}
115345153Sdim
116345153Sdimint FTN_STDCALL FTN_GET_BLOCKTIME(void) {
117345153Sdim#ifdef KMP_STUB
118345153Sdim  return __kmps_get_blocktime();
119345153Sdim#else
120345153Sdim  int gtid, tid;
121345153Sdim  kmp_info_t *thread;
122345153Sdim  kmp_team_p *team;
123345153Sdim
124345153Sdim  gtid = __kmp_entry_gtid();
125345153Sdim  tid = __kmp_tid_from_gtid(gtid);
126345153Sdim  thread = __kmp_thread_from_gtid(gtid);
127345153Sdim  team = __kmp_threads[gtid]->th.th_team;
128345153Sdim
129345153Sdim  /* These must match the settings used in __kmp_wait_sleep() */
130345153Sdim  if (__kmp_dflt_blocktime == KMP_MAX_BLOCKTIME) {
131345153Sdim    KF_TRACE(10, ("kmp_get_blocktime: T#%d(%d:%d), blocktime=%d\n", gtid,
132345153Sdim                  team->t.t_id, tid, KMP_MAX_BLOCKTIME));
133345153Sdim    return KMP_MAX_BLOCKTIME;
134345153Sdim  }
135345153Sdim#ifdef KMP_ADJUST_BLOCKTIME
136345153Sdim  else if (__kmp_zero_bt && !get__bt_set(team, tid)) {
137345153Sdim    KF_TRACE(10, ("kmp_get_blocktime: T#%d(%d:%d), blocktime=%d\n", gtid,
138345153Sdim                  team->t.t_id, tid, 0));
139345153Sdim    return 0;
140345153Sdim  }
141345153Sdim#endif /* KMP_ADJUST_BLOCKTIME */
142345153Sdim  else {
143345153Sdim    KF_TRACE(10, ("kmp_get_blocktime: T#%d(%d:%d), blocktime=%d\n", gtid,
144345153Sdim                  team->t.t_id, tid, get__blocktime(team, tid)));
145345153Sdim    return get__blocktime(team, tid);
146345153Sdim  }
147345153Sdim#endif
148345153Sdim}
149345153Sdim
150345153Sdimvoid FTN_STDCALL FTN_SET_LIBRARY_SERIAL(void) {
151345153Sdim#ifdef KMP_STUB
152345153Sdim  __kmps_set_library(library_serial);
153345153Sdim#else
154345153Sdim  // __kmp_user_set_library initializes the library if needed
155345153Sdim  __kmp_user_set_library(library_serial);
156345153Sdim#endif
157345153Sdim}
158345153Sdim
159345153Sdimvoid FTN_STDCALL FTN_SET_LIBRARY_TURNAROUND(void) {
160345153Sdim#ifdef KMP_STUB
161345153Sdim  __kmps_set_library(library_turnaround);
162345153Sdim#else
163345153Sdim  // __kmp_user_set_library initializes the library if needed
164345153Sdim  __kmp_user_set_library(library_turnaround);
165345153Sdim#endif
166345153Sdim}
167345153Sdim
168345153Sdimvoid FTN_STDCALL FTN_SET_LIBRARY_THROUGHPUT(void) {
169345153Sdim#ifdef KMP_STUB
170345153Sdim  __kmps_set_library(library_throughput);
171345153Sdim#else
172345153Sdim  // __kmp_user_set_library initializes the library if needed
173345153Sdim  __kmp_user_set_library(library_throughput);
174345153Sdim#endif
175345153Sdim}
176345153Sdim
177345153Sdimvoid FTN_STDCALL FTN_SET_LIBRARY(int KMP_DEREF arg) {
178345153Sdim#ifdef KMP_STUB
179345153Sdim  __kmps_set_library(KMP_DEREF arg);
180345153Sdim#else
181345153Sdim  enum library_type lib;
182345153Sdim  lib = (enum library_type)KMP_DEREF arg;
183345153Sdim  // __kmp_user_set_library initializes the library if needed
184345153Sdim  __kmp_user_set_library(lib);
185345153Sdim#endif
186345153Sdim}
187345153Sdim
188345153Sdimint FTN_STDCALL FTN_GET_LIBRARY(void) {
189345153Sdim#ifdef KMP_STUB
190345153Sdim  return __kmps_get_library();
191345153Sdim#else
192345153Sdim  if (!__kmp_init_serial) {
193345153Sdim    __kmp_serial_initialize();
194345153Sdim  }
195345153Sdim  return ((int)__kmp_library);
196345153Sdim#endif
197345153Sdim}
198345153Sdim
199345153Sdimvoid FTN_STDCALL FTN_SET_DISP_NUM_BUFFERS(int KMP_DEREF arg) {
200345153Sdim#ifdef KMP_STUB
201345153Sdim  ; // empty routine
202345153Sdim#else
203345153Sdim  // ignore after initialization because some teams have already
204345153Sdim  // allocated dispatch buffers
205345153Sdim  if (__kmp_init_serial == 0 && (KMP_DEREF arg) > 0)
206345153Sdim    __kmp_dispatch_num_buffers = KMP_DEREF arg;
207345153Sdim#endif
208345153Sdim}
209345153Sdim
210345153Sdimint FTN_STDCALL FTN_SET_AFFINITY(void **mask) {
211345153Sdim#if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
212345153Sdim  return -1;
213345153Sdim#else
214345153Sdim  if (!TCR_4(__kmp_init_middle)) {
215345153Sdim    __kmp_middle_initialize();
216345153Sdim  }
217345153Sdim  return __kmp_aux_set_affinity(mask);
218345153Sdim#endif
219345153Sdim}
220345153Sdim
221345153Sdimint FTN_STDCALL FTN_GET_AFFINITY(void **mask) {
222345153Sdim#if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
223345153Sdim  return -1;
224345153Sdim#else
225345153Sdim  if (!TCR_4(__kmp_init_middle)) {
226345153Sdim    __kmp_middle_initialize();
227345153Sdim  }
228345153Sdim  return __kmp_aux_get_affinity(mask);
229345153Sdim#endif
230345153Sdim}
231345153Sdim
232345153Sdimint FTN_STDCALL FTN_GET_AFFINITY_MAX_PROC(void) {
233345153Sdim#if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
234345153Sdim  return 0;
235345153Sdim#else
236345153Sdim  // We really only NEED serial initialization here.
237345153Sdim  if (!TCR_4(__kmp_init_middle)) {
238345153Sdim    __kmp_middle_initialize();
239345153Sdim  }
240345153Sdim  return __kmp_aux_get_affinity_max_proc();
241345153Sdim#endif
242345153Sdim}
243345153Sdim
244345153Sdimvoid FTN_STDCALL FTN_CREATE_AFFINITY_MASK(void **mask) {
245345153Sdim#if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
246345153Sdim  *mask = NULL;
247345153Sdim#else
248345153Sdim  // We really only NEED serial initialization here.
249345153Sdim  kmp_affin_mask_t *mask_internals;
250345153Sdim  if (!TCR_4(__kmp_init_middle)) {
251345153Sdim    __kmp_middle_initialize();
252345153Sdim  }
253345153Sdim  mask_internals = __kmp_affinity_dispatch->allocate_mask();
254345153Sdim  KMP_CPU_ZERO(mask_internals);
255345153Sdim  *mask = mask_internals;
256345153Sdim#endif
257345153Sdim}
258345153Sdim
259345153Sdimvoid FTN_STDCALL FTN_DESTROY_AFFINITY_MASK(void **mask) {
260345153Sdim#if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
261345153Sdim// Nothing
262345153Sdim#else
263345153Sdim  // We really only NEED serial initialization here.
264345153Sdim  kmp_affin_mask_t *mask_internals;
265345153Sdim  if (!TCR_4(__kmp_init_middle)) {
266345153Sdim    __kmp_middle_initialize();
267345153Sdim  }
268345153Sdim  if (__kmp_env_consistency_check) {
269345153Sdim    if (*mask == NULL) {
270345153Sdim      KMP_FATAL(AffinityInvalidMask, "kmp_destroy_affinity_mask");
271345153Sdim    }
272345153Sdim  }
273345153Sdim  mask_internals = (kmp_affin_mask_t *)(*mask);
274345153Sdim  __kmp_affinity_dispatch->deallocate_mask(mask_internals);
275345153Sdim  *mask = NULL;
276345153Sdim#endif
277345153Sdim}
278345153Sdim
279345153Sdimint FTN_STDCALL FTN_SET_AFFINITY_MASK_PROC(int KMP_DEREF proc, void **mask) {
280345153Sdim#if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
281345153Sdim  return -1;
282345153Sdim#else
283345153Sdim  if (!TCR_4(__kmp_init_middle)) {
284345153Sdim    __kmp_middle_initialize();
285345153Sdim  }
286345153Sdim  return __kmp_aux_set_affinity_mask_proc(KMP_DEREF proc, mask);
287345153Sdim#endif
288345153Sdim}
289345153Sdim
290345153Sdimint FTN_STDCALL FTN_UNSET_AFFINITY_MASK_PROC(int KMP_DEREF proc, void **mask) {
291345153Sdim#if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
292345153Sdim  return -1;
293345153Sdim#else
294345153Sdim  if (!TCR_4(__kmp_init_middle)) {
295345153Sdim    __kmp_middle_initialize();
296345153Sdim  }
297345153Sdim  return __kmp_aux_unset_affinity_mask_proc(KMP_DEREF proc, mask);
298345153Sdim#endif
299345153Sdim}
300345153Sdim
301345153Sdimint FTN_STDCALL FTN_GET_AFFINITY_MASK_PROC(int KMP_DEREF proc, void **mask) {
302345153Sdim#if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
303345153Sdim  return -1;
304345153Sdim#else
305345153Sdim  if (!TCR_4(__kmp_init_middle)) {
306345153Sdim    __kmp_middle_initialize();
307345153Sdim  }
308345153Sdim  return __kmp_aux_get_affinity_mask_proc(KMP_DEREF proc, mask);
309345153Sdim#endif
310345153Sdim}
311345153Sdim
312345153Sdim/* ------------------------------------------------------------------------ */
313345153Sdim
314345153Sdim/* sets the requested number of threads for the next parallel region */
315345153Sdimvoid FTN_STDCALL KMP_EXPAND_NAME(FTN_SET_NUM_THREADS)(int KMP_DEREF arg) {
316345153Sdim#ifdef KMP_STUB
317345153Sdim// Nothing.
318345153Sdim#else
319345153Sdim  __kmp_set_num_threads(KMP_DEREF arg, __kmp_entry_gtid());
320345153Sdim#endif
321345153Sdim}
322345153Sdim
323345153Sdim/* returns the number of threads in current team */
324345153Sdimint FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_NUM_THREADS)(void) {
325345153Sdim#ifdef KMP_STUB
326345153Sdim  return 1;
327345153Sdim#else
328345153Sdim  // __kmpc_bound_num_threads initializes the library if needed
329345153Sdim  return __kmpc_bound_num_threads(NULL);
330345153Sdim#endif
331345153Sdim}
332345153Sdim
333345153Sdimint FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_MAX_THREADS)(void) {
334345153Sdim#ifdef KMP_STUB
335345153Sdim  return 1;
336345153Sdim#else
337345153Sdim  int gtid;
338345153Sdim  kmp_info_t *thread;
339345153Sdim  if (!TCR_4(__kmp_init_middle)) {
340345153Sdim    __kmp_middle_initialize();
341345153Sdim  }
342345153Sdim  gtid = __kmp_entry_gtid();
343345153Sdim  thread = __kmp_threads[gtid];
344345153Sdim  // return thread -> th.th_team -> t.t_current_task[
345345153Sdim  // thread->th.th_info.ds.ds_tid ] -> icvs.nproc;
346345153Sdim  return thread->th.th_current_task->td_icvs.nproc;
347345153Sdim#endif
348345153Sdim}
349345153Sdim
350345153Sdimint FTN_STDCALL FTN_CONTROL_TOOL(int command, int modifier, void *arg) {
351345153Sdim#if defined(KMP_STUB) || !OMPT_SUPPORT
352345153Sdim  return -2;
353345153Sdim#else
354345153Sdim  OMPT_STORE_RETURN_ADDRESS(__kmp_entry_gtid());
355345153Sdim  if (!TCR_4(__kmp_init_middle)) {
356345153Sdim    return -2;
357345153Sdim  }
358345153Sdim  kmp_info_t *this_thr = __kmp_threads[__kmp_entry_gtid()];
359345153Sdim  ompt_task_info_t *parent_task_info = OMPT_CUR_TASK_INFO(this_thr);
360345153Sdim  parent_task_info->frame.enter_frame.ptr = OMPT_GET_FRAME_ADDRESS(0);
361345153Sdim  int ret = __kmp_control_tool(command, modifier, arg);
362345153Sdim  parent_task_info->frame.enter_frame.ptr = 0;
363345153Sdim  return ret;
364345153Sdim#endif
365345153Sdim}
366345153Sdim
367345153Sdim/* OpenMP 5.0 Memory Management support */
368353358Sdimomp_allocator_handle_t FTN_STDCALL
369353358SdimFTN_INIT_ALLOCATOR(omp_memspace_handle_t KMP_DEREF m, int KMP_DEREF ntraits,
370353358Sdim                   omp_alloctrait_t tr[]) {
371345153Sdim#ifdef KMP_STUB
372345153Sdim  return NULL;
373345153Sdim#else
374353358Sdim  return __kmpc_init_allocator(__kmp_entry_gtid(), KMP_DEREF m,
375353358Sdim                               KMP_DEREF ntraits, tr);
376345153Sdim#endif
377345153Sdim}
378353358Sdim
379353358Sdimvoid FTN_STDCALL FTN_DESTROY_ALLOCATOR(omp_allocator_handle_t al) {
380353358Sdim#ifndef KMP_STUB
381353358Sdim  __kmpc_destroy_allocator(__kmp_entry_gtid(), al);
382345153Sdim#endif
383345153Sdim}
384353358Sdimvoid FTN_STDCALL FTN_SET_DEFAULT_ALLOCATOR(omp_allocator_handle_t al) {
385353358Sdim#ifndef KMP_STUB
386353358Sdim  __kmpc_set_default_allocator(__kmp_entry_gtid(), al);
387353358Sdim#endif
388353358Sdim}
389353358Sdimomp_allocator_handle_t FTN_STDCALL FTN_GET_DEFAULT_ALLOCATOR(void) {
390345153Sdim#ifdef KMP_STUB
391353358Sdim  return NULL;
392345153Sdim#else
393353358Sdim  return __kmpc_get_default_allocator(__kmp_entry_gtid());
394345153Sdim#endif
395345153Sdim}
396345153Sdim
397345153Sdim/* OpenMP 5.0 affinity format support */
398345153Sdim#ifndef KMP_STUB
399345153Sdimstatic void __kmp_fortran_strncpy_truncate(char *buffer, size_t buf_size,
400345153Sdim                                           char const *csrc, size_t csrc_size) {
401345153Sdim  size_t capped_src_size = csrc_size;
402345153Sdim  if (csrc_size >= buf_size) {
403345153Sdim    capped_src_size = buf_size - 1;
404345153Sdim  }
405345153Sdim  KMP_STRNCPY_S(buffer, buf_size, csrc, capped_src_size);
406345153Sdim  if (csrc_size >= buf_size) {
407345153Sdim    KMP_DEBUG_ASSERT(buffer[buf_size - 1] == '\0');
408345153Sdim    buffer[buf_size - 1] = csrc[buf_size - 1];
409345153Sdim  } else {
410345153Sdim    for (size_t i = csrc_size; i < buf_size; ++i)
411345153Sdim      buffer[i] = ' ';
412345153Sdim  }
413345153Sdim}
414345153Sdim
415345153Sdim// Convert a Fortran string to a C string by adding null byte
416345153Sdimclass ConvertedString {
417345153Sdim  char *buf;
418345153Sdim  kmp_info_t *th;
419345153Sdim
420345153Sdimpublic:
421345153Sdim  ConvertedString(char const *fortran_str, size_t size) {
422345153Sdim    th = __kmp_get_thread();
423345153Sdim    buf = (char *)__kmp_thread_malloc(th, size + 1);
424345153Sdim    KMP_STRNCPY_S(buf, size + 1, fortran_str, size);
425345153Sdim    buf[size] = '\0';
426345153Sdim  }
427345153Sdim  ~ConvertedString() { __kmp_thread_free(th, buf); }
428345153Sdim  const char *get() const { return buf; }
429345153Sdim};
430345153Sdim#endif // KMP_STUB
431345153Sdim
432345153Sdim/*
433345153Sdim * Set the value of the affinity-format-var ICV on the current device to the
434345153Sdim * format specified in the argument.
435345153Sdim*/
436345153Sdimvoid FTN_STDCALL FTN_SET_AFFINITY_FORMAT(char const *format, size_t size) {
437345153Sdim#ifdef KMP_STUB
438345153Sdim  return;
439345153Sdim#else
440345153Sdim  if (!__kmp_init_serial) {
441345153Sdim    __kmp_serial_initialize();
442345153Sdim  }
443345153Sdim  ConvertedString cformat(format, size);
444345153Sdim  // Since the __kmp_affinity_format variable is a C string, do not
445345153Sdim  // use the fortran strncpy function
446345153Sdim  __kmp_strncpy_truncate(__kmp_affinity_format, KMP_AFFINITY_FORMAT_SIZE,
447345153Sdim                         cformat.get(), KMP_STRLEN(cformat.get()));
448345153Sdim#endif
449345153Sdim}
450345153Sdim
451345153Sdim/*
452345153Sdim * Returns the number of characters required to hold the entire affinity format
453345153Sdim * specification (not including null byte character) and writes the value of the
454345153Sdim * affinity-format-var ICV on the current device to buffer. If the return value
455345153Sdim * is larger than size, the affinity format specification is truncated.
456345153Sdim*/
457345153Sdimsize_t FTN_STDCALL FTN_GET_AFFINITY_FORMAT(char *buffer, size_t size) {
458345153Sdim#ifdef KMP_STUB
459345153Sdim  return 0;
460345153Sdim#else
461345153Sdim  size_t format_size;
462345153Sdim  if (!__kmp_init_serial) {
463345153Sdim    __kmp_serial_initialize();
464345153Sdim  }
465345153Sdim  format_size = KMP_STRLEN(__kmp_affinity_format);
466345153Sdim  if (buffer && size) {
467345153Sdim    __kmp_fortran_strncpy_truncate(buffer, size, __kmp_affinity_format,
468345153Sdim                                   format_size);
469345153Sdim  }
470345153Sdim  return format_size;
471345153Sdim#endif
472345153Sdim}
473345153Sdim
474345153Sdim/*
475345153Sdim * Prints the thread affinity information of the current thread in the format
476345153Sdim * specified by the format argument. If the format is NULL or a zero-length
477345153Sdim * string, the value of the affinity-format-var ICV is used.
478345153Sdim*/
479345153Sdimvoid FTN_STDCALL FTN_DISPLAY_AFFINITY(char const *format, size_t size) {
480345153Sdim#ifdef KMP_STUB
481345153Sdim  return;
482345153Sdim#else
483345153Sdim  int gtid;
484345153Sdim  if (!TCR_4(__kmp_init_middle)) {
485345153Sdim    __kmp_middle_initialize();
486345153Sdim  }
487345153Sdim  gtid = __kmp_get_gtid();
488345153Sdim  ConvertedString cformat(format, size);
489345153Sdim  __kmp_aux_display_affinity(gtid, cformat.get());
490345153Sdim#endif
491345153Sdim}
492345153Sdim
493345153Sdim/*
494345153Sdim * Returns the number of characters required to hold the entire affinity format
495345153Sdim * specification (not including null byte) and prints the thread affinity
496345153Sdim * information of the current thread into the character string buffer with the
497345153Sdim * size of size in the format specified by the format argument. If the format is
498345153Sdim * NULL or a zero-length string, the value of the affinity-format-var ICV is
499345153Sdim * used. The buffer must be allocated prior to calling the routine. If the
500345153Sdim * return value is larger than size, the affinity format specification is
501345153Sdim * truncated.
502345153Sdim*/
503345153Sdimsize_t FTN_STDCALL FTN_CAPTURE_AFFINITY(char *buffer, char const *format,
504345153Sdim                                        size_t buf_size, size_t for_size) {
505345153Sdim#if defined(KMP_STUB)
506345153Sdim  return 0;
507345153Sdim#else
508345153Sdim  int gtid;
509345153Sdim  size_t num_required;
510345153Sdim  kmp_str_buf_t capture_buf;
511345153Sdim  if (!TCR_4(__kmp_init_middle)) {
512345153Sdim    __kmp_middle_initialize();
513345153Sdim  }
514345153Sdim  gtid = __kmp_get_gtid();
515345153Sdim  __kmp_str_buf_init(&capture_buf);
516345153Sdim  ConvertedString cformat(format, for_size);
517345153Sdim  num_required = __kmp_aux_capture_affinity(gtid, cformat.get(), &capture_buf);
518345153Sdim  if (buffer && buf_size) {
519345153Sdim    __kmp_fortran_strncpy_truncate(buffer, buf_size, capture_buf.str,
520345153Sdim                                   capture_buf.used);
521345153Sdim  }
522345153Sdim  __kmp_str_buf_free(&capture_buf);
523345153Sdim  return num_required;
524345153Sdim#endif
525345153Sdim}
526345153Sdim
527345153Sdimint FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_THREAD_NUM)(void) {
528345153Sdim#ifdef KMP_STUB
529345153Sdim  return 0;
530345153Sdim#else
531345153Sdim  int gtid;
532345153Sdim
533345153Sdim#if KMP_OS_DARWIN || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD ||    \
534360784Sdim        KMP_OS_HURD|| KMP_OS_OPENBSD
535345153Sdim  gtid = __kmp_entry_gtid();
536345153Sdim#elif KMP_OS_WINDOWS
537345153Sdim  if (!__kmp_init_parallel ||
538345153Sdim      (gtid = (int)((kmp_intptr_t)TlsGetValue(__kmp_gtid_threadprivate_key))) ==
539345153Sdim          0) {
540345153Sdim    // Either library isn't initialized or thread is not registered
541345153Sdim    // 0 is the correct TID in this case
542345153Sdim    return 0;
543345153Sdim  }
544345153Sdim  --gtid; // We keep (gtid+1) in TLS
545345153Sdim#elif KMP_OS_LINUX
546345153Sdim#ifdef KMP_TDATA_GTID
547345153Sdim  if (__kmp_gtid_mode >= 3) {
548345153Sdim    if ((gtid = __kmp_gtid) == KMP_GTID_DNE) {
549345153Sdim      return 0;
550345153Sdim    }
551345153Sdim  } else {
552345153Sdim#endif
553345153Sdim    if (!__kmp_init_parallel ||
554345153Sdim        (gtid = (kmp_intptr_t)(
555345153Sdim             pthread_getspecific(__kmp_gtid_threadprivate_key))) == 0) {
556345153Sdim      return 0;
557345153Sdim    }
558345153Sdim    --gtid;
559345153Sdim#ifdef KMP_TDATA_GTID
560345153Sdim  }
561345153Sdim#endif
562345153Sdim#else
563345153Sdim#error Unknown or unsupported OS
564345153Sdim#endif
565345153Sdim
566345153Sdim  return __kmp_tid_from_gtid(gtid);
567345153Sdim#endif
568345153Sdim}
569345153Sdim
570345153Sdimint FTN_STDCALL FTN_GET_NUM_KNOWN_THREADS(void) {
571345153Sdim#ifdef KMP_STUB
572345153Sdim  return 1;
573345153Sdim#else
574345153Sdim  if (!__kmp_init_serial) {
575345153Sdim    __kmp_serial_initialize();
576345153Sdim  }
577345153Sdim  /* NOTE: this is not syncronized, so it can change at any moment */
578345153Sdim  /* NOTE: this number also includes threads preallocated in hot-teams */
579345153Sdim  return TCR_4(__kmp_nth);
580345153Sdim#endif
581345153Sdim}
582345153Sdim
583345153Sdimint FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_NUM_PROCS)(void) {
584345153Sdim#ifdef KMP_STUB
585345153Sdim  return 1;
586345153Sdim#else
587345153Sdim  if (!TCR_4(__kmp_init_middle)) {
588345153Sdim    __kmp_middle_initialize();
589345153Sdim  }
590345153Sdim  return __kmp_avail_proc;
591345153Sdim#endif
592345153Sdim}
593345153Sdim
594345153Sdimvoid FTN_STDCALL KMP_EXPAND_NAME(FTN_SET_NESTED)(int KMP_DEREF flag) {
595353358Sdim  KMP_INFORM(APIDeprecated, "omp_set_nested", "omp_set_max_active_levels");
596345153Sdim#ifdef KMP_STUB
597345153Sdim  __kmps_set_nested(KMP_DEREF flag);
598345153Sdim#else
599345153Sdim  kmp_info_t *thread;
600345153Sdim  /* For the thread-private internal controls implementation */
601345153Sdim  thread = __kmp_entry_thread();
602345153Sdim  __kmp_save_internal_controls(thread);
603353358Sdim  // Somewhat arbitrarily decide where to get a value for max_active_levels
604353358Sdim  int max_active_levels = get__max_active_levels(thread);
605353358Sdim  if (max_active_levels == 1)
606353358Sdim    max_active_levels = KMP_MAX_ACTIVE_LEVELS_LIMIT;
607353358Sdim  set__max_active_levels(thread, (KMP_DEREF flag) ? max_active_levels : 1);
608345153Sdim#endif
609345153Sdim}
610345153Sdim
611345153Sdimint FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_NESTED)(void) {
612353358Sdim  KMP_INFORM(APIDeprecated, "omp_get_nested", "omp_get_max_active_levels");
613345153Sdim#ifdef KMP_STUB
614345153Sdim  return __kmps_get_nested();
615345153Sdim#else
616345153Sdim  kmp_info_t *thread;
617345153Sdim  thread = __kmp_entry_thread();
618353358Sdim  return get__max_active_levels(thread) > 1;
619345153Sdim#endif
620345153Sdim}
621345153Sdim
622345153Sdimvoid FTN_STDCALL KMP_EXPAND_NAME(FTN_SET_DYNAMIC)(int KMP_DEREF flag) {
623345153Sdim#ifdef KMP_STUB
624345153Sdim  __kmps_set_dynamic(KMP_DEREF flag ? TRUE : FALSE);
625345153Sdim#else
626345153Sdim  kmp_info_t *thread;
627345153Sdim  /* For the thread-private implementation of the internal controls */
628345153Sdim  thread = __kmp_entry_thread();
629345153Sdim  // !!! What if foreign thread calls it?
630345153Sdim  __kmp_save_internal_controls(thread);
631345153Sdim  set__dynamic(thread, KMP_DEREF flag ? TRUE : FALSE);
632345153Sdim#endif
633345153Sdim}
634345153Sdim
635345153Sdimint FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_DYNAMIC)(void) {
636345153Sdim#ifdef KMP_STUB
637345153Sdim  return __kmps_get_dynamic();
638345153Sdim#else
639345153Sdim  kmp_info_t *thread;
640345153Sdim  thread = __kmp_entry_thread();
641345153Sdim  return get__dynamic(thread);
642345153Sdim#endif
643345153Sdim}
644345153Sdim
645345153Sdimint FTN_STDCALL KMP_EXPAND_NAME(FTN_IN_PARALLEL)(void) {
646345153Sdim#ifdef KMP_STUB
647345153Sdim  return 0;
648345153Sdim#else
649345153Sdim  kmp_info_t *th = __kmp_entry_thread();
650345153Sdim  if (th->th.th_teams_microtask) {
651345153Sdim    // AC: r_in_parallel does not work inside teams construct where real
652345153Sdim    // parallel is inactive, but all threads have same root, so setting it in
653345153Sdim    // one team affects other teams.
654345153Sdim    // The solution is to use per-team nesting level
655345153Sdim    return (th->th.th_team->t.t_active_level ? 1 : 0);
656345153Sdim  } else
657345153Sdim    return (th->th.th_root->r.r_in_parallel ? FTN_TRUE : FTN_FALSE);
658345153Sdim#endif
659345153Sdim}
660345153Sdim
661345153Sdimvoid FTN_STDCALL KMP_EXPAND_NAME(FTN_SET_SCHEDULE)(kmp_sched_t KMP_DEREF kind,
662345153Sdim                                                   int KMP_DEREF modifier) {
663345153Sdim#ifdef KMP_STUB
664345153Sdim  __kmps_set_schedule(KMP_DEREF kind, KMP_DEREF modifier);
665345153Sdim#else
666345153Sdim  /* TO DO: For the per-task implementation of the internal controls */
667345153Sdim  __kmp_set_schedule(__kmp_entry_gtid(), KMP_DEREF kind, KMP_DEREF modifier);
668345153Sdim#endif
669345153Sdim}
670345153Sdim
671345153Sdimvoid FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_SCHEDULE)(kmp_sched_t *kind,
672345153Sdim                                                   int *modifier) {
673345153Sdim#ifdef KMP_STUB
674345153Sdim  __kmps_get_schedule(kind, modifier);
675345153Sdim#else
676345153Sdim  /* TO DO: For the per-task implementation of the internal controls */
677345153Sdim  __kmp_get_schedule(__kmp_entry_gtid(), kind, modifier);
678345153Sdim#endif
679345153Sdim}
680345153Sdim
681345153Sdimvoid FTN_STDCALL KMP_EXPAND_NAME(FTN_SET_MAX_ACTIVE_LEVELS)(int KMP_DEREF arg) {
682345153Sdim#ifdef KMP_STUB
683345153Sdim// Nothing.
684345153Sdim#else
685345153Sdim  /* TO DO: We want per-task implementation of this internal control */
686345153Sdim  __kmp_set_max_active_levels(__kmp_entry_gtid(), KMP_DEREF arg);
687345153Sdim#endif
688345153Sdim}
689345153Sdim
690345153Sdimint FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_MAX_ACTIVE_LEVELS)(void) {
691345153Sdim#ifdef KMP_STUB
692345153Sdim  return 0;
693345153Sdim#else
694345153Sdim  /* TO DO: We want per-task implementation of this internal control */
695345153Sdim  return __kmp_get_max_active_levels(__kmp_entry_gtid());
696345153Sdim#endif
697345153Sdim}
698345153Sdim
699345153Sdimint FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_ACTIVE_LEVEL)(void) {
700345153Sdim#ifdef KMP_STUB
701345153Sdim  return 0; // returns 0 if it is called from the sequential part of the program
702345153Sdim#else
703345153Sdim  /* TO DO: For the per-task implementation of the internal controls */
704345153Sdim  return __kmp_entry_thread()->th.th_team->t.t_active_level;
705345153Sdim#endif
706345153Sdim}
707345153Sdim
708345153Sdimint FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_LEVEL)(void) {
709345153Sdim#ifdef KMP_STUB
710345153Sdim  return 0; // returns 0 if it is called from the sequential part of the program
711345153Sdim#else
712345153Sdim  /* TO DO: For the per-task implementation of the internal controls */
713345153Sdim  return __kmp_entry_thread()->th.th_team->t.t_level;
714345153Sdim#endif
715345153Sdim}
716345153Sdim
717345153Sdimint FTN_STDCALL
718345153Sdim    KMP_EXPAND_NAME(FTN_GET_ANCESTOR_THREAD_NUM)(int KMP_DEREF level) {
719345153Sdim#ifdef KMP_STUB
720345153Sdim  return (KMP_DEREF level) ? (-1) : (0);
721345153Sdim#else
722345153Sdim  return __kmp_get_ancestor_thread_num(__kmp_entry_gtid(), KMP_DEREF level);
723345153Sdim#endif
724345153Sdim}
725345153Sdim
726345153Sdimint FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_TEAM_SIZE)(int KMP_DEREF level) {
727345153Sdim#ifdef KMP_STUB
728345153Sdim  return (KMP_DEREF level) ? (-1) : (1);
729345153Sdim#else
730345153Sdim  return __kmp_get_team_size(__kmp_entry_gtid(), KMP_DEREF level);
731345153Sdim#endif
732345153Sdim}
733345153Sdim
734345153Sdimint FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_THREAD_LIMIT)(void) {
735345153Sdim#ifdef KMP_STUB
736345153Sdim  return 1; // TO DO: clarify whether it returns 1 or 0?
737345153Sdim#else
738353358Sdim  int gtid;
739353358Sdim  kmp_info_t *thread;
740345153Sdim  if (!__kmp_init_serial) {
741345153Sdim    __kmp_serial_initialize();
742345153Sdim  }
743353358Sdim
744353358Sdim  gtid = __kmp_entry_gtid();
745353358Sdim  thread = __kmp_threads[gtid];
746353358Sdim  return thread->th.th_current_task->td_icvs.thread_limit;
747345153Sdim#endif
748345153Sdim}
749345153Sdim
750345153Sdimint FTN_STDCALL KMP_EXPAND_NAME(FTN_IN_FINAL)(void) {
751345153Sdim#ifdef KMP_STUB
752345153Sdim  return 0; // TO DO: clarify whether it returns 1 or 0?
753345153Sdim#else
754345153Sdim  if (!TCR_4(__kmp_init_parallel)) {
755345153Sdim    return 0;
756345153Sdim  }
757345153Sdim  return __kmp_entry_thread()->th.th_current_task->td_flags.final;
758345153Sdim#endif
759345153Sdim}
760345153Sdim
761345153Sdimkmp_proc_bind_t FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_PROC_BIND)(void) {
762345153Sdim#ifdef KMP_STUB
763345153Sdim  return __kmps_get_proc_bind();
764345153Sdim#else
765345153Sdim  return get__proc_bind(__kmp_entry_thread());
766345153Sdim#endif
767345153Sdim}
768345153Sdim
769345153Sdimint FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_NUM_PLACES)(void) {
770345153Sdim#if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
771345153Sdim  return 0;
772345153Sdim#else
773345153Sdim  if (!TCR_4(__kmp_init_middle)) {
774345153Sdim    __kmp_middle_initialize();
775345153Sdim  }
776345153Sdim  if (!KMP_AFFINITY_CAPABLE())
777345153Sdim    return 0;
778345153Sdim  return __kmp_affinity_num_masks;
779345153Sdim#endif
780345153Sdim}
781345153Sdim
782345153Sdimint FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_PLACE_NUM_PROCS)(int place_num) {
783345153Sdim#if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
784345153Sdim  return 0;
785345153Sdim#else
786345153Sdim  int i;
787345153Sdim  int retval = 0;
788345153Sdim  if (!TCR_4(__kmp_init_middle)) {
789345153Sdim    __kmp_middle_initialize();
790345153Sdim  }
791345153Sdim  if (!KMP_AFFINITY_CAPABLE())
792345153Sdim    return 0;
793345153Sdim  if (place_num < 0 || place_num >= (int)__kmp_affinity_num_masks)
794345153Sdim    return 0;
795345153Sdim  kmp_affin_mask_t *mask = KMP_CPU_INDEX(__kmp_affinity_masks, place_num);
796345153Sdim  KMP_CPU_SET_ITERATE(i, mask) {
797345153Sdim    if ((!KMP_CPU_ISSET(i, __kmp_affin_fullMask)) ||
798345153Sdim        (!KMP_CPU_ISSET(i, mask))) {
799345153Sdim      continue;
800345153Sdim    }
801345153Sdim    ++retval;
802345153Sdim  }
803345153Sdim  return retval;
804345153Sdim#endif
805345153Sdim}
806345153Sdim
807345153Sdimvoid FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_PLACE_PROC_IDS)(int place_num,
808345153Sdim                                                         int *ids) {
809345153Sdim#if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
810345153Sdim// Nothing.
811345153Sdim#else
812345153Sdim  int i, j;
813345153Sdim  if (!TCR_4(__kmp_init_middle)) {
814345153Sdim    __kmp_middle_initialize();
815345153Sdim  }
816345153Sdim  if (!KMP_AFFINITY_CAPABLE())
817345153Sdim    return;
818345153Sdim  if (place_num < 0 || place_num >= (int)__kmp_affinity_num_masks)
819345153Sdim    return;
820345153Sdim  kmp_affin_mask_t *mask = KMP_CPU_INDEX(__kmp_affinity_masks, place_num);
821345153Sdim  j = 0;
822345153Sdim  KMP_CPU_SET_ITERATE(i, mask) {
823345153Sdim    if ((!KMP_CPU_ISSET(i, __kmp_affin_fullMask)) ||
824345153Sdim        (!KMP_CPU_ISSET(i, mask))) {
825345153Sdim      continue;
826345153Sdim    }
827345153Sdim    ids[j++] = i;
828345153Sdim  }
829345153Sdim#endif
830345153Sdim}
831345153Sdim
832345153Sdimint FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_PLACE_NUM)(void) {
833345153Sdim#if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
834345153Sdim  return -1;
835345153Sdim#else
836345153Sdim  int gtid;
837345153Sdim  kmp_info_t *thread;
838345153Sdim  if (!TCR_4(__kmp_init_middle)) {
839345153Sdim    __kmp_middle_initialize();
840345153Sdim  }
841345153Sdim  if (!KMP_AFFINITY_CAPABLE())
842345153Sdim    return -1;
843345153Sdim  gtid = __kmp_entry_gtid();
844345153Sdim  thread = __kmp_thread_from_gtid(gtid);
845345153Sdim  if (thread->th.th_current_place < 0)
846345153Sdim    return -1;
847345153Sdim  return thread->th.th_current_place;
848345153Sdim#endif
849345153Sdim}
850345153Sdim
851345153Sdimint FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_PARTITION_NUM_PLACES)(void) {
852345153Sdim#if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
853345153Sdim  return 0;
854345153Sdim#else
855345153Sdim  int gtid, num_places, first_place, last_place;
856345153Sdim  kmp_info_t *thread;
857345153Sdim  if (!TCR_4(__kmp_init_middle)) {
858345153Sdim    __kmp_middle_initialize();
859345153Sdim  }
860345153Sdim  if (!KMP_AFFINITY_CAPABLE())
861345153Sdim    return 0;
862345153Sdim  gtid = __kmp_entry_gtid();
863345153Sdim  thread = __kmp_thread_from_gtid(gtid);
864345153Sdim  first_place = thread->th.th_first_place;
865345153Sdim  last_place = thread->th.th_last_place;
866345153Sdim  if (first_place < 0 || last_place < 0)
867345153Sdim    return 0;
868345153Sdim  if (first_place <= last_place)
869345153Sdim    num_places = last_place - first_place + 1;
870345153Sdim  else
871345153Sdim    num_places = __kmp_affinity_num_masks - first_place + last_place + 1;
872345153Sdim  return num_places;
873345153Sdim#endif
874345153Sdim}
875345153Sdim
876345153Sdimvoid
877345153Sdim    FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_PARTITION_PLACE_NUMS)(int *place_nums) {
878345153Sdim#if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
879345153Sdim// Nothing.
880345153Sdim#else
881345153Sdim  int i, gtid, place_num, first_place, last_place, start, end;
882345153Sdim  kmp_info_t *thread;
883345153Sdim  if (!TCR_4(__kmp_init_middle)) {
884345153Sdim    __kmp_middle_initialize();
885345153Sdim  }
886345153Sdim  if (!KMP_AFFINITY_CAPABLE())
887345153Sdim    return;
888345153Sdim  gtid = __kmp_entry_gtid();
889345153Sdim  thread = __kmp_thread_from_gtid(gtid);
890345153Sdim  first_place = thread->th.th_first_place;
891345153Sdim  last_place = thread->th.th_last_place;
892345153Sdim  if (first_place < 0 || last_place < 0)
893345153Sdim    return;
894345153Sdim  if (first_place <= last_place) {
895345153Sdim    start = first_place;
896345153Sdim    end = last_place;
897345153Sdim  } else {
898345153Sdim    start = last_place;
899345153Sdim    end = first_place;
900345153Sdim  }
901345153Sdim  for (i = 0, place_num = start; place_num <= end; ++place_num, ++i) {
902345153Sdim    place_nums[i] = place_num;
903345153Sdim  }
904345153Sdim#endif
905345153Sdim}
906345153Sdim
907345153Sdimint FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_NUM_TEAMS)(void) {
908345153Sdim#ifdef KMP_STUB
909345153Sdim  return 1;
910345153Sdim#else
911345153Sdim  return __kmp_aux_get_num_teams();
912345153Sdim#endif
913345153Sdim}
914345153Sdim
915345153Sdimint FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_TEAM_NUM)(void) {
916345153Sdim#ifdef KMP_STUB
917345153Sdim  return 0;
918345153Sdim#else
919345153Sdim  return __kmp_aux_get_team_num();
920345153Sdim#endif
921345153Sdim}
922345153Sdim
923345153Sdimint FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_DEFAULT_DEVICE)(void) {
924345153Sdim#if KMP_MIC || KMP_OS_DARWIN || defined(KMP_STUB)
925345153Sdim  return 0;
926345153Sdim#else
927345153Sdim  return __kmp_entry_thread()->th.th_current_task->td_icvs.default_device;
928345153Sdim#endif
929345153Sdim}
930345153Sdim
931345153Sdimvoid FTN_STDCALL KMP_EXPAND_NAME(FTN_SET_DEFAULT_DEVICE)(int KMP_DEREF arg) {
932345153Sdim#if KMP_MIC || KMP_OS_DARWIN || defined(KMP_STUB)
933345153Sdim// Nothing.
934345153Sdim#else
935345153Sdim  __kmp_entry_thread()->th.th_current_task->td_icvs.default_device =
936345153Sdim      KMP_DEREF arg;
937345153Sdim#endif
938345153Sdim}
939345153Sdim
940345153Sdim// Get number of NON-HOST devices.
941345153Sdim// libomptarget, if loaded, provides this function in api.cpp.
942345153Sdimint FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_NUM_DEVICES)(void) KMP_WEAK_ATTRIBUTE;
943345153Sdimint FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_NUM_DEVICES)(void) {
944345153Sdim#if KMP_MIC || KMP_OS_DARWIN || KMP_OS_WINDOWS || defined(KMP_STUB)
945345153Sdim  return 0;
946345153Sdim#else
947345153Sdim  int (*fptr)();
948345153Sdim  if ((*(void **)(&fptr) = dlsym(RTLD_DEFAULT, "_Offload_number_of_devices"))) {
949345153Sdim    return (*fptr)();
950345153Sdim  } else if ((*(void **)(&fptr) = dlsym(RTLD_NEXT, "omp_get_num_devices"))) {
951345153Sdim    return (*fptr)();
952345153Sdim  } else { // liboffload & libomptarget don't exist
953345153Sdim    return 0;
954345153Sdim  }
955345153Sdim#endif // KMP_MIC || KMP_OS_DARWIN || KMP_OS_WINDOWS || defined(KMP_STUB)
956345153Sdim}
957345153Sdim
958345153Sdim// This function always returns true when called on host device.
959360784Sdim// Compiler/libomptarget should handle when it is called inside target region.
960345153Sdimint FTN_STDCALL KMP_EXPAND_NAME(FTN_IS_INITIAL_DEVICE)(void) KMP_WEAK_ATTRIBUTE;
961345153Sdimint FTN_STDCALL KMP_EXPAND_NAME(FTN_IS_INITIAL_DEVICE)(void) {
962345153Sdim  return 1; // This is the host
963345153Sdim}
964345153Sdim
965345153Sdim// libomptarget, if loaded, provides this function
966345153Sdimint FTN_STDCALL FTN_GET_INITIAL_DEVICE(void) KMP_WEAK_ATTRIBUTE;
967345153Sdimint FTN_STDCALL FTN_GET_INITIAL_DEVICE(void) {
968345153Sdim#if KMP_MIC || KMP_OS_DARWIN || KMP_OS_WINDOWS || defined(KMP_STUB)
969345153Sdim  return KMP_HOST_DEVICE;
970345153Sdim#else
971345153Sdim  int (*fptr)();
972345153Sdim  if ((*(void **)(&fptr) = dlsym(RTLD_NEXT, "omp_get_initial_device"))) {
973345153Sdim    return (*fptr)();
974345153Sdim  } else { // liboffload & libomptarget don't exist
975345153Sdim    return KMP_HOST_DEVICE;
976345153Sdim  }
977345153Sdim#endif
978345153Sdim}
979345153Sdim
980345153Sdim#if defined(KMP_STUB)
981345153Sdim// Entries for stubs library
982345153Sdim// As all *target* functions are C-only parameters always passed by value
983345153Sdimvoid *FTN_STDCALL FTN_TARGET_ALLOC(size_t size, int device_num) { return 0; }
984345153Sdim
985345153Sdimvoid FTN_STDCALL FTN_TARGET_FREE(void *device_ptr, int device_num) {}
986345153Sdim
987345153Sdimint FTN_STDCALL FTN_TARGET_IS_PRESENT(void *ptr, int device_num) { return 0; }
988345153Sdim
989345153Sdimint FTN_STDCALL FTN_TARGET_MEMCPY(void *dst, void *src, size_t length,
990345153Sdim                                  size_t dst_offset, size_t src_offset,
991345153Sdim                                  int dst_device, int src_device) {
992345153Sdim  return -1;
993345153Sdim}
994345153Sdim
995345153Sdimint FTN_STDCALL FTN_TARGET_MEMCPY_RECT(
996345153Sdim    void *dst, void *src, size_t element_size, int num_dims,
997345153Sdim    const size_t *volume, const size_t *dst_offsets, const size_t *src_offsets,
998345153Sdim    const size_t *dst_dimensions, const size_t *src_dimensions, int dst_device,
999345153Sdim    int src_device) {
1000345153Sdim  return -1;
1001345153Sdim}
1002345153Sdim
1003345153Sdimint FTN_STDCALL FTN_TARGET_ASSOCIATE_PTR(void *host_ptr, void *device_ptr,
1004345153Sdim                                         size_t size, size_t device_offset,
1005345153Sdim                                         int device_num) {
1006345153Sdim  return -1;
1007345153Sdim}
1008345153Sdim
1009345153Sdimint FTN_STDCALL FTN_TARGET_DISASSOCIATE_PTR(void *host_ptr, int device_num) {
1010345153Sdim  return -1;
1011345153Sdim}
1012345153Sdim#endif // defined(KMP_STUB)
1013345153Sdim
1014345153Sdim#ifdef KMP_STUB
1015345153Sdimtypedef enum { UNINIT = -1, UNLOCKED, LOCKED } kmp_stub_lock_t;
1016345153Sdim#endif /* KMP_STUB */
1017345153Sdim
1018345153Sdim#if KMP_USE_DYNAMIC_LOCK
1019345153Sdimvoid FTN_STDCALL FTN_INIT_LOCK_WITH_HINT(void **user_lock,
1020345153Sdim                                         uintptr_t KMP_DEREF hint) {
1021345153Sdim#ifdef KMP_STUB
1022345153Sdim  *((kmp_stub_lock_t *)user_lock) = UNLOCKED;
1023345153Sdim#else
1024345153Sdim  int gtid = __kmp_entry_gtid();
1025345153Sdim#if OMPT_SUPPORT && OMPT_OPTIONAL
1026345153Sdim  OMPT_STORE_RETURN_ADDRESS(gtid);
1027345153Sdim#endif
1028345153Sdim  __kmpc_init_lock_with_hint(NULL, gtid, user_lock, KMP_DEREF hint);
1029345153Sdim#endif
1030345153Sdim}
1031345153Sdim
1032345153Sdimvoid FTN_STDCALL FTN_INIT_NEST_LOCK_WITH_HINT(void **user_lock,
1033345153Sdim                                              uintptr_t KMP_DEREF hint) {
1034345153Sdim#ifdef KMP_STUB
1035345153Sdim  *((kmp_stub_lock_t *)user_lock) = UNLOCKED;
1036345153Sdim#else
1037345153Sdim  int gtid = __kmp_entry_gtid();
1038345153Sdim#if OMPT_SUPPORT && OMPT_OPTIONAL
1039345153Sdim  OMPT_STORE_RETURN_ADDRESS(gtid);
1040345153Sdim#endif
1041345153Sdim  __kmpc_init_nest_lock_with_hint(NULL, gtid, user_lock, KMP_DEREF hint);
1042345153Sdim#endif
1043345153Sdim}
1044345153Sdim#endif
1045345153Sdim
1046345153Sdim/* initialize the lock */
1047345153Sdimvoid FTN_STDCALL KMP_EXPAND_NAME(FTN_INIT_LOCK)(void **user_lock) {
1048345153Sdim#ifdef KMP_STUB
1049345153Sdim  *((kmp_stub_lock_t *)user_lock) = UNLOCKED;
1050345153Sdim#else
1051345153Sdim  int gtid = __kmp_entry_gtid();
1052345153Sdim#if OMPT_SUPPORT && OMPT_OPTIONAL
1053345153Sdim  OMPT_STORE_RETURN_ADDRESS(gtid);
1054345153Sdim#endif
1055345153Sdim  __kmpc_init_lock(NULL, gtid, user_lock);
1056345153Sdim#endif
1057345153Sdim}
1058345153Sdim
1059345153Sdim/* initialize the lock */
1060345153Sdimvoid FTN_STDCALL KMP_EXPAND_NAME(FTN_INIT_NEST_LOCK)(void **user_lock) {
1061345153Sdim#ifdef KMP_STUB
1062345153Sdim  *((kmp_stub_lock_t *)user_lock) = UNLOCKED;
1063345153Sdim#else
1064345153Sdim  int gtid = __kmp_entry_gtid();
1065345153Sdim#if OMPT_SUPPORT && OMPT_OPTIONAL
1066345153Sdim  OMPT_STORE_RETURN_ADDRESS(gtid);
1067345153Sdim#endif
1068345153Sdim  __kmpc_init_nest_lock(NULL, gtid, user_lock);
1069345153Sdim#endif
1070345153Sdim}
1071345153Sdim
1072345153Sdimvoid FTN_STDCALL KMP_EXPAND_NAME(FTN_DESTROY_LOCK)(void **user_lock) {
1073345153Sdim#ifdef KMP_STUB
1074345153Sdim  *((kmp_stub_lock_t *)user_lock) = UNINIT;
1075345153Sdim#else
1076345153Sdim  int gtid = __kmp_entry_gtid();
1077345153Sdim#if OMPT_SUPPORT && OMPT_OPTIONAL
1078345153Sdim  OMPT_STORE_RETURN_ADDRESS(gtid);
1079345153Sdim#endif
1080345153Sdim  __kmpc_destroy_lock(NULL, gtid, user_lock);
1081345153Sdim#endif
1082345153Sdim}
1083345153Sdim
1084345153Sdimvoid FTN_STDCALL KMP_EXPAND_NAME(FTN_DESTROY_NEST_LOCK)(void **user_lock) {
1085345153Sdim#ifdef KMP_STUB
1086345153Sdim  *((kmp_stub_lock_t *)user_lock) = UNINIT;
1087345153Sdim#else
1088345153Sdim  int gtid = __kmp_entry_gtid();
1089345153Sdim#if OMPT_SUPPORT && OMPT_OPTIONAL
1090345153Sdim  OMPT_STORE_RETURN_ADDRESS(gtid);
1091345153Sdim#endif
1092345153Sdim  __kmpc_destroy_nest_lock(NULL, gtid, user_lock);
1093345153Sdim#endif
1094345153Sdim}
1095345153Sdim
1096345153Sdimvoid FTN_STDCALL KMP_EXPAND_NAME(FTN_SET_LOCK)(void **user_lock) {
1097345153Sdim#ifdef KMP_STUB
1098345153Sdim  if (*((kmp_stub_lock_t *)user_lock) == UNINIT) {
1099345153Sdim    // TODO: Issue an error.
1100345153Sdim  }
1101345153Sdim  if (*((kmp_stub_lock_t *)user_lock) != UNLOCKED) {
1102345153Sdim    // TODO: Issue an error.
1103345153Sdim  }
1104345153Sdim  *((kmp_stub_lock_t *)user_lock) = LOCKED;
1105345153Sdim#else
1106345153Sdim  int gtid = __kmp_entry_gtid();
1107345153Sdim#if OMPT_SUPPORT && OMPT_OPTIONAL
1108345153Sdim  OMPT_STORE_RETURN_ADDRESS(gtid);
1109345153Sdim#endif
1110345153Sdim  __kmpc_set_lock(NULL, gtid, user_lock);
1111345153Sdim#endif
1112345153Sdim}
1113345153Sdim
1114345153Sdimvoid FTN_STDCALL KMP_EXPAND_NAME(FTN_SET_NEST_LOCK)(void **user_lock) {
1115345153Sdim#ifdef KMP_STUB
1116345153Sdim  if (*((kmp_stub_lock_t *)user_lock) == UNINIT) {
1117345153Sdim    // TODO: Issue an error.
1118345153Sdim  }
1119345153Sdim  (*((int *)user_lock))++;
1120345153Sdim#else
1121345153Sdim  int gtid = __kmp_entry_gtid();
1122345153Sdim#if OMPT_SUPPORT && OMPT_OPTIONAL
1123345153Sdim  OMPT_STORE_RETURN_ADDRESS(gtid);
1124345153Sdim#endif
1125345153Sdim  __kmpc_set_nest_lock(NULL, gtid, user_lock);
1126345153Sdim#endif
1127345153Sdim}
1128345153Sdim
1129345153Sdimvoid FTN_STDCALL KMP_EXPAND_NAME(FTN_UNSET_LOCK)(void **user_lock) {
1130345153Sdim#ifdef KMP_STUB
1131345153Sdim  if (*((kmp_stub_lock_t *)user_lock) == UNINIT) {
1132345153Sdim    // TODO: Issue an error.
1133345153Sdim  }
1134345153Sdim  if (*((kmp_stub_lock_t *)user_lock) == UNLOCKED) {
1135345153Sdim    // TODO: Issue an error.
1136345153Sdim  }
1137345153Sdim  *((kmp_stub_lock_t *)user_lock) = UNLOCKED;
1138345153Sdim#else
1139345153Sdim  int gtid = __kmp_entry_gtid();
1140345153Sdim#if OMPT_SUPPORT && OMPT_OPTIONAL
1141345153Sdim  OMPT_STORE_RETURN_ADDRESS(gtid);
1142345153Sdim#endif
1143345153Sdim  __kmpc_unset_lock(NULL, gtid, user_lock);
1144345153Sdim#endif
1145345153Sdim}
1146345153Sdim
1147345153Sdimvoid FTN_STDCALL KMP_EXPAND_NAME(FTN_UNSET_NEST_LOCK)(void **user_lock) {
1148345153Sdim#ifdef KMP_STUB
1149345153Sdim  if (*((kmp_stub_lock_t *)user_lock) == UNINIT) {
1150345153Sdim    // TODO: Issue an error.
1151345153Sdim  }
1152345153Sdim  if (*((kmp_stub_lock_t *)user_lock) == UNLOCKED) {
1153345153Sdim    // TODO: Issue an error.
1154345153Sdim  }
1155345153Sdim  (*((int *)user_lock))--;
1156345153Sdim#else
1157345153Sdim  int gtid = __kmp_entry_gtid();
1158345153Sdim#if OMPT_SUPPORT && OMPT_OPTIONAL
1159345153Sdim  OMPT_STORE_RETURN_ADDRESS(gtid);
1160345153Sdim#endif
1161345153Sdim  __kmpc_unset_nest_lock(NULL, gtid, user_lock);
1162345153Sdim#endif
1163345153Sdim}
1164345153Sdim
1165345153Sdimint FTN_STDCALL KMP_EXPAND_NAME(FTN_TEST_LOCK)(void **user_lock) {
1166345153Sdim#ifdef KMP_STUB
1167345153Sdim  if (*((kmp_stub_lock_t *)user_lock) == UNINIT) {
1168345153Sdim    // TODO: Issue an error.
1169345153Sdim  }
1170345153Sdim  if (*((kmp_stub_lock_t *)user_lock) == LOCKED) {
1171345153Sdim    return 0;
1172345153Sdim  }
1173345153Sdim  *((kmp_stub_lock_t *)user_lock) = LOCKED;
1174345153Sdim  return 1;
1175345153Sdim#else
1176345153Sdim  int gtid = __kmp_entry_gtid();
1177345153Sdim#if OMPT_SUPPORT && OMPT_OPTIONAL
1178345153Sdim  OMPT_STORE_RETURN_ADDRESS(gtid);
1179345153Sdim#endif
1180345153Sdim  return __kmpc_test_lock(NULL, gtid, user_lock);
1181345153Sdim#endif
1182345153Sdim}
1183345153Sdim
1184345153Sdimint FTN_STDCALL KMP_EXPAND_NAME(FTN_TEST_NEST_LOCK)(void **user_lock) {
1185345153Sdim#ifdef KMP_STUB
1186345153Sdim  if (*((kmp_stub_lock_t *)user_lock) == UNINIT) {
1187345153Sdim    // TODO: Issue an error.
1188345153Sdim  }
1189345153Sdim  return ++(*((int *)user_lock));
1190345153Sdim#else
1191345153Sdim  int gtid = __kmp_entry_gtid();
1192345153Sdim#if OMPT_SUPPORT && OMPT_OPTIONAL
1193345153Sdim  OMPT_STORE_RETURN_ADDRESS(gtid);
1194345153Sdim#endif
1195345153Sdim  return __kmpc_test_nest_lock(NULL, gtid, user_lock);
1196345153Sdim#endif
1197345153Sdim}
1198345153Sdim
1199345153Sdimdouble FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_WTIME)(void) {
1200345153Sdim#ifdef KMP_STUB
1201345153Sdim  return __kmps_get_wtime();
1202345153Sdim#else
1203345153Sdim  double data;
1204345153Sdim#if !KMP_OS_LINUX
1205345153Sdim  // We don't need library initialization to get the time on Linux* OS. The
1206345153Sdim  // routine can be used to measure library initialization time on Linux* OS now
1207345153Sdim  if (!__kmp_init_serial) {
1208345153Sdim    __kmp_serial_initialize();
1209345153Sdim  }
1210345153Sdim#endif
1211345153Sdim  __kmp_elapsed(&data);
1212345153Sdim  return data;
1213345153Sdim#endif
1214345153Sdim}
1215345153Sdim
1216345153Sdimdouble FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_WTICK)(void) {
1217345153Sdim#ifdef KMP_STUB
1218345153Sdim  return __kmps_get_wtick();
1219345153Sdim#else
1220345153Sdim  double data;
1221345153Sdim  if (!__kmp_init_serial) {
1222345153Sdim    __kmp_serial_initialize();
1223345153Sdim  }
1224345153Sdim  __kmp_elapsed_tick(&data);
1225345153Sdim  return data;
1226345153Sdim#endif
1227345153Sdim}
1228345153Sdim
1229345153Sdim/* ------------------------------------------------------------------------ */
1230345153Sdim
1231345153Sdimvoid *FTN_STDCALL FTN_MALLOC(size_t KMP_DEREF size) {
1232345153Sdim  // kmpc_malloc initializes the library if needed
1233345153Sdim  return kmpc_malloc(KMP_DEREF size);
1234345153Sdim}
1235345153Sdim
1236345153Sdimvoid *FTN_STDCALL FTN_ALIGNED_MALLOC(size_t KMP_DEREF size,
1237345153Sdim                                     size_t KMP_DEREF alignment) {
1238345153Sdim  // kmpc_aligned_malloc initializes the library if needed
1239345153Sdim  return kmpc_aligned_malloc(KMP_DEREF size, KMP_DEREF alignment);
1240345153Sdim}
1241345153Sdim
1242345153Sdimvoid *FTN_STDCALL FTN_CALLOC(size_t KMP_DEREF nelem, size_t KMP_DEREF elsize) {
1243345153Sdim  // kmpc_calloc initializes the library if needed
1244345153Sdim  return kmpc_calloc(KMP_DEREF nelem, KMP_DEREF elsize);
1245345153Sdim}
1246345153Sdim
1247345153Sdimvoid *FTN_STDCALL FTN_REALLOC(void *KMP_DEREF ptr, size_t KMP_DEREF size) {
1248345153Sdim  // kmpc_realloc initializes the library if needed
1249345153Sdim  return kmpc_realloc(KMP_DEREF ptr, KMP_DEREF size);
1250345153Sdim}
1251345153Sdim
1252345153Sdimvoid FTN_STDCALL FTN_KFREE(void *KMP_DEREF ptr) {
1253345153Sdim  // does nothing if the library is not initialized
1254345153Sdim  kmpc_free(KMP_DEREF ptr);
1255345153Sdim}
1256345153Sdim
1257345153Sdimvoid FTN_STDCALL FTN_SET_WARNINGS_ON(void) {
1258345153Sdim#ifndef KMP_STUB
1259345153Sdim  __kmp_generate_warnings = kmp_warnings_explicit;
1260345153Sdim#endif
1261345153Sdim}
1262345153Sdim
1263345153Sdimvoid FTN_STDCALL FTN_SET_WARNINGS_OFF(void) {
1264345153Sdim#ifndef KMP_STUB
1265345153Sdim  __kmp_generate_warnings = FALSE;
1266345153Sdim#endif
1267345153Sdim}
1268345153Sdim
1269345153Sdimvoid FTN_STDCALL FTN_SET_DEFAULTS(char const *str
1270345153Sdim#ifndef PASS_ARGS_BY_VALUE
1271345153Sdim                                  ,
1272345153Sdim                                  int len
1273345153Sdim#endif
1274345153Sdim                                  ) {
1275345153Sdim#ifndef KMP_STUB
1276345153Sdim#ifdef PASS_ARGS_BY_VALUE
1277345153Sdim  int len = (int)KMP_STRLEN(str);
1278345153Sdim#endif
1279345153Sdim  __kmp_aux_set_defaults(str, len);
1280345153Sdim#endif
1281345153Sdim}
1282345153Sdim
1283345153Sdim/* ------------------------------------------------------------------------ */
1284345153Sdim
1285345153Sdim/* returns the status of cancellation */
1286345153Sdimint FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_CANCELLATION)(void) {
1287345153Sdim#ifdef KMP_STUB
1288345153Sdim  return 0 /* false */;
1289345153Sdim#else
1290345153Sdim  // initialize the library if needed
1291345153Sdim  if (!__kmp_init_serial) {
1292345153Sdim    __kmp_serial_initialize();
1293345153Sdim  }
1294345153Sdim  return __kmp_omp_cancellation;
1295345153Sdim#endif
1296345153Sdim}
1297345153Sdim
1298345153Sdimint FTN_STDCALL FTN_GET_CANCELLATION_STATUS(int cancel_kind) {
1299345153Sdim#ifdef KMP_STUB
1300345153Sdim  return 0 /* false */;
1301345153Sdim#else
1302345153Sdim  return __kmp_get_cancellation_status(cancel_kind);
1303345153Sdim#endif
1304345153Sdim}
1305345153Sdim
1306345153Sdim/* returns the maximum allowed task priority */
1307345153Sdimint FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_MAX_TASK_PRIORITY)(void) {
1308345153Sdim#ifdef KMP_STUB
1309345153Sdim  return 0;
1310345153Sdim#else
1311345153Sdim  if (!__kmp_init_serial) {
1312345153Sdim    __kmp_serial_initialize();
1313345153Sdim  }
1314345153Sdim  return __kmp_max_task_priority;
1315345153Sdim#endif
1316345153Sdim}
1317345153Sdim
1318345153Sdim// This function will be defined in libomptarget. When libomptarget is not
1319345153Sdim// loaded, we assume we are on the host and return KMP_HOST_DEVICE.
1320345153Sdim// Compiler/libomptarget will handle this if called inside target.
1321345153Sdimint FTN_STDCALL FTN_GET_DEVICE_NUM(void) KMP_WEAK_ATTRIBUTE;
1322345153Sdimint FTN_STDCALL FTN_GET_DEVICE_NUM(void) { return KMP_HOST_DEVICE; }
1323345153Sdim
1324353358Sdim// Compiler will ensure that this is only called from host in sequential region
1325353358Sdimint FTN_STDCALL FTN_PAUSE_RESOURCE(kmp_pause_status_t kind, int device_num) {
1326353358Sdim#ifdef KMP_STUB
1327353358Sdim  return 1; // just fail
1328353358Sdim#else
1329353358Sdim  if (device_num == KMP_HOST_DEVICE)
1330353358Sdim    return __kmpc_pause_resource(kind);
1331353358Sdim  else {
1332353358Sdim#if !KMP_OS_WINDOWS
1333353358Sdim    int (*fptr)(kmp_pause_status_t, int);
1334353358Sdim    if ((*(void **)(&fptr) = dlsym(RTLD_DEFAULT, "tgt_pause_resource")))
1335353358Sdim      return (*fptr)(kind, device_num);
1336353358Sdim    else
1337353358Sdim#endif
1338353358Sdim      return 1; // just fail if there is no libomptarget
1339353358Sdim  }
1340353358Sdim#endif
1341353358Sdim}
1342353358Sdim
1343353358Sdim// Compiler will ensure that this is only called from host in sequential region
1344353358Sdimint FTN_STDCALL FTN_PAUSE_RESOURCE_ALL(kmp_pause_status_t kind) {
1345353358Sdim#ifdef KMP_STUB
1346353358Sdim  return 1; // just fail
1347353358Sdim#else
1348353358Sdim  int fails = 0;
1349353358Sdim#if !KMP_OS_WINDOWS
1350353358Sdim  int (*fptr)(kmp_pause_status_t, int);
1351353358Sdim  if ((*(void **)(&fptr) = dlsym(RTLD_DEFAULT, "tgt_pause_resource")))
1352353358Sdim    fails = (*fptr)(kind, KMP_DEVICE_ALL); // pause devices
1353353358Sdim#endif
1354353358Sdim  fails += __kmpc_pause_resource(kind); // pause host
1355353358Sdim  return fails;
1356353358Sdim#endif
1357353358Sdim}
1358353358Sdim
1359353358Sdim// Returns the maximum number of nesting levels supported by implementation
1360353358Sdimint FTN_STDCALL FTN_GET_SUPPORTED_ACTIVE_LEVELS(void) {
1361353358Sdim#ifdef KMP_STUB
1362353358Sdim  return 1;
1363353358Sdim#else
1364353358Sdim  return KMP_MAX_ACTIVE_LEVELS_LIMIT;
1365353358Sdim#endif
1366353358Sdim}
1367353358Sdim
1368353358Sdimvoid FTN_STDCALL FTN_FULFILL_EVENT(kmp_event_t *event) {
1369353358Sdim#ifndef KMP_STUB
1370353358Sdim  __kmp_fulfill_event(event);
1371353358Sdim#endif
1372353358Sdim}
1373353358Sdim
1374345153Sdim// GCC compatibility (versioned symbols)
1375345153Sdim#ifdef KMP_USE_VERSION_SYMBOLS
1376345153Sdim
1377345153Sdim/* These following sections create versioned symbols for the
1378345153Sdim   omp_* routines. The KMP_VERSION_SYMBOL macro expands the API name and
1379345153Sdim   then maps it to a versioned symbol.
1380345153Sdim   libgomp ``versions'' its symbols (OMP_1.0, OMP_2.0, OMP_3.0, ...) while also
1381345153Sdim   retaining the default version which libomp uses: VERSION (defined in
1382345153Sdim   exports_so.txt). If you want to see the versioned symbols for libgomp.so.1
1383345153Sdim   then just type:
1384345153Sdim
1385345153Sdim   objdump -T /path/to/libgomp.so.1 | grep omp_
1386345153Sdim
1387345153Sdim   Example:
1388345153Sdim   Step 1) Create __kmp_api_omp_set_num_threads_10_alias which is alias of
1389345153Sdim     __kmp_api_omp_set_num_threads
1390345153Sdim   Step 2) Set __kmp_api_omp_set_num_threads_10_alias to version:
1391345153Sdim     omp_set_num_threads@OMP_1.0
1392345153Sdim   Step 2B) Set __kmp_api_omp_set_num_threads to default version:
1393345153Sdim     omp_set_num_threads@@VERSION
1394345153Sdim*/
1395345153Sdim
1396345153Sdim// OMP_1.0 versioned symbols
1397345153SdimKMP_VERSION_SYMBOL(FTN_SET_NUM_THREADS, 10, "OMP_1.0");
1398345153SdimKMP_VERSION_SYMBOL(FTN_GET_NUM_THREADS, 10, "OMP_1.0");
1399345153SdimKMP_VERSION_SYMBOL(FTN_GET_MAX_THREADS, 10, "OMP_1.0");
1400345153SdimKMP_VERSION_SYMBOL(FTN_GET_THREAD_NUM, 10, "OMP_1.0");
1401345153SdimKMP_VERSION_SYMBOL(FTN_GET_NUM_PROCS, 10, "OMP_1.0");
1402345153SdimKMP_VERSION_SYMBOL(FTN_IN_PARALLEL, 10, "OMP_1.0");
1403345153SdimKMP_VERSION_SYMBOL(FTN_SET_DYNAMIC, 10, "OMP_1.0");
1404345153SdimKMP_VERSION_SYMBOL(FTN_GET_DYNAMIC, 10, "OMP_1.0");
1405345153SdimKMP_VERSION_SYMBOL(FTN_SET_NESTED, 10, "OMP_1.0");
1406345153SdimKMP_VERSION_SYMBOL(FTN_GET_NESTED, 10, "OMP_1.0");
1407345153SdimKMP_VERSION_SYMBOL(FTN_INIT_LOCK, 10, "OMP_1.0");
1408345153SdimKMP_VERSION_SYMBOL(FTN_INIT_NEST_LOCK, 10, "OMP_1.0");
1409345153SdimKMP_VERSION_SYMBOL(FTN_DESTROY_LOCK, 10, "OMP_1.0");
1410345153SdimKMP_VERSION_SYMBOL(FTN_DESTROY_NEST_LOCK, 10, "OMP_1.0");
1411345153SdimKMP_VERSION_SYMBOL(FTN_SET_LOCK, 10, "OMP_1.0");
1412345153SdimKMP_VERSION_SYMBOL(FTN_SET_NEST_LOCK, 10, "OMP_1.0");
1413345153SdimKMP_VERSION_SYMBOL(FTN_UNSET_LOCK, 10, "OMP_1.0");
1414345153SdimKMP_VERSION_SYMBOL(FTN_UNSET_NEST_LOCK, 10, "OMP_1.0");
1415345153SdimKMP_VERSION_SYMBOL(FTN_TEST_LOCK, 10, "OMP_1.0");
1416345153SdimKMP_VERSION_SYMBOL(FTN_TEST_NEST_LOCK, 10, "OMP_1.0");
1417345153Sdim
1418345153Sdim// OMP_2.0 versioned symbols
1419345153SdimKMP_VERSION_SYMBOL(FTN_GET_WTICK, 20, "OMP_2.0");
1420345153SdimKMP_VERSION_SYMBOL(FTN_GET_WTIME, 20, "OMP_2.0");
1421345153Sdim
1422345153Sdim// OMP_3.0 versioned symbols
1423345153SdimKMP_VERSION_SYMBOL(FTN_SET_SCHEDULE, 30, "OMP_3.0");
1424345153SdimKMP_VERSION_SYMBOL(FTN_GET_SCHEDULE, 30, "OMP_3.0");
1425345153SdimKMP_VERSION_SYMBOL(FTN_GET_THREAD_LIMIT, 30, "OMP_3.0");
1426345153SdimKMP_VERSION_SYMBOL(FTN_SET_MAX_ACTIVE_LEVELS, 30, "OMP_3.0");
1427345153SdimKMP_VERSION_SYMBOL(FTN_GET_MAX_ACTIVE_LEVELS, 30, "OMP_3.0");
1428345153SdimKMP_VERSION_SYMBOL(FTN_GET_ANCESTOR_THREAD_NUM, 30, "OMP_3.0");
1429345153SdimKMP_VERSION_SYMBOL(FTN_GET_LEVEL, 30, "OMP_3.0");
1430345153SdimKMP_VERSION_SYMBOL(FTN_GET_TEAM_SIZE, 30, "OMP_3.0");
1431345153SdimKMP_VERSION_SYMBOL(FTN_GET_ACTIVE_LEVEL, 30, "OMP_3.0");
1432345153Sdim
1433345153Sdim// the lock routines have a 1.0 and 3.0 version
1434345153SdimKMP_VERSION_SYMBOL(FTN_INIT_LOCK, 30, "OMP_3.0");
1435345153SdimKMP_VERSION_SYMBOL(FTN_INIT_NEST_LOCK, 30, "OMP_3.0");
1436345153SdimKMP_VERSION_SYMBOL(FTN_DESTROY_LOCK, 30, "OMP_3.0");
1437345153SdimKMP_VERSION_SYMBOL(FTN_DESTROY_NEST_LOCK, 30, "OMP_3.0");
1438345153SdimKMP_VERSION_SYMBOL(FTN_SET_LOCK, 30, "OMP_3.0");
1439345153SdimKMP_VERSION_SYMBOL(FTN_SET_NEST_LOCK, 30, "OMP_3.0");
1440345153SdimKMP_VERSION_SYMBOL(FTN_UNSET_LOCK, 30, "OMP_3.0");
1441345153SdimKMP_VERSION_SYMBOL(FTN_UNSET_NEST_LOCK, 30, "OMP_3.0");
1442345153SdimKMP_VERSION_SYMBOL(FTN_TEST_LOCK, 30, "OMP_3.0");
1443345153SdimKMP_VERSION_SYMBOL(FTN_TEST_NEST_LOCK, 30, "OMP_3.0");
1444345153Sdim
1445345153Sdim// OMP_3.1 versioned symbol
1446345153SdimKMP_VERSION_SYMBOL(FTN_IN_FINAL, 31, "OMP_3.1");
1447345153Sdim
1448345153Sdim// OMP_4.0 versioned symbols
1449345153SdimKMP_VERSION_SYMBOL(FTN_GET_PROC_BIND, 40, "OMP_4.0");
1450345153SdimKMP_VERSION_SYMBOL(FTN_GET_NUM_TEAMS, 40, "OMP_4.0");
1451345153SdimKMP_VERSION_SYMBOL(FTN_GET_TEAM_NUM, 40, "OMP_4.0");
1452345153SdimKMP_VERSION_SYMBOL(FTN_GET_CANCELLATION, 40, "OMP_4.0");
1453345153SdimKMP_VERSION_SYMBOL(FTN_GET_DEFAULT_DEVICE, 40, "OMP_4.0");
1454345153SdimKMP_VERSION_SYMBOL(FTN_SET_DEFAULT_DEVICE, 40, "OMP_4.0");
1455345153SdimKMP_VERSION_SYMBOL(FTN_IS_INITIAL_DEVICE, 40, "OMP_4.0");
1456345153SdimKMP_VERSION_SYMBOL(FTN_GET_NUM_DEVICES, 40, "OMP_4.0");
1457345153Sdim
1458345153Sdim// OMP_4.5 versioned symbols
1459345153SdimKMP_VERSION_SYMBOL(FTN_GET_MAX_TASK_PRIORITY, 45, "OMP_4.5");
1460345153SdimKMP_VERSION_SYMBOL(FTN_GET_NUM_PLACES, 45, "OMP_4.5");
1461345153SdimKMP_VERSION_SYMBOL(FTN_GET_PLACE_NUM_PROCS, 45, "OMP_4.5");
1462345153SdimKMP_VERSION_SYMBOL(FTN_GET_PLACE_PROC_IDS, 45, "OMP_4.5");
1463345153SdimKMP_VERSION_SYMBOL(FTN_GET_PLACE_NUM, 45, "OMP_4.5");
1464345153SdimKMP_VERSION_SYMBOL(FTN_GET_PARTITION_NUM_PLACES, 45, "OMP_4.5");
1465345153SdimKMP_VERSION_SYMBOL(FTN_GET_PARTITION_PLACE_NUMS, 45, "OMP_4.5");
1466345153Sdim// KMP_VERSION_SYMBOL(FTN_GET_INITIAL_DEVICE, 45, "OMP_4.5");
1467345153Sdim
1468345153Sdim// OMP_5.0 versioned symbols
1469345153Sdim// KMP_VERSION_SYMBOL(FTN_GET_DEVICE_NUM, 50, "OMP_5.0");
1470353358Sdim// KMP_VERSION_SYMBOL(FTN_PAUSE_RESOURCE, 50, "OMP_5.0");
1471353358Sdim// KMP_VERSION_SYMBOL(FTN_PAUSE_RESOURCE_ALL, 50, "OMP_5.0");
1472353358Sdim// KMP_VERSION_SYMBOL(FTN_GET_SUPPORTED_ACTIVE_LEVELS, 50, "OMP_5.0");
1473353358Sdim// KMP_VERSION_SYMBOL(FTN_FULFILL_EVENT, 50, "OMP_5.0");
1474345153Sdim
1475345153Sdim#endif // KMP_USE_VERSION_SYMBOLS
1476345153Sdim
1477345153Sdim#ifdef __cplusplus
1478345153Sdim} // extern "C"
1479345153Sdim#endif // __cplusplus
1480345153Sdim
1481345153Sdim// end of file //
1482