2 * kmp_ftn_entry.h -- Fortran entry linkage support for OpenMP.
5 //===----------------------------------------------------------------------===//
7 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
8 // See https://llvm.org/LICENSE.txt for license information.
9 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
11 //===----------------------------------------------------------------------===//
14 #error The support file kmp_ftn_entry.h should not be compiled by itself.
23 // For affinity format functions
28 #include "ompt-specific.h"
35 /* For compatibility with the Gnu/MS Open MP codegen, omp_set_num_threads(),
36 * omp_set_nested(), and omp_set_dynamic() [in lowercase on MS, and w/o
37 * a trailing underscore on Linux* OS] take call by value integer arguments.
38 * + omp_set_max_active_levels()
39 * + omp_set_schedule()
41 * For backward compatibility with 9.1 and previous Intel compiler, these
42 * entry points take call by reference integer arguments. */
43 #ifdef KMP_GOMP_COMPAT
44 #if (KMP_FTN_ENTRIES == KMP_FTN_PLAIN) || (KMP_FTN_ENTRIES == KMP_FTN_UPPER)
45 #define PASS_ARGS_BY_VALUE 1
49 #if (KMP_FTN_ENTRIES == KMP_FTN_PLAIN) || (KMP_FTN_ENTRIES == KMP_FTN_APPEND)
50 #define PASS_ARGS_BY_VALUE 1
54 // This macro helps to reduce code duplication.
55 #ifdef PASS_ARGS_BY_VALUE
61 // For API with specific C vs. Fortran interfaces (ompc_* exists in
62 // kmp_csupport.cpp), only create GOMP versioned symbols of the API for the
63 // APPEND Fortran entries in this file. The GOMP versioned symbols of the C API
64 // will take place where the ompc_* functions are defined.
65 #if KMP_FTN_ENTRIES == KMP_FTN_APPEND
66 #define KMP_EXPAND_NAME_IF_APPEND(name) KMP_EXPAND_NAME(name)
68 #define KMP_EXPAND_NAME_IF_APPEND(name) name
71 void FTN_STDCALL
FTN_SET_STACKSIZE(int KMP_DEREF arg
) {
73 __kmps_set_stacksize(KMP_DEREF arg
);
75 // __kmp_aux_set_stacksize initializes the library if needed
76 __kmp_aux_set_stacksize((size_t)KMP_DEREF arg
);
80 void FTN_STDCALL
FTN_SET_STACKSIZE_S(size_t KMP_DEREF arg
) {
82 __kmps_set_stacksize(KMP_DEREF arg
);
84 // __kmp_aux_set_stacksize initializes the library if needed
85 __kmp_aux_set_stacksize(KMP_DEREF arg
);
89 int FTN_STDCALL
FTN_GET_STACKSIZE(void) {
91 return (int)__kmps_get_stacksize();
93 if (!__kmp_init_serial
) {
94 __kmp_serial_initialize();
96 return (int)__kmp_stksize
;
100 size_t FTN_STDCALL
FTN_GET_STACKSIZE_S(void) {
102 return __kmps_get_stacksize();
104 if (!__kmp_init_serial
) {
105 __kmp_serial_initialize();
107 return __kmp_stksize
;
111 void FTN_STDCALL
FTN_SET_BLOCKTIME(int KMP_DEREF arg
) {
113 __kmps_set_blocktime(KMP_DEREF arg
);
115 int gtid
, tid
, bt
= (KMP_DEREF arg
);
118 gtid
= __kmp_entry_gtid();
119 tid
= __kmp_tid_from_gtid(gtid
);
120 thread
= __kmp_thread_from_gtid(gtid
);
122 __kmp_aux_convert_blocktime(&bt
);
123 __kmp_aux_set_blocktime(bt
, thread
, tid
);
127 // Gets blocktime in units used for KMP_BLOCKTIME, ms otherwise
128 int FTN_STDCALL
FTN_GET_BLOCKTIME(void) {
130 return __kmps_get_blocktime();
135 gtid
= __kmp_entry_gtid();
136 tid
= __kmp_tid_from_gtid(gtid
);
137 team
= __kmp_threads
[gtid
]->th
.th_team
;
139 /* These must match the settings used in __kmp_wait_sleep() */
140 if (__kmp_dflt_blocktime
== KMP_MAX_BLOCKTIME
) {
141 KF_TRACE(10, ("kmp_get_blocktime: T#%d(%d:%d), blocktime=%d%cs\n", gtid
,
142 team
->t
.t_id
, tid
, KMP_MAX_BLOCKTIME
, __kmp_blocktime_units
));
143 return KMP_MAX_BLOCKTIME
;
145 #ifdef KMP_ADJUST_BLOCKTIME
146 else if (__kmp_zero_bt
&& !get__bt_set(team
, tid
)) {
147 KF_TRACE(10, ("kmp_get_blocktime: T#%d(%d:%d), blocktime=%d%cs\n", gtid
,
148 team
->t
.t_id
, tid
, 0, __kmp_blocktime_units
));
151 #endif /* KMP_ADJUST_BLOCKTIME */
153 int bt
= get__blocktime(team
, tid
);
154 if (__kmp_blocktime_units
== 'm')
156 KF_TRACE(10, ("kmp_get_blocktime: T#%d(%d:%d), blocktime=%d%cs\n", gtid
,
157 team
->t
.t_id
, tid
, bt
, __kmp_blocktime_units
));
163 void FTN_STDCALL
FTN_SET_LIBRARY_SERIAL(void) {
165 __kmps_set_library(library_serial
);
167 // __kmp_user_set_library initializes the library if needed
168 __kmp_user_set_library(library_serial
);
172 void FTN_STDCALL
FTN_SET_LIBRARY_TURNAROUND(void) {
174 __kmps_set_library(library_turnaround
);
176 // __kmp_user_set_library initializes the library if needed
177 __kmp_user_set_library(library_turnaround
);
181 void FTN_STDCALL
FTN_SET_LIBRARY_THROUGHPUT(void) {
183 __kmps_set_library(library_throughput
);
185 // __kmp_user_set_library initializes the library if needed
186 __kmp_user_set_library(library_throughput
);
190 void FTN_STDCALL
FTN_SET_LIBRARY(int KMP_DEREF arg
) {
192 __kmps_set_library(KMP_DEREF arg
);
194 enum library_type lib
;
195 lib
= (enum library_type
)KMP_DEREF arg
;
196 // __kmp_user_set_library initializes the library if needed
197 __kmp_user_set_library(lib
);
201 int FTN_STDCALL
FTN_GET_LIBRARY(void) {
203 return __kmps_get_library();
205 if (!__kmp_init_serial
) {
206 __kmp_serial_initialize();
208 return ((int)__kmp_library
);
212 void FTN_STDCALL
FTN_SET_DISP_NUM_BUFFERS(int KMP_DEREF arg
) {
216 // ignore after initialization because some teams have already
217 // allocated dispatch buffers
218 int num_buffers
= KMP_DEREF arg
;
219 if (__kmp_init_serial
== FALSE
&& num_buffers
>= KMP_MIN_DISP_NUM_BUFF
&&
220 num_buffers
<= KMP_MAX_DISP_NUM_BUFF
) {
221 __kmp_dispatch_num_buffers
= num_buffers
;
226 int FTN_STDCALL
FTN_SET_AFFINITY(void **mask
) {
227 #if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
230 if (!TCR_4(__kmp_init_middle
)) {
231 __kmp_middle_initialize();
233 __kmp_assign_root_init_mask();
234 return __kmp_aux_set_affinity(mask
);
238 int FTN_STDCALL
FTN_GET_AFFINITY(void **mask
) {
239 #if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
242 if (!TCR_4(__kmp_init_middle
)) {
243 __kmp_middle_initialize();
245 __kmp_assign_root_init_mask();
246 int gtid
= __kmp_get_gtid();
247 if (__kmp_threads
[gtid
]->th
.th_team
->t
.t_level
== 0 &&
248 __kmp_affinity
.flags
.reset
) {
249 __kmp_reset_root_init_mask(gtid
);
251 return __kmp_aux_get_affinity(mask
);
255 int FTN_STDCALL
FTN_GET_AFFINITY_MAX_PROC(void) {
256 #if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
259 // We really only NEED serial initialization here.
260 if (!TCR_4(__kmp_init_middle
)) {
261 __kmp_middle_initialize();
263 __kmp_assign_root_init_mask();
264 return __kmp_aux_get_affinity_max_proc();
268 void FTN_STDCALL
FTN_CREATE_AFFINITY_MASK(void **mask
) {
269 #if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
272 // We really only NEED serial initialization here.
273 kmp_affin_mask_t
*mask_internals
;
274 if (!TCR_4(__kmp_init_middle
)) {
275 __kmp_middle_initialize();
277 __kmp_assign_root_init_mask();
278 mask_internals
= __kmp_affinity_dispatch
->allocate_mask();
279 KMP_CPU_ZERO(mask_internals
);
280 *mask
= mask_internals
;
284 void FTN_STDCALL
FTN_DESTROY_AFFINITY_MASK(void **mask
) {
285 #if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
288 // We really only NEED serial initialization here.
289 kmp_affin_mask_t
*mask_internals
;
290 if (!TCR_4(__kmp_init_middle
)) {
291 __kmp_middle_initialize();
293 __kmp_assign_root_init_mask();
294 if (__kmp_env_consistency_check
) {
296 KMP_FATAL(AffinityInvalidMask
, "kmp_destroy_affinity_mask");
299 mask_internals
= (kmp_affin_mask_t
*)(*mask
);
300 __kmp_affinity_dispatch
->deallocate_mask(mask_internals
);
305 int FTN_STDCALL
FTN_SET_AFFINITY_MASK_PROC(int KMP_DEREF proc
, void **mask
) {
306 #if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
309 if (!TCR_4(__kmp_init_middle
)) {
310 __kmp_middle_initialize();
312 __kmp_assign_root_init_mask();
313 return __kmp_aux_set_affinity_mask_proc(KMP_DEREF proc
, mask
);
317 int FTN_STDCALL
FTN_UNSET_AFFINITY_MASK_PROC(int KMP_DEREF proc
, void **mask
) {
318 #if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
321 if (!TCR_4(__kmp_init_middle
)) {
322 __kmp_middle_initialize();
324 __kmp_assign_root_init_mask();
325 return __kmp_aux_unset_affinity_mask_proc(KMP_DEREF proc
, mask
);
329 int FTN_STDCALL
FTN_GET_AFFINITY_MASK_PROC(int KMP_DEREF proc
, void **mask
) {
330 #if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
333 if (!TCR_4(__kmp_init_middle
)) {
334 __kmp_middle_initialize();
336 __kmp_assign_root_init_mask();
337 return __kmp_aux_get_affinity_mask_proc(KMP_DEREF proc
, mask
);
341 /* ------------------------------------------------------------------------ */
343 /* sets the requested number of threads for the next parallel region */
344 void FTN_STDCALL
KMP_EXPAND_NAME(FTN_SET_NUM_THREADS
)(int KMP_DEREF arg
) {
348 __kmp_set_num_threads(KMP_DEREF arg
, __kmp_entry_gtid());
352 /* returns the number of threads in current team */
353 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_GET_NUM_THREADS
)(void) {
357 // __kmpc_bound_num_threads initializes the library if needed
358 return __kmpc_bound_num_threads(NULL
);
362 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_GET_MAX_THREADS
)(void) {
368 if (!TCR_4(__kmp_init_middle
)) {
369 __kmp_middle_initialize();
371 gtid
= __kmp_entry_gtid();
372 thread
= __kmp_threads
[gtid
];
373 #if KMP_AFFINITY_SUPPORTED
374 if (thread
->th
.th_team
->t
.t_level
== 0 && !__kmp_affinity
.flags
.reset
) {
375 __kmp_assign_root_init_mask();
378 // return thread -> th.th_team -> t.t_current_task[
379 // thread->th.th_info.ds.ds_tid ] -> icvs.nproc;
380 return thread
->th
.th_current_task
->td_icvs
.nproc
;
384 int FTN_STDCALL
FTN_CONTROL_TOOL(int command
, int modifier
, void *arg
) {
385 #if defined(KMP_STUB) || !OMPT_SUPPORT
388 OMPT_STORE_RETURN_ADDRESS(__kmp_entry_gtid());
389 if (!TCR_4(__kmp_init_middle
)) {
392 kmp_info_t
*this_thr
= __kmp_threads
[__kmp_entry_gtid()];
393 ompt_task_info_t
*parent_task_info
= OMPT_CUR_TASK_INFO(this_thr
);
394 parent_task_info
->frame
.enter_frame
.ptr
= OMPT_GET_FRAME_ADDRESS(0);
395 int ret
= __kmp_control_tool(command
, modifier
, arg
);
396 parent_task_info
->frame
.enter_frame
.ptr
= 0;
401 /* OpenMP 5.0 Memory Management support */
402 omp_allocator_handle_t FTN_STDCALL
403 FTN_INIT_ALLOCATOR(omp_memspace_handle_t KMP_DEREF m
, int KMP_DEREF ntraits
,
404 omp_alloctrait_t tr
[]) {
408 return __kmpc_init_allocator(__kmp_entry_gtid(), KMP_DEREF m
,
409 KMP_DEREF ntraits
, tr
);
413 void FTN_STDCALL
FTN_DESTROY_ALLOCATOR(omp_allocator_handle_t al
) {
415 __kmpc_destroy_allocator(__kmp_entry_gtid(), al
);
418 void FTN_STDCALL
FTN_SET_DEFAULT_ALLOCATOR(omp_allocator_handle_t al
) {
420 __kmpc_set_default_allocator(__kmp_entry_gtid(), al
);
423 omp_allocator_handle_t FTN_STDCALL
FTN_GET_DEFAULT_ALLOCATOR(void) {
427 return __kmpc_get_default_allocator(__kmp_entry_gtid());
431 /* OpenMP 5.0 affinity format support */
433 static void __kmp_fortran_strncpy_truncate(char *buffer
, size_t buf_size
,
434 char const *csrc
, size_t csrc_size
) {
435 size_t capped_src_size
= csrc_size
;
436 if (csrc_size
>= buf_size
) {
437 capped_src_size
= buf_size
- 1;
439 KMP_STRNCPY_S(buffer
, buf_size
, csrc
, capped_src_size
);
440 if (csrc_size
>= buf_size
) {
441 KMP_DEBUG_ASSERT(buffer
[buf_size
- 1] == '\0');
442 buffer
[buf_size
- 1] = csrc
[buf_size
- 1];
444 for (size_t i
= csrc_size
; i
< buf_size
; ++i
)
449 // Convert a Fortran string to a C string by adding null byte
450 class ConvertedString
{
455 ConvertedString(char const *fortran_str
, size_t size
) {
456 th
= __kmp_get_thread();
457 buf
= (char *)__kmp_thread_malloc(th
, size
+ 1);
458 KMP_STRNCPY_S(buf
, size
+ 1, fortran_str
, size
);
461 ~ConvertedString() { __kmp_thread_free(th
, buf
); }
462 const char *get() const { return buf
; }
467 * Set the value of the affinity-format-var ICV on the current device to the
468 * format specified in the argument.
470 void FTN_STDCALL
KMP_EXPAND_NAME_IF_APPEND(FTN_SET_AFFINITY_FORMAT
)(
471 char const *format
, size_t size
) {
475 if (!__kmp_init_serial
) {
476 __kmp_serial_initialize();
478 ConvertedString
cformat(format
, size
);
479 // Since the __kmp_affinity_format variable is a C string, do not
480 // use the fortran strncpy function
481 __kmp_strncpy_truncate(__kmp_affinity_format
, KMP_AFFINITY_FORMAT_SIZE
,
482 cformat
.get(), KMP_STRLEN(cformat
.get()));
487 * Returns the number of characters required to hold the entire affinity format
488 * specification (not including null byte character) and writes the value of the
489 * affinity-format-var ICV on the current device to buffer. If the return value
490 * is larger than size, the affinity format specification is truncated.
492 size_t FTN_STDCALL
KMP_EXPAND_NAME_IF_APPEND(FTN_GET_AFFINITY_FORMAT
)(
493 char *buffer
, size_t size
) {
498 if (!__kmp_init_serial
) {
499 __kmp_serial_initialize();
501 format_size
= KMP_STRLEN(__kmp_affinity_format
);
502 if (buffer
&& size
) {
503 __kmp_fortran_strncpy_truncate(buffer
, size
, __kmp_affinity_format
,
511 * Prints the thread affinity information of the current thread in the format
512 * specified by the format argument. If the format is NULL or a zero-length
513 * string, the value of the affinity-format-var ICV is used.
515 void FTN_STDCALL
KMP_EXPAND_NAME_IF_APPEND(FTN_DISPLAY_AFFINITY
)(
516 char const *format
, size_t size
) {
521 if (!TCR_4(__kmp_init_middle
)) {
522 __kmp_middle_initialize();
524 __kmp_assign_root_init_mask();
525 gtid
= __kmp_get_gtid();
526 #if KMP_AFFINITY_SUPPORTED
527 if (__kmp_threads
[gtid
]->th
.th_team
->t
.t_level
== 0 &&
528 __kmp_affinity
.flags
.reset
) {
529 __kmp_reset_root_init_mask(gtid
);
532 ConvertedString
cformat(format
, size
);
533 __kmp_aux_display_affinity(gtid
, cformat
.get());
538 * Returns the number of characters required to hold the entire affinity format
539 * specification (not including null byte) and prints the thread affinity
540 * information of the current thread into the character string buffer with the
541 * size of size in the format specified by the format argument. If the format is
542 * NULL or a zero-length string, the value of the affinity-format-var ICV is
543 * used. The buffer must be allocated prior to calling the routine. If the
544 * return value is larger than size, the affinity format specification is
547 size_t FTN_STDCALL
KMP_EXPAND_NAME_IF_APPEND(FTN_CAPTURE_AFFINITY
)(
548 char *buffer
, char const *format
, size_t buf_size
, size_t for_size
) {
549 #if defined(KMP_STUB)
554 kmp_str_buf_t capture_buf
;
555 if (!TCR_4(__kmp_init_middle
)) {
556 __kmp_middle_initialize();
558 __kmp_assign_root_init_mask();
559 gtid
= __kmp_get_gtid();
560 #if KMP_AFFINITY_SUPPORTED
561 if (__kmp_threads
[gtid
]->th
.th_team
->t
.t_level
== 0 &&
562 __kmp_affinity
.flags
.reset
) {
563 __kmp_reset_root_init_mask(gtid
);
566 __kmp_str_buf_init(&capture_buf
);
567 ConvertedString
cformat(format
, for_size
);
568 num_required
= __kmp_aux_capture_affinity(gtid
, cformat
.get(), &capture_buf
);
569 if (buffer
&& buf_size
) {
570 __kmp_fortran_strncpy_truncate(buffer
, buf_size
, capture_buf
.str
,
573 __kmp_str_buf_free(&capture_buf
);
578 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_GET_THREAD_NUM
)(void) {
584 #if KMP_OS_DARWIN || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || \
585 KMP_OS_OPENBSD || KMP_OS_HURD || KMP_OS_SOLARIS || KMP_OS_AIX
586 gtid
= __kmp_entry_gtid();
588 if (!__kmp_init_parallel
||
589 (gtid
= (int)((kmp_intptr_t
)TlsGetValue(__kmp_gtid_threadprivate_key
))) ==
591 // Either library isn't initialized or thread is not registered
592 // 0 is the correct TID in this case
595 --gtid
; // We keep (gtid+1) in TLS
596 #elif KMP_OS_LINUX || KMP_OS_WASI
597 #ifdef KMP_TDATA_GTID
598 if (__kmp_gtid_mode
>= 3) {
599 if ((gtid
= __kmp_gtid
) == KMP_GTID_DNE
) {
604 if (!__kmp_init_parallel
||
605 (gtid
= (int)((kmp_intptr_t
)(
606 pthread_getspecific(__kmp_gtid_threadprivate_key
)))) == 0) {
610 #ifdef KMP_TDATA_GTID
614 #error Unknown or unsupported OS
617 return __kmp_tid_from_gtid(gtid
);
621 int FTN_STDCALL
FTN_GET_NUM_KNOWN_THREADS(void) {
625 if (!__kmp_init_serial
) {
626 __kmp_serial_initialize();
628 /* NOTE: this is not syncronized, so it can change at any moment */
629 /* NOTE: this number also includes threads preallocated in hot-teams */
630 return TCR_4(__kmp_nth
);
634 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_GET_NUM_PROCS
)(void) {
638 if (!TCR_4(__kmp_init_middle
)) {
639 __kmp_middle_initialize();
641 #if KMP_AFFINITY_SUPPORTED
642 if (!__kmp_affinity
.flags
.reset
) {
643 // only bind root here if its affinity reset is not requested
644 int gtid
= __kmp_entry_gtid();
645 kmp_info_t
*thread
= __kmp_threads
[gtid
];
646 if (thread
->th
.th_team
->t
.t_level
== 0) {
647 __kmp_assign_root_init_mask();
651 return __kmp_avail_proc
;
655 void FTN_STDCALL
KMP_EXPAND_NAME(FTN_SET_NESTED
)(int KMP_DEREF flag
) {
657 __kmps_set_nested(KMP_DEREF flag
);
660 /* For the thread-private internal controls implementation */
661 thread
= __kmp_entry_thread();
662 KMP_INFORM(APIDeprecated
, "omp_set_nested", "omp_set_max_active_levels");
663 __kmp_save_internal_controls(thread
);
664 // Somewhat arbitrarily decide where to get a value for max_active_levels
665 int max_active_levels
= get__max_active_levels(thread
);
666 if (max_active_levels
== 1)
667 max_active_levels
= KMP_MAX_ACTIVE_LEVELS_LIMIT
;
668 set__max_active_levels(thread
, (KMP_DEREF flag
) ? max_active_levels
: 1);
672 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_GET_NESTED
)(void) {
674 return __kmps_get_nested();
677 thread
= __kmp_entry_thread();
678 KMP_INFORM(APIDeprecated
, "omp_get_nested", "omp_get_max_active_levels");
679 return get__max_active_levels(thread
) > 1;
683 void FTN_STDCALL
KMP_EXPAND_NAME(FTN_SET_DYNAMIC
)(int KMP_DEREF flag
) {
685 __kmps_set_dynamic(KMP_DEREF flag
? TRUE
: FALSE
);
688 /* For the thread-private implementation of the internal controls */
689 thread
= __kmp_entry_thread();
690 // !!! What if foreign thread calls it?
691 __kmp_save_internal_controls(thread
);
692 set__dynamic(thread
, KMP_DEREF flag
? true : false);
696 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_GET_DYNAMIC
)(void) {
698 return __kmps_get_dynamic();
701 thread
= __kmp_entry_thread();
702 return get__dynamic(thread
);
706 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_IN_PARALLEL
)(void) {
710 kmp_info_t
*th
= __kmp_entry_thread();
711 if (th
->th
.th_teams_microtask
) {
712 // AC: r_in_parallel does not work inside teams construct where real
713 // parallel is inactive, but all threads have same root, so setting it in
714 // one team affects other teams.
715 // The solution is to use per-team nesting level
716 return (th
->th
.th_team
->t
.t_active_level
? 1 : 0);
718 return (th
->th
.th_root
->r
.r_in_parallel
? FTN_TRUE
: FTN_FALSE
);
722 void FTN_STDCALL
KMP_EXPAND_NAME(FTN_SET_SCHEDULE
)(kmp_sched_t KMP_DEREF kind
,
723 int KMP_DEREF modifier
) {
725 __kmps_set_schedule(KMP_DEREF kind
, KMP_DEREF modifier
);
727 /* TO DO: For the per-task implementation of the internal controls */
728 __kmp_set_schedule(__kmp_entry_gtid(), KMP_DEREF kind
, KMP_DEREF modifier
);
732 void FTN_STDCALL
KMP_EXPAND_NAME(FTN_GET_SCHEDULE
)(kmp_sched_t
*kind
,
735 __kmps_get_schedule(kind
, modifier
);
737 /* TO DO: For the per-task implementation of the internal controls */
738 __kmp_get_schedule(__kmp_entry_gtid(), kind
, modifier
);
742 void FTN_STDCALL
KMP_EXPAND_NAME(FTN_SET_MAX_ACTIVE_LEVELS
)(int KMP_DEREF arg
) {
746 /* TO DO: We want per-task implementation of this internal control */
747 __kmp_set_max_active_levels(__kmp_entry_gtid(), KMP_DEREF arg
);
751 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_GET_MAX_ACTIVE_LEVELS
)(void) {
755 /* TO DO: We want per-task implementation of this internal control */
756 if (!TCR_4(__kmp_init_middle
)) {
757 __kmp_middle_initialize();
759 return __kmp_get_max_active_levels(__kmp_entry_gtid());
763 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_GET_ACTIVE_LEVEL
)(void) {
765 return 0; // returns 0 if it is called from the sequential part of the program
767 /* TO DO: For the per-task implementation of the internal controls */
768 return __kmp_entry_thread()->th
.th_team
->t
.t_active_level
;
772 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_GET_LEVEL
)(void) {
774 return 0; // returns 0 if it is called from the sequential part of the program
776 /* TO DO: For the per-task implementation of the internal controls */
777 return __kmp_entry_thread()->th
.th_team
->t
.t_level
;
782 KMP_EXPAND_NAME(FTN_GET_ANCESTOR_THREAD_NUM
)(int KMP_DEREF level
) {
784 return (KMP_DEREF level
) ? (-1) : (0);
786 return __kmp_get_ancestor_thread_num(__kmp_entry_gtid(), KMP_DEREF level
);
790 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_GET_TEAM_SIZE
)(int KMP_DEREF level
) {
792 return (KMP_DEREF level
) ? (-1) : (1);
794 return __kmp_get_team_size(__kmp_entry_gtid(), KMP_DEREF level
);
798 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_GET_THREAD_LIMIT
)(void) {
800 return 1; // TO DO: clarify whether it returns 1 or 0?
804 if (!__kmp_init_serial
) {
805 __kmp_serial_initialize();
808 gtid
= __kmp_entry_gtid();
809 thread
= __kmp_threads
[gtid
];
810 // If thread_limit for the target task is defined, return that instead of the
811 // regular task thread_limit
812 if (int thread_limit
= thread
->th
.th_current_task
->td_icvs
.task_thread_limit
)
814 return thread
->th
.th_current_task
->td_icvs
.thread_limit
;
818 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_IN_FINAL
)(void) {
820 return 0; // TO DO: clarify whether it returns 1 or 0?
822 if (!TCR_4(__kmp_init_parallel
)) {
825 return __kmp_entry_thread()->th
.th_current_task
->td_flags
.final
;
829 kmp_proc_bind_t FTN_STDCALL
KMP_EXPAND_NAME(FTN_GET_PROC_BIND
)(void) {
831 return __kmps_get_proc_bind();
833 return get__proc_bind(__kmp_entry_thread());
837 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_GET_NUM_PLACES
)(void) {
838 #if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
841 if (!TCR_4(__kmp_init_middle
)) {
842 __kmp_middle_initialize();
844 if (!KMP_AFFINITY_CAPABLE())
846 if (!__kmp_affinity
.flags
.reset
) {
847 // only bind root here if its affinity reset is not requested
848 int gtid
= __kmp_entry_gtid();
849 kmp_info_t
*thread
= __kmp_threads
[gtid
];
850 if (thread
->th
.th_team
->t
.t_level
== 0) {
851 __kmp_assign_root_init_mask();
854 return __kmp_affinity
.num_masks
;
858 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_GET_PLACE_NUM_PROCS
)(int place_num
) {
859 #if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
864 if (!TCR_4(__kmp_init_middle
)) {
865 __kmp_middle_initialize();
867 if (!KMP_AFFINITY_CAPABLE())
869 if (!__kmp_affinity
.flags
.reset
) {
870 // only bind root here if its affinity reset is not requested
871 int gtid
= __kmp_entry_gtid();
872 kmp_info_t
*thread
= __kmp_threads
[gtid
];
873 if (thread
->th
.th_team
->t
.t_level
== 0) {
874 __kmp_assign_root_init_mask();
877 if (place_num
< 0 || place_num
>= (int)__kmp_affinity
.num_masks
)
879 kmp_affin_mask_t
*mask
= KMP_CPU_INDEX(__kmp_affinity
.masks
, place_num
);
880 KMP_CPU_SET_ITERATE(i
, mask
) {
881 if ((!KMP_CPU_ISSET(i
, __kmp_affin_fullMask
)) ||
882 (!KMP_CPU_ISSET(i
, mask
))) {
891 void FTN_STDCALL
KMP_EXPAND_NAME(FTN_GET_PLACE_PROC_IDS
)(int place_num
,
893 #if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
897 if (!TCR_4(__kmp_init_middle
)) {
898 __kmp_middle_initialize();
900 if (!KMP_AFFINITY_CAPABLE())
902 if (!__kmp_affinity
.flags
.reset
) {
903 // only bind root here if its affinity reset is not requested
904 int gtid
= __kmp_entry_gtid();
905 kmp_info_t
*thread
= __kmp_threads
[gtid
];
906 if (thread
->th
.th_team
->t
.t_level
== 0) {
907 __kmp_assign_root_init_mask();
910 if (place_num
< 0 || place_num
>= (int)__kmp_affinity
.num_masks
)
912 kmp_affin_mask_t
*mask
= KMP_CPU_INDEX(__kmp_affinity
.masks
, place_num
);
914 KMP_CPU_SET_ITERATE(i
, mask
) {
915 if ((!KMP_CPU_ISSET(i
, __kmp_affin_fullMask
)) ||
916 (!KMP_CPU_ISSET(i
, mask
))) {
924 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_GET_PLACE_NUM
)(void) {
925 #if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
930 if (!TCR_4(__kmp_init_middle
)) {
931 __kmp_middle_initialize();
933 if (!KMP_AFFINITY_CAPABLE())
935 gtid
= __kmp_entry_gtid();
936 thread
= __kmp_thread_from_gtid(gtid
);
937 if (thread
->th
.th_team
->t
.t_level
== 0 && !__kmp_affinity
.flags
.reset
) {
938 __kmp_assign_root_init_mask();
940 if (thread
->th
.th_current_place
< 0)
942 return thread
->th
.th_current_place
;
946 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_GET_PARTITION_NUM_PLACES
)(void) {
947 #if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
950 int gtid
, num_places
, first_place
, last_place
;
952 if (!TCR_4(__kmp_init_middle
)) {
953 __kmp_middle_initialize();
955 if (!KMP_AFFINITY_CAPABLE())
957 gtid
= __kmp_entry_gtid();
958 thread
= __kmp_thread_from_gtid(gtid
);
959 if (thread
->th
.th_team
->t
.t_level
== 0 && !__kmp_affinity
.flags
.reset
) {
960 __kmp_assign_root_init_mask();
962 first_place
= thread
->th
.th_first_place
;
963 last_place
= thread
->th
.th_last_place
;
964 if (first_place
< 0 || last_place
< 0)
966 if (first_place
<= last_place
)
967 num_places
= last_place
- first_place
+ 1;
969 num_places
= __kmp_affinity
.num_masks
- first_place
+ last_place
+ 1;
975 KMP_EXPAND_NAME(FTN_GET_PARTITION_PLACE_NUMS
)(int *place_nums
) {
976 #if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
979 int i
, gtid
, place_num
, first_place
, last_place
, start
, end
;
981 if (!TCR_4(__kmp_init_middle
)) {
982 __kmp_middle_initialize();
984 if (!KMP_AFFINITY_CAPABLE())
986 gtid
= __kmp_entry_gtid();
987 thread
= __kmp_thread_from_gtid(gtid
);
988 if (thread
->th
.th_team
->t
.t_level
== 0 && !__kmp_affinity
.flags
.reset
) {
989 __kmp_assign_root_init_mask();
991 first_place
= thread
->th
.th_first_place
;
992 last_place
= thread
->th
.th_last_place
;
993 if (first_place
< 0 || last_place
< 0)
995 if (first_place
<= last_place
) {
1002 for (i
= 0, place_num
= start
; place_num
<= end
; ++place_num
, ++i
) {
1003 place_nums
[i
] = place_num
;
1008 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_GET_NUM_TEAMS
)(void) {
1012 return __kmp_aux_get_num_teams();
1016 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_GET_TEAM_NUM
)(void) {
1020 return __kmp_aux_get_team_num();
1024 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_GET_DEFAULT_DEVICE
)(void) {
1025 #if KMP_MIC || KMP_OS_DARWIN || defined(KMP_STUB)
1028 return __kmp_entry_thread()->th
.th_current_task
->td_icvs
.default_device
;
1032 void FTN_STDCALL
KMP_EXPAND_NAME(FTN_SET_DEFAULT_DEVICE
)(int KMP_DEREF arg
) {
1033 #if KMP_MIC || KMP_OS_DARWIN || defined(KMP_STUB)
1036 __kmp_entry_thread()->th
.th_current_task
->td_icvs
.default_device
=
1041 // Get number of NON-HOST devices.
1042 // libomptarget, if loaded, provides this function in api.cpp.
1043 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_GET_NUM_DEVICES
)(void)
1044 KMP_WEAK_ATTRIBUTE_EXTERNAL
;
1045 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_GET_NUM_DEVICES
)(void) {
1046 #if KMP_MIC || KMP_OS_DARWIN || KMP_OS_WASI || defined(KMP_STUB)
1050 if ((*(void **)(&fptr
) = KMP_DLSYM("__tgt_get_num_devices"))) {
1052 } else if ((*(void **)(&fptr
) = KMP_DLSYM_NEXT("omp_get_num_devices"))) {
1054 } else if ((*(void **)(&fptr
) = KMP_DLSYM("_Offload_number_of_devices"))) {
1056 } else { // liboffload & libomptarget don't exist
1059 #endif // KMP_MIC || KMP_OS_DARWIN || KMP_OS_WINDOWS || defined(KMP_STUB)
1062 // This function always returns true when called on host device.
1063 // Compiler/libomptarget should handle when it is called inside target region.
1064 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_IS_INITIAL_DEVICE
)(void)
1065 KMP_WEAK_ATTRIBUTE_EXTERNAL
;
1066 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_IS_INITIAL_DEVICE
)(void) {
1067 return 1; // This is the host
1070 // libomptarget, if loaded, provides this function
1071 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_GET_INITIAL_DEVICE
)(void)
1072 KMP_WEAK_ATTRIBUTE_EXTERNAL
;
1073 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_GET_INITIAL_DEVICE
)(void) {
1074 // same as omp_get_num_devices()
1075 return KMP_EXPAND_NAME(FTN_GET_NUM_DEVICES
)();
1078 #if defined(KMP_STUB)
1079 // Entries for stubs library
1080 // As all *target* functions are C-only parameters always passed by value
1081 void *FTN_STDCALL
FTN_TARGET_ALLOC(size_t size
, int device_num
) { return 0; }
1083 void FTN_STDCALL
FTN_TARGET_FREE(void *device_ptr
, int device_num
) {}
1085 int FTN_STDCALL
FTN_TARGET_IS_PRESENT(void *ptr
, int device_num
) { return 0; }
1087 int FTN_STDCALL
FTN_TARGET_MEMCPY(void *dst
, void *src
, size_t length
,
1088 size_t dst_offset
, size_t src_offset
,
1089 int dst_device
, int src_device
) {
1093 int FTN_STDCALL
FTN_TARGET_MEMCPY_RECT(
1094 void *dst
, void *src
, size_t element_size
, int num_dims
,
1095 const size_t *volume
, const size_t *dst_offsets
, const size_t *src_offsets
,
1096 const size_t *dst_dimensions
, const size_t *src_dimensions
, int dst_device
,
1101 int FTN_STDCALL
FTN_TARGET_ASSOCIATE_PTR(void *host_ptr
, void *device_ptr
,
1102 size_t size
, size_t device_offset
,
1107 int FTN_STDCALL
FTN_TARGET_DISASSOCIATE_PTR(void *host_ptr
, int device_num
) {
1110 #endif // defined(KMP_STUB)
1113 typedef enum { UNINIT
= -1, UNLOCKED
, LOCKED
} kmp_stub_lock_t
;
1114 #endif /* KMP_STUB */
1116 #if KMP_USE_DYNAMIC_LOCK
1117 void FTN_STDCALL
FTN_INIT_LOCK_WITH_HINT(void **user_lock
,
1118 uintptr_t KMP_DEREF hint
) {
1120 *((kmp_stub_lock_t
*)user_lock
) = UNLOCKED
;
1122 int gtid
= __kmp_entry_gtid();
1123 #if OMPT_SUPPORT && OMPT_OPTIONAL
1124 OMPT_STORE_RETURN_ADDRESS(gtid
);
1126 __kmpc_init_lock_with_hint(NULL
, gtid
, user_lock
, KMP_DEREF hint
);
1130 void FTN_STDCALL
FTN_INIT_NEST_LOCK_WITH_HINT(void **user_lock
,
1131 uintptr_t KMP_DEREF hint
) {
1133 *((kmp_stub_lock_t
*)user_lock
) = UNLOCKED
;
1135 int gtid
= __kmp_entry_gtid();
1136 #if OMPT_SUPPORT && OMPT_OPTIONAL
1137 OMPT_STORE_RETURN_ADDRESS(gtid
);
1139 __kmpc_init_nest_lock_with_hint(NULL
, gtid
, user_lock
, KMP_DEREF hint
);
1144 /* initialize the lock */
1145 void FTN_STDCALL
KMP_EXPAND_NAME(FTN_INIT_LOCK
)(void **user_lock
) {
1147 *((kmp_stub_lock_t
*)user_lock
) = UNLOCKED
;
1149 int gtid
= __kmp_entry_gtid();
1150 #if OMPT_SUPPORT && OMPT_OPTIONAL
1151 OMPT_STORE_RETURN_ADDRESS(gtid
);
1153 __kmpc_init_lock(NULL
, gtid
, user_lock
);
1157 /* initialize the lock */
1158 void FTN_STDCALL
KMP_EXPAND_NAME(FTN_INIT_NEST_LOCK
)(void **user_lock
) {
1160 *((kmp_stub_lock_t
*)user_lock
) = UNLOCKED
;
1162 int gtid
= __kmp_entry_gtid();
1163 #if OMPT_SUPPORT && OMPT_OPTIONAL
1164 OMPT_STORE_RETURN_ADDRESS(gtid
);
1166 __kmpc_init_nest_lock(NULL
, gtid
, user_lock
);
1170 void FTN_STDCALL
KMP_EXPAND_NAME(FTN_DESTROY_LOCK
)(void **user_lock
) {
1172 *((kmp_stub_lock_t
*)user_lock
) = UNINIT
;
1174 int gtid
= __kmp_entry_gtid();
1175 #if OMPT_SUPPORT && OMPT_OPTIONAL
1176 OMPT_STORE_RETURN_ADDRESS(gtid
);
1178 __kmpc_destroy_lock(NULL
, gtid
, user_lock
);
1182 void FTN_STDCALL
KMP_EXPAND_NAME(FTN_DESTROY_NEST_LOCK
)(void **user_lock
) {
1184 *((kmp_stub_lock_t
*)user_lock
) = UNINIT
;
1186 int gtid
= __kmp_entry_gtid();
1187 #if OMPT_SUPPORT && OMPT_OPTIONAL
1188 OMPT_STORE_RETURN_ADDRESS(gtid
);
1190 __kmpc_destroy_nest_lock(NULL
, gtid
, user_lock
);
1194 void FTN_STDCALL
KMP_EXPAND_NAME(FTN_SET_LOCK
)(void **user_lock
) {
1196 if (*((kmp_stub_lock_t
*)user_lock
) == UNINIT
) {
1197 // TODO: Issue an error.
1199 if (*((kmp_stub_lock_t
*)user_lock
) != UNLOCKED
) {
1200 // TODO: Issue an error.
1202 *((kmp_stub_lock_t
*)user_lock
) = LOCKED
;
1204 int gtid
= __kmp_entry_gtid();
1205 #if OMPT_SUPPORT && OMPT_OPTIONAL
1206 OMPT_STORE_RETURN_ADDRESS(gtid
);
1208 __kmpc_set_lock(NULL
, gtid
, user_lock
);
1212 void FTN_STDCALL
KMP_EXPAND_NAME(FTN_SET_NEST_LOCK
)(void **user_lock
) {
1214 if (*((kmp_stub_lock_t
*)user_lock
) == UNINIT
) {
1215 // TODO: Issue an error.
1217 (*((int *)user_lock
))++;
1219 int gtid
= __kmp_entry_gtid();
1220 #if OMPT_SUPPORT && OMPT_OPTIONAL
1221 OMPT_STORE_RETURN_ADDRESS(gtid
);
1223 __kmpc_set_nest_lock(NULL
, gtid
, user_lock
);
1227 void FTN_STDCALL
KMP_EXPAND_NAME(FTN_UNSET_LOCK
)(void **user_lock
) {
1229 if (*((kmp_stub_lock_t
*)user_lock
) == UNINIT
) {
1230 // TODO: Issue an error.
1232 if (*((kmp_stub_lock_t
*)user_lock
) == UNLOCKED
) {
1233 // TODO: Issue an error.
1235 *((kmp_stub_lock_t
*)user_lock
) = UNLOCKED
;
1237 int gtid
= __kmp_entry_gtid();
1238 #if OMPT_SUPPORT && OMPT_OPTIONAL
1239 OMPT_STORE_RETURN_ADDRESS(gtid
);
1241 __kmpc_unset_lock(NULL
, gtid
, user_lock
);
1245 void FTN_STDCALL
KMP_EXPAND_NAME(FTN_UNSET_NEST_LOCK
)(void **user_lock
) {
1247 if (*((kmp_stub_lock_t
*)user_lock
) == UNINIT
) {
1248 // TODO: Issue an error.
1250 if (*((kmp_stub_lock_t
*)user_lock
) == UNLOCKED
) {
1251 // TODO: Issue an error.
1253 (*((int *)user_lock
))--;
1255 int gtid
= __kmp_entry_gtid();
1256 #if OMPT_SUPPORT && OMPT_OPTIONAL
1257 OMPT_STORE_RETURN_ADDRESS(gtid
);
1259 __kmpc_unset_nest_lock(NULL
, gtid
, user_lock
);
1263 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_TEST_LOCK
)(void **user_lock
) {
1265 if (*((kmp_stub_lock_t
*)user_lock
) == UNINIT
) {
1266 // TODO: Issue an error.
1268 if (*((kmp_stub_lock_t
*)user_lock
) == LOCKED
) {
1271 *((kmp_stub_lock_t
*)user_lock
) = LOCKED
;
1274 int gtid
= __kmp_entry_gtid();
1275 #if OMPT_SUPPORT && OMPT_OPTIONAL
1276 OMPT_STORE_RETURN_ADDRESS(gtid
);
1278 return __kmpc_test_lock(NULL
, gtid
, user_lock
);
1282 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_TEST_NEST_LOCK
)(void **user_lock
) {
1284 if (*((kmp_stub_lock_t
*)user_lock
) == UNINIT
) {
1285 // TODO: Issue an error.
1287 return ++(*((int *)user_lock
));
1289 int gtid
= __kmp_entry_gtid();
1290 #if OMPT_SUPPORT && OMPT_OPTIONAL
1291 OMPT_STORE_RETURN_ADDRESS(gtid
);
1293 return __kmpc_test_nest_lock(NULL
, gtid
, user_lock
);
1297 double FTN_STDCALL
KMP_EXPAND_NAME(FTN_GET_WTIME
)(void) {
1299 return __kmps_get_wtime();
1303 // We don't need library initialization to get the time on Linux* OS. The
1304 // routine can be used to measure library initialization time on Linux* OS now
1305 if (!__kmp_init_serial
) {
1306 __kmp_serial_initialize();
1309 __kmp_elapsed(&data
);
1314 double FTN_STDCALL
KMP_EXPAND_NAME(FTN_GET_WTICK
)(void) {
1316 return __kmps_get_wtick();
1319 if (!__kmp_init_serial
) {
1320 __kmp_serial_initialize();
1322 __kmp_elapsed_tick(&data
);
1327 /* ------------------------------------------------------------------------ */
1329 void *FTN_STDCALL
FTN_MALLOC(size_t KMP_DEREF size
) {
1330 // kmpc_malloc initializes the library if needed
1331 return kmpc_malloc(KMP_DEREF size
);
1334 void *FTN_STDCALL
FTN_ALIGNED_MALLOC(size_t KMP_DEREF size
,
1335 size_t KMP_DEREF alignment
) {
1336 // kmpc_aligned_malloc initializes the library if needed
1337 return kmpc_aligned_malloc(KMP_DEREF size
, KMP_DEREF alignment
);
1340 void *FTN_STDCALL
FTN_CALLOC(size_t KMP_DEREF nelem
, size_t KMP_DEREF elsize
) {
1341 // kmpc_calloc initializes the library if needed
1342 return kmpc_calloc(KMP_DEREF nelem
, KMP_DEREF elsize
);
1345 void *FTN_STDCALL
FTN_REALLOC(void *KMP_DEREF ptr
, size_t KMP_DEREF size
) {
1346 // kmpc_realloc initializes the library if needed
1347 return kmpc_realloc(KMP_DEREF ptr
, KMP_DEREF size
);
1350 void FTN_STDCALL
FTN_KFREE(void *KMP_DEREF ptr
) {
1351 // does nothing if the library is not initialized
1352 kmpc_free(KMP_DEREF ptr
);
1355 void FTN_STDCALL
FTN_SET_WARNINGS_ON(void) {
1357 __kmp_generate_warnings
= kmp_warnings_explicit
;
1361 void FTN_STDCALL
FTN_SET_WARNINGS_OFF(void) {
1363 __kmp_generate_warnings
= FALSE
;
1367 void FTN_STDCALL
FTN_SET_DEFAULTS(char const *str
1368 #ifndef PASS_ARGS_BY_VALUE
1374 #ifdef PASS_ARGS_BY_VALUE
1375 int len
= (int)KMP_STRLEN(str
);
1377 __kmp_aux_set_defaults(str
, len
);
1381 /* ------------------------------------------------------------------------ */
1383 /* returns the status of cancellation */
1384 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_GET_CANCELLATION
)(void) {
1386 return 0 /* false */;
1388 // initialize the library if needed
1389 if (!__kmp_init_serial
) {
1390 __kmp_serial_initialize();
1392 return __kmp_omp_cancellation
;
1396 int FTN_STDCALL
FTN_GET_CANCELLATION_STATUS(int cancel_kind
) {
1398 return 0 /* false */;
1400 return __kmp_get_cancellation_status(cancel_kind
);
1404 /* returns the maximum allowed task priority */
1405 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_GET_MAX_TASK_PRIORITY
)(void) {
1409 if (!__kmp_init_serial
) {
1410 __kmp_serial_initialize();
1412 return __kmp_max_task_priority
;
1416 // This function will be defined in libomptarget. When libomptarget is not
1417 // loaded, we assume we are on the host and return KMP_HOST_DEVICE.
1418 // Compiler/libomptarget will handle this if called inside target.
1419 int FTN_STDCALL
FTN_GET_DEVICE_NUM(void) KMP_WEAK_ATTRIBUTE_EXTERNAL
;
1420 int FTN_STDCALL
FTN_GET_DEVICE_NUM(void) {
1421 return KMP_EXPAND_NAME(FTN_GET_INITIAL_DEVICE
)();
1424 // Compiler will ensure that this is only called from host in sequential region
1425 int FTN_STDCALL
KMP_EXPAND_NAME(FTN_PAUSE_RESOURCE
)(kmp_pause_status_t kind
,
1428 return 1; // just fail
1430 if (kind
== kmp_stop_tool_paused
)
1431 return 1; // stop_tool must not be specified
1432 if (device_num
== KMP_EXPAND_NAME(FTN_GET_INITIAL_DEVICE
)())
1433 return __kmpc_pause_resource(kind
);
1435 int (*fptr
)(kmp_pause_status_t
, int);
1436 if ((*(void **)(&fptr
) = KMP_DLSYM("tgt_pause_resource")))
1437 return (*fptr
)(kind
, device_num
);
1439 return 1; // just fail if there is no libomptarget
1444 // Compiler will ensure that this is only called from host in sequential region
1446 KMP_EXPAND_NAME(FTN_PAUSE_RESOURCE_ALL
)(kmp_pause_status_t kind
) {
1448 return 1; // just fail
1451 int (*fptr
)(kmp_pause_status_t
, int);
1452 if ((*(void **)(&fptr
) = KMP_DLSYM("tgt_pause_resource")))
1453 fails
= (*fptr
)(kind
, KMP_DEVICE_ALL
); // pause devices
1454 fails
+= __kmpc_pause_resource(kind
); // pause host
1459 // Returns the maximum number of nesting levels supported by implementation
1460 int FTN_STDCALL
FTN_GET_SUPPORTED_ACTIVE_LEVELS(void) {
1464 return KMP_MAX_ACTIVE_LEVELS_LIMIT
;
1468 void FTN_STDCALL
FTN_FULFILL_EVENT(kmp_event_t
*event
) {
1470 __kmp_fulfill_event(event
);
1474 // nteams-var per-device ICV
1475 void FTN_STDCALL
FTN_SET_NUM_TEAMS(int KMP_DEREF num_teams
) {
1479 if (!__kmp_init_serial
) {
1480 __kmp_serial_initialize();
1482 __kmp_set_num_teams(KMP_DEREF num_teams
);
1485 int FTN_STDCALL
FTN_GET_MAX_TEAMS(void) {
1489 if (!__kmp_init_serial
) {
1490 __kmp_serial_initialize();
1492 return __kmp_get_max_teams();
1495 // teams-thread-limit-var per-device ICV
1496 void FTN_STDCALL
FTN_SET_TEAMS_THREAD_LIMIT(int KMP_DEREF limit
) {
1500 if (!__kmp_init_serial
) {
1501 __kmp_serial_initialize();
1503 __kmp_set_teams_thread_limit(KMP_DEREF limit
);
1506 int FTN_STDCALL
FTN_GET_TEAMS_THREAD_LIMIT(void) {
1510 if (!__kmp_init_serial
) {
1511 __kmp_serial_initialize();
1513 return __kmp_get_teams_thread_limit();
1517 /// TODO: Include the `omp.h` of the current build
1518 /* OpenMP 5.1 interop */
1519 typedef intptr_t omp_intptr_t
;
1521 /* 0..omp_get_num_interop_properties()-1 are reserved for implementation-defined
1523 typedef enum omp_interop_property
{
1525 omp_ipr_fr_name
= -2,
1526 omp_ipr_vendor
= -3,
1527 omp_ipr_vendor_name
= -4,
1528 omp_ipr_device_num
= -5,
1529 omp_ipr_platform
= -6,
1530 omp_ipr_device
= -7,
1531 omp_ipr_device_context
= -8,
1532 omp_ipr_targetsync
= -9,
1534 } omp_interop_property_t
;
1536 #define omp_interop_none 0
1538 typedef enum omp_interop_rc
{
1539 omp_irc_no_value
= 1,
1540 omp_irc_success
= 0,
1542 omp_irc_out_of_range
= -2,
1543 omp_irc_type_int
= -3,
1544 omp_irc_type_ptr
= -4,
1545 omp_irc_type_str
= -5,
1549 typedef enum omp_interop_fr
{
1551 omp_ifr_cuda_driver
= 2,
1555 omp_ifr_level_zero
= 6,
1559 typedef void *omp_interop_t
;
1561 // libomptarget, if loaded, provides this function
1562 int FTN_STDCALL
FTN_GET_NUM_INTEROP_PROPERTIES(const omp_interop_t interop
) {
1563 #if KMP_OS_DARWIN || KMP_OS_WASI || defined(KMP_STUB)
1566 int (*fptr
)(const omp_interop_t
);
1567 if ((*(void **)(&fptr
) = KMP_DLSYM_NEXT("omp_get_num_interop_properties")))
1568 return (*fptr
)(interop
);
1573 /// TODO Convert FTN_GET_INTEROP_XXX functions into a macro like interop.cpp
1574 // libomptarget, if loaded, provides this function
1575 intptr_t FTN_STDCALL
FTN_GET_INTEROP_INT(const omp_interop_t interop
,
1576 omp_interop_property_t property_id
,
1578 #if KMP_OS_DARWIN || KMP_OS_WASI || defined(KMP_STUB)
1581 intptr_t (*fptr
)(const omp_interop_t
, omp_interop_property_t
, int *);
1582 if ((*(void **)(&fptr
) = KMP_DLSYM_NEXT("omp_get_interop_int")))
1583 return (*fptr
)(interop
, property_id
, err
);
1588 // libomptarget, if loaded, provides this function
1589 void *FTN_STDCALL
FTN_GET_INTEROP_PTR(const omp_interop_t interop
,
1590 omp_interop_property_t property_id
,
1592 #if KMP_OS_DARWIN || KMP_OS_WASI || defined(KMP_STUB)
1595 void *(*fptr
)(const omp_interop_t
, omp_interop_property_t
, int *);
1596 if ((*(void **)(&fptr
) = KMP_DLSYM_NEXT("omp_get_interop_ptr")))
1597 return (*fptr
)(interop
, property_id
, err
);
1602 // libomptarget, if loaded, provides this function
1603 const char *FTN_STDCALL
FTN_GET_INTEROP_STR(const omp_interop_t interop
,
1604 omp_interop_property_t property_id
,
1606 #if KMP_OS_DARWIN || KMP_OS_WASI || defined(KMP_STUB)
1609 const char *(*fptr
)(const omp_interop_t
, omp_interop_property_t
, int *);
1610 if ((*(void **)(&fptr
) = KMP_DLSYM_NEXT("omp_get_interop_str")))
1611 return (*fptr
)(interop
, property_id
, err
);
1616 // libomptarget, if loaded, provides this function
1617 const char *FTN_STDCALL
FTN_GET_INTEROP_NAME(
1618 const omp_interop_t interop
, omp_interop_property_t property_id
) {
1619 #if KMP_OS_DARWIN || KMP_OS_WASI || defined(KMP_STUB)
1622 const char *(*fptr
)(const omp_interop_t
, omp_interop_property_t
);
1623 if ((*(void **)(&fptr
) = KMP_DLSYM_NEXT("omp_get_interop_name")))
1624 return (*fptr
)(interop
, property_id
);
1629 // libomptarget, if loaded, provides this function
1630 const char *FTN_STDCALL
FTN_GET_INTEROP_TYPE_DESC(
1631 const omp_interop_t interop
, omp_interop_property_t property_id
) {
1632 #if KMP_OS_DARWIN || KMP_OS_WASI || defined(KMP_STUB)
1635 const char *(*fptr
)(const omp_interop_t
, omp_interop_property_t
);
1636 if ((*(void **)(&fptr
) = KMP_DLSYM_NEXT("omp_get_interop_type_desc")))
1637 return (*fptr
)(interop
, property_id
);
1642 // libomptarget, if loaded, provides this function
1643 const char *FTN_STDCALL
FTN_GET_INTEROP_RC_DESC(
1644 const omp_interop_t interop
, omp_interop_property_t property_id
) {
1645 #if KMP_OS_DARWIN || KMP_OS_WASI || defined(KMP_STUB)
1648 const char *(*fptr
)(const omp_interop_t
, omp_interop_property_t
);
1649 if ((*(void **)(&fptr
) = KMP_DLSYM_NEXT("omp_get_interop_rec_desc")))
1650 return (*fptr
)(interop
, property_id
);
1655 // display environment variables when requested
1656 void FTN_STDCALL
FTN_DISPLAY_ENV(int verbose
) {
1658 __kmp_omp_display_env(verbose
);
1662 int FTN_STDCALL
FTN_IN_EXPLICIT_TASK(void) {
1666 int gtid
= __kmp_entry_gtid();
1667 return __kmp_thread_from_gtid(gtid
)->th
.th_current_task
->td_flags
.tasktype
;
1671 // GCC compatibility (versioned symbols)
1672 #ifdef KMP_USE_VERSION_SYMBOLS
1674 /* These following sections create versioned symbols for the
1675 omp_* routines. The KMP_VERSION_SYMBOL macro expands the API name and
1676 then maps it to a versioned symbol.
1677 libgomp ``versions'' its symbols (OMP_1.0, OMP_2.0, OMP_3.0, ...) while also
1678 retaining the default version which libomp uses: VERSION (defined in
1679 exports_so.txt). If you want to see the versioned symbols for libgomp.so.1
1682 objdump -T /path/to/libgomp.so.1 | grep omp_
1685 Step 1) Create __kmp_api_omp_set_num_threads_10_alias which is alias of
1686 __kmp_api_omp_set_num_threads
1687 Step 2) Set __kmp_api_omp_set_num_threads_10_alias to version:
1688 omp_set_num_threads@OMP_1.0
1689 Step 2B) Set __kmp_api_omp_set_num_threads to default version:
1690 omp_set_num_threads@@VERSION
1693 // OMP_1.0 versioned symbols
1694 KMP_VERSION_SYMBOL(FTN_SET_NUM_THREADS
, 10, "OMP_1.0");
1695 KMP_VERSION_SYMBOL(FTN_GET_NUM_THREADS
, 10, "OMP_1.0");
1696 KMP_VERSION_SYMBOL(FTN_GET_MAX_THREADS
, 10, "OMP_1.0");
1697 KMP_VERSION_SYMBOL(FTN_GET_THREAD_NUM
, 10, "OMP_1.0");
1698 KMP_VERSION_SYMBOL(FTN_GET_NUM_PROCS
, 10, "OMP_1.0");
1699 KMP_VERSION_SYMBOL(FTN_IN_PARALLEL
, 10, "OMP_1.0");
1700 KMP_VERSION_SYMBOL(FTN_SET_DYNAMIC
, 10, "OMP_1.0");
1701 KMP_VERSION_SYMBOL(FTN_GET_DYNAMIC
, 10, "OMP_1.0");
1702 KMP_VERSION_SYMBOL(FTN_SET_NESTED
, 10, "OMP_1.0");
1703 KMP_VERSION_SYMBOL(FTN_GET_NESTED
, 10, "OMP_1.0");
1704 KMP_VERSION_SYMBOL(FTN_INIT_LOCK
, 10, "OMP_1.0");
1705 KMP_VERSION_SYMBOL(FTN_INIT_NEST_LOCK
, 10, "OMP_1.0");
1706 KMP_VERSION_SYMBOL(FTN_DESTROY_LOCK
, 10, "OMP_1.0");
1707 KMP_VERSION_SYMBOL(FTN_DESTROY_NEST_LOCK
, 10, "OMP_1.0");
1708 KMP_VERSION_SYMBOL(FTN_SET_LOCK
, 10, "OMP_1.0");
1709 KMP_VERSION_SYMBOL(FTN_SET_NEST_LOCK
, 10, "OMP_1.0");
1710 KMP_VERSION_SYMBOL(FTN_UNSET_LOCK
, 10, "OMP_1.0");
1711 KMP_VERSION_SYMBOL(FTN_UNSET_NEST_LOCK
, 10, "OMP_1.0");
1712 KMP_VERSION_SYMBOL(FTN_TEST_LOCK
, 10, "OMP_1.0");
1713 KMP_VERSION_SYMBOL(FTN_TEST_NEST_LOCK
, 10, "OMP_1.0");
1715 // OMP_2.0 versioned symbols
1716 KMP_VERSION_SYMBOL(FTN_GET_WTICK
, 20, "OMP_2.0");
1717 KMP_VERSION_SYMBOL(FTN_GET_WTIME
, 20, "OMP_2.0");
1719 // OMP_3.0 versioned symbols
1720 KMP_VERSION_SYMBOL(FTN_SET_SCHEDULE
, 30, "OMP_3.0");
1721 KMP_VERSION_SYMBOL(FTN_GET_SCHEDULE
, 30, "OMP_3.0");
1722 KMP_VERSION_SYMBOL(FTN_GET_THREAD_LIMIT
, 30, "OMP_3.0");
1723 KMP_VERSION_SYMBOL(FTN_SET_MAX_ACTIVE_LEVELS
, 30, "OMP_3.0");
1724 KMP_VERSION_SYMBOL(FTN_GET_MAX_ACTIVE_LEVELS
, 30, "OMP_3.0");
1725 KMP_VERSION_SYMBOL(FTN_GET_ANCESTOR_THREAD_NUM
, 30, "OMP_3.0");
1726 KMP_VERSION_SYMBOL(FTN_GET_LEVEL
, 30, "OMP_3.0");
1727 KMP_VERSION_SYMBOL(FTN_GET_TEAM_SIZE
, 30, "OMP_3.0");
1728 KMP_VERSION_SYMBOL(FTN_GET_ACTIVE_LEVEL
, 30, "OMP_3.0");
1730 // the lock routines have a 1.0 and 3.0 version
1731 KMP_VERSION_SYMBOL(FTN_INIT_LOCK
, 30, "OMP_3.0");
1732 KMP_VERSION_SYMBOL(FTN_INIT_NEST_LOCK
, 30, "OMP_3.0");
1733 KMP_VERSION_SYMBOL(FTN_DESTROY_LOCK
, 30, "OMP_3.0");
1734 KMP_VERSION_SYMBOL(FTN_DESTROY_NEST_LOCK
, 30, "OMP_3.0");
1735 KMP_VERSION_SYMBOL(FTN_SET_LOCK
, 30, "OMP_3.0");
1736 KMP_VERSION_SYMBOL(FTN_SET_NEST_LOCK
, 30, "OMP_3.0");
1737 KMP_VERSION_SYMBOL(FTN_UNSET_LOCK
, 30, "OMP_3.0");
1738 KMP_VERSION_SYMBOL(FTN_UNSET_NEST_LOCK
, 30, "OMP_3.0");
1739 KMP_VERSION_SYMBOL(FTN_TEST_LOCK
, 30, "OMP_3.0");
1740 KMP_VERSION_SYMBOL(FTN_TEST_NEST_LOCK
, 30, "OMP_3.0");
1742 // OMP_3.1 versioned symbol
1743 KMP_VERSION_SYMBOL(FTN_IN_FINAL
, 31, "OMP_3.1");
1745 // OMP_4.0 versioned symbols
1746 KMP_VERSION_SYMBOL(FTN_GET_PROC_BIND
, 40, "OMP_4.0");
1747 KMP_VERSION_SYMBOL(FTN_GET_NUM_TEAMS
, 40, "OMP_4.0");
1748 KMP_VERSION_SYMBOL(FTN_GET_TEAM_NUM
, 40, "OMP_4.0");
1749 KMP_VERSION_SYMBOL(FTN_GET_CANCELLATION
, 40, "OMP_4.0");
1750 KMP_VERSION_SYMBOL(FTN_GET_DEFAULT_DEVICE
, 40, "OMP_4.0");
1751 KMP_VERSION_SYMBOL(FTN_SET_DEFAULT_DEVICE
, 40, "OMP_4.0");
1752 KMP_VERSION_SYMBOL(FTN_IS_INITIAL_DEVICE
, 40, "OMP_4.0");
1753 KMP_VERSION_SYMBOL(FTN_GET_NUM_DEVICES
, 40, "OMP_4.0");
1755 // OMP_4.5 versioned symbols
1756 KMP_VERSION_SYMBOL(FTN_GET_MAX_TASK_PRIORITY
, 45, "OMP_4.5");
1757 KMP_VERSION_SYMBOL(FTN_GET_NUM_PLACES
, 45, "OMP_4.5");
1758 KMP_VERSION_SYMBOL(FTN_GET_PLACE_NUM_PROCS
, 45, "OMP_4.5");
1759 KMP_VERSION_SYMBOL(FTN_GET_PLACE_PROC_IDS
, 45, "OMP_4.5");
1760 KMP_VERSION_SYMBOL(FTN_GET_PLACE_NUM
, 45, "OMP_4.5");
1761 KMP_VERSION_SYMBOL(FTN_GET_PARTITION_NUM_PLACES
, 45, "OMP_4.5");
1762 KMP_VERSION_SYMBOL(FTN_GET_PARTITION_PLACE_NUMS
, 45, "OMP_4.5");
1763 KMP_VERSION_SYMBOL(FTN_GET_INITIAL_DEVICE
, 45, "OMP_4.5");
1765 // OMP_5.0 versioned symbols
1766 // KMP_VERSION_SYMBOL(FTN_GET_DEVICE_NUM, 50, "OMP_5.0");
1767 KMP_VERSION_SYMBOL(FTN_PAUSE_RESOURCE
, 50, "OMP_5.0");
1768 KMP_VERSION_SYMBOL(FTN_PAUSE_RESOURCE_ALL
, 50, "OMP_5.0");
1769 // The C versions (KMP_FTN_PLAIN) of these symbols are in kmp_csupport.c
1770 #if KMP_FTN_ENTRIES == KMP_FTN_APPEND
1771 KMP_VERSION_SYMBOL(FTN_CAPTURE_AFFINITY
, 50, "OMP_5.0");
1772 KMP_VERSION_SYMBOL(FTN_DISPLAY_AFFINITY
, 50, "OMP_5.0");
1773 KMP_VERSION_SYMBOL(FTN_GET_AFFINITY_FORMAT
, 50, "OMP_5.0");
1774 KMP_VERSION_SYMBOL(FTN_SET_AFFINITY_FORMAT
, 50, "OMP_5.0");
1776 // KMP_VERSION_SYMBOL(FTN_GET_SUPPORTED_ACTIVE_LEVELS, 50, "OMP_5.0");
1777 // KMP_VERSION_SYMBOL(FTN_FULFILL_EVENT, 50, "OMP_5.0");
1779 #endif // KMP_USE_VERSION_SYMBOLS
1783 #endif // __cplusplus