xref: /freebsd/contrib/llvm-project/openmp/runtime/src/kmp.h (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
10b57cec5SDimitry Andric /*! \file */
20b57cec5SDimitry Andric /*
30b57cec5SDimitry Andric  * kmp.h -- KPTS runtime header file.
40b57cec5SDimitry Andric  */
50b57cec5SDimitry Andric 
60b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
70b57cec5SDimitry Andric //
80b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
90b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
100b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #ifndef KMP_H
150b57cec5SDimitry Andric #define KMP_H
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric #include "kmp_config.h"
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric /* #define BUILD_PARALLEL_ORDERED 1 */
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric /* This fix replaces gettimeofday with clock_gettime for better scalability on
220b57cec5SDimitry Andric    the Altix.  Requires user code to be linked with -lrt. */
230b57cec5SDimitry Andric //#define FIX_SGI_CLOCK
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric /* Defines for OpenMP 3.0 tasking and auto scheduling */
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric #ifndef KMP_STATIC_STEAL_ENABLED
280b57cec5SDimitry Andric #define KMP_STATIC_STEAL_ENABLED 1
290b57cec5SDimitry Andric #endif
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric #define TASK_CURRENT_NOT_QUEUED 0
320b57cec5SDimitry Andric #define TASK_CURRENT_QUEUED 1
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric #ifdef BUILD_TIED_TASK_STACK
350b57cec5SDimitry Andric #define TASK_STACK_EMPTY 0 // entries when the stack is empty
360b57cec5SDimitry Andric #define TASK_STACK_BLOCK_BITS 5 // Used in TASK_STACK_SIZE and TASK_STACK_MASK
370b57cec5SDimitry Andric // Number of entries in each task stack array
380b57cec5SDimitry Andric #define TASK_STACK_BLOCK_SIZE (1 << TASK_STACK_BLOCK_BITS)
390b57cec5SDimitry Andric // Mask for determining index into stack block
400b57cec5SDimitry Andric #define TASK_STACK_INDEX_MASK (TASK_STACK_BLOCK_SIZE - 1)
410b57cec5SDimitry Andric #endif // BUILD_TIED_TASK_STACK
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric #define TASK_NOT_PUSHED 1
440b57cec5SDimitry Andric #define TASK_SUCCESSFULLY_PUSHED 0
450b57cec5SDimitry Andric #define TASK_TIED 1
460b57cec5SDimitry Andric #define TASK_UNTIED 0
470b57cec5SDimitry Andric #define TASK_EXPLICIT 1
480b57cec5SDimitry Andric #define TASK_IMPLICIT 0
490b57cec5SDimitry Andric #define TASK_PROXY 1
500b57cec5SDimitry Andric #define TASK_FULL 0
510b57cec5SDimitry Andric #define TASK_DETACHABLE 1
520b57cec5SDimitry Andric #define TASK_UNDETACHABLE 0
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric #define KMP_CANCEL_THREADS
550b57cec5SDimitry Andric #define KMP_THREAD_ATTR
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric // Android does not have pthread_cancel.  Undefine KMP_CANCEL_THREADS if being
580b57cec5SDimitry Andric // built on Android
590b57cec5SDimitry Andric #if defined(__ANDROID__)
600b57cec5SDimitry Andric #undef KMP_CANCEL_THREADS
610b57cec5SDimitry Andric #endif
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric #include <signal.h>
640b57cec5SDimitry Andric #include <stdarg.h>
650b57cec5SDimitry Andric #include <stddef.h>
660b57cec5SDimitry Andric #include <stdio.h>
670b57cec5SDimitry Andric #include <stdlib.h>
680b57cec5SDimitry Andric #include <string.h>
69e8d8bef9SDimitry Andric #include <limits>
70e8d8bef9SDimitry Andric #include <type_traits>
710b57cec5SDimitry Andric /* include <ctype.h> don't use; problems with /MD on Windows* OS NT due to bad
720b57cec5SDimitry Andric    Microsoft library. Some macros provided below to replace these functions  */
730b57cec5SDimitry Andric #ifndef __ABSOFT_WIN
740b57cec5SDimitry Andric #include <sys/types.h>
750b57cec5SDimitry Andric #endif
760b57cec5SDimitry Andric #include <limits.h>
770b57cec5SDimitry Andric #include <time.h>
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric #include <errno.h>
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric #include "kmp_os.h"
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric #include "kmp_safe_c_api.h"
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric #if KMP_STATS_ENABLED
860b57cec5SDimitry Andric class kmp_stats_list;
870b57cec5SDimitry Andric #endif
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric #if KMP_USE_HIER_SCHED
900b57cec5SDimitry Andric // Only include hierarchical scheduling if affinity is supported
910b57cec5SDimitry Andric #undef KMP_USE_HIER_SCHED
920b57cec5SDimitry Andric #define KMP_USE_HIER_SCHED KMP_AFFINITY_SUPPORTED
930b57cec5SDimitry Andric #endif
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric #if KMP_USE_HWLOC && KMP_AFFINITY_SUPPORTED
960b57cec5SDimitry Andric #include "hwloc.h"
970b57cec5SDimitry Andric #ifndef HWLOC_OBJ_NUMANODE
980b57cec5SDimitry Andric #define HWLOC_OBJ_NUMANODE HWLOC_OBJ_NODE
990b57cec5SDimitry Andric #endif
1000b57cec5SDimitry Andric #ifndef HWLOC_OBJ_PACKAGE
1010b57cec5SDimitry Andric #define HWLOC_OBJ_PACKAGE HWLOC_OBJ_SOCKET
1020b57cec5SDimitry Andric #endif
1030b57cec5SDimitry Andric #endif
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
1060b57cec5SDimitry Andric #include <xmmintrin.h>
1070b57cec5SDimitry Andric #endif
1080b57cec5SDimitry Andric 
10981ad6265SDimitry Andric // The below has to be defined before including "kmp_barrier.h".
11081ad6265SDimitry Andric #define KMP_INTERNAL_MALLOC(sz) malloc(sz)
11181ad6265SDimitry Andric #define KMP_INTERNAL_FREE(p) free(p)
11281ad6265SDimitry Andric #define KMP_INTERNAL_REALLOC(p, sz) realloc((p), (sz))
11381ad6265SDimitry Andric #define KMP_INTERNAL_CALLOC(n, sz) calloc((n), (sz))
11481ad6265SDimitry Andric 
1150b57cec5SDimitry Andric #include "kmp_debug.h"
1160b57cec5SDimitry Andric #include "kmp_lock.h"
1170b57cec5SDimitry Andric #include "kmp_version.h"
118349cc55cSDimitry Andric #include "kmp_barrier.h"
1190b57cec5SDimitry Andric #if USE_DEBUGGER
1200b57cec5SDimitry Andric #include "kmp_debugger.h"
1210b57cec5SDimitry Andric #endif
1220b57cec5SDimitry Andric #include "kmp_i18n.h"
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric #define KMP_HANDLE_SIGNALS (KMP_OS_UNIX || KMP_OS_WINDOWS)
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric #include "kmp_wrapper_malloc.h"
1270b57cec5SDimitry Andric #if KMP_OS_UNIX
1280b57cec5SDimitry Andric #include <unistd.h>
1290b57cec5SDimitry Andric #if !defined NSIG && defined _NSIG
1300b57cec5SDimitry Andric #define NSIG _NSIG
1310b57cec5SDimitry Andric #endif
1320b57cec5SDimitry Andric #endif
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric #if KMP_OS_LINUX
1350b57cec5SDimitry Andric #pragma weak clock_gettime
1360b57cec5SDimitry Andric #endif
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric #if OMPT_SUPPORT
1390b57cec5SDimitry Andric #include "ompt-internal.h"
1400b57cec5SDimitry Andric #endif
1410b57cec5SDimitry Andric 
142fe6060f1SDimitry Andric #if OMPD_SUPPORT
143fe6060f1SDimitry Andric #include "ompd-specific.h"
144fe6060f1SDimitry Andric #endif
145fe6060f1SDimitry Andric 
146e8d8bef9SDimitry Andric #ifndef UNLIKELY
147e8d8bef9SDimitry Andric #define UNLIKELY(x) (x)
148e8d8bef9SDimitry Andric #endif
149e8d8bef9SDimitry Andric 
1500b57cec5SDimitry Andric // Affinity format function
1510b57cec5SDimitry Andric #include "kmp_str.h"
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric // 0 - no fast memory allocation, alignment: 8-byte on x86, 16-byte on x64.
1540b57cec5SDimitry Andric // 3 - fast allocation using sync, non-sync free lists of any size, non-self
1550b57cec5SDimitry Andric // free lists of limited size.
1560b57cec5SDimitry Andric #ifndef USE_FAST_MEMORY
1570b57cec5SDimitry Andric #define USE_FAST_MEMORY 3
1580b57cec5SDimitry Andric #endif
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric #ifndef KMP_NESTED_HOT_TEAMS
1610b57cec5SDimitry Andric #define KMP_NESTED_HOT_TEAMS 0
1620b57cec5SDimitry Andric #define USE_NESTED_HOT_ARG(x)
1630b57cec5SDimitry Andric #else
1640b57cec5SDimitry Andric #if KMP_NESTED_HOT_TEAMS
1650b57cec5SDimitry Andric #define USE_NESTED_HOT_ARG(x) , x
1660b57cec5SDimitry Andric #else
1670b57cec5SDimitry Andric #define USE_NESTED_HOT_ARG(x)
1680b57cec5SDimitry Andric #endif
1690b57cec5SDimitry Andric #endif
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric // Assume using BGET compare_exchange instruction instead of lock by default.
1720b57cec5SDimitry Andric #ifndef USE_CMP_XCHG_FOR_BGET
1730b57cec5SDimitry Andric #define USE_CMP_XCHG_FOR_BGET 1
1740b57cec5SDimitry Andric #endif
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric // Test to see if queuing lock is better than bootstrap lock for bget
1770b57cec5SDimitry Andric // #ifndef USE_QUEUING_LOCK_FOR_BGET
1780b57cec5SDimitry Andric // #define USE_QUEUING_LOCK_FOR_BGET
1790b57cec5SDimitry Andric // #endif
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric #define KMP_NSEC_PER_SEC 1000000000L
1820b57cec5SDimitry Andric #define KMP_USEC_PER_SEC 1000000L
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric /*!
1850b57cec5SDimitry Andric @ingroup BASIC_TYPES
1860b57cec5SDimitry Andric @{
1870b57cec5SDimitry Andric */
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric /*!
1900b57cec5SDimitry Andric Values for bit flags used in the ident_t to describe the fields.
1910b57cec5SDimitry Andric */
1920b57cec5SDimitry Andric enum {
1930b57cec5SDimitry Andric   /*! Use trampoline for internal microtasks */
1940b57cec5SDimitry Andric   KMP_IDENT_IMB = 0x01,
1950b57cec5SDimitry Andric   /*! Use c-style ident structure */
1960b57cec5SDimitry Andric   KMP_IDENT_KMPC = 0x02,
1970b57cec5SDimitry Andric   /* 0x04 is no longer used */
1980b57cec5SDimitry Andric   /*! Entry point generated by auto-parallelization */
1990b57cec5SDimitry Andric   KMP_IDENT_AUTOPAR = 0x08,
2000b57cec5SDimitry Andric   /*! Compiler generates atomic reduction option for kmpc_reduce* */
2010b57cec5SDimitry Andric   KMP_IDENT_ATOMIC_REDUCE = 0x10,
2020b57cec5SDimitry Andric   /*! To mark a 'barrier' directive in user code */
2030b57cec5SDimitry Andric   KMP_IDENT_BARRIER_EXPL = 0x20,
2040b57cec5SDimitry Andric   /*! To Mark implicit barriers. */
2050b57cec5SDimitry Andric   KMP_IDENT_BARRIER_IMPL = 0x0040,
2060b57cec5SDimitry Andric   KMP_IDENT_BARRIER_IMPL_MASK = 0x01C0,
2070b57cec5SDimitry Andric   KMP_IDENT_BARRIER_IMPL_FOR = 0x0040,
2080b57cec5SDimitry Andric   KMP_IDENT_BARRIER_IMPL_SECTIONS = 0x00C0,
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric   KMP_IDENT_BARRIER_IMPL_SINGLE = 0x0140,
2110b57cec5SDimitry Andric   KMP_IDENT_BARRIER_IMPL_WORKSHARE = 0x01C0,
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric   /*! To mark a static loop in OMPT callbacks */
2140b57cec5SDimitry Andric   KMP_IDENT_WORK_LOOP = 0x200,
2150b57cec5SDimitry Andric   /*! To mark a sections directive in OMPT callbacks */
2160b57cec5SDimitry Andric   KMP_IDENT_WORK_SECTIONS = 0x400,
217480093f4SDimitry Andric   /*! To mark a distribute construct in OMPT callbacks */
2180b57cec5SDimitry Andric   KMP_IDENT_WORK_DISTRIBUTE = 0x800,
2190b57cec5SDimitry Andric   /*! Atomic hint; bottom four bits as omp_sync_hint_t. Top four reserved and
2200b57cec5SDimitry Andric       not currently used. If one day we need more bits, then we can use
2210b57cec5SDimitry Andric       an invalid combination of hints to mean that another, larger field
2220b57cec5SDimitry Andric       should be used in a different flag. */
2230b57cec5SDimitry Andric   KMP_IDENT_ATOMIC_HINT_MASK = 0xFF0000,
2240b57cec5SDimitry Andric   KMP_IDENT_ATOMIC_HINT_UNCONTENDED = 0x010000,
2250b57cec5SDimitry Andric   KMP_IDENT_ATOMIC_HINT_CONTENDED = 0x020000,
2260b57cec5SDimitry Andric   KMP_IDENT_ATOMIC_HINT_NONSPECULATIVE = 0x040000,
2270b57cec5SDimitry Andric   KMP_IDENT_ATOMIC_HINT_SPECULATIVE = 0x080000,
228e8d8bef9SDimitry Andric   KMP_IDENT_OPENMP_SPEC_VERSION_MASK = 0xFF000000
2290b57cec5SDimitry Andric };
2300b57cec5SDimitry Andric 
2310b57cec5SDimitry Andric /*!
2320b57cec5SDimitry Andric  * The ident structure that describes a source location.
2330b57cec5SDimitry Andric  */
2340b57cec5SDimitry Andric typedef struct ident {
2350b57cec5SDimitry Andric   kmp_int32 reserved_1; /**<  might be used in Fortran; see above  */
2360b57cec5SDimitry Andric   kmp_int32 flags; /**<  also f.flags; KMP_IDENT_xxx flags; KMP_IDENT_KMPC
2370b57cec5SDimitry Andric                       identifies this union member  */
2380b57cec5SDimitry Andric   kmp_int32 reserved_2; /**<  not really used in Fortran any more; see above */
2390b57cec5SDimitry Andric #if USE_ITT_BUILD
2400b57cec5SDimitry Andric /*  but currently used for storing region-specific ITT */
2410b57cec5SDimitry Andric /*  contextual information. */
2420b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */
2430b57cec5SDimitry Andric   kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for C++  */
2440b57cec5SDimitry Andric   char const *psource; /**< String describing the source location.
2450b57cec5SDimitry Andric                        The string is composed of semi-colon separated fields
2460b57cec5SDimitry Andric                        which describe the source file, the function and a pair
2470b57cec5SDimitry Andric                        of line numbers that delimit the construct. */
248e8d8bef9SDimitry Andric   // Returns the OpenMP version in form major*10+minor (e.g., 50 for 5.0)
249e8d8bef9SDimitry Andric   kmp_int32 get_openmp_version() {
250e8d8bef9SDimitry Andric     return (((flags & KMP_IDENT_OPENMP_SPEC_VERSION_MASK) >> 24) & 0xFF);
251e8d8bef9SDimitry Andric   }
2520b57cec5SDimitry Andric } ident_t;
2530b57cec5SDimitry Andric /*!
2540b57cec5SDimitry Andric @}
2550b57cec5SDimitry Andric */
2560b57cec5SDimitry Andric 
2570b57cec5SDimitry Andric // Some forward declarations.
2580b57cec5SDimitry Andric typedef union kmp_team kmp_team_t;
2590b57cec5SDimitry Andric typedef struct kmp_taskdata kmp_taskdata_t;
2600b57cec5SDimitry Andric typedef union kmp_task_team kmp_task_team_t;
2610b57cec5SDimitry Andric typedef union kmp_team kmp_team_p;
2620b57cec5SDimitry Andric typedef union kmp_info kmp_info_p;
2630b57cec5SDimitry Andric typedef union kmp_root kmp_root_p;
2640b57cec5SDimitry Andric 
265e8d8bef9SDimitry Andric template <bool C = false, bool S = true> class kmp_flag_32;
266e8d8bef9SDimitry Andric template <bool C = false, bool S = true> class kmp_flag_64;
267349cc55cSDimitry Andric template <bool C = false, bool S = true> class kmp_atomic_flag_64;
268e8d8bef9SDimitry Andric class kmp_flag_oncore;
269e8d8bef9SDimitry Andric 
2700b57cec5SDimitry Andric #ifdef __cplusplus
2710b57cec5SDimitry Andric extern "C" {
2720b57cec5SDimitry Andric #endif
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric /* Pack two 32-bit signed integers into a 64-bit signed integer */
2770b57cec5SDimitry Andric /* ToDo: Fix word ordering for big-endian machines. */
2780b57cec5SDimitry Andric #define KMP_PACK_64(HIGH_32, LOW_32)                                           \
2790b57cec5SDimitry Andric   ((kmp_int64)((((kmp_uint64)(HIGH_32)) << 32) | (kmp_uint64)(LOW_32)))
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric // Generic string manipulation macros. Assume that _x is of type char *
2820b57cec5SDimitry Andric #define SKIP_WS(_x)                                                            \
2830b57cec5SDimitry Andric   {                                                                            \
2840b57cec5SDimitry Andric     while (*(_x) == ' ' || *(_x) == '\t')                                      \
2850b57cec5SDimitry Andric       (_x)++;                                                                  \
2860b57cec5SDimitry Andric   }
2870b57cec5SDimitry Andric #define SKIP_DIGITS(_x)                                                        \
2880b57cec5SDimitry Andric   {                                                                            \
2890b57cec5SDimitry Andric     while (*(_x) >= '0' && *(_x) <= '9')                                       \
2900b57cec5SDimitry Andric       (_x)++;                                                                  \
2910b57cec5SDimitry Andric   }
2920b57cec5SDimitry Andric #define SKIP_TOKEN(_x)                                                         \
2930b57cec5SDimitry Andric   {                                                                            \
2940b57cec5SDimitry Andric     while ((*(_x) >= '0' && *(_x) <= '9') || (*(_x) >= 'a' && *(_x) <= 'z') || \
2950b57cec5SDimitry Andric            (*(_x) >= 'A' && *(_x) <= 'Z') || *(_x) == '_')                     \
2960b57cec5SDimitry Andric       (_x)++;                                                                  \
2970b57cec5SDimitry Andric   }
2980b57cec5SDimitry Andric #define SKIP_TO(_x, _c)                                                        \
2990b57cec5SDimitry Andric   {                                                                            \
3000b57cec5SDimitry Andric     while (*(_x) != '\0' && *(_x) != (_c))                                     \
3010b57cec5SDimitry Andric       (_x)++;                                                                  \
3020b57cec5SDimitry Andric   }
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
3050b57cec5SDimitry Andric 
3060b57cec5SDimitry Andric #define KMP_MAX(x, y) ((x) > (y) ? (x) : (y))
3070b57cec5SDimitry Andric #define KMP_MIN(x, y) ((x) < (y) ? (x) : (y))
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
3100b57cec5SDimitry Andric /* Enumeration types */
3110b57cec5SDimitry Andric 
3120b57cec5SDimitry Andric enum kmp_state_timer {
3130b57cec5SDimitry Andric   ts_stop,
3140b57cec5SDimitry Andric   ts_start,
3150b57cec5SDimitry Andric   ts_pause,
3160b57cec5SDimitry Andric 
3170b57cec5SDimitry Andric   ts_last_state
3180b57cec5SDimitry Andric };
3190b57cec5SDimitry Andric 
3200b57cec5SDimitry Andric enum dynamic_mode {
3210b57cec5SDimitry Andric   dynamic_default,
3220b57cec5SDimitry Andric #ifdef USE_LOAD_BALANCE
3230b57cec5SDimitry Andric   dynamic_load_balance,
3240b57cec5SDimitry Andric #endif /* USE_LOAD_BALANCE */
3250b57cec5SDimitry Andric   dynamic_random,
3260b57cec5SDimitry Andric   dynamic_thread_limit,
3270b57cec5SDimitry Andric   dynamic_max
3280b57cec5SDimitry Andric };
3290b57cec5SDimitry Andric 
3300b57cec5SDimitry Andric /* external schedule constants, duplicate enum omp_sched in omp.h in order to
3310b57cec5SDimitry Andric  * not include it here */
3320b57cec5SDimitry Andric #ifndef KMP_SCHED_TYPE_DEFINED
3330b57cec5SDimitry Andric #define KMP_SCHED_TYPE_DEFINED
3340b57cec5SDimitry Andric typedef enum kmp_sched {
3350b57cec5SDimitry Andric   kmp_sched_lower = 0, // lower and upper bounds are for routine parameter check
3360b57cec5SDimitry Andric   // Note: need to adjust __kmp_sch_map global array in case enum is changed
3370b57cec5SDimitry Andric   kmp_sched_static = 1, // mapped to kmp_sch_static_chunked           (33)
3380b57cec5SDimitry Andric   kmp_sched_dynamic = 2, // mapped to kmp_sch_dynamic_chunked          (35)
3390b57cec5SDimitry Andric   kmp_sched_guided = 3, // mapped to kmp_sch_guided_chunked           (36)
3400b57cec5SDimitry Andric   kmp_sched_auto = 4, // mapped to kmp_sch_auto                     (38)
3410b57cec5SDimitry Andric   kmp_sched_upper_std = 5, // upper bound for standard schedules
3420b57cec5SDimitry Andric   kmp_sched_lower_ext = 100, // lower bound of Intel extension schedules
3430b57cec5SDimitry Andric   kmp_sched_trapezoidal = 101, // mapped to kmp_sch_trapezoidal (39)
3440b57cec5SDimitry Andric #if KMP_STATIC_STEAL_ENABLED
3450b57cec5SDimitry Andric   kmp_sched_static_steal = 102, // mapped to kmp_sch_static_steal (44)
3460b57cec5SDimitry Andric #endif
3470b57cec5SDimitry Andric   kmp_sched_upper,
3480b57cec5SDimitry Andric   kmp_sched_default = kmp_sched_static, // default scheduling
3490b57cec5SDimitry Andric   kmp_sched_monotonic = 0x80000000
3500b57cec5SDimitry Andric } kmp_sched_t;
3510b57cec5SDimitry Andric #endif
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric /*!
3540b57cec5SDimitry Andric  @ingroup WORK_SHARING
3550b57cec5SDimitry Andric  * Describes the loop schedule to be used for a parallel for loop.
3560b57cec5SDimitry Andric  */
3570b57cec5SDimitry Andric enum sched_type : kmp_int32 {
3580b57cec5SDimitry Andric   kmp_sch_lower = 32, /**< lower bound for unordered values */
3590b57cec5SDimitry Andric   kmp_sch_static_chunked = 33,
3600b57cec5SDimitry Andric   kmp_sch_static = 34, /**< static unspecialized */
3610b57cec5SDimitry Andric   kmp_sch_dynamic_chunked = 35,
3620b57cec5SDimitry Andric   kmp_sch_guided_chunked = 36, /**< guided unspecialized */
3630b57cec5SDimitry Andric   kmp_sch_runtime = 37,
3640b57cec5SDimitry Andric   kmp_sch_auto = 38, /**< auto */
3650b57cec5SDimitry Andric   kmp_sch_trapezoidal = 39,
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric   /* accessible only through KMP_SCHEDULE environment variable */
3680b57cec5SDimitry Andric   kmp_sch_static_greedy = 40,
3690b57cec5SDimitry Andric   kmp_sch_static_balanced = 41,
3700b57cec5SDimitry Andric   /* accessible only through KMP_SCHEDULE environment variable */
3710b57cec5SDimitry Andric   kmp_sch_guided_iterative_chunked = 42,
3720b57cec5SDimitry Andric   kmp_sch_guided_analytical_chunked = 43,
3730b57cec5SDimitry Andric   /* accessible only through KMP_SCHEDULE environment variable */
3740b57cec5SDimitry Andric   kmp_sch_static_steal = 44,
3750b57cec5SDimitry Andric 
3760b57cec5SDimitry Andric   /* static with chunk adjustment (e.g., simd) */
3770b57cec5SDimitry Andric   kmp_sch_static_balanced_chunked = 45,
3780b57cec5SDimitry Andric   kmp_sch_guided_simd = 46, /**< guided with chunk adjustment */
3790b57cec5SDimitry Andric   kmp_sch_runtime_simd = 47, /**< runtime with chunk adjustment */
3800b57cec5SDimitry Andric 
3810b57cec5SDimitry Andric   /* accessible only through KMP_SCHEDULE environment variable */
3820b57cec5SDimitry Andric   kmp_sch_upper, /**< upper bound for unordered values */
3830b57cec5SDimitry Andric 
3840b57cec5SDimitry Andric   kmp_ord_lower = 64, /**< lower bound for ordered values, must be power of 2 */
3850b57cec5SDimitry Andric   kmp_ord_static_chunked = 65,
3860b57cec5SDimitry Andric   kmp_ord_static = 66, /**< ordered static unspecialized */
3870b57cec5SDimitry Andric   kmp_ord_dynamic_chunked = 67,
3880b57cec5SDimitry Andric   kmp_ord_guided_chunked = 68,
3890b57cec5SDimitry Andric   kmp_ord_runtime = 69,
3900b57cec5SDimitry Andric   kmp_ord_auto = 70, /**< ordered auto */
3910b57cec5SDimitry Andric   kmp_ord_trapezoidal = 71,
3920b57cec5SDimitry Andric   kmp_ord_upper, /**< upper bound for ordered values */
3930b57cec5SDimitry Andric 
3940b57cec5SDimitry Andric   /* Schedules for Distribute construct */
3950b57cec5SDimitry Andric   kmp_distribute_static_chunked = 91, /**< distribute static chunked */
3960b57cec5SDimitry Andric   kmp_distribute_static = 92, /**< distribute static unspecialized */
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric   /* For the "nomerge" versions, kmp_dispatch_next*() will always return a
3990b57cec5SDimitry Andric      single iteration/chunk, even if the loop is serialized. For the schedule
4000b57cec5SDimitry Andric      types listed above, the entire iteration vector is returned if the loop is
4010b57cec5SDimitry Andric      serialized. This doesn't work for gcc/gcomp sections. */
4020b57cec5SDimitry Andric   kmp_nm_lower = 160, /**< lower bound for nomerge values */
4030b57cec5SDimitry Andric 
4040b57cec5SDimitry Andric   kmp_nm_static_chunked =
4050b57cec5SDimitry Andric       (kmp_sch_static_chunked - kmp_sch_lower + kmp_nm_lower),
4060b57cec5SDimitry Andric   kmp_nm_static = 162, /**< static unspecialized */
4070b57cec5SDimitry Andric   kmp_nm_dynamic_chunked = 163,
4080b57cec5SDimitry Andric   kmp_nm_guided_chunked = 164, /**< guided unspecialized */
4090b57cec5SDimitry Andric   kmp_nm_runtime = 165,
4100b57cec5SDimitry Andric   kmp_nm_auto = 166, /**< auto */
4110b57cec5SDimitry Andric   kmp_nm_trapezoidal = 167,
4120b57cec5SDimitry Andric 
4130b57cec5SDimitry Andric   /* accessible only through KMP_SCHEDULE environment variable */
4140b57cec5SDimitry Andric   kmp_nm_static_greedy = 168,
4150b57cec5SDimitry Andric   kmp_nm_static_balanced = 169,
4160b57cec5SDimitry Andric   /* accessible only through KMP_SCHEDULE environment variable */
4170b57cec5SDimitry Andric   kmp_nm_guided_iterative_chunked = 170,
4180b57cec5SDimitry Andric   kmp_nm_guided_analytical_chunked = 171,
4190b57cec5SDimitry Andric   kmp_nm_static_steal =
4200b57cec5SDimitry Andric       172, /* accessible only through OMP_SCHEDULE environment variable */
4210b57cec5SDimitry Andric 
4220b57cec5SDimitry Andric   kmp_nm_ord_static_chunked = 193,
4230b57cec5SDimitry Andric   kmp_nm_ord_static = 194, /**< ordered static unspecialized */
4240b57cec5SDimitry Andric   kmp_nm_ord_dynamic_chunked = 195,
4250b57cec5SDimitry Andric   kmp_nm_ord_guided_chunked = 196,
4260b57cec5SDimitry Andric   kmp_nm_ord_runtime = 197,
4270b57cec5SDimitry Andric   kmp_nm_ord_auto = 198, /**< auto */
4280b57cec5SDimitry Andric   kmp_nm_ord_trapezoidal = 199,
4290b57cec5SDimitry Andric   kmp_nm_upper, /**< upper bound for nomerge values */
4300b57cec5SDimitry Andric 
4310b57cec5SDimitry Andric   /* Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers. Since
4320b57cec5SDimitry Andric      we need to distinguish the three possible cases (no modifier, monotonic
4330b57cec5SDimitry Andric      modifier, nonmonotonic modifier), we need separate bits for each modifier.
4340b57cec5SDimitry Andric      The absence of monotonic does not imply nonmonotonic, especially since 4.5
4350b57cec5SDimitry Andric      says that the behaviour of the "no modifier" case is implementation defined
4360b57cec5SDimitry Andric      in 4.5, but will become "nonmonotonic" in 5.0.
4370b57cec5SDimitry Andric 
4380b57cec5SDimitry Andric      Since we're passing a full 32 bit value, we can use a couple of high bits
4390b57cec5SDimitry Andric      for these flags; out of paranoia we avoid the sign bit.
4400b57cec5SDimitry Andric 
4410b57cec5SDimitry Andric      These modifiers can be or-ed into non-static schedules by the compiler to
4420b57cec5SDimitry Andric      pass the additional information. They will be stripped early in the
4430b57cec5SDimitry Andric      processing in __kmp_dispatch_init when setting up schedules, so most of the
4440b57cec5SDimitry Andric      code won't ever see schedules with these bits set.  */
4450b57cec5SDimitry Andric   kmp_sch_modifier_monotonic =
4460b57cec5SDimitry Andric       (1 << 29), /**< Set if the monotonic schedule modifier was present */
4470b57cec5SDimitry Andric   kmp_sch_modifier_nonmonotonic =
4480b57cec5SDimitry Andric       (1 << 30), /**< Set if the nonmonotonic schedule modifier was present */
4490b57cec5SDimitry Andric 
4500b57cec5SDimitry Andric #define SCHEDULE_WITHOUT_MODIFIERS(s)                                          \
4510b57cec5SDimitry Andric   (enum sched_type)(                                                           \
4520b57cec5SDimitry Andric       (s) & ~(kmp_sch_modifier_nonmonotonic | kmp_sch_modifier_monotonic))
4530b57cec5SDimitry Andric #define SCHEDULE_HAS_MONOTONIC(s) (((s)&kmp_sch_modifier_monotonic) != 0)
4540b57cec5SDimitry Andric #define SCHEDULE_HAS_NONMONOTONIC(s) (((s)&kmp_sch_modifier_nonmonotonic) != 0)
4550b57cec5SDimitry Andric #define SCHEDULE_HAS_NO_MODIFIERS(s)                                           \
4560b57cec5SDimitry Andric   (((s) & (kmp_sch_modifier_nonmonotonic | kmp_sch_modifier_monotonic)) == 0)
4570b57cec5SDimitry Andric #define SCHEDULE_GET_MODIFIERS(s)                                              \
4580b57cec5SDimitry Andric   ((enum sched_type)(                                                          \
4590b57cec5SDimitry Andric       (s) & (kmp_sch_modifier_nonmonotonic | kmp_sch_modifier_monotonic)))
4600b57cec5SDimitry Andric #define SCHEDULE_SET_MODIFIERS(s, m)                                           \
4610b57cec5SDimitry Andric   (s = (enum sched_type)((kmp_int32)s | (kmp_int32)m))
4620b57cec5SDimitry Andric #define SCHEDULE_NONMONOTONIC 0
4630b57cec5SDimitry Andric #define SCHEDULE_MONOTONIC 1
4640b57cec5SDimitry Andric 
4650b57cec5SDimitry Andric   kmp_sch_default = kmp_sch_static /**< default scheduling algorithm */
4660b57cec5SDimitry Andric };
4670b57cec5SDimitry Andric 
4680b57cec5SDimitry Andric // Apply modifiers on internal kind to standard kind
4690b57cec5SDimitry Andric static inline void
4700b57cec5SDimitry Andric __kmp_sched_apply_mods_stdkind(kmp_sched_t *kind,
4710b57cec5SDimitry Andric                                enum sched_type internal_kind) {
4720b57cec5SDimitry Andric   if (SCHEDULE_HAS_MONOTONIC(internal_kind)) {
4730b57cec5SDimitry Andric     *kind = (kmp_sched_t)((int)*kind | (int)kmp_sched_monotonic);
4740b57cec5SDimitry Andric   }
4750b57cec5SDimitry Andric }
4760b57cec5SDimitry Andric 
4770b57cec5SDimitry Andric // Apply modifiers on standard kind to internal kind
4780b57cec5SDimitry Andric static inline void
4790b57cec5SDimitry Andric __kmp_sched_apply_mods_intkind(kmp_sched_t kind,
4800b57cec5SDimitry Andric                                enum sched_type *internal_kind) {
4810b57cec5SDimitry Andric   if ((int)kind & (int)kmp_sched_monotonic) {
4820b57cec5SDimitry Andric     *internal_kind = (enum sched_type)((int)*internal_kind |
4830b57cec5SDimitry Andric                                        (int)kmp_sch_modifier_monotonic);
4840b57cec5SDimitry Andric   }
4850b57cec5SDimitry Andric }
4860b57cec5SDimitry Andric 
4870b57cec5SDimitry Andric // Get standard schedule without modifiers
4880b57cec5SDimitry Andric static inline kmp_sched_t __kmp_sched_without_mods(kmp_sched_t kind) {
4890b57cec5SDimitry Andric   return (kmp_sched_t)((int)kind & ~((int)kmp_sched_monotonic));
4900b57cec5SDimitry Andric }
4910b57cec5SDimitry Andric 
4920b57cec5SDimitry Andric /* Type to keep runtime schedule set via OMP_SCHEDULE or omp_set_schedule() */
4930b57cec5SDimitry Andric typedef union kmp_r_sched {
4940b57cec5SDimitry Andric   struct {
4950b57cec5SDimitry Andric     enum sched_type r_sched_type;
4960b57cec5SDimitry Andric     int chunk;
4970b57cec5SDimitry Andric   };
4980b57cec5SDimitry Andric   kmp_int64 sched;
4990b57cec5SDimitry Andric } kmp_r_sched_t;
5000b57cec5SDimitry Andric 
5010b57cec5SDimitry Andric extern enum sched_type __kmp_sch_map[]; // map OMP 3.0 schedule types with our
5020b57cec5SDimitry Andric // internal schedule types
5030b57cec5SDimitry Andric 
5040b57cec5SDimitry Andric enum library_type {
5050b57cec5SDimitry Andric   library_none,
5060b57cec5SDimitry Andric   library_serial,
5070b57cec5SDimitry Andric   library_turnaround,
5080b57cec5SDimitry Andric   library_throughput
5090b57cec5SDimitry Andric };
5100b57cec5SDimitry Andric 
5110b57cec5SDimitry Andric #if KMP_OS_LINUX
5120b57cec5SDimitry Andric enum clock_function_type {
5130b57cec5SDimitry Andric   clock_function_gettimeofday,
5140b57cec5SDimitry Andric   clock_function_clock_gettime
5150b57cec5SDimitry Andric };
5160b57cec5SDimitry Andric #endif /* KMP_OS_LINUX */
5170b57cec5SDimitry Andric 
5180b57cec5SDimitry Andric #if KMP_MIC_SUPPORTED
5190b57cec5SDimitry Andric enum mic_type { non_mic, mic1, mic2, mic3, dummy };
5200b57cec5SDimitry Andric #endif
5210b57cec5SDimitry Andric 
5220b57cec5SDimitry Andric /* -- fast reduction stuff ------------------------------------------------ */
5230b57cec5SDimitry Andric 
5240b57cec5SDimitry Andric #undef KMP_FAST_REDUCTION_BARRIER
5250b57cec5SDimitry Andric #define KMP_FAST_REDUCTION_BARRIER 1
5260b57cec5SDimitry Andric 
5270b57cec5SDimitry Andric #undef KMP_FAST_REDUCTION_CORE_DUO
5280b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
5290b57cec5SDimitry Andric #define KMP_FAST_REDUCTION_CORE_DUO 1
5300b57cec5SDimitry Andric #endif
5310b57cec5SDimitry Andric 
5320b57cec5SDimitry Andric enum _reduction_method {
5330b57cec5SDimitry Andric   reduction_method_not_defined = 0,
5340b57cec5SDimitry Andric   critical_reduce_block = (1 << 8),
5350b57cec5SDimitry Andric   atomic_reduce_block = (2 << 8),
5360b57cec5SDimitry Andric   tree_reduce_block = (3 << 8),
5370b57cec5SDimitry Andric   empty_reduce_block = (4 << 8)
5380b57cec5SDimitry Andric };
5390b57cec5SDimitry Andric 
5400b57cec5SDimitry Andric // Description of the packed_reduction_method variable:
5410b57cec5SDimitry Andric // The packed_reduction_method variable consists of two enum types variables
5420b57cec5SDimitry Andric // that are packed together into 0-th byte and 1-st byte:
5430b57cec5SDimitry Andric // 0: (packed_reduction_method & 0x000000FF) is a 'enum barrier_type' value of
5440b57cec5SDimitry Andric // barrier that will be used in fast reduction: bs_plain_barrier or
5450b57cec5SDimitry Andric // bs_reduction_barrier
5460b57cec5SDimitry Andric // 1: (packed_reduction_method & 0x0000FF00) is a reduction method that will
5470b57cec5SDimitry Andric // be used in fast reduction;
5480b57cec5SDimitry Andric // Reduction method is of 'enum _reduction_method' type and it's defined the way
5490b57cec5SDimitry Andric // so that the bits of 0-th byte are empty, so no need to execute a shift
5500b57cec5SDimitry Andric // instruction while packing/unpacking
5510b57cec5SDimitry Andric 
5520b57cec5SDimitry Andric #if KMP_FAST_REDUCTION_BARRIER
5530b57cec5SDimitry Andric #define PACK_REDUCTION_METHOD_AND_BARRIER(reduction_method, barrier_type)      \
5540b57cec5SDimitry Andric   ((reduction_method) | (barrier_type))
5550b57cec5SDimitry Andric 
5560b57cec5SDimitry Andric #define UNPACK_REDUCTION_METHOD(packed_reduction_method)                       \
5570b57cec5SDimitry Andric   ((enum _reduction_method)((packed_reduction_method) & (0x0000FF00)))
5580b57cec5SDimitry Andric 
5590b57cec5SDimitry Andric #define UNPACK_REDUCTION_BARRIER(packed_reduction_method)                      \
5600b57cec5SDimitry Andric   ((enum barrier_type)((packed_reduction_method) & (0x000000FF)))
5610b57cec5SDimitry Andric #else
5620b57cec5SDimitry Andric #define PACK_REDUCTION_METHOD_AND_BARRIER(reduction_method, barrier_type)      \
5630b57cec5SDimitry Andric   (reduction_method)
5640b57cec5SDimitry Andric 
5650b57cec5SDimitry Andric #define UNPACK_REDUCTION_METHOD(packed_reduction_method)                       \
5660b57cec5SDimitry Andric   (packed_reduction_method)
5670b57cec5SDimitry Andric 
5680b57cec5SDimitry Andric #define UNPACK_REDUCTION_BARRIER(packed_reduction_method) (bs_plain_barrier)
5690b57cec5SDimitry Andric #endif
5700b57cec5SDimitry Andric 
5710b57cec5SDimitry Andric #define TEST_REDUCTION_METHOD(packed_reduction_method, which_reduction_block)  \
5720b57cec5SDimitry Andric   ((UNPACK_REDUCTION_METHOD(packed_reduction_method)) ==                       \
5730b57cec5SDimitry Andric    (which_reduction_block))
5740b57cec5SDimitry Andric 
5750b57cec5SDimitry Andric #if KMP_FAST_REDUCTION_BARRIER
5760b57cec5SDimitry Andric #define TREE_REDUCE_BLOCK_WITH_REDUCTION_BARRIER                               \
5770b57cec5SDimitry Andric   (PACK_REDUCTION_METHOD_AND_BARRIER(tree_reduce_block, bs_reduction_barrier))
5780b57cec5SDimitry Andric 
5790b57cec5SDimitry Andric #define TREE_REDUCE_BLOCK_WITH_PLAIN_BARRIER                                   \
5800b57cec5SDimitry Andric   (PACK_REDUCTION_METHOD_AND_BARRIER(tree_reduce_block, bs_plain_barrier))
5810b57cec5SDimitry Andric #endif
5820b57cec5SDimitry Andric 
5830b57cec5SDimitry Andric typedef int PACKED_REDUCTION_METHOD_T;
5840b57cec5SDimitry Andric 
5850b57cec5SDimitry Andric /* -- end of fast reduction stuff ----------------------------------------- */
5860b57cec5SDimitry Andric 
5870b57cec5SDimitry Andric #if KMP_OS_WINDOWS
5880b57cec5SDimitry Andric #define USE_CBLKDATA
5890b57cec5SDimitry Andric #if KMP_MSVC_COMPAT
5900b57cec5SDimitry Andric #pragma warning(push)
5910b57cec5SDimitry Andric #pragma warning(disable : 271 310)
5920b57cec5SDimitry Andric #endif
5930b57cec5SDimitry Andric #include <windows.h>
5940b57cec5SDimitry Andric #if KMP_MSVC_COMPAT
5950b57cec5SDimitry Andric #pragma warning(pop)
5960b57cec5SDimitry Andric #endif
5970b57cec5SDimitry Andric #endif
5980b57cec5SDimitry Andric 
5990b57cec5SDimitry Andric #if KMP_OS_UNIX
6000b57cec5SDimitry Andric #include <dlfcn.h>
6010b57cec5SDimitry Andric #include <pthread.h>
6020b57cec5SDimitry Andric #endif
6030b57cec5SDimitry Andric 
604fe6060f1SDimitry Andric enum kmp_hw_t : int {
605fe6060f1SDimitry Andric   KMP_HW_UNKNOWN = -1,
606fe6060f1SDimitry Andric   KMP_HW_SOCKET = 0,
607fe6060f1SDimitry Andric   KMP_HW_PROC_GROUP,
608fe6060f1SDimitry Andric   KMP_HW_NUMA,
609fe6060f1SDimitry Andric   KMP_HW_DIE,
610fe6060f1SDimitry Andric   KMP_HW_LLC,
611fe6060f1SDimitry Andric   KMP_HW_L3,
612fe6060f1SDimitry Andric   KMP_HW_TILE,
613fe6060f1SDimitry Andric   KMP_HW_MODULE,
614fe6060f1SDimitry Andric   KMP_HW_L2,
615fe6060f1SDimitry Andric   KMP_HW_L1,
616fe6060f1SDimitry Andric   KMP_HW_CORE,
617fe6060f1SDimitry Andric   KMP_HW_THREAD,
618fe6060f1SDimitry Andric   KMP_HW_LAST
619fe6060f1SDimitry Andric };
620fe6060f1SDimitry Andric 
6210eae32dcSDimitry Andric typedef enum kmp_hw_core_type_t {
6220eae32dcSDimitry Andric   KMP_HW_CORE_TYPE_UNKNOWN = 0x0,
6230eae32dcSDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
6240eae32dcSDimitry Andric   KMP_HW_CORE_TYPE_ATOM = 0x20,
6250eae32dcSDimitry Andric   KMP_HW_CORE_TYPE_CORE = 0x40,
6260eae32dcSDimitry Andric   KMP_HW_MAX_NUM_CORE_TYPES = 3,
6270eae32dcSDimitry Andric #else
6280eae32dcSDimitry Andric   KMP_HW_MAX_NUM_CORE_TYPES = 1,
6290eae32dcSDimitry Andric #endif
6300eae32dcSDimitry Andric } kmp_hw_core_type_t;
6310eae32dcSDimitry Andric 
6320eae32dcSDimitry Andric #define KMP_HW_MAX_NUM_CORE_EFFS 8
6330eae32dcSDimitry Andric 
634fe6060f1SDimitry Andric #define KMP_DEBUG_ASSERT_VALID_HW_TYPE(type)                                   \
635fe6060f1SDimitry Andric   KMP_DEBUG_ASSERT(type >= (kmp_hw_t)0 && type < KMP_HW_LAST)
636fe6060f1SDimitry Andric #define KMP_ASSERT_VALID_HW_TYPE(type)                                         \
637fe6060f1SDimitry Andric   KMP_ASSERT(type >= (kmp_hw_t)0 && type < KMP_HW_LAST)
638fe6060f1SDimitry Andric 
639fe6060f1SDimitry Andric #define KMP_FOREACH_HW_TYPE(type)                                              \
640fe6060f1SDimitry Andric   for (kmp_hw_t type = (kmp_hw_t)0; type < KMP_HW_LAST;                        \
641fe6060f1SDimitry Andric        type = (kmp_hw_t)((int)type + 1))
642fe6060f1SDimitry Andric 
643fe6060f1SDimitry Andric const char *__kmp_hw_get_keyword(kmp_hw_t type, bool plural = false);
644fe6060f1SDimitry Andric const char *__kmp_hw_get_catalog_string(kmp_hw_t type, bool plural = false);
6450eae32dcSDimitry Andric const char *__kmp_hw_get_core_type_string(kmp_hw_core_type_t type);
646fe6060f1SDimitry Andric 
6470b57cec5SDimitry Andric /* Only Linux* OS and Windows* OS support thread affinity. */
6480b57cec5SDimitry Andric #if KMP_AFFINITY_SUPPORTED
6490b57cec5SDimitry Andric 
6500b57cec5SDimitry Andric // GROUP_AFFINITY is already defined for _MSC_VER>=1600 (VS2010 and later).
6510b57cec5SDimitry Andric #if KMP_OS_WINDOWS
6520b57cec5SDimitry Andric #if _MSC_VER < 1600 && KMP_MSVC_COMPAT
6530b57cec5SDimitry Andric typedef struct GROUP_AFFINITY {
6540b57cec5SDimitry Andric   KAFFINITY Mask;
6550b57cec5SDimitry Andric   WORD Group;
6560b57cec5SDimitry Andric   WORD Reserved[3];
6570b57cec5SDimitry Andric } GROUP_AFFINITY;
6580b57cec5SDimitry Andric #endif /* _MSC_VER < 1600 */
6590b57cec5SDimitry Andric #if KMP_GROUP_AFFINITY
6600b57cec5SDimitry Andric extern int __kmp_num_proc_groups;
6610b57cec5SDimitry Andric #else
6620b57cec5SDimitry Andric static const int __kmp_num_proc_groups = 1;
6630b57cec5SDimitry Andric #endif /* KMP_GROUP_AFFINITY */
6640b57cec5SDimitry Andric typedef DWORD (*kmp_GetActiveProcessorCount_t)(WORD);
6650b57cec5SDimitry Andric extern kmp_GetActiveProcessorCount_t __kmp_GetActiveProcessorCount;
6660b57cec5SDimitry Andric 
6670b57cec5SDimitry Andric typedef WORD (*kmp_GetActiveProcessorGroupCount_t)(void);
6680b57cec5SDimitry Andric extern kmp_GetActiveProcessorGroupCount_t __kmp_GetActiveProcessorGroupCount;
6690b57cec5SDimitry Andric 
6700b57cec5SDimitry Andric typedef BOOL (*kmp_GetThreadGroupAffinity_t)(HANDLE, GROUP_AFFINITY *);
6710b57cec5SDimitry Andric extern kmp_GetThreadGroupAffinity_t __kmp_GetThreadGroupAffinity;
6720b57cec5SDimitry Andric 
6730b57cec5SDimitry Andric typedef BOOL (*kmp_SetThreadGroupAffinity_t)(HANDLE, const GROUP_AFFINITY *,
6740b57cec5SDimitry Andric                                              GROUP_AFFINITY *);
6750b57cec5SDimitry Andric extern kmp_SetThreadGroupAffinity_t __kmp_SetThreadGroupAffinity;
6760b57cec5SDimitry Andric #endif /* KMP_OS_WINDOWS */
6770b57cec5SDimitry Andric 
6780b57cec5SDimitry Andric #if KMP_USE_HWLOC
6790b57cec5SDimitry Andric extern hwloc_topology_t __kmp_hwloc_topology;
6800b57cec5SDimitry Andric extern int __kmp_hwloc_error;
6810b57cec5SDimitry Andric #endif
6820b57cec5SDimitry Andric 
6830b57cec5SDimitry Andric extern size_t __kmp_affin_mask_size;
6840b57cec5SDimitry Andric #define KMP_AFFINITY_CAPABLE() (__kmp_affin_mask_size > 0)
6850b57cec5SDimitry Andric #define KMP_AFFINITY_DISABLE() (__kmp_affin_mask_size = 0)
6860b57cec5SDimitry Andric #define KMP_AFFINITY_ENABLE(mask_size) (__kmp_affin_mask_size = mask_size)
6870b57cec5SDimitry Andric #define KMP_CPU_SET_ITERATE(i, mask)                                           \
6880b57cec5SDimitry Andric   for (i = (mask)->begin(); (int)i != (mask)->end(); i = (mask)->next(i))
6890b57cec5SDimitry Andric #define KMP_CPU_SET(i, mask) (mask)->set(i)
6900b57cec5SDimitry Andric #define KMP_CPU_ISSET(i, mask) (mask)->is_set(i)
6910b57cec5SDimitry Andric #define KMP_CPU_CLR(i, mask) (mask)->clear(i)
6920b57cec5SDimitry Andric #define KMP_CPU_ZERO(mask) (mask)->zero()
6930b57cec5SDimitry Andric #define KMP_CPU_COPY(dest, src) (dest)->copy(src)
6940b57cec5SDimitry Andric #define KMP_CPU_AND(dest, src) (dest)->bitwise_and(src)
6950b57cec5SDimitry Andric #define KMP_CPU_COMPLEMENT(max_bit_number, mask) (mask)->bitwise_not()
6960b57cec5SDimitry Andric #define KMP_CPU_UNION(dest, src) (dest)->bitwise_or(src)
6970b57cec5SDimitry Andric #define KMP_CPU_ALLOC(ptr) (ptr = __kmp_affinity_dispatch->allocate_mask())
6980b57cec5SDimitry Andric #define KMP_CPU_FREE(ptr) __kmp_affinity_dispatch->deallocate_mask(ptr)
6990b57cec5SDimitry Andric #define KMP_CPU_ALLOC_ON_STACK(ptr) KMP_CPU_ALLOC(ptr)
7000b57cec5SDimitry Andric #define KMP_CPU_FREE_FROM_STACK(ptr) KMP_CPU_FREE(ptr)
7010b57cec5SDimitry Andric #define KMP_CPU_INTERNAL_ALLOC(ptr) KMP_CPU_ALLOC(ptr)
7020b57cec5SDimitry Andric #define KMP_CPU_INTERNAL_FREE(ptr) KMP_CPU_FREE(ptr)
7030b57cec5SDimitry Andric #define KMP_CPU_INDEX(arr, i) __kmp_affinity_dispatch->index_mask_array(arr, i)
7040b57cec5SDimitry Andric #define KMP_CPU_ALLOC_ARRAY(arr, n)                                            \
7050b57cec5SDimitry Andric   (arr = __kmp_affinity_dispatch->allocate_mask_array(n))
7060b57cec5SDimitry Andric #define KMP_CPU_FREE_ARRAY(arr, n)                                             \
7070b57cec5SDimitry Andric   __kmp_affinity_dispatch->deallocate_mask_array(arr)
7080b57cec5SDimitry Andric #define KMP_CPU_INTERNAL_ALLOC_ARRAY(arr, n) KMP_CPU_ALLOC_ARRAY(arr, n)
7090b57cec5SDimitry Andric #define KMP_CPU_INTERNAL_FREE_ARRAY(arr, n) KMP_CPU_FREE_ARRAY(arr, n)
7100b57cec5SDimitry Andric #define __kmp_get_system_affinity(mask, abort_bool)                            \
7110b57cec5SDimitry Andric   (mask)->get_system_affinity(abort_bool)
7120b57cec5SDimitry Andric #define __kmp_set_system_affinity(mask, abort_bool)                            \
7130b57cec5SDimitry Andric   (mask)->set_system_affinity(abort_bool)
7140b57cec5SDimitry Andric #define __kmp_get_proc_group(mask) (mask)->get_proc_group()
7150b57cec5SDimitry Andric 
7160b57cec5SDimitry Andric class KMPAffinity {
7170b57cec5SDimitry Andric public:
7180b57cec5SDimitry Andric   class Mask {
7190b57cec5SDimitry Andric   public:
7200b57cec5SDimitry Andric     void *operator new(size_t n);
7210b57cec5SDimitry Andric     void operator delete(void *p);
7220b57cec5SDimitry Andric     void *operator new[](size_t n);
7230b57cec5SDimitry Andric     void operator delete[](void *p);
7240b57cec5SDimitry Andric     virtual ~Mask() {}
7250b57cec5SDimitry Andric     // Set bit i to 1
7260b57cec5SDimitry Andric     virtual void set(int i) {}
7270b57cec5SDimitry Andric     // Return bit i
7280b57cec5SDimitry Andric     virtual bool is_set(int i) const { return false; }
7290b57cec5SDimitry Andric     // Set bit i to 0
7300b57cec5SDimitry Andric     virtual void clear(int i) {}
7310b57cec5SDimitry Andric     // Zero out entire mask
7320b57cec5SDimitry Andric     virtual void zero() {}
7330b57cec5SDimitry Andric     // Copy src into this mask
7340b57cec5SDimitry Andric     virtual void copy(const Mask *src) {}
7350b57cec5SDimitry Andric     // this &= rhs
7360b57cec5SDimitry Andric     virtual void bitwise_and(const Mask *rhs) {}
7370b57cec5SDimitry Andric     // this |= rhs
7380b57cec5SDimitry Andric     virtual void bitwise_or(const Mask *rhs) {}
7390b57cec5SDimitry Andric     // this = ~this
7400b57cec5SDimitry Andric     virtual void bitwise_not() {}
7410b57cec5SDimitry Andric     // API for iterating over an affinity mask
7420b57cec5SDimitry Andric     // for (int i = mask->begin(); i != mask->end(); i = mask->next(i))
7430b57cec5SDimitry Andric     virtual int begin() const { return 0; }
7440b57cec5SDimitry Andric     virtual int end() const { return 0; }
7450b57cec5SDimitry Andric     virtual int next(int previous) const { return 0; }
746e8d8bef9SDimitry Andric #if KMP_OS_WINDOWS
747e8d8bef9SDimitry Andric     virtual int set_process_affinity(bool abort_on_error) const { return -1; }
748e8d8bef9SDimitry Andric #endif
7490b57cec5SDimitry Andric     // Set the system's affinity to this affinity mask's value
7500b57cec5SDimitry Andric     virtual int set_system_affinity(bool abort_on_error) const { return -1; }
7510b57cec5SDimitry Andric     // Set this affinity mask to the current system affinity
7520b57cec5SDimitry Andric     virtual int get_system_affinity(bool abort_on_error) { return -1; }
7530b57cec5SDimitry Andric     // Only 1 DWORD in the mask should have any procs set.
7540b57cec5SDimitry Andric     // Return the appropriate index, or -1 for an invalid mask.
7550b57cec5SDimitry Andric     virtual int get_proc_group() const { return -1; }
756*bdd1243dSDimitry Andric     int get_max_cpu() const {
757*bdd1243dSDimitry Andric       int cpu;
758*bdd1243dSDimitry Andric       int max_cpu = -1;
759*bdd1243dSDimitry Andric       KMP_CPU_SET_ITERATE(cpu, this) {
760*bdd1243dSDimitry Andric         if (cpu > max_cpu)
761*bdd1243dSDimitry Andric           max_cpu = cpu;
762*bdd1243dSDimitry Andric       }
763*bdd1243dSDimitry Andric       return max_cpu;
764*bdd1243dSDimitry Andric     }
7650b57cec5SDimitry Andric   };
7660b57cec5SDimitry Andric   void *operator new(size_t n);
7670b57cec5SDimitry Andric   void operator delete(void *p);
7680b57cec5SDimitry Andric   // Need virtual destructor
7690b57cec5SDimitry Andric   virtual ~KMPAffinity() = default;
7700b57cec5SDimitry Andric   // Determine if affinity is capable
7710b57cec5SDimitry Andric   virtual void determine_capable(const char *env_var) {}
7720b57cec5SDimitry Andric   // Bind the current thread to os proc
7730b57cec5SDimitry Andric   virtual void bind_thread(int proc) {}
7740b57cec5SDimitry Andric   // Factory functions to allocate/deallocate a mask
7750b57cec5SDimitry Andric   virtual Mask *allocate_mask() { return nullptr; }
7760b57cec5SDimitry Andric   virtual void deallocate_mask(Mask *m) {}
7770b57cec5SDimitry Andric   virtual Mask *allocate_mask_array(int num) { return nullptr; }
7780b57cec5SDimitry Andric   virtual void deallocate_mask_array(Mask *m) {}
7790b57cec5SDimitry Andric   virtual Mask *index_mask_array(Mask *m, int index) { return nullptr; }
7800b57cec5SDimitry Andric   static void pick_api();
7810b57cec5SDimitry Andric   static void destroy_api();
7820b57cec5SDimitry Andric   enum api_type {
7830b57cec5SDimitry Andric     NATIVE_OS
7840b57cec5SDimitry Andric #if KMP_USE_HWLOC
7850b57cec5SDimitry Andric     ,
7860b57cec5SDimitry Andric     HWLOC
7870b57cec5SDimitry Andric #endif
7880b57cec5SDimitry Andric   };
7890b57cec5SDimitry Andric   virtual api_type get_api_type() const {
7900b57cec5SDimitry Andric     KMP_ASSERT(0);
7910b57cec5SDimitry Andric     return NATIVE_OS;
7920b57cec5SDimitry Andric   }
7930b57cec5SDimitry Andric 
7940b57cec5SDimitry Andric private:
7950b57cec5SDimitry Andric   static bool picked_api;
7960b57cec5SDimitry Andric };
7970b57cec5SDimitry Andric 
7980b57cec5SDimitry Andric typedef KMPAffinity::Mask kmp_affin_mask_t;
7990b57cec5SDimitry Andric extern KMPAffinity *__kmp_affinity_dispatch;
8000b57cec5SDimitry Andric 
8010b57cec5SDimitry Andric // Declare local char buffers with this size for printing debug and info
8020b57cec5SDimitry Andric // messages, using __kmp_affinity_print_mask().
8030b57cec5SDimitry Andric #define KMP_AFFIN_MASK_PRINT_LEN 1024
8040b57cec5SDimitry Andric 
8050b57cec5SDimitry Andric enum affinity_type {
8060b57cec5SDimitry Andric   affinity_none = 0,
8070b57cec5SDimitry Andric   affinity_physical,
8080b57cec5SDimitry Andric   affinity_logical,
8090b57cec5SDimitry Andric   affinity_compact,
8100b57cec5SDimitry Andric   affinity_scatter,
8110b57cec5SDimitry Andric   affinity_explicit,
8120b57cec5SDimitry Andric   affinity_balanced,
8130b57cec5SDimitry Andric   affinity_disabled, // not used outsize the env var parser
8140b57cec5SDimitry Andric   affinity_default
8150b57cec5SDimitry Andric };
8160b57cec5SDimitry Andric 
8170b57cec5SDimitry Andric enum affinity_top_method {
8180b57cec5SDimitry Andric   affinity_top_method_all = 0, // try all (supported) methods, in order
8190b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
8200b57cec5SDimitry Andric   affinity_top_method_apicid,
8210b57cec5SDimitry Andric   affinity_top_method_x2apicid,
822fe6060f1SDimitry Andric   affinity_top_method_x2apicid_1f,
8230b57cec5SDimitry Andric #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
8240b57cec5SDimitry Andric   affinity_top_method_cpuinfo, // KMP_CPUINFO_FILE is usable on Windows* OS, too
8250b57cec5SDimitry Andric #if KMP_GROUP_AFFINITY
8260b57cec5SDimitry Andric   affinity_top_method_group,
8270b57cec5SDimitry Andric #endif /* KMP_GROUP_AFFINITY */
8280b57cec5SDimitry Andric   affinity_top_method_flat,
8290b57cec5SDimitry Andric #if KMP_USE_HWLOC
8300b57cec5SDimitry Andric   affinity_top_method_hwloc,
8310b57cec5SDimitry Andric #endif
8320b57cec5SDimitry Andric   affinity_top_method_default
8330b57cec5SDimitry Andric };
8340b57cec5SDimitry Andric 
835*bdd1243dSDimitry Andric #define affinity_respect_mask_default (2)
8360b57cec5SDimitry Andric 
837*bdd1243dSDimitry Andric typedef struct kmp_affinity_flags_t {
838*bdd1243dSDimitry Andric   unsigned dups : 1;
839*bdd1243dSDimitry Andric   unsigned verbose : 1;
840*bdd1243dSDimitry Andric   unsigned warnings : 1;
841*bdd1243dSDimitry Andric   unsigned respect : 2;
842*bdd1243dSDimitry Andric   unsigned reset : 1;
843*bdd1243dSDimitry Andric   unsigned initialized : 1;
844*bdd1243dSDimitry Andric   unsigned reserved : 25;
845*bdd1243dSDimitry Andric } kmp_affinity_flags_t;
846*bdd1243dSDimitry Andric KMP_BUILD_ASSERT(sizeof(kmp_affinity_flags_t) == 4);
847*bdd1243dSDimitry Andric 
848*bdd1243dSDimitry Andric typedef struct kmp_affinity_ids_t {
849*bdd1243dSDimitry Andric   int ids[KMP_HW_LAST];
850*bdd1243dSDimitry Andric   int operator[](size_t idx) const { return ids[idx]; }
851*bdd1243dSDimitry Andric   int &operator[](size_t idx) { return ids[idx]; }
852*bdd1243dSDimitry Andric   kmp_affinity_ids_t &operator=(const kmp_affinity_ids_t &rhs) {
853*bdd1243dSDimitry Andric     for (int i = 0; i < KMP_HW_LAST; ++i)
854*bdd1243dSDimitry Andric       ids[i] = rhs[i];
855*bdd1243dSDimitry Andric     return *this;
856*bdd1243dSDimitry Andric   }
857*bdd1243dSDimitry Andric } kmp_affinity_ids_t;
858*bdd1243dSDimitry Andric 
859*bdd1243dSDimitry Andric typedef struct kmp_affinity_attrs_t {
860*bdd1243dSDimitry Andric   int core_type : 8;
861*bdd1243dSDimitry Andric   int core_eff : 8;
862*bdd1243dSDimitry Andric   unsigned valid : 1;
863*bdd1243dSDimitry Andric   unsigned reserved : 15;
864*bdd1243dSDimitry Andric } kmp_affinity_attrs_t;
865*bdd1243dSDimitry Andric #define KMP_AFFINITY_ATTRS_UNKNOWN                                             \
866*bdd1243dSDimitry Andric   { KMP_HW_CORE_TYPE_UNKNOWN, kmp_hw_attr_t::UNKNOWN_CORE_EFF, 0, 0 }
867*bdd1243dSDimitry Andric 
868*bdd1243dSDimitry Andric typedef struct kmp_affinity_t {
869*bdd1243dSDimitry Andric   char *proclist;
870*bdd1243dSDimitry Andric   enum affinity_type type;
871*bdd1243dSDimitry Andric   kmp_hw_t gran;
872*bdd1243dSDimitry Andric   int gran_levels;
873*bdd1243dSDimitry Andric   int compact;
874*bdd1243dSDimitry Andric   int offset;
875*bdd1243dSDimitry Andric   kmp_affinity_flags_t flags;
876*bdd1243dSDimitry Andric   unsigned num_masks;
877*bdd1243dSDimitry Andric   kmp_affin_mask_t *masks;
878*bdd1243dSDimitry Andric   kmp_affinity_ids_t *ids;
879*bdd1243dSDimitry Andric   kmp_affinity_attrs_t *attrs;
880*bdd1243dSDimitry Andric   unsigned num_os_id_masks;
881*bdd1243dSDimitry Andric   kmp_affin_mask_t *os_id_masks;
882*bdd1243dSDimitry Andric   const char *env_var;
883*bdd1243dSDimitry Andric } kmp_affinity_t;
884*bdd1243dSDimitry Andric 
885*bdd1243dSDimitry Andric #define KMP_AFFINITY_INIT(env)                                                 \
886*bdd1243dSDimitry Andric   {                                                                            \
887*bdd1243dSDimitry Andric     nullptr, affinity_default, KMP_HW_UNKNOWN, -1, 0, 0,                       \
888*bdd1243dSDimitry Andric         {TRUE, FALSE, TRUE, affinity_respect_mask_default, FALSE, FALSE}, 0,   \
889*bdd1243dSDimitry Andric         nullptr, nullptr, nullptr, 0, nullptr, env                             \
890*bdd1243dSDimitry Andric   }
891*bdd1243dSDimitry Andric 
8920b57cec5SDimitry Andric extern enum affinity_top_method __kmp_affinity_top_method;
893*bdd1243dSDimitry Andric extern kmp_affinity_t __kmp_affinity;
894*bdd1243dSDimitry Andric extern kmp_affinity_t __kmp_hh_affinity;
895*bdd1243dSDimitry Andric extern kmp_affinity_t *__kmp_affinities[2];
896*bdd1243dSDimitry Andric 
8970b57cec5SDimitry Andric extern void __kmp_affinity_bind_thread(int which);
8980b57cec5SDimitry Andric 
8990b57cec5SDimitry Andric extern kmp_affin_mask_t *__kmp_affin_fullMask;
900fcaf7f86SDimitry Andric extern kmp_affin_mask_t *__kmp_affin_origMask;
9010b57cec5SDimitry Andric extern char *__kmp_cpuinfo_file;
9020b57cec5SDimitry Andric 
9030b57cec5SDimitry Andric #endif /* KMP_AFFINITY_SUPPORTED */
9040b57cec5SDimitry Andric 
9050b57cec5SDimitry Andric // This needs to be kept in sync with the values in omp.h !!!
9060b57cec5SDimitry Andric typedef enum kmp_proc_bind_t {
9070b57cec5SDimitry Andric   proc_bind_false = 0,
9080b57cec5SDimitry Andric   proc_bind_true,
909fe6060f1SDimitry Andric   proc_bind_primary,
9100b57cec5SDimitry Andric   proc_bind_close,
9110b57cec5SDimitry Andric   proc_bind_spread,
9120b57cec5SDimitry Andric   proc_bind_intel, // use KMP_AFFINITY interface
9130b57cec5SDimitry Andric   proc_bind_default
9140b57cec5SDimitry Andric } kmp_proc_bind_t;
9150b57cec5SDimitry Andric 
9160b57cec5SDimitry Andric typedef struct kmp_nested_proc_bind_t {
9170b57cec5SDimitry Andric   kmp_proc_bind_t *bind_types;
9180b57cec5SDimitry Andric   int size;
9190b57cec5SDimitry Andric   int used;
9200b57cec5SDimitry Andric } kmp_nested_proc_bind_t;
9210b57cec5SDimitry Andric 
9220b57cec5SDimitry Andric extern kmp_nested_proc_bind_t __kmp_nested_proc_bind;
923349cc55cSDimitry Andric extern kmp_proc_bind_t __kmp_teams_proc_bind;
9240b57cec5SDimitry Andric 
9250b57cec5SDimitry Andric extern int __kmp_display_affinity;
9260b57cec5SDimitry Andric extern char *__kmp_affinity_format;
9270b57cec5SDimitry Andric static const size_t KMP_AFFINITY_FORMAT_SIZE = 512;
928fe6060f1SDimitry Andric #if OMPT_SUPPORT
929fe6060f1SDimitry Andric extern int __kmp_tool;
930fe6060f1SDimitry Andric extern char *__kmp_tool_libraries;
931fe6060f1SDimitry Andric #endif // OMPT_SUPPORT
9320b57cec5SDimitry Andric 
9330b57cec5SDimitry Andric #if KMP_AFFINITY_SUPPORTED
9340b57cec5SDimitry Andric #define KMP_PLACE_ALL (-1)
9350b57cec5SDimitry Andric #define KMP_PLACE_UNDEFINED (-2)
9360b57cec5SDimitry Andric // Is KMP_AFFINITY is being used instead of OMP_PROC_BIND/OMP_PLACES?
9370b57cec5SDimitry Andric #define KMP_AFFINITY_NON_PROC_BIND                                             \
9380b57cec5SDimitry Andric   ((__kmp_nested_proc_bind.bind_types[0] == proc_bind_false ||                 \
9390b57cec5SDimitry Andric     __kmp_nested_proc_bind.bind_types[0] == proc_bind_intel) &&                \
940*bdd1243dSDimitry Andric    (__kmp_affinity.num_masks > 0 || __kmp_affinity.type == affinity_balanced))
9410b57cec5SDimitry Andric #endif /* KMP_AFFINITY_SUPPORTED */
9420b57cec5SDimitry Andric 
9430b57cec5SDimitry Andric extern int __kmp_affinity_num_places;
9440b57cec5SDimitry Andric 
9450b57cec5SDimitry Andric typedef enum kmp_cancel_kind_t {
9460b57cec5SDimitry Andric   cancel_noreq = 0,
9470b57cec5SDimitry Andric   cancel_parallel = 1,
9480b57cec5SDimitry Andric   cancel_loop = 2,
9490b57cec5SDimitry Andric   cancel_sections = 3,
9500b57cec5SDimitry Andric   cancel_taskgroup = 4
9510b57cec5SDimitry Andric } kmp_cancel_kind_t;
9520b57cec5SDimitry Andric 
9530b57cec5SDimitry Andric // KMP_HW_SUBSET support:
9540b57cec5SDimitry Andric typedef struct kmp_hws_item {
9550b57cec5SDimitry Andric   int num;
9560b57cec5SDimitry Andric   int offset;
9570b57cec5SDimitry Andric } kmp_hws_item_t;
9580b57cec5SDimitry Andric 
9590b57cec5SDimitry Andric extern kmp_hws_item_t __kmp_hws_socket;
960fe6060f1SDimitry Andric extern kmp_hws_item_t __kmp_hws_die;
9610b57cec5SDimitry Andric extern kmp_hws_item_t __kmp_hws_node;
9620b57cec5SDimitry Andric extern kmp_hws_item_t __kmp_hws_tile;
9630b57cec5SDimitry Andric extern kmp_hws_item_t __kmp_hws_core;
9640b57cec5SDimitry Andric extern kmp_hws_item_t __kmp_hws_proc;
9650b57cec5SDimitry Andric extern int __kmp_hws_requested;
9660b57cec5SDimitry Andric extern int __kmp_hws_abs_flag; // absolute or per-item number requested
9670b57cec5SDimitry Andric 
9680b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
9690b57cec5SDimitry Andric 
9700b57cec5SDimitry Andric #define KMP_PAD(type, sz)                                                      \
9710b57cec5SDimitry Andric   (sizeof(type) + (sz - ((sizeof(type) - 1) % (sz)) - 1))
9720b57cec5SDimitry Andric 
9730b57cec5SDimitry Andric // We need to avoid using -1 as a GTID as +1 is added to the gtid
9740b57cec5SDimitry Andric // when storing it in a lock, and the value 0 is reserved.
9750b57cec5SDimitry Andric #define KMP_GTID_DNE (-2) /* Does not exist */
9760b57cec5SDimitry Andric #define KMP_GTID_SHUTDOWN (-3) /* Library is shutting down */
9770b57cec5SDimitry Andric #define KMP_GTID_MONITOR (-4) /* Monitor thread ID */
9780b57cec5SDimitry Andric #define KMP_GTID_UNKNOWN (-5) /* Is not known */
9790b57cec5SDimitry Andric #define KMP_GTID_MIN (-6) /* Minimal gtid for low bound check in DEBUG */
9800b57cec5SDimitry Andric 
9810b57cec5SDimitry Andric /* OpenMP 5.0 Memory Management support */
9820b57cec5SDimitry Andric 
9830b57cec5SDimitry Andric #ifndef __OMP_H
984480093f4SDimitry Andric // Duplicate type definitions from omp.h
9850b57cec5SDimitry Andric typedef uintptr_t omp_uintptr_t;
9860b57cec5SDimitry Andric 
9870b57cec5SDimitry Andric typedef enum {
988e8d8bef9SDimitry Andric   omp_atk_sync_hint = 1,
9895ffd83dbSDimitry Andric   omp_atk_alignment = 2,
9905ffd83dbSDimitry Andric   omp_atk_access = 3,
9915ffd83dbSDimitry Andric   omp_atk_pool_size = 4,
9925ffd83dbSDimitry Andric   omp_atk_fallback = 5,
9935ffd83dbSDimitry Andric   omp_atk_fb_data = 6,
9945ffd83dbSDimitry Andric   omp_atk_pinned = 7,
9955ffd83dbSDimitry Andric   omp_atk_partition = 8
9960b57cec5SDimitry Andric } omp_alloctrait_key_t;
9970b57cec5SDimitry Andric 
9980b57cec5SDimitry Andric typedef enum {
9995ffd83dbSDimitry Andric   omp_atv_false = 0,
10005ffd83dbSDimitry Andric   omp_atv_true = 1,
10015ffd83dbSDimitry Andric   omp_atv_contended = 3,
10025ffd83dbSDimitry Andric   omp_atv_uncontended = 4,
1003e8d8bef9SDimitry Andric   omp_atv_serialized = 5,
1004e8d8bef9SDimitry Andric   omp_atv_sequential = omp_atv_serialized, // (deprecated)
10055ffd83dbSDimitry Andric   omp_atv_private = 6,
10065ffd83dbSDimitry Andric   omp_atv_all = 7,
10075ffd83dbSDimitry Andric   omp_atv_thread = 8,
10085ffd83dbSDimitry Andric   omp_atv_pteam = 9,
10095ffd83dbSDimitry Andric   omp_atv_cgroup = 10,
10105ffd83dbSDimitry Andric   omp_atv_default_mem_fb = 11,
10115ffd83dbSDimitry Andric   omp_atv_null_fb = 12,
10125ffd83dbSDimitry Andric   omp_atv_abort_fb = 13,
10135ffd83dbSDimitry Andric   omp_atv_allocator_fb = 14,
10145ffd83dbSDimitry Andric   omp_atv_environment = 15,
10155ffd83dbSDimitry Andric   omp_atv_nearest = 16,
10165ffd83dbSDimitry Andric   omp_atv_blocked = 17,
10175ffd83dbSDimitry Andric   omp_atv_interleaved = 18
10180b57cec5SDimitry Andric } omp_alloctrait_value_t;
1019e8d8bef9SDimitry Andric #define omp_atv_default ((omp_uintptr_t)-1)
10200b57cec5SDimitry Andric 
10210b57cec5SDimitry Andric typedef void *omp_memspace_handle_t;
10220b57cec5SDimitry Andric extern omp_memspace_handle_t const omp_default_mem_space;
10230b57cec5SDimitry Andric extern omp_memspace_handle_t const omp_large_cap_mem_space;
10240b57cec5SDimitry Andric extern omp_memspace_handle_t const omp_const_mem_space;
10250b57cec5SDimitry Andric extern omp_memspace_handle_t const omp_high_bw_mem_space;
10260b57cec5SDimitry Andric extern omp_memspace_handle_t const omp_low_lat_mem_space;
1027fe6060f1SDimitry Andric extern omp_memspace_handle_t const llvm_omp_target_host_mem_space;
1028fe6060f1SDimitry Andric extern omp_memspace_handle_t const llvm_omp_target_shared_mem_space;
1029fe6060f1SDimitry Andric extern omp_memspace_handle_t const llvm_omp_target_device_mem_space;
10300b57cec5SDimitry Andric 
10310b57cec5SDimitry Andric typedef struct {
10320b57cec5SDimitry Andric   omp_alloctrait_key_t key;
10330b57cec5SDimitry Andric   omp_uintptr_t value;
10340b57cec5SDimitry Andric } omp_alloctrait_t;
10350b57cec5SDimitry Andric 
10360b57cec5SDimitry Andric typedef void *omp_allocator_handle_t;
10370b57cec5SDimitry Andric extern omp_allocator_handle_t const omp_null_allocator;
10380b57cec5SDimitry Andric extern omp_allocator_handle_t const omp_default_mem_alloc;
10390b57cec5SDimitry Andric extern omp_allocator_handle_t const omp_large_cap_mem_alloc;
10400b57cec5SDimitry Andric extern omp_allocator_handle_t const omp_const_mem_alloc;
10410b57cec5SDimitry Andric extern omp_allocator_handle_t const omp_high_bw_mem_alloc;
10420b57cec5SDimitry Andric extern omp_allocator_handle_t const omp_low_lat_mem_alloc;
10430b57cec5SDimitry Andric extern omp_allocator_handle_t const omp_cgroup_mem_alloc;
10440b57cec5SDimitry Andric extern omp_allocator_handle_t const omp_pteam_mem_alloc;
10450b57cec5SDimitry Andric extern omp_allocator_handle_t const omp_thread_mem_alloc;
1046fe6060f1SDimitry Andric extern omp_allocator_handle_t const llvm_omp_target_host_mem_alloc;
1047fe6060f1SDimitry Andric extern omp_allocator_handle_t const llvm_omp_target_shared_mem_alloc;
1048fe6060f1SDimitry Andric extern omp_allocator_handle_t const llvm_omp_target_device_mem_alloc;
10490b57cec5SDimitry Andric extern omp_allocator_handle_t const kmp_max_mem_alloc;
10500b57cec5SDimitry Andric extern omp_allocator_handle_t __kmp_def_allocator;
10510b57cec5SDimitry Andric 
1052480093f4SDimitry Andric // end of duplicate type definitions from omp.h
10530b57cec5SDimitry Andric #endif
10540b57cec5SDimitry Andric 
10550b57cec5SDimitry Andric extern int __kmp_memkind_available;
10560b57cec5SDimitry Andric 
10570b57cec5SDimitry Andric typedef omp_memspace_handle_t kmp_memspace_t; // placeholder
10580b57cec5SDimitry Andric 
10590b57cec5SDimitry Andric typedef struct kmp_allocator_t {
10600b57cec5SDimitry Andric   omp_memspace_handle_t memspace;
10610b57cec5SDimitry Andric   void **memkind; // pointer to memkind
1062349cc55cSDimitry Andric   size_t alignment;
10630b57cec5SDimitry Andric   omp_alloctrait_value_t fb;
10640b57cec5SDimitry Andric   kmp_allocator_t *fb_data;
10650b57cec5SDimitry Andric   kmp_uint64 pool_size;
10660b57cec5SDimitry Andric   kmp_uint64 pool_used;
1067*bdd1243dSDimitry Andric   bool pinned;
10680b57cec5SDimitry Andric } kmp_allocator_t;
10690b57cec5SDimitry Andric 
10700b57cec5SDimitry Andric extern omp_allocator_handle_t __kmpc_init_allocator(int gtid,
10710b57cec5SDimitry Andric                                                     omp_memspace_handle_t,
10720b57cec5SDimitry Andric                                                     int ntraits,
10730b57cec5SDimitry Andric                                                     omp_alloctrait_t traits[]);
10740b57cec5SDimitry Andric extern void __kmpc_destroy_allocator(int gtid, omp_allocator_handle_t al);
10750b57cec5SDimitry Andric extern void __kmpc_set_default_allocator(int gtid, omp_allocator_handle_t al);
10760b57cec5SDimitry Andric extern omp_allocator_handle_t __kmpc_get_default_allocator(int gtid);
1077349cc55cSDimitry Andric // external interfaces, may be used by compiler
10780b57cec5SDimitry Andric extern void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t al);
1079349cc55cSDimitry Andric extern void *__kmpc_aligned_alloc(int gtid, size_t align, size_t sz,
1080349cc55cSDimitry Andric                                   omp_allocator_handle_t al);
1081e8d8bef9SDimitry Andric extern void *__kmpc_calloc(int gtid, size_t nmemb, size_t sz,
1082e8d8bef9SDimitry Andric                            omp_allocator_handle_t al);
1083e8d8bef9SDimitry Andric extern void *__kmpc_realloc(int gtid, void *ptr, size_t sz,
1084e8d8bef9SDimitry Andric                             omp_allocator_handle_t al,
1085e8d8bef9SDimitry Andric                             omp_allocator_handle_t free_al);
10860b57cec5SDimitry Andric extern void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t al);
1087349cc55cSDimitry Andric // internal interfaces, contain real implementation
1088349cc55cSDimitry Andric extern void *__kmp_alloc(int gtid, size_t align, size_t sz,
1089349cc55cSDimitry Andric                          omp_allocator_handle_t al);
1090349cc55cSDimitry Andric extern void *__kmp_calloc(int gtid, size_t align, size_t nmemb, size_t sz,
1091349cc55cSDimitry Andric                           omp_allocator_handle_t al);
1092349cc55cSDimitry Andric extern void *__kmp_realloc(int gtid, void *ptr, size_t sz,
1093349cc55cSDimitry Andric                            omp_allocator_handle_t al,
1094349cc55cSDimitry Andric                            omp_allocator_handle_t free_al);
1095349cc55cSDimitry Andric extern void ___kmpc_free(int gtid, void *ptr, omp_allocator_handle_t al);
10960b57cec5SDimitry Andric 
10970b57cec5SDimitry Andric extern void __kmp_init_memkind();
10980b57cec5SDimitry Andric extern void __kmp_fini_memkind();
1099fe6060f1SDimitry Andric extern void __kmp_init_target_mem();
11000b57cec5SDimitry Andric 
11010b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
11020b57cec5SDimitry Andric 
11030b57cec5SDimitry Andric #define KMP_UINT64_MAX                                                         \
11040b57cec5SDimitry Andric   (~((kmp_uint64)1 << ((sizeof(kmp_uint64) * (1 << 3)) - 1)))
11050b57cec5SDimitry Andric 
11060b57cec5SDimitry Andric #define KMP_MIN_NTH 1
11070b57cec5SDimitry Andric 
11080b57cec5SDimitry Andric #ifndef KMP_MAX_NTH
11090b57cec5SDimitry Andric #if defined(PTHREAD_THREADS_MAX) && PTHREAD_THREADS_MAX < INT_MAX
11100b57cec5SDimitry Andric #define KMP_MAX_NTH PTHREAD_THREADS_MAX
11110b57cec5SDimitry Andric #else
11120b57cec5SDimitry Andric #define KMP_MAX_NTH INT_MAX
11130b57cec5SDimitry Andric #endif
11140b57cec5SDimitry Andric #endif /* KMP_MAX_NTH */
11150b57cec5SDimitry Andric 
11160b57cec5SDimitry Andric #ifdef PTHREAD_STACK_MIN
11170b57cec5SDimitry Andric #define KMP_MIN_STKSIZE PTHREAD_STACK_MIN
11180b57cec5SDimitry Andric #else
11190b57cec5SDimitry Andric #define KMP_MIN_STKSIZE ((size_t)(32 * 1024))
11200b57cec5SDimitry Andric #endif
11210b57cec5SDimitry Andric 
11220b57cec5SDimitry Andric #define KMP_MAX_STKSIZE (~((size_t)1 << ((sizeof(size_t) * (1 << 3)) - 1)))
11230b57cec5SDimitry Andric 
11240b57cec5SDimitry Andric #if KMP_ARCH_X86
11250b57cec5SDimitry Andric #define KMP_DEFAULT_STKSIZE ((size_t)(2 * 1024 * 1024))
11260b57cec5SDimitry Andric #elif KMP_ARCH_X86_64
11270b57cec5SDimitry Andric #define KMP_DEFAULT_STKSIZE ((size_t)(4 * 1024 * 1024))
11280b57cec5SDimitry Andric #define KMP_BACKUP_STKSIZE ((size_t)(2 * 1024 * 1024))
11290b57cec5SDimitry Andric #else
11300b57cec5SDimitry Andric #define KMP_DEFAULT_STKSIZE ((size_t)(1024 * 1024))
11310b57cec5SDimitry Andric #endif
11320b57cec5SDimitry Andric 
11330b57cec5SDimitry Andric #define KMP_DEFAULT_MALLOC_POOL_INCR ((size_t)(1024 * 1024))
11340b57cec5SDimitry Andric #define KMP_MIN_MALLOC_POOL_INCR ((size_t)(4 * 1024))
11350b57cec5SDimitry Andric #define KMP_MAX_MALLOC_POOL_INCR                                               \
11360b57cec5SDimitry Andric   (~((size_t)1 << ((sizeof(size_t) * (1 << 3)) - 1)))
11370b57cec5SDimitry Andric 
11380b57cec5SDimitry Andric #define KMP_MIN_STKOFFSET (0)
11390b57cec5SDimitry Andric #define KMP_MAX_STKOFFSET KMP_MAX_STKSIZE
11400b57cec5SDimitry Andric #if KMP_OS_DARWIN
11410b57cec5SDimitry Andric #define KMP_DEFAULT_STKOFFSET KMP_MIN_STKOFFSET
11420b57cec5SDimitry Andric #else
11430b57cec5SDimitry Andric #define KMP_DEFAULT_STKOFFSET CACHE_LINE
11440b57cec5SDimitry Andric #endif
11450b57cec5SDimitry Andric 
11460b57cec5SDimitry Andric #define KMP_MIN_STKPADDING (0)
11470b57cec5SDimitry Andric #define KMP_MAX_STKPADDING (2 * 1024 * 1024)
11480b57cec5SDimitry Andric 
11490b57cec5SDimitry Andric #define KMP_BLOCKTIME_MULTIPLIER                                               \
11500b57cec5SDimitry Andric   (1000) /* number of blocktime units per second */
11510b57cec5SDimitry Andric #define KMP_MIN_BLOCKTIME (0)
11520b57cec5SDimitry Andric #define KMP_MAX_BLOCKTIME                                                      \
11530b57cec5SDimitry Andric   (INT_MAX) /* Must be this for "infinite" setting the work */
1154349cc55cSDimitry Andric 
1155349cc55cSDimitry Andric /* __kmp_blocktime is in milliseconds */
1156349cc55cSDimitry Andric #define KMP_DEFAULT_BLOCKTIME (__kmp_is_hybrid_cpu() ? (0) : (200))
11570b57cec5SDimitry Andric 
11580b57cec5SDimitry Andric #if KMP_USE_MONITOR
11590b57cec5SDimitry Andric #define KMP_DEFAULT_MONITOR_STKSIZE ((size_t)(64 * 1024))
11600b57cec5SDimitry Andric #define KMP_MIN_MONITOR_WAKEUPS (1) // min times monitor wakes up per second
11610b57cec5SDimitry Andric #define KMP_MAX_MONITOR_WAKEUPS (1000) // max times monitor can wake up per sec
11620b57cec5SDimitry Andric 
11630b57cec5SDimitry Andric /* Calculate new number of monitor wakeups for a specific block time based on
11640b57cec5SDimitry Andric    previous monitor_wakeups. Only allow increasing number of wakeups */
11650b57cec5SDimitry Andric #define KMP_WAKEUPS_FROM_BLOCKTIME(blocktime, monitor_wakeups)                 \
1166fe6060f1SDimitry Andric   (((blocktime) == KMP_MAX_BLOCKTIME)   ? (monitor_wakeups)                    \
1167fe6060f1SDimitry Andric    : ((blocktime) == KMP_MIN_BLOCKTIME) ? KMP_MAX_MONITOR_WAKEUPS              \
11680b57cec5SDimitry Andric    : ((monitor_wakeups) > (KMP_BLOCKTIME_MULTIPLIER / (blocktime)))            \
11690b57cec5SDimitry Andric        ? (monitor_wakeups)                                                     \
11700b57cec5SDimitry Andric        : (KMP_BLOCKTIME_MULTIPLIER) / (blocktime))
11710b57cec5SDimitry Andric 
11720b57cec5SDimitry Andric /* Calculate number of intervals for a specific block time based on
11730b57cec5SDimitry Andric    monitor_wakeups */
11740b57cec5SDimitry Andric #define KMP_INTERVALS_FROM_BLOCKTIME(blocktime, monitor_wakeups)               \
11750b57cec5SDimitry Andric   (((blocktime) + (KMP_BLOCKTIME_MULTIPLIER / (monitor_wakeups)) - 1) /        \
11760b57cec5SDimitry Andric    (KMP_BLOCKTIME_MULTIPLIER / (monitor_wakeups)))
11770b57cec5SDimitry Andric #else
11780b57cec5SDimitry Andric #define KMP_BLOCKTIME(team, tid)                                               \
11790b57cec5SDimitry Andric   (get__bt_set(team, tid) ? get__blocktime(team, tid) : __kmp_dflt_blocktime)
11800b57cec5SDimitry Andric #if KMP_OS_UNIX && (KMP_ARCH_X86 || KMP_ARCH_X86_64)
11810b57cec5SDimitry Andric // HW TSC is used to reduce overhead (clock tick instead of nanosecond).
11820b57cec5SDimitry Andric extern kmp_uint64 __kmp_ticks_per_msec;
118381ad6265SDimitry Andric #if KMP_COMPILER_ICC || KMP_COMPILER_ICX
11840b57cec5SDimitry Andric #define KMP_NOW() ((kmp_uint64)_rdtsc())
11850b57cec5SDimitry Andric #else
11860b57cec5SDimitry Andric #define KMP_NOW() __kmp_hardware_timestamp()
11870b57cec5SDimitry Andric #endif
11880b57cec5SDimitry Andric #define KMP_NOW_MSEC() (KMP_NOW() / __kmp_ticks_per_msec)
11890b57cec5SDimitry Andric #define KMP_BLOCKTIME_INTERVAL(team, tid)                                      \
11900b57cec5SDimitry Andric   (KMP_BLOCKTIME(team, tid) * __kmp_ticks_per_msec)
11910b57cec5SDimitry Andric #define KMP_BLOCKING(goal, count) ((goal) > KMP_NOW())
11920b57cec5SDimitry Andric #else
11930b57cec5SDimitry Andric // System time is retrieved sporadically while blocking.
11940b57cec5SDimitry Andric extern kmp_uint64 __kmp_now_nsec();
11950b57cec5SDimitry Andric #define KMP_NOW() __kmp_now_nsec()
11960b57cec5SDimitry Andric #define KMP_NOW_MSEC() (KMP_NOW() / KMP_USEC_PER_SEC)
11970b57cec5SDimitry Andric #define KMP_BLOCKTIME_INTERVAL(team, tid)                                      \
11980b57cec5SDimitry Andric   (KMP_BLOCKTIME(team, tid) * KMP_USEC_PER_SEC)
11990b57cec5SDimitry Andric #define KMP_BLOCKING(goal, count) ((count) % 1000 != 0 || (goal) > KMP_NOW())
12000b57cec5SDimitry Andric #endif
12010b57cec5SDimitry Andric #endif // KMP_USE_MONITOR
12020b57cec5SDimitry Andric 
12030b57cec5SDimitry Andric #define KMP_MIN_STATSCOLS 40
12040b57cec5SDimitry Andric #define KMP_MAX_STATSCOLS 4096
12050b57cec5SDimitry Andric #define KMP_DEFAULT_STATSCOLS 80
12060b57cec5SDimitry Andric 
12070b57cec5SDimitry Andric #define KMP_MIN_INTERVAL 0
12080b57cec5SDimitry Andric #define KMP_MAX_INTERVAL (INT_MAX - 1)
12090b57cec5SDimitry Andric #define KMP_DEFAULT_INTERVAL 0
12100b57cec5SDimitry Andric 
12110b57cec5SDimitry Andric #define KMP_MIN_CHUNK 1
12120b57cec5SDimitry Andric #define KMP_MAX_CHUNK (INT_MAX - 1)
12130b57cec5SDimitry Andric #define KMP_DEFAULT_CHUNK 1
12140b57cec5SDimitry Andric 
1215fe6060f1SDimitry Andric #define KMP_MIN_DISP_NUM_BUFF 1
12160b57cec5SDimitry Andric #define KMP_DFLT_DISP_NUM_BUFF 7
1217fe6060f1SDimitry Andric #define KMP_MAX_DISP_NUM_BUFF 4096
1218fe6060f1SDimitry Andric 
12190b57cec5SDimitry Andric #define KMP_MAX_ORDERED 8
12200b57cec5SDimitry Andric 
12210b57cec5SDimitry Andric #define KMP_MAX_FIELDS 32
12220b57cec5SDimitry Andric 
12230b57cec5SDimitry Andric #define KMP_MAX_BRANCH_BITS 31
12240b57cec5SDimitry Andric 
12250b57cec5SDimitry Andric #define KMP_MAX_ACTIVE_LEVELS_LIMIT INT_MAX
12260b57cec5SDimitry Andric 
12270b57cec5SDimitry Andric #define KMP_MAX_DEFAULT_DEVICE_LIMIT INT_MAX
12280b57cec5SDimitry Andric 
12290b57cec5SDimitry Andric #define KMP_MAX_TASK_PRIORITY_LIMIT INT_MAX
12300b57cec5SDimitry Andric 
12310b57cec5SDimitry Andric /* Minimum number of threads before switch to TLS gtid (experimentally
12320b57cec5SDimitry Andric    determined) */
12330b57cec5SDimitry Andric /* josh TODO: what about OS X* tuning? */
12340b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
12350b57cec5SDimitry Andric #define KMP_TLS_GTID_MIN 5
12360b57cec5SDimitry Andric #else
12370b57cec5SDimitry Andric #define KMP_TLS_GTID_MIN INT_MAX
12380b57cec5SDimitry Andric #endif
12390b57cec5SDimitry Andric 
1240e8d8bef9SDimitry Andric #define KMP_MASTER_TID(tid) (0 == (tid))
1241e8d8bef9SDimitry Andric #define KMP_WORKER_TID(tid) (0 != (tid))
12420b57cec5SDimitry Andric 
1243e8d8bef9SDimitry Andric #define KMP_MASTER_GTID(gtid) (0 == __kmp_tid_from_gtid((gtid)))
1244e8d8bef9SDimitry Andric #define KMP_WORKER_GTID(gtid) (0 != __kmp_tid_from_gtid((gtid)))
1245e8d8bef9SDimitry Andric #define KMP_INITIAL_GTID(gtid) (0 == (gtid))
12460b57cec5SDimitry Andric 
12470b57cec5SDimitry Andric #ifndef TRUE
12480b57cec5SDimitry Andric #define FALSE 0
12490b57cec5SDimitry Andric #define TRUE (!FALSE)
12500b57cec5SDimitry Andric #endif
12510b57cec5SDimitry Andric 
12520b57cec5SDimitry Andric /* NOTE: all of the following constants must be even */
12530b57cec5SDimitry Andric 
12540b57cec5SDimitry Andric #if KMP_OS_WINDOWS
12550b57cec5SDimitry Andric #define KMP_INIT_WAIT 64U /* initial number of spin-tests   */
12560b57cec5SDimitry Andric #define KMP_NEXT_WAIT 32U /* susequent number of spin-tests */
12570b57cec5SDimitry Andric #elif KMP_OS_LINUX
12580b57cec5SDimitry Andric #define KMP_INIT_WAIT 1024U /* initial number of spin-tests   */
12590b57cec5SDimitry Andric #define KMP_NEXT_WAIT 512U /* susequent number of spin-tests */
12600b57cec5SDimitry Andric #elif KMP_OS_DARWIN
12610b57cec5SDimitry Andric /* TODO: tune for KMP_OS_DARWIN */
12620b57cec5SDimitry Andric #define KMP_INIT_WAIT 1024U /* initial number of spin-tests   */
12630b57cec5SDimitry Andric #define KMP_NEXT_WAIT 512U /* susequent number of spin-tests */
12640b57cec5SDimitry Andric #elif KMP_OS_DRAGONFLY
12650b57cec5SDimitry Andric /* TODO: tune for KMP_OS_DRAGONFLY */
12660b57cec5SDimitry Andric #define KMP_INIT_WAIT 1024U /* initial number of spin-tests   */
12670b57cec5SDimitry Andric #define KMP_NEXT_WAIT 512U /* susequent number of spin-tests */
12680b57cec5SDimitry Andric #elif KMP_OS_FREEBSD
12690b57cec5SDimitry Andric /* TODO: tune for KMP_OS_FREEBSD */
12700b57cec5SDimitry Andric #define KMP_INIT_WAIT 1024U /* initial number of spin-tests   */
12710b57cec5SDimitry Andric #define KMP_NEXT_WAIT 512U /* susequent number of spin-tests */
12720b57cec5SDimitry Andric #elif KMP_OS_NETBSD
12730b57cec5SDimitry Andric /* TODO: tune for KMP_OS_NETBSD */
12740b57cec5SDimitry Andric #define KMP_INIT_WAIT 1024U /* initial number of spin-tests   */
12750b57cec5SDimitry Andric #define KMP_NEXT_WAIT 512U /* susequent number of spin-tests */
12760b57cec5SDimitry Andric #elif KMP_OS_HURD
12770b57cec5SDimitry Andric /* TODO: tune for KMP_OS_HURD */
12780b57cec5SDimitry Andric #define KMP_INIT_WAIT 1024U /* initial number of spin-tests   */
12790b57cec5SDimitry Andric #define KMP_NEXT_WAIT 512U /* susequent number of spin-tests */
12800b57cec5SDimitry Andric #elif KMP_OS_OPENBSD
12810b57cec5SDimitry Andric /* TODO: tune for KMP_OS_OPENBSD */
12820b57cec5SDimitry Andric #define KMP_INIT_WAIT 1024U /* initial number of spin-tests   */
12830b57cec5SDimitry Andric #define KMP_NEXT_WAIT 512U /* susequent number of spin-tests */
12840b57cec5SDimitry Andric #endif
12850b57cec5SDimitry Andric 
12860b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
12870b57cec5SDimitry Andric typedef struct kmp_cpuid {
12880b57cec5SDimitry Andric   kmp_uint32 eax;
12890b57cec5SDimitry Andric   kmp_uint32 ebx;
12900b57cec5SDimitry Andric   kmp_uint32 ecx;
12910b57cec5SDimitry Andric   kmp_uint32 edx;
12920b57cec5SDimitry Andric } kmp_cpuid_t;
12930b57cec5SDimitry Andric 
1294349cc55cSDimitry Andric typedef struct kmp_cpuinfo_flags_t {
1295349cc55cSDimitry Andric   unsigned sse2 : 1; // 0 if SSE2 instructions are not supported, 1 otherwise.
1296349cc55cSDimitry Andric   unsigned rtm : 1; // 0 if RTM instructions are not supported, 1 otherwise.
1297349cc55cSDimitry Andric   unsigned hybrid : 1;
1298349cc55cSDimitry Andric   unsigned reserved : 29; // Ensure size of 32 bits
1299349cc55cSDimitry Andric } kmp_cpuinfo_flags_t;
1300349cc55cSDimitry Andric 
13010b57cec5SDimitry Andric typedef struct kmp_cpuinfo {
13020b57cec5SDimitry Andric   int initialized; // If 0, other fields are not initialized.
13030b57cec5SDimitry Andric   int signature; // CPUID(1).EAX
13040b57cec5SDimitry Andric   int family; // CPUID(1).EAX[27:20]+CPUID(1).EAX[11:8] (Extended Family+Family)
13050b57cec5SDimitry Andric   int model; // ( CPUID(1).EAX[19:16] << 4 ) + CPUID(1).EAX[7:4] ( ( Extended
13060b57cec5SDimitry Andric   // Model << 4 ) + Model)
13070b57cec5SDimitry Andric   int stepping; // CPUID(1).EAX[3:0] ( Stepping )
1308349cc55cSDimitry Andric   kmp_cpuinfo_flags_t flags;
13090b57cec5SDimitry Andric   int apic_id;
13100b57cec5SDimitry Andric   int physical_id;
13110b57cec5SDimitry Andric   int logical_id;
13120b57cec5SDimitry Andric   kmp_uint64 frequency; // Nominal CPU frequency in Hz.
13130b57cec5SDimitry Andric   char name[3 * sizeof(kmp_cpuid_t)]; // CPUID(0x80000002,0x80000003,0x80000004)
13140b57cec5SDimitry Andric } kmp_cpuinfo_t;
13150b57cec5SDimitry Andric 
13160b57cec5SDimitry Andric extern void __kmp_query_cpuid(kmp_cpuinfo_t *p);
13170b57cec5SDimitry Andric 
13180b57cec5SDimitry Andric #if KMP_OS_UNIX
13190b57cec5SDimitry Andric // subleaf is only needed for cache and topology discovery and can be set to
13200b57cec5SDimitry Andric // zero in most cases
13210b57cec5SDimitry Andric static inline void __kmp_x86_cpuid(int leaf, int subleaf, struct kmp_cpuid *p) {
13220b57cec5SDimitry Andric   __asm__ __volatile__("cpuid"
13230b57cec5SDimitry Andric                        : "=a"(p->eax), "=b"(p->ebx), "=c"(p->ecx), "=d"(p->edx)
13240b57cec5SDimitry Andric                        : "a"(leaf), "c"(subleaf));
13250b57cec5SDimitry Andric }
13260b57cec5SDimitry Andric // Load p into FPU control word
13270b57cec5SDimitry Andric static inline void __kmp_load_x87_fpu_control_word(const kmp_int16 *p) {
13280b57cec5SDimitry Andric   __asm__ __volatile__("fldcw %0" : : "m"(*p));
13290b57cec5SDimitry Andric }
13300b57cec5SDimitry Andric // Store FPU control word into p
13310b57cec5SDimitry Andric static inline void __kmp_store_x87_fpu_control_word(kmp_int16 *p) {
13320b57cec5SDimitry Andric   __asm__ __volatile__("fstcw %0" : "=m"(*p));
13330b57cec5SDimitry Andric }
13340b57cec5SDimitry Andric static inline void __kmp_clear_x87_fpu_status_word() {
13350b57cec5SDimitry Andric #if KMP_MIC
13360b57cec5SDimitry Andric   // 32-bit protected mode x87 FPU state
13370b57cec5SDimitry Andric   struct x87_fpu_state {
13380b57cec5SDimitry Andric     unsigned cw;
13390b57cec5SDimitry Andric     unsigned sw;
13400b57cec5SDimitry Andric     unsigned tw;
13410b57cec5SDimitry Andric     unsigned fip;
13420b57cec5SDimitry Andric     unsigned fips;
13430b57cec5SDimitry Andric     unsigned fdp;
13440b57cec5SDimitry Andric     unsigned fds;
13450b57cec5SDimitry Andric   };
13460b57cec5SDimitry Andric   struct x87_fpu_state fpu_state = {0, 0, 0, 0, 0, 0, 0};
13470b57cec5SDimitry Andric   __asm__ __volatile__("fstenv %0\n\t" // store FP env
13480b57cec5SDimitry Andric                        "andw $0x7f00, %1\n\t" // clear 0-7,15 bits of FP SW
13490b57cec5SDimitry Andric                        "fldenv %0\n\t" // load FP env back
13500b57cec5SDimitry Andric                        : "+m"(fpu_state), "+m"(fpu_state.sw));
13510b57cec5SDimitry Andric #else
13520b57cec5SDimitry Andric   __asm__ __volatile__("fnclex");
13530b57cec5SDimitry Andric #endif // KMP_MIC
13540b57cec5SDimitry Andric }
13550b57cec5SDimitry Andric #if __SSE__
13560b57cec5SDimitry Andric static inline void __kmp_load_mxcsr(const kmp_uint32 *p) { _mm_setcsr(*p); }
13570b57cec5SDimitry Andric static inline void __kmp_store_mxcsr(kmp_uint32 *p) { *p = _mm_getcsr(); }
13580b57cec5SDimitry Andric #else
13590b57cec5SDimitry Andric static inline void __kmp_load_mxcsr(const kmp_uint32 *p) {}
13600b57cec5SDimitry Andric static inline void __kmp_store_mxcsr(kmp_uint32 *p) { *p = 0; }
13610b57cec5SDimitry Andric #endif
13620b57cec5SDimitry Andric #else
13630b57cec5SDimitry Andric // Windows still has these as external functions in assembly file
13640b57cec5SDimitry Andric extern void __kmp_x86_cpuid(int mode, int mode2, struct kmp_cpuid *p);
13650b57cec5SDimitry Andric extern void __kmp_load_x87_fpu_control_word(const kmp_int16 *p);
13660b57cec5SDimitry Andric extern void __kmp_store_x87_fpu_control_word(kmp_int16 *p);
13670b57cec5SDimitry Andric extern void __kmp_clear_x87_fpu_status_word();
13680b57cec5SDimitry Andric static inline void __kmp_load_mxcsr(const kmp_uint32 *p) { _mm_setcsr(*p); }
13690b57cec5SDimitry Andric static inline void __kmp_store_mxcsr(kmp_uint32 *p) { *p = _mm_getcsr(); }
13700b57cec5SDimitry Andric #endif // KMP_OS_UNIX
13710b57cec5SDimitry Andric 
13720b57cec5SDimitry Andric #define KMP_X86_MXCSR_MASK 0xffffffc0 /* ignore status flags (6 lsb) */
13730b57cec5SDimitry Andric 
1374e8d8bef9SDimitry Andric // User-level Monitor/Mwait
1375e8d8bef9SDimitry Andric #if KMP_HAVE_UMWAIT
1376e8d8bef9SDimitry Andric // We always try for UMWAIT first
1377e8d8bef9SDimitry Andric #if KMP_HAVE_WAITPKG_INTRINSICS
1378e8d8bef9SDimitry Andric #if KMP_HAVE_IMMINTRIN_H
1379e8d8bef9SDimitry Andric #include <immintrin.h>
1380e8d8bef9SDimitry Andric #elif KMP_HAVE_INTRIN_H
1381e8d8bef9SDimitry Andric #include <intrin.h>
1382e8d8bef9SDimitry Andric #endif
1383e8d8bef9SDimitry Andric #endif // KMP_HAVE_WAITPKG_INTRINSICS
138404eeddc0SDimitry Andric 
1385e8d8bef9SDimitry Andric KMP_ATTRIBUTE_TARGET_WAITPKG
1386fe6060f1SDimitry Andric static inline int __kmp_tpause(uint32_t hint, uint64_t counter) {
1387e8d8bef9SDimitry Andric #if !KMP_HAVE_WAITPKG_INTRINSICS
1388e8d8bef9SDimitry Andric   uint32_t timeHi = uint32_t(counter >> 32);
1389e8d8bef9SDimitry Andric   uint32_t timeLo = uint32_t(counter & 0xffffffff);
1390e8d8bef9SDimitry Andric   char flag;
1391e8d8bef9SDimitry Andric   __asm__ volatile("#tpause\n.byte 0x66, 0x0F, 0xAE, 0xF1\n"
1392e8d8bef9SDimitry Andric                    "setb   %0"
139381ad6265SDimitry Andric                    // The "=q" restraint means any register accessible as rl
139481ad6265SDimitry Andric                    //   in 32-bit mode: a, b, c, and d;
139581ad6265SDimitry Andric                    //   in 64-bit mode: any integer register
139681ad6265SDimitry Andric                    : "=q"(flag)
1397e8d8bef9SDimitry Andric                    : "a"(timeLo), "d"(timeHi), "c"(hint)
1398e8d8bef9SDimitry Andric                    :);
1399e8d8bef9SDimitry Andric   return flag;
1400e8d8bef9SDimitry Andric #else
1401e8d8bef9SDimitry Andric   return _tpause(hint, counter);
1402e8d8bef9SDimitry Andric #endif
1403e8d8bef9SDimitry Andric }
1404e8d8bef9SDimitry Andric KMP_ATTRIBUTE_TARGET_WAITPKG
1405fe6060f1SDimitry Andric static inline void __kmp_umonitor(void *cacheline) {
1406e8d8bef9SDimitry Andric #if !KMP_HAVE_WAITPKG_INTRINSICS
1407e8d8bef9SDimitry Andric   __asm__ volatile("# umonitor\n.byte 0xF3, 0x0F, 0xAE, 0x01 "
1408e8d8bef9SDimitry Andric                    :
1409e8d8bef9SDimitry Andric                    : "a"(cacheline)
1410e8d8bef9SDimitry Andric                    :);
1411e8d8bef9SDimitry Andric #else
1412e8d8bef9SDimitry Andric   _umonitor(cacheline);
1413e8d8bef9SDimitry Andric #endif
1414e8d8bef9SDimitry Andric }
1415e8d8bef9SDimitry Andric KMP_ATTRIBUTE_TARGET_WAITPKG
1416fe6060f1SDimitry Andric static inline int __kmp_umwait(uint32_t hint, uint64_t counter) {
1417e8d8bef9SDimitry Andric #if !KMP_HAVE_WAITPKG_INTRINSICS
1418e8d8bef9SDimitry Andric   uint32_t timeHi = uint32_t(counter >> 32);
1419e8d8bef9SDimitry Andric   uint32_t timeLo = uint32_t(counter & 0xffffffff);
1420e8d8bef9SDimitry Andric   char flag;
1421e8d8bef9SDimitry Andric   __asm__ volatile("#umwait\n.byte 0xF2, 0x0F, 0xAE, 0xF1\n"
1422e8d8bef9SDimitry Andric                    "setb   %0"
142381ad6265SDimitry Andric                    // The "=q" restraint means any register accessible as rl
142481ad6265SDimitry Andric                    //   in 32-bit mode: a, b, c, and d;
142581ad6265SDimitry Andric                    //   in 64-bit mode: any integer register
142681ad6265SDimitry Andric                    : "=q"(flag)
1427e8d8bef9SDimitry Andric                    : "a"(timeLo), "d"(timeHi), "c"(hint)
1428e8d8bef9SDimitry Andric                    :);
1429e8d8bef9SDimitry Andric   return flag;
1430e8d8bef9SDimitry Andric #else
1431e8d8bef9SDimitry Andric   return _umwait(hint, counter);
1432e8d8bef9SDimitry Andric #endif
1433e8d8bef9SDimitry Andric }
1434e8d8bef9SDimitry Andric #elif KMP_HAVE_MWAIT
1435e8d8bef9SDimitry Andric #if KMP_OS_UNIX
1436e8d8bef9SDimitry Andric #include <pmmintrin.h>
1437e8d8bef9SDimitry Andric #else
1438e8d8bef9SDimitry Andric #include <intrin.h>
1439e8d8bef9SDimitry Andric #endif
1440e8d8bef9SDimitry Andric #if KMP_OS_UNIX
1441e8d8bef9SDimitry Andric __attribute__((target("sse3")))
1442e8d8bef9SDimitry Andric #endif
1443e8d8bef9SDimitry Andric static inline void
1444e8d8bef9SDimitry Andric __kmp_mm_monitor(void *cacheline, unsigned extensions, unsigned hints) {
1445e8d8bef9SDimitry Andric   _mm_monitor(cacheline, extensions, hints);
1446e8d8bef9SDimitry Andric }
1447e8d8bef9SDimitry Andric #if KMP_OS_UNIX
1448e8d8bef9SDimitry Andric __attribute__((target("sse3")))
1449e8d8bef9SDimitry Andric #endif
1450e8d8bef9SDimitry Andric static inline void
1451e8d8bef9SDimitry Andric __kmp_mm_mwait(unsigned extensions, unsigned hints) {
1452e8d8bef9SDimitry Andric   _mm_mwait(extensions, hints);
1453e8d8bef9SDimitry Andric }
1454e8d8bef9SDimitry Andric #endif // KMP_HAVE_UMWAIT
1455e8d8bef9SDimitry Andric 
145604eeddc0SDimitry Andric #if KMP_ARCH_X86
145704eeddc0SDimitry Andric extern void __kmp_x86_pause(void);
145804eeddc0SDimitry Andric #elif KMP_MIC
145904eeddc0SDimitry Andric // Performance testing on KNC (C0QS-7120 P/A/X/D, 61-core, 16 GB Memory) showed
146004eeddc0SDimitry Andric // regression after removal of extra PAUSE from spin loops. Changing
146104eeddc0SDimitry Andric // the delay from 100 to 300 showed even better performance than double PAUSE
146204eeddc0SDimitry Andric // on Spec OMP2001 and LCPC tasking tests, no regressions on EPCC.
146304eeddc0SDimitry Andric static inline void __kmp_x86_pause(void) { _mm_delay_32(300); }
146404eeddc0SDimitry Andric #else
146504eeddc0SDimitry Andric static inline void __kmp_x86_pause(void) { _mm_pause(); }
146604eeddc0SDimitry Andric #endif
146704eeddc0SDimitry Andric #define KMP_CPU_PAUSE() __kmp_x86_pause()
146804eeddc0SDimitry Andric #elif KMP_ARCH_PPC64
146904eeddc0SDimitry Andric #define KMP_PPC64_PRI_LOW() __asm__ volatile("or 1, 1, 1")
147004eeddc0SDimitry Andric #define KMP_PPC64_PRI_MED() __asm__ volatile("or 2, 2, 2")
147104eeddc0SDimitry Andric #define KMP_PPC64_PRI_LOC_MB() __asm__ volatile("" : : : "memory")
147204eeddc0SDimitry Andric #define KMP_CPU_PAUSE()                                                        \
147304eeddc0SDimitry Andric   do {                                                                         \
147404eeddc0SDimitry Andric     KMP_PPC64_PRI_LOW();                                                       \
147504eeddc0SDimitry Andric     KMP_PPC64_PRI_MED();                                                       \
147604eeddc0SDimitry Andric     KMP_PPC64_PRI_LOC_MB();                                                    \
147704eeddc0SDimitry Andric   } while (0)
147804eeddc0SDimitry Andric #else
147904eeddc0SDimitry Andric #define KMP_CPU_PAUSE() /* nothing to do */
148004eeddc0SDimitry Andric #endif
148104eeddc0SDimitry Andric 
148204eeddc0SDimitry Andric #define KMP_INIT_YIELD(count)                                                  \
148304eeddc0SDimitry Andric   { (count) = __kmp_yield_init; }
148404eeddc0SDimitry Andric 
148504eeddc0SDimitry Andric #define KMP_INIT_BACKOFF(time)                                                 \
148604eeddc0SDimitry Andric   { (time) = __kmp_pause_init; }
148704eeddc0SDimitry Andric 
148804eeddc0SDimitry Andric #define KMP_OVERSUBSCRIBED                                                     \
148904eeddc0SDimitry Andric   (TCR_4(__kmp_nth) > (__kmp_avail_proc ? __kmp_avail_proc : __kmp_xproc))
149004eeddc0SDimitry Andric 
149104eeddc0SDimitry Andric #define KMP_TRY_YIELD                                                          \
149204eeddc0SDimitry Andric   ((__kmp_use_yield == 1) || (__kmp_use_yield == 2 && (KMP_OVERSUBSCRIBED)))
149304eeddc0SDimitry Andric 
149404eeddc0SDimitry Andric #define KMP_TRY_YIELD_OVERSUB                                                  \
149504eeddc0SDimitry Andric   ((__kmp_use_yield == 1 || __kmp_use_yield == 2) && (KMP_OVERSUBSCRIBED))
149604eeddc0SDimitry Andric 
149704eeddc0SDimitry Andric #define KMP_YIELD(cond)                                                        \
149804eeddc0SDimitry Andric   {                                                                            \
149904eeddc0SDimitry Andric     KMP_CPU_PAUSE();                                                           \
150004eeddc0SDimitry Andric     if ((cond) && (KMP_TRY_YIELD))                                             \
150104eeddc0SDimitry Andric       __kmp_yield();                                                           \
150204eeddc0SDimitry Andric   }
150304eeddc0SDimitry Andric 
150404eeddc0SDimitry Andric #define KMP_YIELD_OVERSUB()                                                    \
150504eeddc0SDimitry Andric   {                                                                            \
150604eeddc0SDimitry Andric     KMP_CPU_PAUSE();                                                           \
150704eeddc0SDimitry Andric     if ((KMP_TRY_YIELD_OVERSUB))                                               \
150804eeddc0SDimitry Andric       __kmp_yield();                                                           \
150904eeddc0SDimitry Andric   }
151004eeddc0SDimitry Andric 
151104eeddc0SDimitry Andric // Note the decrement of 2 in the following Macros. With KMP_LIBRARY=turnaround,
151204eeddc0SDimitry Andric // there should be no yielding since initial value from KMP_INIT_YIELD() is odd.
151304eeddc0SDimitry Andric #define KMP_YIELD_SPIN(count)                                                  \
151404eeddc0SDimitry Andric   {                                                                            \
151504eeddc0SDimitry Andric     KMP_CPU_PAUSE();                                                           \
151604eeddc0SDimitry Andric     if (KMP_TRY_YIELD) {                                                       \
151704eeddc0SDimitry Andric       (count) -= 2;                                                            \
151804eeddc0SDimitry Andric       if (!(count)) {                                                          \
151904eeddc0SDimitry Andric         __kmp_yield();                                                         \
152004eeddc0SDimitry Andric         (count) = __kmp_yield_next;                                            \
152104eeddc0SDimitry Andric       }                                                                        \
152204eeddc0SDimitry Andric     }                                                                          \
152304eeddc0SDimitry Andric   }
152404eeddc0SDimitry Andric 
152504eeddc0SDimitry Andric // If TPAUSE is available & enabled, use it. If oversubscribed, use the slower
152604eeddc0SDimitry Andric // (C0.2) state, which improves performance of other SMT threads on the same
152704eeddc0SDimitry Andric // core, otherwise, use the fast (C0.1) default state, or whatever the user has
152804eeddc0SDimitry Andric // requested. Uses a timed TPAUSE, and exponential backoff. If TPAUSE isn't
152904eeddc0SDimitry Andric // available, fall back to the regular CPU pause and yield combination.
153004eeddc0SDimitry Andric #if KMP_HAVE_UMWAIT
1531*bdd1243dSDimitry Andric #define KMP_TPAUSE_MAX_MASK ((kmp_uint64)0xFFFF)
153204eeddc0SDimitry Andric #define KMP_YIELD_OVERSUB_ELSE_SPIN(count, time)                               \
153304eeddc0SDimitry Andric   {                                                                            \
153404eeddc0SDimitry Andric     if (__kmp_tpause_enabled) {                                                \
153504eeddc0SDimitry Andric       if (KMP_OVERSUBSCRIBED) {                                                \
153604eeddc0SDimitry Andric         __kmp_tpause(0, (time));                                               \
153704eeddc0SDimitry Andric       } else {                                                                 \
153804eeddc0SDimitry Andric         __kmp_tpause(__kmp_tpause_hint, (time));                               \
153904eeddc0SDimitry Andric       }                                                                        \
1540*bdd1243dSDimitry Andric       (time) = (time << 1 | 1) & KMP_TPAUSE_MAX_MASK;                          \
154104eeddc0SDimitry Andric     } else {                                                                   \
154204eeddc0SDimitry Andric       KMP_CPU_PAUSE();                                                         \
154304eeddc0SDimitry Andric       if ((KMP_TRY_YIELD_OVERSUB)) {                                           \
154404eeddc0SDimitry Andric         __kmp_yield();                                                         \
154504eeddc0SDimitry Andric       } else if (__kmp_use_yield == 1) {                                       \
154604eeddc0SDimitry Andric         (count) -= 2;                                                          \
154704eeddc0SDimitry Andric         if (!(count)) {                                                        \
154804eeddc0SDimitry Andric           __kmp_yield();                                                       \
154904eeddc0SDimitry Andric           (count) = __kmp_yield_next;                                          \
155004eeddc0SDimitry Andric         }                                                                      \
155104eeddc0SDimitry Andric       }                                                                        \
155204eeddc0SDimitry Andric     }                                                                          \
155304eeddc0SDimitry Andric   }
155404eeddc0SDimitry Andric #else
155504eeddc0SDimitry Andric #define KMP_YIELD_OVERSUB_ELSE_SPIN(count, time)                               \
155604eeddc0SDimitry Andric   {                                                                            \
155704eeddc0SDimitry Andric     KMP_CPU_PAUSE();                                                           \
155804eeddc0SDimitry Andric     if ((KMP_TRY_YIELD_OVERSUB))                                               \
155904eeddc0SDimitry Andric       __kmp_yield();                                                           \
156004eeddc0SDimitry Andric     else if (__kmp_use_yield == 1) {                                           \
156104eeddc0SDimitry Andric       (count) -= 2;                                                            \
156204eeddc0SDimitry Andric       if (!(count)) {                                                          \
156304eeddc0SDimitry Andric         __kmp_yield();                                                         \
156404eeddc0SDimitry Andric         (count) = __kmp_yield_next;                                            \
156504eeddc0SDimitry Andric       }                                                                        \
156604eeddc0SDimitry Andric     }                                                                          \
156704eeddc0SDimitry Andric   }
156804eeddc0SDimitry Andric #endif // KMP_HAVE_UMWAIT
156904eeddc0SDimitry Andric 
15700b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
15710b57cec5SDimitry Andric /* Support datatypes for the orphaned construct nesting checks.             */
15720b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
15730b57cec5SDimitry Andric 
1574349cc55cSDimitry Andric /* When adding to this enum, add its corresponding string in cons_text_c[]
1575349cc55cSDimitry Andric  * array in kmp_error.cpp */
15760b57cec5SDimitry Andric enum cons_type {
15770b57cec5SDimitry Andric   ct_none,
15780b57cec5SDimitry Andric   ct_parallel,
15790b57cec5SDimitry Andric   ct_pdo,
15800b57cec5SDimitry Andric   ct_pdo_ordered,
15810b57cec5SDimitry Andric   ct_psections,
15820b57cec5SDimitry Andric   ct_psingle,
15830b57cec5SDimitry Andric   ct_critical,
15840b57cec5SDimitry Andric   ct_ordered_in_parallel,
15850b57cec5SDimitry Andric   ct_ordered_in_pdo,
15860b57cec5SDimitry Andric   ct_master,
15870b57cec5SDimitry Andric   ct_reduce,
1588fe6060f1SDimitry Andric   ct_barrier,
1589fe6060f1SDimitry Andric   ct_masked
15900b57cec5SDimitry Andric };
15910b57cec5SDimitry Andric 
15920b57cec5SDimitry Andric #define IS_CONS_TYPE_ORDERED(ct) ((ct) == ct_pdo_ordered)
15930b57cec5SDimitry Andric 
15940b57cec5SDimitry Andric struct cons_data {
15950b57cec5SDimitry Andric   ident_t const *ident;
15960b57cec5SDimitry Andric   enum cons_type type;
15970b57cec5SDimitry Andric   int prev;
15980b57cec5SDimitry Andric   kmp_user_lock_p
15990b57cec5SDimitry Andric       name; /* address exclusively for critical section name comparison */
16000b57cec5SDimitry Andric };
16010b57cec5SDimitry Andric 
16020b57cec5SDimitry Andric struct cons_header {
16030b57cec5SDimitry Andric   int p_top, w_top, s_top;
16040b57cec5SDimitry Andric   int stack_size, stack_top;
16050b57cec5SDimitry Andric   struct cons_data *stack_data;
16060b57cec5SDimitry Andric };
16070b57cec5SDimitry Andric 
16080b57cec5SDimitry Andric struct kmp_region_info {
16090b57cec5SDimitry Andric   char *text;
16100b57cec5SDimitry Andric   int offset[KMP_MAX_FIELDS];
16110b57cec5SDimitry Andric   int length[KMP_MAX_FIELDS];
16120b57cec5SDimitry Andric };
16130b57cec5SDimitry Andric 
16140b57cec5SDimitry Andric /* ---------------------------------------------------------------------- */
16150b57cec5SDimitry Andric /* ---------------------------------------------------------------------- */
16160b57cec5SDimitry Andric 
16170b57cec5SDimitry Andric #if KMP_OS_WINDOWS
16180b57cec5SDimitry Andric typedef HANDLE kmp_thread_t;
16190b57cec5SDimitry Andric typedef DWORD kmp_key_t;
16200b57cec5SDimitry Andric #endif /* KMP_OS_WINDOWS */
16210b57cec5SDimitry Andric 
16220b57cec5SDimitry Andric #if KMP_OS_UNIX
16230b57cec5SDimitry Andric typedef pthread_t kmp_thread_t;
16240b57cec5SDimitry Andric typedef pthread_key_t kmp_key_t;
16250b57cec5SDimitry Andric #endif
16260b57cec5SDimitry Andric 
16270b57cec5SDimitry Andric extern kmp_key_t __kmp_gtid_threadprivate_key;
16280b57cec5SDimitry Andric 
16290b57cec5SDimitry Andric typedef struct kmp_sys_info {
16300b57cec5SDimitry Andric   long maxrss; /* the maximum resident set size utilized (in kilobytes)     */
16310b57cec5SDimitry Andric   long minflt; /* the number of page faults serviced without any I/O        */
16320b57cec5SDimitry Andric   long majflt; /* the number of page faults serviced that required I/O      */
16330b57cec5SDimitry Andric   long nswap; /* the number of times a process was "swapped" out of memory */
16340b57cec5SDimitry Andric   long inblock; /* the number of times the file system had to perform input  */
16350b57cec5SDimitry Andric   long oublock; /* the number of times the file system had to perform output */
16360b57cec5SDimitry Andric   long nvcsw; /* the number of times a context switch was voluntarily      */
16370b57cec5SDimitry Andric   long nivcsw; /* the number of times a context switch was forced           */
16380b57cec5SDimitry Andric } kmp_sys_info_t;
16390b57cec5SDimitry Andric 
16400b57cec5SDimitry Andric #if USE_ITT_BUILD
16410b57cec5SDimitry Andric // We cannot include "kmp_itt.h" due to circular dependency. Declare the only
16420b57cec5SDimitry Andric // required type here. Later we will check the type meets requirements.
16430b57cec5SDimitry Andric typedef int kmp_itt_mark_t;
16440b57cec5SDimitry Andric #define KMP_ITT_DEBUG 0
16450b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */
16460b57cec5SDimitry Andric 
16470b57cec5SDimitry Andric typedef kmp_int32 kmp_critical_name[8];
16480b57cec5SDimitry Andric 
16490b57cec5SDimitry Andric /*!
16500b57cec5SDimitry Andric @ingroup PARALLEL
16510b57cec5SDimitry Andric The type for a microtask which gets passed to @ref __kmpc_fork_call().
16520b57cec5SDimitry Andric The arguments to the outlined function are
16530b57cec5SDimitry Andric @param global_tid the global thread identity of the thread executing the
16540b57cec5SDimitry Andric function.
1655480093f4SDimitry Andric @param bound_tid  the local identity of the thread executing the function
16560b57cec5SDimitry Andric @param ... pointers to shared variables accessed by the function.
16570b57cec5SDimitry Andric */
16580b57cec5SDimitry Andric typedef void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid, ...);
16590b57cec5SDimitry Andric typedef void (*kmpc_micro_bound)(kmp_int32 *bound_tid, kmp_int32 *bound_nth,
16600b57cec5SDimitry Andric                                  ...);
16610b57cec5SDimitry Andric 
16620b57cec5SDimitry Andric /*!
16630b57cec5SDimitry Andric @ingroup THREADPRIVATE
16640b57cec5SDimitry Andric @{
16650b57cec5SDimitry Andric */
16660b57cec5SDimitry Andric /* ---------------------------------------------------------------------------
16670b57cec5SDimitry Andric  */
16680b57cec5SDimitry Andric /* Threadprivate initialization/finalization function declarations */
16690b57cec5SDimitry Andric 
16700b57cec5SDimitry Andric /*  for non-array objects:  __kmpc_threadprivate_register()  */
16710b57cec5SDimitry Andric 
16720b57cec5SDimitry Andric /*!
16730b57cec5SDimitry Andric  Pointer to the constructor function.
16740b57cec5SDimitry Andric  The first argument is the <tt>this</tt> pointer
16750b57cec5SDimitry Andric */
16760b57cec5SDimitry Andric typedef void *(*kmpc_ctor)(void *);
16770b57cec5SDimitry Andric 
16780b57cec5SDimitry Andric /*!
16790b57cec5SDimitry Andric  Pointer to the destructor function.
16800b57cec5SDimitry Andric  The first argument is the <tt>this</tt> pointer
16810b57cec5SDimitry Andric */
16820b57cec5SDimitry Andric typedef void (*kmpc_dtor)(
16830b57cec5SDimitry Andric     void * /*, size_t */); /* 2nd arg: magic number for KCC unused by Intel
16840b57cec5SDimitry Andric                               compiler */
16850b57cec5SDimitry Andric /*!
16860b57cec5SDimitry Andric  Pointer to an alternate constructor.
16870b57cec5SDimitry Andric  The first argument is the <tt>this</tt> pointer.
16880b57cec5SDimitry Andric */
16890b57cec5SDimitry Andric typedef void *(*kmpc_cctor)(void *, void *);
16900b57cec5SDimitry Andric 
16910b57cec5SDimitry Andric /* for array objects: __kmpc_threadprivate_register_vec() */
16920b57cec5SDimitry Andric /* First arg: "this" pointer */
16930b57cec5SDimitry Andric /* Last arg: number of array elements */
16940b57cec5SDimitry Andric /*!
16950b57cec5SDimitry Andric  Array constructor.
16960b57cec5SDimitry Andric  First argument is the <tt>this</tt> pointer
16970b57cec5SDimitry Andric  Second argument the number of array elements.
16980b57cec5SDimitry Andric */
16990b57cec5SDimitry Andric typedef void *(*kmpc_ctor_vec)(void *, size_t);
17000b57cec5SDimitry Andric /*!
17010b57cec5SDimitry Andric  Pointer to the array destructor function.
17020b57cec5SDimitry Andric  The first argument is the <tt>this</tt> pointer
17030b57cec5SDimitry Andric  Second argument the number of array elements.
17040b57cec5SDimitry Andric */
17050b57cec5SDimitry Andric typedef void (*kmpc_dtor_vec)(void *, size_t);
17060b57cec5SDimitry Andric /*!
17070b57cec5SDimitry Andric  Array constructor.
17080b57cec5SDimitry Andric  First argument is the <tt>this</tt> pointer
17090b57cec5SDimitry Andric  Third argument the number of array elements.
17100b57cec5SDimitry Andric */
17110b57cec5SDimitry Andric typedef void *(*kmpc_cctor_vec)(void *, void *,
17120b57cec5SDimitry Andric                                 size_t); /* function unused by compiler */
17130b57cec5SDimitry Andric 
17140b57cec5SDimitry Andric /*!
17150b57cec5SDimitry Andric @}
17160b57cec5SDimitry Andric */
17170b57cec5SDimitry Andric 
17180b57cec5SDimitry Andric /* keeps tracked of threadprivate cache allocations for cleanup later */
17190b57cec5SDimitry Andric typedef struct kmp_cached_addr {
17200b57cec5SDimitry Andric   void **addr; /* address of allocated cache */
17210b57cec5SDimitry Andric   void ***compiler_cache; /* pointer to compiler's cache */
17220b57cec5SDimitry Andric   void *data; /* pointer to global data */
17230b57cec5SDimitry Andric   struct kmp_cached_addr *next; /* pointer to next cached address */
17240b57cec5SDimitry Andric } kmp_cached_addr_t;
17250b57cec5SDimitry Andric 
17260b57cec5SDimitry Andric struct private_data {
17270b57cec5SDimitry Andric   struct private_data *next; /* The next descriptor in the list      */
17280b57cec5SDimitry Andric   void *data; /* The data buffer for this descriptor  */
17290b57cec5SDimitry Andric   int more; /* The repeat count for this descriptor */
17300b57cec5SDimitry Andric   size_t size; /* The data size for this descriptor    */
17310b57cec5SDimitry Andric };
17320b57cec5SDimitry Andric 
17330b57cec5SDimitry Andric struct private_common {
17340b57cec5SDimitry Andric   struct private_common *next;
17350b57cec5SDimitry Andric   struct private_common *link;
17360b57cec5SDimitry Andric   void *gbl_addr;
1737fe6060f1SDimitry Andric   void *par_addr; /* par_addr == gbl_addr for PRIMARY thread */
17380b57cec5SDimitry Andric   size_t cmn_size;
17390b57cec5SDimitry Andric };
17400b57cec5SDimitry Andric 
17410b57cec5SDimitry Andric struct shared_common {
17420b57cec5SDimitry Andric   struct shared_common *next;
17430b57cec5SDimitry Andric   struct private_data *pod_init;
17440b57cec5SDimitry Andric   void *obj_init;
17450b57cec5SDimitry Andric   void *gbl_addr;
17460b57cec5SDimitry Andric   union {
17470b57cec5SDimitry Andric     kmpc_ctor ctor;
17480b57cec5SDimitry Andric     kmpc_ctor_vec ctorv;
17490b57cec5SDimitry Andric   } ct;
17500b57cec5SDimitry Andric   union {
17510b57cec5SDimitry Andric     kmpc_cctor cctor;
17520b57cec5SDimitry Andric     kmpc_cctor_vec cctorv;
17530b57cec5SDimitry Andric   } cct;
17540b57cec5SDimitry Andric   union {
17550b57cec5SDimitry Andric     kmpc_dtor dtor;
17560b57cec5SDimitry Andric     kmpc_dtor_vec dtorv;
17570b57cec5SDimitry Andric   } dt;
17580b57cec5SDimitry Andric   size_t vec_len;
17590b57cec5SDimitry Andric   int is_vec;
17600b57cec5SDimitry Andric   size_t cmn_size;
17610b57cec5SDimitry Andric };
17620b57cec5SDimitry Andric 
17630b57cec5SDimitry Andric #define KMP_HASH_TABLE_LOG2 9 /* log2 of the hash table size */
17640b57cec5SDimitry Andric #define KMP_HASH_TABLE_SIZE                                                    \
17650b57cec5SDimitry Andric   (1 << KMP_HASH_TABLE_LOG2) /* size of the hash table */
17660b57cec5SDimitry Andric #define KMP_HASH_SHIFT 3 /* throw away this many low bits from the address */
17670b57cec5SDimitry Andric #define KMP_HASH(x)                                                            \
17680b57cec5SDimitry Andric   ((((kmp_uintptr_t)x) >> KMP_HASH_SHIFT) & (KMP_HASH_TABLE_SIZE - 1))
17690b57cec5SDimitry Andric 
17700b57cec5SDimitry Andric struct common_table {
17710b57cec5SDimitry Andric   struct private_common *data[KMP_HASH_TABLE_SIZE];
17720b57cec5SDimitry Andric };
17730b57cec5SDimitry Andric 
17740b57cec5SDimitry Andric struct shared_table {
17750b57cec5SDimitry Andric   struct shared_common *data[KMP_HASH_TABLE_SIZE];
17760b57cec5SDimitry Andric };
17770b57cec5SDimitry Andric 
17780b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
17790b57cec5SDimitry Andric 
17800b57cec5SDimitry Andric #if KMP_USE_HIER_SCHED
17810b57cec5SDimitry Andric // Shared barrier data that exists inside a single unit of the scheduling
17820b57cec5SDimitry Andric // hierarchy
17830b57cec5SDimitry Andric typedef struct kmp_hier_private_bdata_t {
17840b57cec5SDimitry Andric   kmp_int32 num_active;
17850b57cec5SDimitry Andric   kmp_uint64 index;
17860b57cec5SDimitry Andric   kmp_uint64 wait_val[2];
17870b57cec5SDimitry Andric } kmp_hier_private_bdata_t;
17880b57cec5SDimitry Andric #endif
17890b57cec5SDimitry Andric 
17900b57cec5SDimitry Andric typedef struct kmp_sched_flags {
17910b57cec5SDimitry Andric   unsigned ordered : 1;
17920b57cec5SDimitry Andric   unsigned nomerge : 1;
17930b57cec5SDimitry Andric   unsigned contains_last : 1;
17940b57cec5SDimitry Andric #if KMP_USE_HIER_SCHED
17950b57cec5SDimitry Andric   unsigned use_hier : 1;
17960b57cec5SDimitry Andric   unsigned unused : 28;
17970b57cec5SDimitry Andric #else
17980b57cec5SDimitry Andric   unsigned unused : 29;
17990b57cec5SDimitry Andric #endif
18000b57cec5SDimitry Andric } kmp_sched_flags_t;
18010b57cec5SDimitry Andric 
18020b57cec5SDimitry Andric KMP_BUILD_ASSERT(sizeof(kmp_sched_flags_t) == 4);
18030b57cec5SDimitry Andric 
18040b57cec5SDimitry Andric #if KMP_STATIC_STEAL_ENABLED
18050b57cec5SDimitry Andric typedef struct KMP_ALIGN_CACHE dispatch_private_info32 {
18060b57cec5SDimitry Andric   kmp_int32 count;
18070b57cec5SDimitry Andric   kmp_int32 ub;
18080b57cec5SDimitry Andric   /* Adding KMP_ALIGN_CACHE here doesn't help / can hurt performance */
18090b57cec5SDimitry Andric   kmp_int32 lb;
18100b57cec5SDimitry Andric   kmp_int32 st;
18110b57cec5SDimitry Andric   kmp_int32 tc;
1812fe6060f1SDimitry Andric   kmp_lock_t *steal_lock; // lock used for chunk stealing
1813fe6060f1SDimitry Andric   // KMP_ALIGN(32) ensures (if the KMP_ALIGN macro is turned on)
18140b57cec5SDimitry Andric   //    a) parm3 is properly aligned and
1815fe6060f1SDimitry Andric   //    b) all parm1-4 are on the same cache line.
18160b57cec5SDimitry Andric   // Because of parm1-4 are used together, performance seems to be better
1817fe6060f1SDimitry Andric   // if they are on the same cache line (not measured though).
18180b57cec5SDimitry Andric 
18190b57cec5SDimitry Andric   struct KMP_ALIGN(32) { // AC: changed 16 to 32 in order to simplify template
18200b57cec5SDimitry Andric     kmp_int32 parm1; //     structures in kmp_dispatch.cpp. This should
18210b57cec5SDimitry Andric     kmp_int32 parm2; //     make no real change at least while padding is off.
18220b57cec5SDimitry Andric     kmp_int32 parm3;
18230b57cec5SDimitry Andric     kmp_int32 parm4;
18240b57cec5SDimitry Andric   };
18250b57cec5SDimitry Andric 
18260b57cec5SDimitry Andric   kmp_uint32 ordered_lower;
18270b57cec5SDimitry Andric   kmp_uint32 ordered_upper;
18280b57cec5SDimitry Andric #if KMP_OS_WINDOWS
18290b57cec5SDimitry Andric   kmp_int32 last_upper;
18300b57cec5SDimitry Andric #endif /* KMP_OS_WINDOWS */
18310b57cec5SDimitry Andric } dispatch_private_info32_t;
18320b57cec5SDimitry Andric 
18330b57cec5SDimitry Andric typedef struct KMP_ALIGN_CACHE dispatch_private_info64 {
18340b57cec5SDimitry Andric   kmp_int64 count; // current chunk number for static & static-steal scheduling
18350b57cec5SDimitry Andric   kmp_int64 ub; /* upper-bound */
18360b57cec5SDimitry Andric   /* Adding KMP_ALIGN_CACHE here doesn't help / can hurt performance */
18370b57cec5SDimitry Andric   kmp_int64 lb; /* lower-bound */
18380b57cec5SDimitry Andric   kmp_int64 st; /* stride */
18390b57cec5SDimitry Andric   kmp_int64 tc; /* trip count (number of iterations) */
1840fe6060f1SDimitry Andric   kmp_lock_t *steal_lock; // lock used for chunk stealing
18410b57cec5SDimitry Andric   /* parm[1-4] are used in different ways by different scheduling algorithms */
18420b57cec5SDimitry Andric 
18430b57cec5SDimitry Andric   // KMP_ALIGN( 32 ) ensures ( if the KMP_ALIGN macro is turned on )
18440b57cec5SDimitry Andric   //    a) parm3 is properly aligned and
18450b57cec5SDimitry Andric   //    b) all parm1-4 are in the same cache line.
18460b57cec5SDimitry Andric   // Because of parm1-4 are used together, performance seems to be better
18470b57cec5SDimitry Andric   // if they are in the same line (not measured though).
18480b57cec5SDimitry Andric 
18490b57cec5SDimitry Andric   struct KMP_ALIGN(32) {
18500b57cec5SDimitry Andric     kmp_int64 parm1;
18510b57cec5SDimitry Andric     kmp_int64 parm2;
18520b57cec5SDimitry Andric     kmp_int64 parm3;
18530b57cec5SDimitry Andric     kmp_int64 parm4;
18540b57cec5SDimitry Andric   };
18550b57cec5SDimitry Andric 
18560b57cec5SDimitry Andric   kmp_uint64 ordered_lower;
18570b57cec5SDimitry Andric   kmp_uint64 ordered_upper;
18580b57cec5SDimitry Andric #if KMP_OS_WINDOWS
18590b57cec5SDimitry Andric   kmp_int64 last_upper;
18600b57cec5SDimitry Andric #endif /* KMP_OS_WINDOWS */
18610b57cec5SDimitry Andric } dispatch_private_info64_t;
18620b57cec5SDimitry Andric #else /* KMP_STATIC_STEAL_ENABLED */
18630b57cec5SDimitry Andric typedef struct KMP_ALIGN_CACHE dispatch_private_info32 {
18640b57cec5SDimitry Andric   kmp_int32 lb;
18650b57cec5SDimitry Andric   kmp_int32 ub;
18660b57cec5SDimitry Andric   kmp_int32 st;
18670b57cec5SDimitry Andric   kmp_int32 tc;
18680b57cec5SDimitry Andric 
18690b57cec5SDimitry Andric   kmp_int32 parm1;
18700b57cec5SDimitry Andric   kmp_int32 parm2;
18710b57cec5SDimitry Andric   kmp_int32 parm3;
18720b57cec5SDimitry Andric   kmp_int32 parm4;
18730b57cec5SDimitry Andric 
18740b57cec5SDimitry Andric   kmp_int32 count;
18750b57cec5SDimitry Andric 
18760b57cec5SDimitry Andric   kmp_uint32 ordered_lower;
18770b57cec5SDimitry Andric   kmp_uint32 ordered_upper;
18780b57cec5SDimitry Andric #if KMP_OS_WINDOWS
18790b57cec5SDimitry Andric   kmp_int32 last_upper;
18800b57cec5SDimitry Andric #endif /* KMP_OS_WINDOWS */
18810b57cec5SDimitry Andric } dispatch_private_info32_t;
18820b57cec5SDimitry Andric 
18830b57cec5SDimitry Andric typedef struct KMP_ALIGN_CACHE dispatch_private_info64 {
18840b57cec5SDimitry Andric   kmp_int64 lb; /* lower-bound */
18850b57cec5SDimitry Andric   kmp_int64 ub; /* upper-bound */
18860b57cec5SDimitry Andric   kmp_int64 st; /* stride */
18870b57cec5SDimitry Andric   kmp_int64 tc; /* trip count (number of iterations) */
18880b57cec5SDimitry Andric 
18890b57cec5SDimitry Andric   /* parm[1-4] are used in different ways by different scheduling algorithms */
18900b57cec5SDimitry Andric   kmp_int64 parm1;
18910b57cec5SDimitry Andric   kmp_int64 parm2;
18920b57cec5SDimitry Andric   kmp_int64 parm3;
18930b57cec5SDimitry Andric   kmp_int64 parm4;
18940b57cec5SDimitry Andric 
18950b57cec5SDimitry Andric   kmp_int64 count; /* current chunk number for static scheduling */
18960b57cec5SDimitry Andric 
18970b57cec5SDimitry Andric   kmp_uint64 ordered_lower;
18980b57cec5SDimitry Andric   kmp_uint64 ordered_upper;
18990b57cec5SDimitry Andric #if KMP_OS_WINDOWS
19000b57cec5SDimitry Andric   kmp_int64 last_upper;
19010b57cec5SDimitry Andric #endif /* KMP_OS_WINDOWS */
19020b57cec5SDimitry Andric } dispatch_private_info64_t;
19030b57cec5SDimitry Andric #endif /* KMP_STATIC_STEAL_ENABLED */
19040b57cec5SDimitry Andric 
19050b57cec5SDimitry Andric typedef struct KMP_ALIGN_CACHE dispatch_private_info {
19060b57cec5SDimitry Andric   union private_info {
19070b57cec5SDimitry Andric     dispatch_private_info32_t p32;
19080b57cec5SDimitry Andric     dispatch_private_info64_t p64;
19090b57cec5SDimitry Andric   } u;
19100b57cec5SDimitry Andric   enum sched_type schedule; /* scheduling algorithm */
19110b57cec5SDimitry Andric   kmp_sched_flags_t flags; /* flags (e.g., ordered, nomerge, etc.) */
1912fe6060f1SDimitry Andric   std::atomic<kmp_uint32> steal_flag; // static_steal only, state of a buffer
19130b57cec5SDimitry Andric   kmp_int32 ordered_bumped;
19140b57cec5SDimitry Andric   // Stack of buffers for nest of serial regions
19150b57cec5SDimitry Andric   struct dispatch_private_info *next;
19160b57cec5SDimitry Andric   kmp_int32 type_size; /* the size of types in private_info */
19170b57cec5SDimitry Andric #if KMP_USE_HIER_SCHED
19180b57cec5SDimitry Andric   kmp_int32 hier_id;
19190b57cec5SDimitry Andric   void *parent; /* hierarchical scheduling parent pointer */
19200b57cec5SDimitry Andric #endif
19210b57cec5SDimitry Andric   enum cons_type pushed_ws;
19220b57cec5SDimitry Andric } dispatch_private_info_t;
19230b57cec5SDimitry Andric 
19240b57cec5SDimitry Andric typedef struct dispatch_shared_info32 {
19250b57cec5SDimitry Andric   /* chunk index under dynamic, number of idle threads under static-steal;
19260b57cec5SDimitry Andric      iteration index otherwise */
19270b57cec5SDimitry Andric   volatile kmp_uint32 iteration;
1928fe6060f1SDimitry Andric   volatile kmp_int32 num_done;
19290b57cec5SDimitry Andric   volatile kmp_uint32 ordered_iteration;
19300b57cec5SDimitry Andric   // Dummy to retain the structure size after making ordered_iteration scalar
19310b57cec5SDimitry Andric   kmp_int32 ordered_dummy[KMP_MAX_ORDERED - 1];
19320b57cec5SDimitry Andric } dispatch_shared_info32_t;
19330b57cec5SDimitry Andric 
19340b57cec5SDimitry Andric typedef struct dispatch_shared_info64 {
19350b57cec5SDimitry Andric   /* chunk index under dynamic, number of idle threads under static-steal;
19360b57cec5SDimitry Andric      iteration index otherwise */
19370b57cec5SDimitry Andric   volatile kmp_uint64 iteration;
1938fe6060f1SDimitry Andric   volatile kmp_int64 num_done;
19390b57cec5SDimitry Andric   volatile kmp_uint64 ordered_iteration;
19400b57cec5SDimitry Andric   // Dummy to retain the structure size after making ordered_iteration scalar
19410b57cec5SDimitry Andric   kmp_int64 ordered_dummy[KMP_MAX_ORDERED - 3];
19420b57cec5SDimitry Andric } dispatch_shared_info64_t;
19430b57cec5SDimitry Andric 
19440b57cec5SDimitry Andric typedef struct dispatch_shared_info {
19450b57cec5SDimitry Andric   union shared_info {
19460b57cec5SDimitry Andric     dispatch_shared_info32_t s32;
19470b57cec5SDimitry Andric     dispatch_shared_info64_t s64;
19480b57cec5SDimitry Andric   } u;
19490b57cec5SDimitry Andric   volatile kmp_uint32 buffer_index;
19500b57cec5SDimitry Andric   volatile kmp_int32 doacross_buf_idx; // teamwise index
19510b57cec5SDimitry Andric   volatile kmp_uint32 *doacross_flags; // shared array of iteration flags (0/1)
19520b57cec5SDimitry Andric   kmp_int32 doacross_num_done; // count finished threads
19530b57cec5SDimitry Andric #if KMP_USE_HIER_SCHED
19540b57cec5SDimitry Andric   void *hier;
19550b57cec5SDimitry Andric #endif
19560b57cec5SDimitry Andric #if KMP_USE_HWLOC
19570b57cec5SDimitry Andric   // When linking with libhwloc, the ORDERED EPCC test slows down on big
19580b57cec5SDimitry Andric   // machines (> 48 cores). Performance analysis showed that a cache thrash
19590b57cec5SDimitry Andric   // was occurring and this padding helps alleviate the problem.
19600b57cec5SDimitry Andric   char padding[64];
19610b57cec5SDimitry Andric #endif
19620b57cec5SDimitry Andric } dispatch_shared_info_t;
19630b57cec5SDimitry Andric 
19640b57cec5SDimitry Andric typedef struct kmp_disp {
19650b57cec5SDimitry Andric   /* Vector for ORDERED SECTION */
19660b57cec5SDimitry Andric   void (*th_deo_fcn)(int *gtid, int *cid, ident_t *);
19670b57cec5SDimitry Andric   /* Vector for END ORDERED SECTION */
19680b57cec5SDimitry Andric   void (*th_dxo_fcn)(int *gtid, int *cid, ident_t *);
19690b57cec5SDimitry Andric 
19700b57cec5SDimitry Andric   dispatch_shared_info_t *th_dispatch_sh_current;
19710b57cec5SDimitry Andric   dispatch_private_info_t *th_dispatch_pr_current;
19720b57cec5SDimitry Andric 
19730b57cec5SDimitry Andric   dispatch_private_info_t *th_disp_buffer;
1974fe6060f1SDimitry Andric   kmp_uint32 th_disp_index;
19750b57cec5SDimitry Andric   kmp_int32 th_doacross_buf_idx; // thread's doacross buffer index
19760b57cec5SDimitry Andric   volatile kmp_uint32 *th_doacross_flags; // pointer to shared array of flags
19770b57cec5SDimitry Andric   kmp_int64 *th_doacross_info; // info on loop bounds
19780b57cec5SDimitry Andric #if KMP_USE_INTERNODE_ALIGNMENT
19790b57cec5SDimitry Andric   char more_padding[INTERNODE_CACHE_LINE];
19800b57cec5SDimitry Andric #endif
19810b57cec5SDimitry Andric } kmp_disp_t;
19820b57cec5SDimitry Andric 
19830b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
19840b57cec5SDimitry Andric /* Barrier stuff */
19850b57cec5SDimitry Andric 
19860b57cec5SDimitry Andric /* constants for barrier state update */
19870b57cec5SDimitry Andric #define KMP_INIT_BARRIER_STATE 0 /* should probably start from zero */
19880b57cec5SDimitry Andric #define KMP_BARRIER_SLEEP_BIT 0 /* bit used for suspend/sleep part of state */
19890b57cec5SDimitry Andric #define KMP_BARRIER_UNUSED_BIT 1 // bit that must never be set for valid state
19900b57cec5SDimitry Andric #define KMP_BARRIER_BUMP_BIT 2 /* lsb used for bump of go/arrived state */
19910b57cec5SDimitry Andric 
19920b57cec5SDimitry Andric #define KMP_BARRIER_SLEEP_STATE (1 << KMP_BARRIER_SLEEP_BIT)
19930b57cec5SDimitry Andric #define KMP_BARRIER_UNUSED_STATE (1 << KMP_BARRIER_UNUSED_BIT)
19940b57cec5SDimitry Andric #define KMP_BARRIER_STATE_BUMP (1 << KMP_BARRIER_BUMP_BIT)
19950b57cec5SDimitry Andric 
19960b57cec5SDimitry Andric #if (KMP_BARRIER_SLEEP_BIT >= KMP_BARRIER_BUMP_BIT)
19970b57cec5SDimitry Andric #error "Barrier sleep bit must be smaller than barrier bump bit"
19980b57cec5SDimitry Andric #endif
19990b57cec5SDimitry Andric #if (KMP_BARRIER_UNUSED_BIT >= KMP_BARRIER_BUMP_BIT)
20000b57cec5SDimitry Andric #error "Barrier unused bit must be smaller than barrier bump bit"
20010b57cec5SDimitry Andric #endif
20020b57cec5SDimitry Andric 
20030b57cec5SDimitry Andric // Constants for release barrier wait state: currently, hierarchical only
20040b57cec5SDimitry Andric #define KMP_BARRIER_NOT_WAITING 0 // Normal state; worker not in wait_sleep
20050b57cec5SDimitry Andric #define KMP_BARRIER_OWN_FLAG                                                   \
20060b57cec5SDimitry Andric   1 // Normal state; worker waiting on own b_go flag in release
20070b57cec5SDimitry Andric #define KMP_BARRIER_PARENT_FLAG                                                \
20080b57cec5SDimitry Andric   2 // Special state; worker waiting on parent's b_go flag in release
20090b57cec5SDimitry Andric #define KMP_BARRIER_SWITCH_TO_OWN_FLAG                                         \
20100b57cec5SDimitry Andric   3 // Special state; tells worker to shift from parent to own b_go
20110b57cec5SDimitry Andric #define KMP_BARRIER_SWITCHING                                                  \
20120b57cec5SDimitry Andric   4 // Special state; worker resets appropriate flag on wake-up
20130b57cec5SDimitry Andric 
20140b57cec5SDimitry Andric #define KMP_NOT_SAFE_TO_REAP                                                   \
20150b57cec5SDimitry Andric   0 // Thread th_reap_state: not safe to reap (tasking)
20160b57cec5SDimitry Andric #define KMP_SAFE_TO_REAP 1 // Thread th_reap_state: safe to reap (not tasking)
20170b57cec5SDimitry Andric 
2018349cc55cSDimitry Andric // The flag_type describes the storage used for the flag.
2019349cc55cSDimitry Andric enum flag_type {
2020349cc55cSDimitry Andric   flag32, /**< atomic 32 bit flags */
2021349cc55cSDimitry Andric   flag64, /**< 64 bit flags */
2022349cc55cSDimitry Andric   atomic_flag64, /**< atomic 64 bit flags */
2023349cc55cSDimitry Andric   flag_oncore, /**< special 64-bit flag for on-core barrier (hierarchical) */
2024349cc55cSDimitry Andric   flag_unset
2025349cc55cSDimitry Andric };
2026349cc55cSDimitry Andric 
20270b57cec5SDimitry Andric enum barrier_type {
20280b57cec5SDimitry Andric   bs_plain_barrier = 0, /* 0, All non-fork/join barriers (except reduction
20290b57cec5SDimitry Andric                            barriers if enabled) */
20300b57cec5SDimitry Andric   bs_forkjoin_barrier, /* 1, All fork/join (parallel region) barriers */
20310b57cec5SDimitry Andric #if KMP_FAST_REDUCTION_BARRIER
20320b57cec5SDimitry Andric   bs_reduction_barrier, /* 2, All barriers that are used in reduction */
20330b57cec5SDimitry Andric #endif // KMP_FAST_REDUCTION_BARRIER
20340b57cec5SDimitry Andric   bs_last_barrier /* Just a placeholder to mark the end */
20350b57cec5SDimitry Andric };
20360b57cec5SDimitry Andric 
20370b57cec5SDimitry Andric // to work with reduction barriers just like with plain barriers
20380b57cec5SDimitry Andric #if !KMP_FAST_REDUCTION_BARRIER
20390b57cec5SDimitry Andric #define bs_reduction_barrier bs_plain_barrier
20400b57cec5SDimitry Andric #endif // KMP_FAST_REDUCTION_BARRIER
20410b57cec5SDimitry Andric 
20420b57cec5SDimitry Andric typedef enum kmp_bar_pat { /* Barrier communication patterns */
20430b57cec5SDimitry Andric                            bp_linear_bar =
20440b57cec5SDimitry Andric                                0, /* Single level (degenerate) tree */
20450b57cec5SDimitry Andric                            bp_tree_bar =
20460b57cec5SDimitry Andric                                1, /* Balanced tree with branching factor 2^n */
2047fe6060f1SDimitry Andric                            bp_hyper_bar = 2, /* Hypercube-embedded tree with min
2048fe6060f1SDimitry Andric                                                 branching factor 2^n */
20490b57cec5SDimitry Andric                            bp_hierarchical_bar = 3, /* Machine hierarchy tree */
2050349cc55cSDimitry Andric                            bp_dist_bar = 4, /* Distributed barrier */
20510b57cec5SDimitry Andric                            bp_last_bar /* Placeholder to mark the end */
20520b57cec5SDimitry Andric } kmp_bar_pat_e;
20530b57cec5SDimitry Andric 
20540b57cec5SDimitry Andric #define KMP_BARRIER_ICV_PUSH 1
20550b57cec5SDimitry Andric 
20560b57cec5SDimitry Andric /* Record for holding the values of the internal controls stack records */
20570b57cec5SDimitry Andric typedef struct kmp_internal_control {
20580b57cec5SDimitry Andric   int serial_nesting_level; /* corresponds to the value of the
20590b57cec5SDimitry Andric                                th_team_serialized field */
20600b57cec5SDimitry Andric   kmp_int8 dynamic; /* internal control for dynamic adjustment of threads (per
20610b57cec5SDimitry Andric                        thread) */
20620b57cec5SDimitry Andric   kmp_int8
20630b57cec5SDimitry Andric       bt_set; /* internal control for whether blocktime is explicitly set */
20640b57cec5SDimitry Andric   int blocktime; /* internal control for blocktime */
20650b57cec5SDimitry Andric #if KMP_USE_MONITOR
20660b57cec5SDimitry Andric   int bt_intervals; /* internal control for blocktime intervals */
20670b57cec5SDimitry Andric #endif
20680b57cec5SDimitry Andric   int nproc; /* internal control for #threads for next parallel region (per
20690b57cec5SDimitry Andric                 thread) */
20700b57cec5SDimitry Andric   int thread_limit; /* internal control for thread-limit-var */
20710b57cec5SDimitry Andric   int max_active_levels; /* internal control for max_active_levels */
20720b57cec5SDimitry Andric   kmp_r_sched_t
20730b57cec5SDimitry Andric       sched; /* internal control for runtime schedule {sched,chunk} pair */
20740b57cec5SDimitry Andric   kmp_proc_bind_t proc_bind; /* internal control for affinity  */
20750b57cec5SDimitry Andric   kmp_int32 default_device; /* internal control for default device */
20760b57cec5SDimitry Andric   struct kmp_internal_control *next;
20770b57cec5SDimitry Andric } kmp_internal_control_t;
20780b57cec5SDimitry Andric 
20790b57cec5SDimitry Andric static inline void copy_icvs(kmp_internal_control_t *dst,
20800b57cec5SDimitry Andric                              kmp_internal_control_t *src) {
20810b57cec5SDimitry Andric   *dst = *src;
20820b57cec5SDimitry Andric }
20830b57cec5SDimitry Andric 
20840b57cec5SDimitry Andric /* Thread barrier needs volatile barrier fields */
20850b57cec5SDimitry Andric typedef struct KMP_ALIGN_CACHE kmp_bstate {
20860b57cec5SDimitry Andric   // th_fixed_icvs is aligned by virtue of kmp_bstate being aligned (and all
20870b57cec5SDimitry Andric   // uses of it). It is not explicitly aligned below, because we *don't* want
20880b57cec5SDimitry Andric   // it to be padded -- instead, we fit b_go into the same cache line with
20890b57cec5SDimitry Andric   // th_fixed_icvs, enabling NGO cache lines stores in the hierarchical barrier.
20900b57cec5SDimitry Andric   kmp_internal_control_t th_fixed_icvs; // Initial ICVs for the thread
20910b57cec5SDimitry Andric   // Tuck b_go into end of th_fixed_icvs cache line, so it can be stored with
20920b57cec5SDimitry Andric   // same NGO store
20930b57cec5SDimitry Andric   volatile kmp_uint64 b_go; // STATE => task should proceed (hierarchical)
20940b57cec5SDimitry Andric   KMP_ALIGN_CACHE volatile kmp_uint64
20950b57cec5SDimitry Andric       b_arrived; // STATE => task reached synch point.
20960b57cec5SDimitry Andric   kmp_uint32 *skip_per_level;
20970b57cec5SDimitry Andric   kmp_uint32 my_level;
20980b57cec5SDimitry Andric   kmp_int32 parent_tid;
20990b57cec5SDimitry Andric   kmp_int32 old_tid;
21000b57cec5SDimitry Andric   kmp_uint32 depth;
21010b57cec5SDimitry Andric   struct kmp_bstate *parent_bar;
21020b57cec5SDimitry Andric   kmp_team_t *team;
21030b57cec5SDimitry Andric   kmp_uint64 leaf_state;
21040b57cec5SDimitry Andric   kmp_uint32 nproc;
21050b57cec5SDimitry Andric   kmp_uint8 base_leaf_kids;
21060b57cec5SDimitry Andric   kmp_uint8 leaf_kids;
21070b57cec5SDimitry Andric   kmp_uint8 offset;
21080b57cec5SDimitry Andric   kmp_uint8 wait_flag;
21090b57cec5SDimitry Andric   kmp_uint8 use_oncore_barrier;
21100b57cec5SDimitry Andric #if USE_DEBUGGER
21110b57cec5SDimitry Andric   // The following field is intended for the debugger solely. Only the worker
21120b57cec5SDimitry Andric   // thread itself accesses this field: the worker increases it by 1 when it
21130b57cec5SDimitry Andric   // arrives to a barrier.
21140b57cec5SDimitry Andric   KMP_ALIGN_CACHE kmp_uint b_worker_arrived;
21150b57cec5SDimitry Andric #endif /* USE_DEBUGGER */
21160b57cec5SDimitry Andric } kmp_bstate_t;
21170b57cec5SDimitry Andric 
21180b57cec5SDimitry Andric union KMP_ALIGN_CACHE kmp_barrier_union {
21190b57cec5SDimitry Andric   double b_align; /* use worst case alignment */
21200b57cec5SDimitry Andric   char b_pad[KMP_PAD(kmp_bstate_t, CACHE_LINE)];
21210b57cec5SDimitry Andric   kmp_bstate_t bb;
21220b57cec5SDimitry Andric };
21230b57cec5SDimitry Andric 
21240b57cec5SDimitry Andric typedef union kmp_barrier_union kmp_balign_t;
21250b57cec5SDimitry Andric 
21260b57cec5SDimitry Andric /* Team barrier needs only non-volatile arrived counter */
21270b57cec5SDimitry Andric union KMP_ALIGN_CACHE kmp_barrier_team_union {
21280b57cec5SDimitry Andric   double b_align; /* use worst case alignment */
21290b57cec5SDimitry Andric   char b_pad[CACHE_LINE];
21300b57cec5SDimitry Andric   struct {
21310b57cec5SDimitry Andric     kmp_uint64 b_arrived; /* STATE => task reached synch point. */
21320b57cec5SDimitry Andric #if USE_DEBUGGER
21330b57cec5SDimitry Andric     // The following two fields are indended for the debugger solely. Only
2134fe6060f1SDimitry Andric     // primary thread of the team accesses these fields: the first one is
2135fe6060f1SDimitry Andric     // increased by 1 when the primary thread arrives to a barrier, the second
2136fe6060f1SDimitry Andric     // one is increased by one when all the threads arrived.
21370b57cec5SDimitry Andric     kmp_uint b_master_arrived;
21380b57cec5SDimitry Andric     kmp_uint b_team_arrived;
21390b57cec5SDimitry Andric #endif
21400b57cec5SDimitry Andric   };
21410b57cec5SDimitry Andric };
21420b57cec5SDimitry Andric 
21430b57cec5SDimitry Andric typedef union kmp_barrier_team_union kmp_balign_team_t;
21440b57cec5SDimitry Andric 
21450b57cec5SDimitry Andric /* Padding for Linux* OS pthreads condition variables and mutexes used to signal
21460b57cec5SDimitry Andric    threads when a condition changes.  This is to workaround an NPTL bug where
21470b57cec5SDimitry Andric    padding was added to pthread_cond_t which caused the initialization routine
21480b57cec5SDimitry Andric    to write outside of the structure if compiled on pre-NPTL threads.  */
21490b57cec5SDimitry Andric #if KMP_OS_WINDOWS
21500b57cec5SDimitry Andric typedef struct kmp_win32_mutex {
21510b57cec5SDimitry Andric   /* The Lock */
21520b57cec5SDimitry Andric   CRITICAL_SECTION cs;
21530b57cec5SDimitry Andric } kmp_win32_mutex_t;
21540b57cec5SDimitry Andric 
21550b57cec5SDimitry Andric typedef struct kmp_win32_cond {
21560b57cec5SDimitry Andric   /* Count of the number of waiters. */
21570b57cec5SDimitry Andric   int waiters_count_;
21580b57cec5SDimitry Andric 
21590b57cec5SDimitry Andric   /* Serialize access to <waiters_count_> */
21600b57cec5SDimitry Andric   kmp_win32_mutex_t waiters_count_lock_;
21610b57cec5SDimitry Andric 
21620b57cec5SDimitry Andric   /* Number of threads to release via a <cond_broadcast> or a <cond_signal> */
21630b57cec5SDimitry Andric   int release_count_;
21640b57cec5SDimitry Andric 
21650b57cec5SDimitry Andric   /* Keeps track of the current "generation" so that we don't allow */
21660b57cec5SDimitry Andric   /* one thread to steal all the "releases" from the broadcast. */
21670b57cec5SDimitry Andric   int wait_generation_count_;
21680b57cec5SDimitry Andric 
21690b57cec5SDimitry Andric   /* A manual-reset event that's used to block and release waiting threads. */
21700b57cec5SDimitry Andric   HANDLE event_;
21710b57cec5SDimitry Andric } kmp_win32_cond_t;
21720b57cec5SDimitry Andric #endif
21730b57cec5SDimitry Andric 
21740b57cec5SDimitry Andric #if KMP_OS_UNIX
21750b57cec5SDimitry Andric 
21760b57cec5SDimitry Andric union KMP_ALIGN_CACHE kmp_cond_union {
21770b57cec5SDimitry Andric   double c_align;
21780b57cec5SDimitry Andric   char c_pad[CACHE_LINE];
21790b57cec5SDimitry Andric   pthread_cond_t c_cond;
21800b57cec5SDimitry Andric };
21810b57cec5SDimitry Andric 
21820b57cec5SDimitry Andric typedef union kmp_cond_union kmp_cond_align_t;
21830b57cec5SDimitry Andric 
21840b57cec5SDimitry Andric union KMP_ALIGN_CACHE kmp_mutex_union {
21850b57cec5SDimitry Andric   double m_align;
21860b57cec5SDimitry Andric   char m_pad[CACHE_LINE];
21870b57cec5SDimitry Andric   pthread_mutex_t m_mutex;
21880b57cec5SDimitry Andric };
21890b57cec5SDimitry Andric 
21900b57cec5SDimitry Andric typedef union kmp_mutex_union kmp_mutex_align_t;
21910b57cec5SDimitry Andric 
21920b57cec5SDimitry Andric #endif /* KMP_OS_UNIX */
21930b57cec5SDimitry Andric 
21940b57cec5SDimitry Andric typedef struct kmp_desc_base {
21950b57cec5SDimitry Andric   void *ds_stackbase;
21960b57cec5SDimitry Andric   size_t ds_stacksize;
21970b57cec5SDimitry Andric   int ds_stackgrow;
21980b57cec5SDimitry Andric   kmp_thread_t ds_thread;
21990b57cec5SDimitry Andric   volatile int ds_tid;
22000b57cec5SDimitry Andric   int ds_gtid;
22010b57cec5SDimitry Andric #if KMP_OS_WINDOWS
22020b57cec5SDimitry Andric   volatile int ds_alive;
22030b57cec5SDimitry Andric   DWORD ds_thread_id;
22040b57cec5SDimitry Andric /* ds_thread keeps thread handle on Windows* OS. It is enough for RTL purposes.
22050b57cec5SDimitry Andric    However, debugger support (libomp_db) cannot work with handles, because they
22060b57cec5SDimitry Andric    uncomparable. For example, debugger requests info about thread with handle h.
22070b57cec5SDimitry Andric    h is valid within debugger process, and meaningless within debugee process.
22080b57cec5SDimitry Andric    Even if h is duped by call to DuplicateHandle(), so the result h' is valid
22090b57cec5SDimitry Andric    within debugee process, but it is a *new* handle which does *not* equal to
22100b57cec5SDimitry Andric    any other handle in debugee... The only way to compare handles is convert
22110b57cec5SDimitry Andric    them to system-wide ids. GetThreadId() function is available only in
22120b57cec5SDimitry Andric    Longhorn and Server 2003. :-( In contrast, GetCurrentThreadId() is available
22130b57cec5SDimitry Andric    on all Windows* OS flavours (including Windows* 95). Thus, we have to get
22140b57cec5SDimitry Andric    thread id by call to GetCurrentThreadId() from within the thread and save it
22150b57cec5SDimitry Andric    to let libomp_db identify threads.  */
22160b57cec5SDimitry Andric #endif /* KMP_OS_WINDOWS */
22170b57cec5SDimitry Andric } kmp_desc_base_t;
22180b57cec5SDimitry Andric 
22190b57cec5SDimitry Andric typedef union KMP_ALIGN_CACHE kmp_desc {
22200b57cec5SDimitry Andric   double ds_align; /* use worst case alignment */
22210b57cec5SDimitry Andric   char ds_pad[KMP_PAD(kmp_desc_base_t, CACHE_LINE)];
22220b57cec5SDimitry Andric   kmp_desc_base_t ds;
22230b57cec5SDimitry Andric } kmp_desc_t;
22240b57cec5SDimitry Andric 
22250b57cec5SDimitry Andric typedef struct kmp_local {
22260b57cec5SDimitry Andric   volatile int this_construct; /* count of single's encountered by thread */
22270b57cec5SDimitry Andric   void *reduce_data;
22280b57cec5SDimitry Andric #if KMP_USE_BGET
22290b57cec5SDimitry Andric   void *bget_data;
22300b57cec5SDimitry Andric   void *bget_list;
22310b57cec5SDimitry Andric #if !USE_CMP_XCHG_FOR_BGET
22320b57cec5SDimitry Andric #ifdef USE_QUEUING_LOCK_FOR_BGET
22330b57cec5SDimitry Andric   kmp_lock_t bget_lock; /* Lock for accessing bget free list */
22340b57cec5SDimitry Andric #else
22350b57cec5SDimitry Andric   kmp_bootstrap_lock_t bget_lock; // Lock for accessing bget free list. Must be
22360b57cec5SDimitry Andric // bootstrap lock so we can use it at library
22370b57cec5SDimitry Andric // shutdown.
22380b57cec5SDimitry Andric #endif /* USE_LOCK_FOR_BGET */
22390b57cec5SDimitry Andric #endif /* ! USE_CMP_XCHG_FOR_BGET */
22400b57cec5SDimitry Andric #endif /* KMP_USE_BGET */
22410b57cec5SDimitry Andric 
22420b57cec5SDimitry Andric   PACKED_REDUCTION_METHOD_T
22430b57cec5SDimitry Andric   packed_reduction_method; /* stored by __kmpc_reduce*(), used by
22440b57cec5SDimitry Andric                               __kmpc_end_reduce*() */
22450b57cec5SDimitry Andric 
22460b57cec5SDimitry Andric } kmp_local_t;
22470b57cec5SDimitry Andric 
22480b57cec5SDimitry Andric #define KMP_CHECK_UPDATE(a, b)                                                 \
22490b57cec5SDimitry Andric   if ((a) != (b))                                                              \
22500b57cec5SDimitry Andric   (a) = (b)
22510b57cec5SDimitry Andric #define KMP_CHECK_UPDATE_SYNC(a, b)                                            \
22520b57cec5SDimitry Andric   if ((a) != (b))                                                              \
22530b57cec5SDimitry Andric   TCW_SYNC_PTR((a), (b))
22540b57cec5SDimitry Andric 
22550b57cec5SDimitry Andric #define get__blocktime(xteam, xtid)                                            \
22560b57cec5SDimitry Andric   ((xteam)->t.t_threads[(xtid)]->th.th_current_task->td_icvs.blocktime)
22570b57cec5SDimitry Andric #define get__bt_set(xteam, xtid)                                               \
22580b57cec5SDimitry Andric   ((xteam)->t.t_threads[(xtid)]->th.th_current_task->td_icvs.bt_set)
22590b57cec5SDimitry Andric #if KMP_USE_MONITOR
22600b57cec5SDimitry Andric #define get__bt_intervals(xteam, xtid)                                         \
22610b57cec5SDimitry Andric   ((xteam)->t.t_threads[(xtid)]->th.th_current_task->td_icvs.bt_intervals)
22620b57cec5SDimitry Andric #endif
22630b57cec5SDimitry Andric 
22640b57cec5SDimitry Andric #define get__dynamic_2(xteam, xtid)                                            \
22650b57cec5SDimitry Andric   ((xteam)->t.t_threads[(xtid)]->th.th_current_task->td_icvs.dynamic)
22660b57cec5SDimitry Andric #define get__nproc_2(xteam, xtid)                                              \
22670b57cec5SDimitry Andric   ((xteam)->t.t_threads[(xtid)]->th.th_current_task->td_icvs.nproc)
22680b57cec5SDimitry Andric #define get__sched_2(xteam, xtid)                                              \
22690b57cec5SDimitry Andric   ((xteam)->t.t_threads[(xtid)]->th.th_current_task->td_icvs.sched)
22700b57cec5SDimitry Andric 
22710b57cec5SDimitry Andric #define set__blocktime_team(xteam, xtid, xval)                                 \
22720b57cec5SDimitry Andric   (((xteam)->t.t_threads[(xtid)]->th.th_current_task->td_icvs.blocktime) =     \
22730b57cec5SDimitry Andric        (xval))
22740b57cec5SDimitry Andric 
22750b57cec5SDimitry Andric #if KMP_USE_MONITOR
22760b57cec5SDimitry Andric #define set__bt_intervals_team(xteam, xtid, xval)                              \
22770b57cec5SDimitry Andric   (((xteam)->t.t_threads[(xtid)]->th.th_current_task->td_icvs.bt_intervals) =  \
22780b57cec5SDimitry Andric        (xval))
22790b57cec5SDimitry Andric #endif
22800b57cec5SDimitry Andric 
22810b57cec5SDimitry Andric #define set__bt_set_team(xteam, xtid, xval)                                    \
22820b57cec5SDimitry Andric   (((xteam)->t.t_threads[(xtid)]->th.th_current_task->td_icvs.bt_set) = (xval))
22830b57cec5SDimitry Andric 
22840b57cec5SDimitry Andric #define set__dynamic(xthread, xval)                                            \
22850b57cec5SDimitry Andric   (((xthread)->th.th_current_task->td_icvs.dynamic) = (xval))
22860b57cec5SDimitry Andric #define get__dynamic(xthread)                                                  \
22870b57cec5SDimitry Andric   (((xthread)->th.th_current_task->td_icvs.dynamic) ? (FTN_TRUE) : (FTN_FALSE))
22880b57cec5SDimitry Andric 
22890b57cec5SDimitry Andric #define set__nproc(xthread, xval)                                              \
22900b57cec5SDimitry Andric   (((xthread)->th.th_current_task->td_icvs.nproc) = (xval))
22910b57cec5SDimitry Andric 
22920b57cec5SDimitry Andric #define set__thread_limit(xthread, xval)                                       \
22930b57cec5SDimitry Andric   (((xthread)->th.th_current_task->td_icvs.thread_limit) = (xval))
22940b57cec5SDimitry Andric 
22950b57cec5SDimitry Andric #define set__max_active_levels(xthread, xval)                                  \
22960b57cec5SDimitry Andric   (((xthread)->th.th_current_task->td_icvs.max_active_levels) = (xval))
22970b57cec5SDimitry Andric 
22980b57cec5SDimitry Andric #define get__max_active_levels(xthread)                                        \
22990b57cec5SDimitry Andric   ((xthread)->th.th_current_task->td_icvs.max_active_levels)
23000b57cec5SDimitry Andric 
23010b57cec5SDimitry Andric #define set__sched(xthread, xval)                                              \
23020b57cec5SDimitry Andric   (((xthread)->th.th_current_task->td_icvs.sched) = (xval))
23030b57cec5SDimitry Andric 
23040b57cec5SDimitry Andric #define set__proc_bind(xthread, xval)                                          \
23050b57cec5SDimitry Andric   (((xthread)->th.th_current_task->td_icvs.proc_bind) = (xval))
23060b57cec5SDimitry Andric #define get__proc_bind(xthread)                                                \
23070b57cec5SDimitry Andric   ((xthread)->th.th_current_task->td_icvs.proc_bind)
23080b57cec5SDimitry Andric 
23090b57cec5SDimitry Andric // OpenMP tasking data structures
23100b57cec5SDimitry Andric 
23110b57cec5SDimitry Andric typedef enum kmp_tasking_mode {
23120b57cec5SDimitry Andric   tskm_immediate_exec = 0,
23130b57cec5SDimitry Andric   tskm_extra_barrier = 1,
23140b57cec5SDimitry Andric   tskm_task_teams = 2,
23150b57cec5SDimitry Andric   tskm_max = 2
23160b57cec5SDimitry Andric } kmp_tasking_mode_t;
23170b57cec5SDimitry Andric 
23180b57cec5SDimitry Andric extern kmp_tasking_mode_t
23190b57cec5SDimitry Andric     __kmp_tasking_mode; /* determines how/when to execute tasks */
23200b57cec5SDimitry Andric extern int __kmp_task_stealing_constraint;
23210b57cec5SDimitry Andric extern int __kmp_enable_task_throttling;
23220b57cec5SDimitry Andric extern kmp_int32 __kmp_default_device; // Set via OMP_DEFAULT_DEVICE if
23230b57cec5SDimitry Andric // specified, defaults to 0 otherwise
23240b57cec5SDimitry Andric // Set via OMP_MAX_TASK_PRIORITY if specified, defaults to 0 otherwise
23250b57cec5SDimitry Andric extern kmp_int32 __kmp_max_task_priority;
23260b57cec5SDimitry Andric // Set via KMP_TASKLOOP_MIN_TASKS if specified, defaults to 0 otherwise
23270b57cec5SDimitry Andric extern kmp_uint64 __kmp_taskloop_min_tasks;
23280b57cec5SDimitry Andric 
23290b57cec5SDimitry Andric /* NOTE: kmp_taskdata_t and kmp_task_t structures allocated in single block with
23300b57cec5SDimitry Andric    taskdata first */
23310b57cec5SDimitry Andric #define KMP_TASK_TO_TASKDATA(task) (((kmp_taskdata_t *)task) - 1)
23320b57cec5SDimitry Andric #define KMP_TASKDATA_TO_TASK(taskdata) (kmp_task_t *)(taskdata + 1)
23330b57cec5SDimitry Andric 
23340b57cec5SDimitry Andric // The tt_found_tasks flag is a signal to all threads in the team that tasks
23350b57cec5SDimitry Andric // were spawned and queued since the previous barrier release.
23360b57cec5SDimitry Andric #define KMP_TASKING_ENABLED(task_team)                                         \
2337e8d8bef9SDimitry Andric   (TRUE == TCR_SYNC_4((task_team)->tt.tt_found_tasks))
23380b57cec5SDimitry Andric /*!
23390b57cec5SDimitry Andric @ingroup BASIC_TYPES
23400b57cec5SDimitry Andric @{
23410b57cec5SDimitry Andric */
23420b57cec5SDimitry Andric 
23430b57cec5SDimitry Andric /*!
23440b57cec5SDimitry Andric  */
23450b57cec5SDimitry Andric typedef kmp_int32 (*kmp_routine_entry_t)(kmp_int32, void *);
23460b57cec5SDimitry Andric 
23470b57cec5SDimitry Andric typedef union kmp_cmplrdata {
23480b57cec5SDimitry Andric   kmp_int32 priority; /**< priority specified by user for the task */
23490b57cec5SDimitry Andric   kmp_routine_entry_t
23500b57cec5SDimitry Andric       destructors; /* pointer to function to invoke deconstructors of
23510b57cec5SDimitry Andric                       firstprivate C++ objects */
23520b57cec5SDimitry Andric   /* future data */
23530b57cec5SDimitry Andric } kmp_cmplrdata_t;
23540b57cec5SDimitry Andric 
23550b57cec5SDimitry Andric /*  sizeof_kmp_task_t passed as arg to kmpc_omp_task call  */
23560b57cec5SDimitry Andric /*!
23570b57cec5SDimitry Andric  */
23580b57cec5SDimitry Andric typedef struct kmp_task { /* GEH: Shouldn't this be aligned somehow? */
23590b57cec5SDimitry Andric   void *shareds; /**< pointer to block of pointers to shared vars   */
23600b57cec5SDimitry Andric   kmp_routine_entry_t
23610b57cec5SDimitry Andric       routine; /**< pointer to routine to call for executing task */
23620b57cec5SDimitry Andric   kmp_int32 part_id; /**< part id for the task                          */
23630b57cec5SDimitry Andric   kmp_cmplrdata_t
23640b57cec5SDimitry Andric       data1; /* Two known optional additions: destructors and priority */
23650b57cec5SDimitry Andric   kmp_cmplrdata_t data2; /* Process destructors first, priority second */
23660b57cec5SDimitry Andric   /* future data */
23670b57cec5SDimitry Andric   /*  private vars  */
23680b57cec5SDimitry Andric } kmp_task_t;
23690b57cec5SDimitry Andric 
23700b57cec5SDimitry Andric /*!
23710b57cec5SDimitry Andric @}
23720b57cec5SDimitry Andric */
23730b57cec5SDimitry Andric 
23740b57cec5SDimitry Andric typedef struct kmp_taskgroup {
23750b57cec5SDimitry Andric   std::atomic<kmp_int32> count; // number of allocated and incomplete tasks
23760b57cec5SDimitry Andric   std::atomic<kmp_int32>
23770b57cec5SDimitry Andric       cancel_request; // request for cancellation of this taskgroup
23780b57cec5SDimitry Andric   struct kmp_taskgroup *parent; // parent taskgroup
23790b57cec5SDimitry Andric   // Block of data to perform task reduction
23800b57cec5SDimitry Andric   void *reduce_data; // reduction related info
23810b57cec5SDimitry Andric   kmp_int32 reduce_num_data; // number of data items to reduce
2382fe6060f1SDimitry Andric   uintptr_t *gomp_data; // gomp reduction data
23830b57cec5SDimitry Andric } kmp_taskgroup_t;
23840b57cec5SDimitry Andric 
23850b57cec5SDimitry Andric // forward declarations
23860b57cec5SDimitry Andric typedef union kmp_depnode kmp_depnode_t;
23870b57cec5SDimitry Andric typedef struct kmp_depnode_list kmp_depnode_list_t;
23880b57cec5SDimitry Andric typedef struct kmp_dephash_entry kmp_dephash_entry_t;
23890b57cec5SDimitry Andric 
2390349cc55cSDimitry Andric // macros for checking dep flag as an integer
2391fe6060f1SDimitry Andric #define KMP_DEP_IN 0x1
2392fe6060f1SDimitry Andric #define KMP_DEP_OUT 0x2
2393fe6060f1SDimitry Andric #define KMP_DEP_INOUT 0x3
2394fe6060f1SDimitry Andric #define KMP_DEP_MTX 0x4
2395fe6060f1SDimitry Andric #define KMP_DEP_SET 0x8
2396349cc55cSDimitry Andric #define KMP_DEP_ALL 0x80
23970b57cec5SDimitry Andric // Compiler sends us this info:
23980b57cec5SDimitry Andric typedef struct kmp_depend_info {
23990b57cec5SDimitry Andric   kmp_intptr_t base_addr;
24000b57cec5SDimitry Andric   size_t len;
2401fe6060f1SDimitry Andric   union {
2402349cc55cSDimitry Andric     kmp_uint8 flag; // flag as an unsigned char
2403349cc55cSDimitry Andric     struct { // flag as a set of 8 bits
2404fe6060f1SDimitry Andric       unsigned in : 1;
2405fe6060f1SDimitry Andric       unsigned out : 1;
2406fe6060f1SDimitry Andric       unsigned mtx : 1;
2407fe6060f1SDimitry Andric       unsigned set : 1;
2408349cc55cSDimitry Andric       unsigned unused : 3;
2409349cc55cSDimitry Andric       unsigned all : 1;
24100b57cec5SDimitry Andric     } flags;
2411fe6060f1SDimitry Andric   };
24120b57cec5SDimitry Andric } kmp_depend_info_t;
24130b57cec5SDimitry Andric 
24140b57cec5SDimitry Andric // Internal structures to work with task dependencies:
24150b57cec5SDimitry Andric struct kmp_depnode_list {
24160b57cec5SDimitry Andric   kmp_depnode_t *node;
24170b57cec5SDimitry Andric   kmp_depnode_list_t *next;
24180b57cec5SDimitry Andric };
24190b57cec5SDimitry Andric 
24200b57cec5SDimitry Andric // Max number of mutexinoutset dependencies per node
24210b57cec5SDimitry Andric #define MAX_MTX_DEPS 4
24220b57cec5SDimitry Andric 
24230b57cec5SDimitry Andric typedef struct kmp_base_depnode {
24240b57cec5SDimitry Andric   kmp_depnode_list_t *successors; /* used under lock */
24250b57cec5SDimitry Andric   kmp_task_t *task; /* non-NULL if depnode is active, used under lock */
24260b57cec5SDimitry Andric   kmp_lock_t *mtx_locks[MAX_MTX_DEPS]; /* lock mutexinoutset dependent tasks */
24270b57cec5SDimitry Andric   kmp_int32 mtx_num_locks; /* number of locks in mtx_locks array */
24280b57cec5SDimitry Andric   kmp_lock_t lock; /* guards shared fields: task, successors */
24290b57cec5SDimitry Andric #if KMP_SUPPORT_GRAPH_OUTPUT
24300b57cec5SDimitry Andric   kmp_uint32 id;
24310b57cec5SDimitry Andric #endif
24320b57cec5SDimitry Andric   std::atomic<kmp_int32> npredecessors;
24330b57cec5SDimitry Andric   std::atomic<kmp_int32> nrefs;
24340b57cec5SDimitry Andric } kmp_base_depnode_t;
24350b57cec5SDimitry Andric 
24360b57cec5SDimitry Andric union KMP_ALIGN_CACHE kmp_depnode {
24370b57cec5SDimitry Andric   double dn_align; /* use worst case alignment */
24380b57cec5SDimitry Andric   char dn_pad[KMP_PAD(kmp_base_depnode_t, CACHE_LINE)];
24390b57cec5SDimitry Andric   kmp_base_depnode_t dn;
24400b57cec5SDimitry Andric };
24410b57cec5SDimitry Andric 
24420b57cec5SDimitry Andric struct kmp_dephash_entry {
24430b57cec5SDimitry Andric   kmp_intptr_t addr;
24440b57cec5SDimitry Andric   kmp_depnode_t *last_out;
2445fe6060f1SDimitry Andric   kmp_depnode_list_t *last_set;
2446fe6060f1SDimitry Andric   kmp_depnode_list_t *prev_set;
2447fe6060f1SDimitry Andric   kmp_uint8 last_flag;
24480b57cec5SDimitry Andric   kmp_lock_t *mtx_lock; /* is referenced by depnodes w/mutexinoutset dep */
24490b57cec5SDimitry Andric   kmp_dephash_entry_t *next_in_bucket;
24500b57cec5SDimitry Andric };
24510b57cec5SDimitry Andric 
24520b57cec5SDimitry Andric typedef struct kmp_dephash {
24530b57cec5SDimitry Andric   kmp_dephash_entry_t **buckets;
24540b57cec5SDimitry Andric   size_t size;
2455349cc55cSDimitry Andric   kmp_depnode_t *last_all;
2456489b1cf2SDimitry Andric   size_t generation;
24570b57cec5SDimitry Andric   kmp_uint32 nelements;
24580b57cec5SDimitry Andric   kmp_uint32 nconflicts;
24590b57cec5SDimitry Andric } kmp_dephash_t;
24600b57cec5SDimitry Andric 
24610b57cec5SDimitry Andric typedef struct kmp_task_affinity_info {
24620b57cec5SDimitry Andric   kmp_intptr_t base_addr;
24630b57cec5SDimitry Andric   size_t len;
24640b57cec5SDimitry Andric   struct {
24650b57cec5SDimitry Andric     bool flag1 : 1;
24660b57cec5SDimitry Andric     bool flag2 : 1;
24670b57cec5SDimitry Andric     kmp_int32 reserved : 30;
24680b57cec5SDimitry Andric   } flags;
24690b57cec5SDimitry Andric } kmp_task_affinity_info_t;
24700b57cec5SDimitry Andric 
24710b57cec5SDimitry Andric typedef enum kmp_event_type_t {
24720b57cec5SDimitry Andric   KMP_EVENT_UNINITIALIZED = 0,
24730b57cec5SDimitry Andric   KMP_EVENT_ALLOW_COMPLETION = 1
24740b57cec5SDimitry Andric } kmp_event_type_t;
24750b57cec5SDimitry Andric 
24760b57cec5SDimitry Andric typedef struct {
24770b57cec5SDimitry Andric   kmp_event_type_t type;
24780b57cec5SDimitry Andric   kmp_tas_lock_t lock;
24790b57cec5SDimitry Andric   union {
24800b57cec5SDimitry Andric     kmp_task_t *task;
24810b57cec5SDimitry Andric   } ed;
24820b57cec5SDimitry Andric } kmp_event_t;
24830b57cec5SDimitry Andric 
24840b57cec5SDimitry Andric #ifdef BUILD_TIED_TASK_STACK
24850b57cec5SDimitry Andric 
24860b57cec5SDimitry Andric /* Tied Task stack definitions */
24870b57cec5SDimitry Andric typedef struct kmp_stack_block {
24880b57cec5SDimitry Andric   kmp_taskdata_t *sb_block[TASK_STACK_BLOCK_SIZE];
24890b57cec5SDimitry Andric   struct kmp_stack_block *sb_next;
24900b57cec5SDimitry Andric   struct kmp_stack_block *sb_prev;
24910b57cec5SDimitry Andric } kmp_stack_block_t;
24920b57cec5SDimitry Andric 
24930b57cec5SDimitry Andric typedef struct kmp_task_stack {
24940b57cec5SDimitry Andric   kmp_stack_block_t ts_first_block; // first block of stack entries
24950b57cec5SDimitry Andric   kmp_taskdata_t **ts_top; // pointer to the top of stack
24960b57cec5SDimitry Andric   kmp_int32 ts_entries; // number of entries on the stack
24970b57cec5SDimitry Andric } kmp_task_stack_t;
24980b57cec5SDimitry Andric 
24990b57cec5SDimitry Andric #endif // BUILD_TIED_TASK_STACK
25000b57cec5SDimitry Andric 
25010b57cec5SDimitry Andric typedef struct kmp_tasking_flags { /* Total struct must be exactly 32 bits */
25020b57cec5SDimitry Andric   /* Compiler flags */ /* Total compiler flags must be 16 bits */
25030b57cec5SDimitry Andric   unsigned tiedness : 1; /* task is either tied (1) or untied (0) */
25040b57cec5SDimitry Andric   unsigned final : 1; /* task is final(1) so execute immediately */
25050b57cec5SDimitry Andric   unsigned merged_if0 : 1; /* no __kmpc_task_{begin/complete}_if0 calls in if0
25060b57cec5SDimitry Andric                               code path */
25070b57cec5SDimitry Andric   unsigned destructors_thunk : 1; /* set if the compiler creates a thunk to
25080b57cec5SDimitry Andric                                      invoke destructors from the runtime */
25090b57cec5SDimitry Andric   unsigned proxy : 1; /* task is a proxy task (it will be executed outside the
25100b57cec5SDimitry Andric                          context of the RTL) */
25110b57cec5SDimitry Andric   unsigned priority_specified : 1; /* set if the compiler provides priority
25120b57cec5SDimitry Andric                                       setting for the task */
25130b57cec5SDimitry Andric   unsigned detachable : 1; /* 1 == can detach */
2514e8d8bef9SDimitry Andric   unsigned hidden_helper : 1; /* 1 == hidden helper task */
2515e8d8bef9SDimitry Andric   unsigned reserved : 8; /* reserved for compiler use */
25160b57cec5SDimitry Andric 
25170b57cec5SDimitry Andric   /* Library flags */ /* Total library flags must be 16 bits */
25180b57cec5SDimitry Andric   unsigned tasktype : 1; /* task is either explicit(1) or implicit (0) */
25190b57cec5SDimitry Andric   unsigned task_serial : 1; // task is executed immediately (1) or deferred (0)
25200b57cec5SDimitry Andric   unsigned tasking_ser : 1; // all tasks in team are either executed immediately
25210b57cec5SDimitry Andric   // (1) or may be deferred (0)
25220b57cec5SDimitry Andric   unsigned team_serial : 1; // entire team is serial (1) [1 thread] or parallel
25230b57cec5SDimitry Andric   // (0) [>= 2 threads]
25240b57cec5SDimitry Andric   /* If either team_serial or tasking_ser is set, task team may be NULL */
25250b57cec5SDimitry Andric   /* Task State Flags: */
25260b57cec5SDimitry Andric   unsigned started : 1; /* 1==started, 0==not started     */
25270b57cec5SDimitry Andric   unsigned executing : 1; /* 1==executing, 0==not executing */
25280b57cec5SDimitry Andric   unsigned complete : 1; /* 1==complete, 0==not complete   */
2529480093f4SDimitry Andric   unsigned freed : 1; /* 1==freed, 0==allocated        */
25300b57cec5SDimitry Andric   unsigned native : 1; /* 1==gcc-compiled task, 0==intel */
25310b57cec5SDimitry Andric   unsigned reserved31 : 7; /* reserved for library use */
25320b57cec5SDimitry Andric 
25330b57cec5SDimitry Andric } kmp_tasking_flags_t;
25340b57cec5SDimitry Andric 
2535*bdd1243dSDimitry Andric typedef struct kmp_target_data {
2536*bdd1243dSDimitry Andric   void *async_handle; // libomptarget async handle for task completion query
2537*bdd1243dSDimitry Andric } kmp_target_data_t;
2538*bdd1243dSDimitry Andric 
25390b57cec5SDimitry Andric struct kmp_taskdata { /* aligned during dynamic allocation       */
25400b57cec5SDimitry Andric   kmp_int32 td_task_id; /* id, assigned by debugger                */
25410b57cec5SDimitry Andric   kmp_tasking_flags_t td_flags; /* task flags                              */
25420b57cec5SDimitry Andric   kmp_team_t *td_team; /* team for this task                      */
25430b57cec5SDimitry Andric   kmp_info_p *td_alloc_thread; /* thread that allocated data structures   */
25440b57cec5SDimitry Andric   /* Currently not used except for perhaps IDB */
25450b57cec5SDimitry Andric   kmp_taskdata_t *td_parent; /* parent task                             */
25460b57cec5SDimitry Andric   kmp_int32 td_level; /* task nesting level                      */
25470b57cec5SDimitry Andric   std::atomic<kmp_int32> td_untied_count; // untied task active parts counter
25480b57cec5SDimitry Andric   ident_t *td_ident; /* task identifier                         */
25490b57cec5SDimitry Andric   // Taskwait data.
25500b57cec5SDimitry Andric   ident_t *td_taskwait_ident;
25510b57cec5SDimitry Andric   kmp_uint32 td_taskwait_counter;
25520b57cec5SDimitry Andric   kmp_int32 td_taskwait_thread; /* gtid + 1 of thread encountered taskwait */
25530b57cec5SDimitry Andric   KMP_ALIGN_CACHE kmp_internal_control_t
25540b57cec5SDimitry Andric       td_icvs; /* Internal control variables for the task */
25550b57cec5SDimitry Andric   KMP_ALIGN_CACHE std::atomic<kmp_int32>
25560b57cec5SDimitry Andric       td_allocated_child_tasks; /* Child tasks (+ current task) not yet
25570b57cec5SDimitry Andric                                    deallocated */
25580b57cec5SDimitry Andric   std::atomic<kmp_int32>
25590b57cec5SDimitry Andric       td_incomplete_child_tasks; /* Child tasks not yet complete */
25600b57cec5SDimitry Andric   kmp_taskgroup_t
25610b57cec5SDimitry Andric       *td_taskgroup; // Each task keeps pointer to its current taskgroup
25620b57cec5SDimitry Andric   kmp_dephash_t
25630b57cec5SDimitry Andric       *td_dephash; // Dependencies for children tasks are tracked from here
25640b57cec5SDimitry Andric   kmp_depnode_t
25650b57cec5SDimitry Andric       *td_depnode; // Pointer to graph node if this task has dependencies
25660b57cec5SDimitry Andric   kmp_task_team_t *td_task_team;
2567e8d8bef9SDimitry Andric   size_t td_size_alloc; // Size of task structure, including shareds etc.
25680b57cec5SDimitry Andric #if defined(KMP_GOMP_COMPAT)
25690b57cec5SDimitry Andric   // 4 or 8 byte integers for the loop bounds in GOMP_taskloop
25700b57cec5SDimitry Andric   kmp_int32 td_size_loop_bounds;
25710b57cec5SDimitry Andric #endif
25720b57cec5SDimitry Andric   kmp_taskdata_t *td_last_tied; // keep tied task for task scheduling constraint
25730b57cec5SDimitry Andric #if defined(KMP_GOMP_COMPAT)
25740b57cec5SDimitry Andric   // GOMP sends in a copy function for copy constructors
25750b57cec5SDimitry Andric   void (*td_copy_func)(void *, void *);
25760b57cec5SDimitry Andric #endif
25770b57cec5SDimitry Andric   kmp_event_t td_allow_completion_event;
25780b57cec5SDimitry Andric #if OMPT_SUPPORT
25790b57cec5SDimitry Andric   ompt_task_info_t ompt_task_info;
25800b57cec5SDimitry Andric #endif
2581*bdd1243dSDimitry Andric   kmp_target_data_t td_target_data;
25820b57cec5SDimitry Andric }; // struct kmp_taskdata
25830b57cec5SDimitry Andric 
25840b57cec5SDimitry Andric // Make sure padding above worked
25850b57cec5SDimitry Andric KMP_BUILD_ASSERT(sizeof(kmp_taskdata_t) % sizeof(void *) == 0);
25860b57cec5SDimitry Andric 
25870b57cec5SDimitry Andric // Data for task team but per thread
25880b57cec5SDimitry Andric typedef struct kmp_base_thread_data {
25890b57cec5SDimitry Andric   kmp_info_p *td_thr; // Pointer back to thread info
25900b57cec5SDimitry Andric   // Used only in __kmp_execute_tasks_template, maybe not avail until task is
25910b57cec5SDimitry Andric   // queued?
25920b57cec5SDimitry Andric   kmp_bootstrap_lock_t td_deque_lock; // Lock for accessing deque
25930b57cec5SDimitry Andric   kmp_taskdata_t *
25940b57cec5SDimitry Andric       *td_deque; // Deque of tasks encountered by td_thr, dynamically allocated
25950b57cec5SDimitry Andric   kmp_int32 td_deque_size; // Size of deck
25960b57cec5SDimitry Andric   kmp_uint32 td_deque_head; // Head of deque (will wrap)
25970b57cec5SDimitry Andric   kmp_uint32 td_deque_tail; // Tail of deque (will wrap)
25980b57cec5SDimitry Andric   kmp_int32 td_deque_ntasks; // Number of tasks in deque
25990b57cec5SDimitry Andric   // GEH: shouldn't this be volatile since used in while-spin?
26000b57cec5SDimitry Andric   kmp_int32 td_deque_last_stolen; // Thread number of last successful steal
26010b57cec5SDimitry Andric #ifdef BUILD_TIED_TASK_STACK
26020b57cec5SDimitry Andric   kmp_task_stack_t td_susp_tied_tasks; // Stack of suspended tied tasks for task
26030b57cec5SDimitry Andric // scheduling constraint
26040b57cec5SDimitry Andric #endif // BUILD_TIED_TASK_STACK
26050b57cec5SDimitry Andric } kmp_base_thread_data_t;
26060b57cec5SDimitry Andric 
26070b57cec5SDimitry Andric #define TASK_DEQUE_BITS 8 // Used solely to define INITIAL_TASK_DEQUE_SIZE
26080b57cec5SDimitry Andric #define INITIAL_TASK_DEQUE_SIZE (1 << TASK_DEQUE_BITS)
26090b57cec5SDimitry Andric 
26100b57cec5SDimitry Andric #define TASK_DEQUE_SIZE(td) ((td).td_deque_size)
26110b57cec5SDimitry Andric #define TASK_DEQUE_MASK(td) ((td).td_deque_size - 1)
26120b57cec5SDimitry Andric 
26130b57cec5SDimitry Andric typedef union KMP_ALIGN_CACHE kmp_thread_data {
26140b57cec5SDimitry Andric   kmp_base_thread_data_t td;
26150b57cec5SDimitry Andric   double td_align; /* use worst case alignment */
26160b57cec5SDimitry Andric   char td_pad[KMP_PAD(kmp_base_thread_data_t, CACHE_LINE)];
26170b57cec5SDimitry Andric } kmp_thread_data_t;
26180b57cec5SDimitry Andric 
261981ad6265SDimitry Andric typedef struct kmp_task_pri {
262081ad6265SDimitry Andric   kmp_thread_data_t td;
262181ad6265SDimitry Andric   kmp_int32 priority;
262281ad6265SDimitry Andric   kmp_task_pri *next;
262381ad6265SDimitry Andric } kmp_task_pri_t;
262481ad6265SDimitry Andric 
26250b57cec5SDimitry Andric // Data for task teams which are used when tasking is enabled for the team
26260b57cec5SDimitry Andric typedef struct kmp_base_task_team {
26270b57cec5SDimitry Andric   kmp_bootstrap_lock_t
26280b57cec5SDimitry Andric       tt_threads_lock; /* Lock used to allocate per-thread part of task team */
26290b57cec5SDimitry Andric   /* must be bootstrap lock since used at library shutdown*/
263081ad6265SDimitry Andric 
263181ad6265SDimitry Andric   // TODO: check performance vs kmp_tas_lock_t
263281ad6265SDimitry Andric   kmp_bootstrap_lock_t tt_task_pri_lock; /* Lock to access priority tasks */
263381ad6265SDimitry Andric   kmp_task_pri_t *tt_task_pri_list;
263481ad6265SDimitry Andric 
26350b57cec5SDimitry Andric   kmp_task_team_t *tt_next; /* For linking the task team free list */
26360b57cec5SDimitry Andric   kmp_thread_data_t
26370b57cec5SDimitry Andric       *tt_threads_data; /* Array of per-thread structures for task team */
26380b57cec5SDimitry Andric   /* Data survives task team deallocation */
26390b57cec5SDimitry Andric   kmp_int32 tt_found_tasks; /* Have we found tasks and queued them while
26400b57cec5SDimitry Andric                                executing this team? */
26410b57cec5SDimitry Andric   /* TRUE means tt_threads_data is set up and initialized */
26420b57cec5SDimitry Andric   kmp_int32 tt_nproc; /* #threads in team           */
26430b57cec5SDimitry Andric   kmp_int32 tt_max_threads; // # entries allocated for threads_data array
26440b57cec5SDimitry Andric   kmp_int32 tt_found_proxy_tasks; // found proxy tasks since last barrier
26450b57cec5SDimitry Andric   kmp_int32 tt_untied_task_encountered;
264681ad6265SDimitry Andric   std::atomic<kmp_int32> tt_num_task_pri; // number of priority tasks enqueued
2647e8d8bef9SDimitry Andric   // There is hidden helper thread encountered in this task team so that we must
2648e8d8bef9SDimitry Andric   // wait when waiting on task team
2649e8d8bef9SDimitry Andric   kmp_int32 tt_hidden_helper_task_encountered;
26500b57cec5SDimitry Andric 
26510b57cec5SDimitry Andric   KMP_ALIGN_CACHE
26520b57cec5SDimitry Andric   std::atomic<kmp_int32> tt_unfinished_threads; /* #threads still active */
26530b57cec5SDimitry Andric 
26540b57cec5SDimitry Andric   KMP_ALIGN_CACHE
26550b57cec5SDimitry Andric   volatile kmp_uint32
26560b57cec5SDimitry Andric       tt_active; /* is the team still actively executing tasks */
26570b57cec5SDimitry Andric } kmp_base_task_team_t;
26580b57cec5SDimitry Andric 
26590b57cec5SDimitry Andric union KMP_ALIGN_CACHE kmp_task_team {
26600b57cec5SDimitry Andric   kmp_base_task_team_t tt;
26610b57cec5SDimitry Andric   double tt_align; /* use worst case alignment */
26620b57cec5SDimitry Andric   char tt_pad[KMP_PAD(kmp_base_task_team_t, CACHE_LINE)];
26630b57cec5SDimitry Andric };
26640b57cec5SDimitry Andric 
26650b57cec5SDimitry Andric #if (USE_FAST_MEMORY == 3) || (USE_FAST_MEMORY == 5)
26660b57cec5SDimitry Andric // Free lists keep same-size free memory slots for fast memory allocation
26670b57cec5SDimitry Andric // routines
26680b57cec5SDimitry Andric typedef struct kmp_free_list {
26690b57cec5SDimitry Andric   void *th_free_list_self; // Self-allocated tasks free list
26700b57cec5SDimitry Andric   void *th_free_list_sync; // Self-allocated tasks stolen/returned by other
26710b57cec5SDimitry Andric   // threads
26720b57cec5SDimitry Andric   void *th_free_list_other; // Non-self free list (to be returned to owner's
26730b57cec5SDimitry Andric   // sync list)
26740b57cec5SDimitry Andric } kmp_free_list_t;
26750b57cec5SDimitry Andric #endif
26760b57cec5SDimitry Andric #if KMP_NESTED_HOT_TEAMS
26770b57cec5SDimitry Andric // Hot teams array keeps hot teams and their sizes for given thread. Hot teams
26780b57cec5SDimitry Andric // are not put in teams pool, and they don't put threads in threads pool.
26790b57cec5SDimitry Andric typedef struct kmp_hot_team_ptr {
26800b57cec5SDimitry Andric   kmp_team_p *hot_team; // pointer to hot_team of given nesting level
26810b57cec5SDimitry Andric   kmp_int32 hot_team_nth; // number of threads allocated for the hot_team
26820b57cec5SDimitry Andric } kmp_hot_team_ptr_t;
26830b57cec5SDimitry Andric #endif
26840b57cec5SDimitry Andric typedef struct kmp_teams_size {
26850b57cec5SDimitry Andric   kmp_int32 nteams; // number of teams in a league
26860b57cec5SDimitry Andric   kmp_int32 nth; // number of threads in each team of the league
26870b57cec5SDimitry Andric } kmp_teams_size_t;
26880b57cec5SDimitry Andric 
26890b57cec5SDimitry Andric // This struct stores a thread that acts as a "root" for a contention
26900b57cec5SDimitry Andric // group. Contention groups are rooted at kmp_root threads, but also at
2691fe6060f1SDimitry Andric // each primary thread of each team created in the teams construct.
26920b57cec5SDimitry Andric // This struct therefore also stores a thread_limit associated with
26930b57cec5SDimitry Andric // that contention group, and a counter to track the number of threads
26940b57cec5SDimitry Andric // active in that contention group. Each thread has a list of these: CG
26950b57cec5SDimitry Andric // root threads have an entry in their list in which cg_root refers to
26960b57cec5SDimitry Andric // the thread itself, whereas other workers in the CG will have a
26970b57cec5SDimitry Andric // single entry where cg_root is same as the entry containing their CG
26980b57cec5SDimitry Andric // root. When a thread encounters a teams construct, it will add a new
26990b57cec5SDimitry Andric // entry to the front of its list, because it now roots a new CG.
27000b57cec5SDimitry Andric typedef struct kmp_cg_root {
27010b57cec5SDimitry Andric   kmp_info_p *cg_root; // "root" thread for a contention group
27020b57cec5SDimitry Andric   // The CG root's limit comes from OMP_THREAD_LIMIT for root threads, or
2703fe6060f1SDimitry Andric   // thread_limit clause for teams primary threads
27040b57cec5SDimitry Andric   kmp_int32 cg_thread_limit;
27050b57cec5SDimitry Andric   kmp_int32 cg_nthreads; // Count of active threads in CG rooted at cg_root
27060b57cec5SDimitry Andric   struct kmp_cg_root *up; // pointer to higher level CG root in list
27070b57cec5SDimitry Andric } kmp_cg_root_t;
27080b57cec5SDimitry Andric 
27090b57cec5SDimitry Andric // OpenMP thread data structures
27100b57cec5SDimitry Andric 
27110b57cec5SDimitry Andric typedef struct KMP_ALIGN_CACHE kmp_base_info {
27120b57cec5SDimitry Andric   /* Start with the readonly data which is cache aligned and padded. This is
2713fe6060f1SDimitry Andric      written before the thread starts working by the primary thread. Uber
2714fe6060f1SDimitry Andric      masters may update themselves later. Usage does not consider serialized
2715fe6060f1SDimitry Andric      regions.  */
27160b57cec5SDimitry Andric   kmp_desc_t th_info;
27170b57cec5SDimitry Andric   kmp_team_p *th_team; /* team we belong to */
27180b57cec5SDimitry Andric   kmp_root_p *th_root; /* pointer to root of task hierarchy */
27190b57cec5SDimitry Andric   kmp_info_p *th_next_pool; /* next available thread in the pool */
27200b57cec5SDimitry Andric   kmp_disp_t *th_dispatch; /* thread's dispatch data */
27210b57cec5SDimitry Andric   int th_in_pool; /* in thread pool (32 bits for TCR/TCW) */
27220b57cec5SDimitry Andric 
27230b57cec5SDimitry Andric   /* The following are cached from the team info structure */
27240b57cec5SDimitry Andric   /* TODO use these in more places as determined to be needed via profiling */
27250b57cec5SDimitry Andric   int th_team_nproc; /* number of threads in a team */
2726fe6060f1SDimitry Andric   kmp_info_p *th_team_master; /* the team's primary thread */
27270b57cec5SDimitry Andric   int th_team_serialized; /* team is serialized */
27280b57cec5SDimitry Andric   microtask_t th_teams_microtask; /* save entry address for teams construct */
27290b57cec5SDimitry Andric   int th_teams_level; /* save initial level of teams construct */
27300b57cec5SDimitry Andric /* it is 0 on device but may be any on host */
27310b57cec5SDimitry Andric 
27325ffd83dbSDimitry Andric /* The blocktime info is copied from the team struct to the thread struct */
27330b57cec5SDimitry Andric /* at the start of a barrier, and the values stored in the team are used  */
27340b57cec5SDimitry Andric /* at points in the code where the team struct is no longer guaranteed    */
27350b57cec5SDimitry Andric /* to exist (from the POV of worker threads).                             */
27360b57cec5SDimitry Andric #if KMP_USE_MONITOR
27370b57cec5SDimitry Andric   int th_team_bt_intervals;
27380b57cec5SDimitry Andric   int th_team_bt_set;
27390b57cec5SDimitry Andric #else
27400b57cec5SDimitry Andric   kmp_uint64 th_team_bt_intervals;
27410b57cec5SDimitry Andric #endif
27420b57cec5SDimitry Andric 
27430b57cec5SDimitry Andric #if KMP_AFFINITY_SUPPORTED
27440b57cec5SDimitry Andric   kmp_affin_mask_t *th_affin_mask; /* thread's current affinity mask */
2745*bdd1243dSDimitry Andric   kmp_affinity_ids_t th_topology_ids; /* thread's current topology ids */
2746*bdd1243dSDimitry Andric   kmp_affinity_attrs_t th_topology_attrs; /* thread's current topology attrs */
27470b57cec5SDimitry Andric #endif
27480b57cec5SDimitry Andric   omp_allocator_handle_t th_def_allocator; /* default allocator */
2749fe6060f1SDimitry Andric   /* The data set by the primary thread at reinit, then R/W by the worker */
27500b57cec5SDimitry Andric   KMP_ALIGN_CACHE int
27510b57cec5SDimitry Andric       th_set_nproc; /* if > 0, then only use this request for the next fork */
27520b57cec5SDimitry Andric #if KMP_NESTED_HOT_TEAMS
27530b57cec5SDimitry Andric   kmp_hot_team_ptr_t *th_hot_teams; /* array of hot teams */
27540b57cec5SDimitry Andric #endif
27550b57cec5SDimitry Andric   kmp_proc_bind_t
27560b57cec5SDimitry Andric       th_set_proc_bind; /* if != proc_bind_default, use request for next fork */
27570b57cec5SDimitry Andric   kmp_teams_size_t
27580b57cec5SDimitry Andric       th_teams_size; /* number of teams/threads in teams construct */
27590b57cec5SDimitry Andric #if KMP_AFFINITY_SUPPORTED
27600b57cec5SDimitry Andric   int th_current_place; /* place currently bound to */
27610b57cec5SDimitry Andric   int th_new_place; /* place to bind to in par reg */
27620b57cec5SDimitry Andric   int th_first_place; /* first place in partition */
27630b57cec5SDimitry Andric   int th_last_place; /* last place in partition */
27640b57cec5SDimitry Andric #endif
27650b57cec5SDimitry Andric   int th_prev_level; /* previous level for affinity format */
27660b57cec5SDimitry Andric   int th_prev_num_threads; /* previous num_threads for affinity format */
27670b57cec5SDimitry Andric #if USE_ITT_BUILD
27680b57cec5SDimitry Andric   kmp_uint64 th_bar_arrive_time; /* arrival to barrier timestamp */
27690b57cec5SDimitry Andric   kmp_uint64 th_bar_min_time; /* minimum arrival time at the barrier */
27700b57cec5SDimitry Andric   kmp_uint64 th_frame_time; /* frame timestamp */
27710b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */
27720b57cec5SDimitry Andric   kmp_local_t th_local;
27730b57cec5SDimitry Andric   struct private_common *th_pri_head;
27740b57cec5SDimitry Andric 
27750b57cec5SDimitry Andric   /* Now the data only used by the worker (after initial allocation) */
27760b57cec5SDimitry Andric   /* TODO the first serial team should actually be stored in the info_t
27770b57cec5SDimitry Andric      structure.  this will help reduce initial allocation overhead */
27780b57cec5SDimitry Andric   KMP_ALIGN_CACHE kmp_team_p
27790b57cec5SDimitry Andric       *th_serial_team; /*serialized team held in reserve*/
27800b57cec5SDimitry Andric 
27810b57cec5SDimitry Andric #if OMPT_SUPPORT
27820b57cec5SDimitry Andric   ompt_thread_info_t ompt_thread_info;
27830b57cec5SDimitry Andric #endif
27840b57cec5SDimitry Andric 
2785fe6060f1SDimitry Andric   /* The following are also read by the primary thread during reinit */
27860b57cec5SDimitry Andric   struct common_table *th_pri_common;
27870b57cec5SDimitry Andric 
27880b57cec5SDimitry Andric   volatile kmp_uint32 th_spin_here; /* thread-local location for spinning */
27890b57cec5SDimitry Andric   /* while awaiting queuing lock acquire */
27900b57cec5SDimitry Andric 
27910b57cec5SDimitry Andric   volatile void *th_sleep_loc; // this points at a kmp_flag<T>
2792349cc55cSDimitry Andric   flag_type th_sleep_loc_type; // enum type of flag stored in th_sleep_loc
27930b57cec5SDimitry Andric 
27940b57cec5SDimitry Andric   ident_t *th_ident;
27950b57cec5SDimitry Andric   unsigned th_x; // Random number generator data
27960b57cec5SDimitry Andric   unsigned th_a; // Random number generator data
27970b57cec5SDimitry Andric 
27980b57cec5SDimitry Andric   /* Tasking-related data for the thread */
27990b57cec5SDimitry Andric   kmp_task_team_t *th_task_team; // Task team struct
28000b57cec5SDimitry Andric   kmp_taskdata_t *th_current_task; // Innermost Task being executed
28010b57cec5SDimitry Andric   kmp_uint8 th_task_state; // alternating 0/1 for task team identification
28020b57cec5SDimitry Andric   kmp_uint8 *th_task_state_memo_stack; // Stack holding memos of th_task_state
28030b57cec5SDimitry Andric   // at nested levels
28040b57cec5SDimitry Andric   kmp_uint32 th_task_state_top; // Top element of th_task_state_memo_stack
28050b57cec5SDimitry Andric   kmp_uint32 th_task_state_stack_sz; // Size of th_task_state_memo_stack
28060b57cec5SDimitry Andric   kmp_uint32 th_reap_state; // Non-zero indicates thread is not
28070b57cec5SDimitry Andric   // tasking, thus safe to reap
28080b57cec5SDimitry Andric 
28090b57cec5SDimitry Andric   /* More stuff for keeping track of active/sleeping threads (this part is
28100b57cec5SDimitry Andric      written by the worker thread) */
28110b57cec5SDimitry Andric   kmp_uint8 th_active_in_pool; // included in count of #active threads in pool
28120b57cec5SDimitry Andric   int th_active; // ! sleeping; 32 bits for TCR/TCW
2813349cc55cSDimitry Andric   std::atomic<kmp_uint32> th_used_in_team; // Flag indicating use in team
2814349cc55cSDimitry Andric   // 0 = not used in team; 1 = used in team;
2815349cc55cSDimitry Andric   // 2 = transitioning to not used in team; 3 = transitioning to used in team
28160b57cec5SDimitry Andric   struct cons_header *th_cons; // used for consistency check
28170b57cec5SDimitry Andric #if KMP_USE_HIER_SCHED
28180b57cec5SDimitry Andric   // used for hierarchical scheduling
28190b57cec5SDimitry Andric   kmp_hier_private_bdata_t *th_hier_bar_data;
28200b57cec5SDimitry Andric #endif
28210b57cec5SDimitry Andric 
28220b57cec5SDimitry Andric   /* Add the syncronizing data which is cache aligned and padded. */
28230b57cec5SDimitry Andric   KMP_ALIGN_CACHE kmp_balign_t th_bar[bs_last_barrier];
28240b57cec5SDimitry Andric 
28250b57cec5SDimitry Andric   KMP_ALIGN_CACHE volatile kmp_int32
28260b57cec5SDimitry Andric       th_next_waiting; /* gtid+1 of next thread on lock wait queue, 0 if none */
28270b57cec5SDimitry Andric 
28280b57cec5SDimitry Andric #if (USE_FAST_MEMORY == 3) || (USE_FAST_MEMORY == 5)
28290b57cec5SDimitry Andric #define NUM_LISTS 4
28300b57cec5SDimitry Andric   kmp_free_list_t th_free_lists[NUM_LISTS]; // Free lists for fast memory
28310b57cec5SDimitry Andric // allocation routines
28320b57cec5SDimitry Andric #endif
28330b57cec5SDimitry Andric 
28340b57cec5SDimitry Andric #if KMP_OS_WINDOWS
28350b57cec5SDimitry Andric   kmp_win32_cond_t th_suspend_cv;
28360b57cec5SDimitry Andric   kmp_win32_mutex_t th_suspend_mx;
28370b57cec5SDimitry Andric   std::atomic<int> th_suspend_init;
28380b57cec5SDimitry Andric #endif
28390b57cec5SDimitry Andric #if KMP_OS_UNIX
28400b57cec5SDimitry Andric   kmp_cond_align_t th_suspend_cv;
28410b57cec5SDimitry Andric   kmp_mutex_align_t th_suspend_mx;
28420b57cec5SDimitry Andric   std::atomic<int> th_suspend_init_count;
28430b57cec5SDimitry Andric #endif
28440b57cec5SDimitry Andric 
28450b57cec5SDimitry Andric #if USE_ITT_BUILD
28460b57cec5SDimitry Andric   kmp_itt_mark_t th_itt_mark_single;
28470b57cec5SDimitry Andric // alignment ???
28480b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */
28490b57cec5SDimitry Andric #if KMP_STATS_ENABLED
28500b57cec5SDimitry Andric   kmp_stats_list *th_stats;
28510b57cec5SDimitry Andric #endif
28520b57cec5SDimitry Andric #if KMP_OS_UNIX
28530b57cec5SDimitry Andric   std::atomic<bool> th_blocking;
28540b57cec5SDimitry Andric #endif
28550b57cec5SDimitry Andric   kmp_cg_root_t *th_cg_roots; // list of cg_roots associated with this thread
28560b57cec5SDimitry Andric } kmp_base_info_t;
28570b57cec5SDimitry Andric 
28580b57cec5SDimitry Andric typedef union KMP_ALIGN_CACHE kmp_info {
28590b57cec5SDimitry Andric   double th_align; /* use worst case alignment */
28600b57cec5SDimitry Andric   char th_pad[KMP_PAD(kmp_base_info_t, CACHE_LINE)];
28610b57cec5SDimitry Andric   kmp_base_info_t th;
28620b57cec5SDimitry Andric } kmp_info_t;
28630b57cec5SDimitry Andric 
28640b57cec5SDimitry Andric // OpenMP thread team data structures
28650b57cec5SDimitry Andric 
2866fe6060f1SDimitry Andric typedef struct kmp_base_data {
2867fe6060f1SDimitry Andric   volatile kmp_uint32 t_value;
2868fe6060f1SDimitry Andric } kmp_base_data_t;
28690b57cec5SDimitry Andric 
28700b57cec5SDimitry Andric typedef union KMP_ALIGN_CACHE kmp_sleep_team {
28710b57cec5SDimitry Andric   double dt_align; /* use worst case alignment */
28720b57cec5SDimitry Andric   char dt_pad[KMP_PAD(kmp_base_data_t, CACHE_LINE)];
28730b57cec5SDimitry Andric   kmp_base_data_t dt;
28740b57cec5SDimitry Andric } kmp_sleep_team_t;
28750b57cec5SDimitry Andric 
28760b57cec5SDimitry Andric typedef union KMP_ALIGN_CACHE kmp_ordered_team {
28770b57cec5SDimitry Andric   double dt_align; /* use worst case alignment */
28780b57cec5SDimitry Andric   char dt_pad[KMP_PAD(kmp_base_data_t, CACHE_LINE)];
28790b57cec5SDimitry Andric   kmp_base_data_t dt;
28800b57cec5SDimitry Andric } kmp_ordered_team_t;
28810b57cec5SDimitry Andric 
28820b57cec5SDimitry Andric typedef int (*launch_t)(int gtid);
28830b57cec5SDimitry Andric 
28840b57cec5SDimitry Andric /* Minimum number of ARGV entries to malloc if necessary */
28850b57cec5SDimitry Andric #define KMP_MIN_MALLOC_ARGV_ENTRIES 100
28860b57cec5SDimitry Andric 
28870b57cec5SDimitry Andric // Set up how many argv pointers will fit in cache lines containing
28880b57cec5SDimitry Andric // t_inline_argv. Historically, we have supported at least 96 bytes. Using a
2889fe6060f1SDimitry Andric // larger value for more space between the primary write/worker read section and
28900b57cec5SDimitry Andric // read/write by all section seems to buy more performance on EPCC PARALLEL.
28910b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
28920b57cec5SDimitry Andric #define KMP_INLINE_ARGV_BYTES                                                  \
28930b57cec5SDimitry Andric   (4 * CACHE_LINE -                                                            \
28940b57cec5SDimitry Andric    ((3 * KMP_PTR_SKIP + 2 * sizeof(int) + 2 * sizeof(kmp_int8) +               \
28950b57cec5SDimitry Andric      sizeof(kmp_int16) + sizeof(kmp_uint32)) %                                 \
28960b57cec5SDimitry Andric     CACHE_LINE))
28970b57cec5SDimitry Andric #else
28980b57cec5SDimitry Andric #define KMP_INLINE_ARGV_BYTES                                                  \
28990b57cec5SDimitry Andric   (2 * CACHE_LINE - ((3 * KMP_PTR_SKIP + 2 * sizeof(int)) % CACHE_LINE))
29000b57cec5SDimitry Andric #endif
29010b57cec5SDimitry Andric #define KMP_INLINE_ARGV_ENTRIES (int)(KMP_INLINE_ARGV_BYTES / KMP_PTR_SKIP)
29020b57cec5SDimitry Andric 
29030b57cec5SDimitry Andric typedef struct KMP_ALIGN_CACHE kmp_base_team {
29040b57cec5SDimitry Andric   // Synchronization Data
29050b57cec5SDimitry Andric   // ---------------------------------------------------------------------------
29060b57cec5SDimitry Andric   KMP_ALIGN_CACHE kmp_ordered_team_t t_ordered;
29070b57cec5SDimitry Andric   kmp_balign_team_t t_bar[bs_last_barrier];
29080b57cec5SDimitry Andric   std::atomic<int> t_construct; // count of single directive encountered by team
29090b57cec5SDimitry Andric   char pad[sizeof(kmp_lock_t)]; // padding to maintain performance on big iron
29100b57cec5SDimitry Andric 
29110b57cec5SDimitry Andric   // [0] - parallel / [1] - worksharing task reduction data shared by taskgroups
29120b57cec5SDimitry Andric   std::atomic<void *> t_tg_reduce_data[2]; // to support task modifier
29130b57cec5SDimitry Andric   std::atomic<int> t_tg_fini_counter[2]; // sync end of task reductions
29140b57cec5SDimitry Andric 
2915fe6060f1SDimitry Andric   // Primary thread only
29160b57cec5SDimitry Andric   // ---------------------------------------------------------------------------
2917fe6060f1SDimitry Andric   KMP_ALIGN_CACHE int t_master_tid; // tid of primary thread in parent team
2918fe6060f1SDimitry Andric   int t_master_this_cons; // "this_construct" single counter of primary thread
2919fe6060f1SDimitry Andric   // in parent team
29200b57cec5SDimitry Andric   ident_t *t_ident; // if volatile, have to change too much other crud to
29210b57cec5SDimitry Andric   // volatile too
29220b57cec5SDimitry Andric   kmp_team_p *t_parent; // parent team
29230b57cec5SDimitry Andric   kmp_team_p *t_next_pool; // next free team in the team pool
29240b57cec5SDimitry Andric   kmp_disp_t *t_dispatch; // thread's dispatch data
29250b57cec5SDimitry Andric   kmp_task_team_t *t_task_team[2]; // Task team struct; switch between 2
29260b57cec5SDimitry Andric   kmp_proc_bind_t t_proc_bind; // bind type for par region
29270b57cec5SDimitry Andric #if USE_ITT_BUILD
29280b57cec5SDimitry Andric   kmp_uint64 t_region_time; // region begin timestamp
29290b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */
29300b57cec5SDimitry Andric 
2931fe6060f1SDimitry Andric   // Primary thread write, workers read
29320b57cec5SDimitry Andric   // --------------------------------------------------------------------------
29330b57cec5SDimitry Andric   KMP_ALIGN_CACHE void **t_argv;
29340b57cec5SDimitry Andric   int t_argc;
29350b57cec5SDimitry Andric   int t_nproc; // number of threads in team
29360b57cec5SDimitry Andric   microtask_t t_pkfn;
29370b57cec5SDimitry Andric   launch_t t_invoke; // procedure to launch the microtask
29380b57cec5SDimitry Andric 
29390b57cec5SDimitry Andric #if OMPT_SUPPORT
29400b57cec5SDimitry Andric   ompt_team_info_t ompt_team_info;
29410b57cec5SDimitry Andric   ompt_lw_taskteam_t *ompt_serialized_team_info;
29420b57cec5SDimitry Andric #endif
29430b57cec5SDimitry Andric 
29440b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
29450b57cec5SDimitry Andric   kmp_int8 t_fp_control_saved;
29460b57cec5SDimitry Andric   kmp_int8 t_pad2b;
29470b57cec5SDimitry Andric   kmp_int16 t_x87_fpu_control_word; // FP control regs
29480b57cec5SDimitry Andric   kmp_uint32 t_mxcsr;
29490b57cec5SDimitry Andric #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
29500b57cec5SDimitry Andric 
29510b57cec5SDimitry Andric   void *t_inline_argv[KMP_INLINE_ARGV_ENTRIES];
29520b57cec5SDimitry Andric 
29530b57cec5SDimitry Andric   KMP_ALIGN_CACHE kmp_info_t **t_threads;
29540b57cec5SDimitry Andric   kmp_taskdata_t
29550b57cec5SDimitry Andric       *t_implicit_task_taskdata; // Taskdata for the thread's implicit task
29560b57cec5SDimitry Andric   int t_level; // nested parallel level
29570b57cec5SDimitry Andric 
29580b57cec5SDimitry Andric   KMP_ALIGN_CACHE int t_max_argc;
2959480093f4SDimitry Andric   int t_max_nproc; // max threads this team can handle (dynamically expandable)
29600b57cec5SDimitry Andric   int t_serialized; // levels deep of serialized teams
29610b57cec5SDimitry Andric   dispatch_shared_info_t *t_disp_buffer; // buffers for dispatch system
29620b57cec5SDimitry Andric   int t_id; // team's id, assigned by debugger.
29630b57cec5SDimitry Andric   int t_active_level; // nested active parallel level
29640b57cec5SDimitry Andric   kmp_r_sched_t t_sched; // run-time schedule for the team
29650b57cec5SDimitry Andric #if KMP_AFFINITY_SUPPORTED
29660b57cec5SDimitry Andric   int t_first_place; // first & last place in parent thread's partition.
2967fe6060f1SDimitry Andric   int t_last_place; // Restore these values to primary thread after par region.
29680b57cec5SDimitry Andric #endif // KMP_AFFINITY_SUPPORTED
29690b57cec5SDimitry Andric   int t_display_affinity;
29700b57cec5SDimitry Andric   int t_size_changed; // team size was changed?: 0: no, 1: yes, -1: changed via
29710b57cec5SDimitry Andric   // omp_set_num_threads() call
29720b57cec5SDimitry Andric   omp_allocator_handle_t t_def_allocator; /* default allocator */
29730b57cec5SDimitry Andric 
29740b57cec5SDimitry Andric // Read/write by workers as well
29750b57cec5SDimitry Andric #if (KMP_ARCH_X86 || KMP_ARCH_X86_64)
29760b57cec5SDimitry Andric   // Using CACHE_LINE=64 reduces memory footprint, but causes a big perf
29770b57cec5SDimitry Andric   // regression of epcc 'parallel' and 'barrier' on fxe256lin01. This extra
29780b57cec5SDimitry Andric   // padding serves to fix the performance of epcc 'parallel' and 'barrier' when
29790b57cec5SDimitry Andric   // CACHE_LINE=64. TODO: investigate more and get rid if this padding.
29800b57cec5SDimitry Andric   char dummy_padding[1024];
29810b57cec5SDimitry Andric #endif
29820b57cec5SDimitry Andric   // Internal control stack for additional nested teams.
29830b57cec5SDimitry Andric   KMP_ALIGN_CACHE kmp_internal_control_t *t_control_stack_top;
29840b57cec5SDimitry Andric   // for SERIALIZED teams nested 2 or more levels deep
29850b57cec5SDimitry Andric   // typed flag to store request state of cancellation
29860b57cec5SDimitry Andric   std::atomic<kmp_int32> t_cancel_request;
29870b57cec5SDimitry Andric   int t_master_active; // save on fork, restore on join
29880b57cec5SDimitry Andric   void *t_copypriv_data; // team specific pointer to copyprivate data array
29890b57cec5SDimitry Andric #if KMP_OS_WINDOWS
29900b57cec5SDimitry Andric   std::atomic<kmp_uint32> t_copyin_counter;
29910b57cec5SDimitry Andric #endif
29920b57cec5SDimitry Andric #if USE_ITT_BUILD
29930b57cec5SDimitry Andric   void *t_stack_id; // team specific stack stitching id (for ittnotify)
29940b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */
2995349cc55cSDimitry Andric   distributedBarrier *b; // Distributed barrier data associated with team
29960b57cec5SDimitry Andric } kmp_base_team_t;
29970b57cec5SDimitry Andric 
29980b57cec5SDimitry Andric union KMP_ALIGN_CACHE kmp_team {
29990b57cec5SDimitry Andric   kmp_base_team_t t;
30000b57cec5SDimitry Andric   double t_align; /* use worst case alignment */
30010b57cec5SDimitry Andric   char t_pad[KMP_PAD(kmp_base_team_t, CACHE_LINE)];
30020b57cec5SDimitry Andric };
30030b57cec5SDimitry Andric 
30040b57cec5SDimitry Andric typedef union KMP_ALIGN_CACHE kmp_time_global {
30050b57cec5SDimitry Andric   double dt_align; /* use worst case alignment */
30060b57cec5SDimitry Andric   char dt_pad[KMP_PAD(kmp_base_data_t, CACHE_LINE)];
30070b57cec5SDimitry Andric   kmp_base_data_t dt;
30080b57cec5SDimitry Andric } kmp_time_global_t;
30090b57cec5SDimitry Andric 
30100b57cec5SDimitry Andric typedef struct kmp_base_global {
30110b57cec5SDimitry Andric   /* cache-aligned */
30120b57cec5SDimitry Andric   kmp_time_global_t g_time;
30130b57cec5SDimitry Andric 
30140b57cec5SDimitry Andric   /* non cache-aligned */
30150b57cec5SDimitry Andric   volatile int g_abort;
30160b57cec5SDimitry Andric   volatile int g_done;
30170b57cec5SDimitry Andric 
30180b57cec5SDimitry Andric   int g_dynamic;
30190b57cec5SDimitry Andric   enum dynamic_mode g_dynamic_mode;
30200b57cec5SDimitry Andric } kmp_base_global_t;
30210b57cec5SDimitry Andric 
30220b57cec5SDimitry Andric typedef union KMP_ALIGN_CACHE kmp_global {
30230b57cec5SDimitry Andric   kmp_base_global_t g;
30240b57cec5SDimitry Andric   double g_align; /* use worst case alignment */
30250b57cec5SDimitry Andric   char g_pad[KMP_PAD(kmp_base_global_t, CACHE_LINE)];
30260b57cec5SDimitry Andric } kmp_global_t;
30270b57cec5SDimitry Andric 
30280b57cec5SDimitry Andric typedef struct kmp_base_root {
30290b57cec5SDimitry Andric   // TODO: GEH - combine r_active with r_in_parallel then r_active ==
30300b57cec5SDimitry Andric   // (r_in_parallel>= 0)
30310b57cec5SDimitry Andric   // TODO: GEH - then replace r_active with t_active_levels if we can to reduce
30320b57cec5SDimitry Andric   // the synch overhead or keeping r_active
30330b57cec5SDimitry Andric   volatile int r_active; /* TRUE if some region in a nest has > 1 thread */
30340b57cec5SDimitry Andric   // keeps a count of active parallel regions per root
30350b57cec5SDimitry Andric   std::atomic<int> r_in_parallel;
30360b57cec5SDimitry Andric   // GEH: This is misnamed, should be r_active_levels
30370b57cec5SDimitry Andric   kmp_team_t *r_root_team;
30380b57cec5SDimitry Andric   kmp_team_t *r_hot_team;
30390b57cec5SDimitry Andric   kmp_info_t *r_uber_thread;
30400b57cec5SDimitry Andric   kmp_lock_t r_begin_lock;
30410b57cec5SDimitry Andric   volatile int r_begin;
30420b57cec5SDimitry Andric   int r_blocktime; /* blocktime for this root and descendants */
3043fe6060f1SDimitry Andric #if KMP_AFFINITY_SUPPORTED
3044fe6060f1SDimitry Andric   int r_affinity_assigned;
3045fe6060f1SDimitry Andric #endif // KMP_AFFINITY_SUPPORTED
30460b57cec5SDimitry Andric } kmp_base_root_t;
30470b57cec5SDimitry Andric 
30480b57cec5SDimitry Andric typedef union KMP_ALIGN_CACHE kmp_root {
30490b57cec5SDimitry Andric   kmp_base_root_t r;
30500b57cec5SDimitry Andric   double r_align; /* use worst case alignment */
30510b57cec5SDimitry Andric   char r_pad[KMP_PAD(kmp_base_root_t, CACHE_LINE)];
30520b57cec5SDimitry Andric } kmp_root_t;
30530b57cec5SDimitry Andric 
30540b57cec5SDimitry Andric struct fortran_inx_info {
30550b57cec5SDimitry Andric   kmp_int32 data;
30560b57cec5SDimitry Andric };
30570b57cec5SDimitry Andric 
305881ad6265SDimitry Andric // This list type exists to hold old __kmp_threads arrays so that
305981ad6265SDimitry Andric // old references to them may complete while reallocation takes place when
306081ad6265SDimitry Andric // expanding the array. The items in this list are kept alive until library
306181ad6265SDimitry Andric // shutdown.
306281ad6265SDimitry Andric typedef struct kmp_old_threads_list_t {
306381ad6265SDimitry Andric   kmp_info_t **threads;
306481ad6265SDimitry Andric   struct kmp_old_threads_list_t *next;
306581ad6265SDimitry Andric } kmp_old_threads_list_t;
306681ad6265SDimitry Andric 
30670b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
30680b57cec5SDimitry Andric 
30690b57cec5SDimitry Andric extern int __kmp_settings;
30700b57cec5SDimitry Andric extern int __kmp_duplicate_library_ok;
30710b57cec5SDimitry Andric #if USE_ITT_BUILD
30720b57cec5SDimitry Andric extern int __kmp_forkjoin_frames;
30730b57cec5SDimitry Andric extern int __kmp_forkjoin_frames_mode;
30740b57cec5SDimitry Andric #endif
30750b57cec5SDimitry Andric extern PACKED_REDUCTION_METHOD_T __kmp_force_reduction_method;
30760b57cec5SDimitry Andric extern int __kmp_determ_red;
30770b57cec5SDimitry Andric 
30780b57cec5SDimitry Andric #ifdef KMP_DEBUG
30790b57cec5SDimitry Andric extern int kmp_a_debug;
30800b57cec5SDimitry Andric extern int kmp_b_debug;
30810b57cec5SDimitry Andric extern int kmp_c_debug;
30820b57cec5SDimitry Andric extern int kmp_d_debug;
30830b57cec5SDimitry Andric extern int kmp_e_debug;
30840b57cec5SDimitry Andric extern int kmp_f_debug;
30850b57cec5SDimitry Andric #endif /* KMP_DEBUG */
30860b57cec5SDimitry Andric 
30870b57cec5SDimitry Andric /* For debug information logging using rotating buffer */
30880b57cec5SDimitry Andric #define KMP_DEBUG_BUF_LINES_INIT 512
30890b57cec5SDimitry Andric #define KMP_DEBUG_BUF_LINES_MIN 1
30900b57cec5SDimitry Andric 
30910b57cec5SDimitry Andric #define KMP_DEBUG_BUF_CHARS_INIT 128
30920b57cec5SDimitry Andric #define KMP_DEBUG_BUF_CHARS_MIN 2
30930b57cec5SDimitry Andric 
30940b57cec5SDimitry Andric extern int
30950b57cec5SDimitry Andric     __kmp_debug_buf; /* TRUE means use buffer, FALSE means print to stderr */
30960b57cec5SDimitry Andric extern int __kmp_debug_buf_lines; /* How many lines of debug stored in buffer */
30970b57cec5SDimitry Andric extern int
30980b57cec5SDimitry Andric     __kmp_debug_buf_chars; /* How many characters allowed per line in buffer */
30990b57cec5SDimitry Andric extern int __kmp_debug_buf_atomic; /* TRUE means use atomic update of buffer
31000b57cec5SDimitry Andric                                       entry pointer */
31010b57cec5SDimitry Andric 
31020b57cec5SDimitry Andric extern char *__kmp_debug_buffer; /* Debug buffer itself */
31030b57cec5SDimitry Andric extern std::atomic<int> __kmp_debug_count; /* Counter for number of lines
31040b57cec5SDimitry Andric                                               printed in buffer so far */
31050b57cec5SDimitry Andric extern int __kmp_debug_buf_warn_chars; /* Keep track of char increase
31060b57cec5SDimitry Andric                                           recommended in warnings */
31070b57cec5SDimitry Andric /* end rotating debug buffer */
31080b57cec5SDimitry Andric 
31090b57cec5SDimitry Andric #ifdef KMP_DEBUG
31100b57cec5SDimitry Andric extern int __kmp_par_range; /* +1 => only go par for constructs in range */
31110b57cec5SDimitry Andric 
31120b57cec5SDimitry Andric #define KMP_PAR_RANGE_ROUTINE_LEN 1024
31130b57cec5SDimitry Andric extern char __kmp_par_range_routine[KMP_PAR_RANGE_ROUTINE_LEN];
31140b57cec5SDimitry Andric #define KMP_PAR_RANGE_FILENAME_LEN 1024
31150b57cec5SDimitry Andric extern char __kmp_par_range_filename[KMP_PAR_RANGE_FILENAME_LEN];
31160b57cec5SDimitry Andric extern int __kmp_par_range_lb;
31170b57cec5SDimitry Andric extern int __kmp_par_range_ub;
31180b57cec5SDimitry Andric #endif
31190b57cec5SDimitry Andric 
31200b57cec5SDimitry Andric /* For printing out dynamic storage map for threads and teams */
31210b57cec5SDimitry Andric extern int
31220b57cec5SDimitry Andric     __kmp_storage_map; /* True means print storage map for threads and teams */
31230b57cec5SDimitry Andric extern int __kmp_storage_map_verbose; /* True means storage map includes
31240b57cec5SDimitry Andric                                          placement info */
31250b57cec5SDimitry Andric extern int __kmp_storage_map_verbose_specified;
31260b57cec5SDimitry Andric 
31270b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
31280b57cec5SDimitry Andric extern kmp_cpuinfo_t __kmp_cpuinfo;
3129349cc55cSDimitry Andric static inline bool __kmp_is_hybrid_cpu() { return __kmp_cpuinfo.flags.hybrid; }
313081ad6265SDimitry Andric #elif KMP_OS_DARWIN && KMP_ARCH_AARCH64
313181ad6265SDimitry Andric static inline bool __kmp_is_hybrid_cpu() { return true; }
3132349cc55cSDimitry Andric #else
3133349cc55cSDimitry Andric static inline bool __kmp_is_hybrid_cpu() { return false; }
31340b57cec5SDimitry Andric #endif
31350b57cec5SDimitry Andric 
31360b57cec5SDimitry Andric extern volatile int __kmp_init_serial;
31370b57cec5SDimitry Andric extern volatile int __kmp_init_gtid;
31380b57cec5SDimitry Andric extern volatile int __kmp_init_common;
3139fcaf7f86SDimitry Andric extern volatile int __kmp_need_register_serial;
31400b57cec5SDimitry Andric extern volatile int __kmp_init_middle;
31410b57cec5SDimitry Andric extern volatile int __kmp_init_parallel;
31420b57cec5SDimitry Andric #if KMP_USE_MONITOR
31430b57cec5SDimitry Andric extern volatile int __kmp_init_monitor;
31440b57cec5SDimitry Andric #endif
31450b57cec5SDimitry Andric extern volatile int __kmp_init_user_locks;
3146e8d8bef9SDimitry Andric extern volatile int __kmp_init_hidden_helper_threads;
31470b57cec5SDimitry Andric extern int __kmp_init_counter;
31480b57cec5SDimitry Andric extern int __kmp_root_counter;
31490b57cec5SDimitry Andric extern int __kmp_version;
31500b57cec5SDimitry Andric 
31510b57cec5SDimitry Andric /* list of address of allocated caches for commons */
31520b57cec5SDimitry Andric extern kmp_cached_addr_t *__kmp_threadpriv_cache_list;
31530b57cec5SDimitry Andric 
31540b57cec5SDimitry Andric /* Barrier algorithm types and options */
31550b57cec5SDimitry Andric extern kmp_uint32 __kmp_barrier_gather_bb_dflt;
31560b57cec5SDimitry Andric extern kmp_uint32 __kmp_barrier_release_bb_dflt;
31570b57cec5SDimitry Andric extern kmp_bar_pat_e __kmp_barrier_gather_pat_dflt;
31580b57cec5SDimitry Andric extern kmp_bar_pat_e __kmp_barrier_release_pat_dflt;
31590b57cec5SDimitry Andric extern kmp_uint32 __kmp_barrier_gather_branch_bits[bs_last_barrier];
31600b57cec5SDimitry Andric extern kmp_uint32 __kmp_barrier_release_branch_bits[bs_last_barrier];
31610b57cec5SDimitry Andric extern kmp_bar_pat_e __kmp_barrier_gather_pattern[bs_last_barrier];
31620b57cec5SDimitry Andric extern kmp_bar_pat_e __kmp_barrier_release_pattern[bs_last_barrier];
31630b57cec5SDimitry Andric extern char const *__kmp_barrier_branch_bit_env_name[bs_last_barrier];
31640b57cec5SDimitry Andric extern char const *__kmp_barrier_pattern_env_name[bs_last_barrier];
31650b57cec5SDimitry Andric extern char const *__kmp_barrier_type_name[bs_last_barrier];
31660b57cec5SDimitry Andric extern char const *__kmp_barrier_pattern_name[bp_last_bar];
31670b57cec5SDimitry Andric 
31680b57cec5SDimitry Andric /* Global Locks */
31690b57cec5SDimitry Andric extern kmp_bootstrap_lock_t __kmp_initz_lock; /* control initialization */
31700b57cec5SDimitry Andric extern kmp_bootstrap_lock_t __kmp_forkjoin_lock; /* control fork/join access */
31710b57cec5SDimitry Andric extern kmp_bootstrap_lock_t __kmp_task_team_lock;
31720b57cec5SDimitry Andric extern kmp_bootstrap_lock_t
31730b57cec5SDimitry Andric     __kmp_exit_lock; /* exit() is not always thread-safe */
31740b57cec5SDimitry Andric #if KMP_USE_MONITOR
31750b57cec5SDimitry Andric extern kmp_bootstrap_lock_t
31760b57cec5SDimitry Andric     __kmp_monitor_lock; /* control monitor thread creation */
31770b57cec5SDimitry Andric #endif
31780b57cec5SDimitry Andric extern kmp_bootstrap_lock_t
31790b57cec5SDimitry Andric     __kmp_tp_cached_lock; /* used for the hack to allow threadprivate cache and
31800b57cec5SDimitry Andric                              __kmp_threads expansion to co-exist */
31810b57cec5SDimitry Andric 
31820b57cec5SDimitry Andric extern kmp_lock_t __kmp_global_lock; /* control OS/global access  */
31830b57cec5SDimitry Andric extern kmp_queuing_lock_t __kmp_dispatch_lock; /* control dispatch access  */
31840b57cec5SDimitry Andric extern kmp_lock_t __kmp_debug_lock; /* control I/O access for KMP_DEBUG */
31850b57cec5SDimitry Andric 
31860b57cec5SDimitry Andric extern enum library_type __kmp_library;
31870b57cec5SDimitry Andric 
31880b57cec5SDimitry Andric extern enum sched_type __kmp_sched; /* default runtime scheduling */
31890b57cec5SDimitry Andric extern enum sched_type __kmp_static; /* default static scheduling method */
31900b57cec5SDimitry Andric extern enum sched_type __kmp_guided; /* default guided scheduling method */
31910b57cec5SDimitry Andric extern enum sched_type __kmp_auto; /* default auto scheduling method */
31920b57cec5SDimitry Andric extern int __kmp_chunk; /* default runtime chunk size */
3193fe6060f1SDimitry Andric extern int __kmp_force_monotonic; /* whether monotonic scheduling forced */
31940b57cec5SDimitry Andric 
31950b57cec5SDimitry Andric extern size_t __kmp_stksize; /* stack size per thread         */
31960b57cec5SDimitry Andric #if KMP_USE_MONITOR
31970b57cec5SDimitry Andric extern size_t __kmp_monitor_stksize; /* stack size for monitor thread */
31980b57cec5SDimitry Andric #endif
31990b57cec5SDimitry Andric extern size_t __kmp_stkoffset; /* stack offset per thread       */
32000b57cec5SDimitry Andric extern int __kmp_stkpadding; /* Should we pad root thread(s) stack */
32010b57cec5SDimitry Andric 
32020b57cec5SDimitry Andric extern size_t
32030b57cec5SDimitry Andric     __kmp_malloc_pool_incr; /* incremental size of pool for kmp_malloc() */
32040b57cec5SDimitry Andric extern int __kmp_env_stksize; /* was KMP_STACKSIZE specified? */
32050b57cec5SDimitry Andric extern int __kmp_env_blocktime; /* was KMP_BLOCKTIME specified? */
32060b57cec5SDimitry Andric extern int __kmp_env_checks; /* was KMP_CHECKS specified?    */
32070b57cec5SDimitry Andric extern int __kmp_env_consistency_check; // was KMP_CONSISTENCY_CHECK specified?
32080b57cec5SDimitry Andric extern int __kmp_generate_warnings; /* should we issue warnings? */
32090b57cec5SDimitry Andric extern int __kmp_reserve_warn; /* have we issued reserve_threads warning? */
32100b57cec5SDimitry Andric 
32110b57cec5SDimitry Andric #ifdef DEBUG_SUSPEND
32120b57cec5SDimitry Andric extern int __kmp_suspend_count; /* count inside __kmp_suspend_template() */
32130b57cec5SDimitry Andric #endif
32140b57cec5SDimitry Andric 
32150b57cec5SDimitry Andric extern kmp_int32 __kmp_use_yield;
32160b57cec5SDimitry Andric extern kmp_int32 __kmp_use_yield_exp_set;
32170b57cec5SDimitry Andric extern kmp_uint32 __kmp_yield_init;
32180b57cec5SDimitry Andric extern kmp_uint32 __kmp_yield_next;
321904eeddc0SDimitry Andric extern kmp_uint64 __kmp_pause_init;
32200b57cec5SDimitry Andric 
32210b57cec5SDimitry Andric /* ------------------------------------------------------------------------- */
32220b57cec5SDimitry Andric extern int __kmp_allThreadsSpecified;
32230b57cec5SDimitry Andric 
32240b57cec5SDimitry Andric extern size_t __kmp_align_alloc;
32250b57cec5SDimitry Andric /* following data protected by initialization routines */
32260b57cec5SDimitry Andric extern int __kmp_xproc; /* number of processors in the system */
32270b57cec5SDimitry Andric extern int __kmp_avail_proc; /* number of processors available to the process */
32280b57cec5SDimitry Andric extern size_t __kmp_sys_min_stksize; /* system-defined minimum stack size */
32290b57cec5SDimitry Andric extern int __kmp_sys_max_nth; /* system-imposed maximum number of threads */
32300b57cec5SDimitry Andric // maximum total number of concurrently-existing threads on device
32310b57cec5SDimitry Andric extern int __kmp_max_nth;
32320b57cec5SDimitry Andric // maximum total number of concurrently-existing threads in a contention group
32330b57cec5SDimitry Andric extern int __kmp_cg_max_nth;
32340b57cec5SDimitry Andric extern int __kmp_teams_max_nth; // max threads used in a teams construct
32350b57cec5SDimitry Andric extern int __kmp_threads_capacity; /* capacity of the arrays __kmp_threads and
32360b57cec5SDimitry Andric                                       __kmp_root */
32370b57cec5SDimitry Andric extern int __kmp_dflt_team_nth; /* default number of threads in a parallel
32380b57cec5SDimitry Andric                                    region a la OMP_NUM_THREADS */
32390b57cec5SDimitry Andric extern int __kmp_dflt_team_nth_ub; /* upper bound on "" determined at serial
32400b57cec5SDimitry Andric                                       initialization */
32410b57cec5SDimitry Andric extern int __kmp_tp_capacity; /* capacity of __kmp_threads if threadprivate is
32420b57cec5SDimitry Andric                                  used (fixed) */
32430b57cec5SDimitry Andric extern int __kmp_tp_cached; /* whether threadprivate cache has been created
32440b57cec5SDimitry Andric                                (__kmpc_threadprivate_cached()) */
32450b57cec5SDimitry Andric extern int __kmp_dflt_blocktime; /* number of milliseconds to wait before
32460b57cec5SDimitry Andric                                     blocking (env setting) */
324781ad6265SDimitry Andric extern bool __kmp_wpolicy_passive; /* explicitly set passive wait policy */
32480b57cec5SDimitry Andric #if KMP_USE_MONITOR
32490b57cec5SDimitry Andric extern int
32500b57cec5SDimitry Andric     __kmp_monitor_wakeups; /* number of times monitor wakes up per second */
32510b57cec5SDimitry Andric extern int __kmp_bt_intervals; /* number of monitor timestamp intervals before
32520b57cec5SDimitry Andric                                   blocking */
32530b57cec5SDimitry Andric #endif
32540b57cec5SDimitry Andric #ifdef KMP_ADJUST_BLOCKTIME
32550b57cec5SDimitry Andric extern int __kmp_zero_bt; /* whether blocktime has been forced to zero */
32560b57cec5SDimitry Andric #endif /* KMP_ADJUST_BLOCKTIME */
32570b57cec5SDimitry Andric #ifdef KMP_DFLT_NTH_CORES
32580b57cec5SDimitry Andric extern int __kmp_ncores; /* Total number of cores for threads placement */
32590b57cec5SDimitry Andric #endif
32600b57cec5SDimitry Andric /* Number of millisecs to delay on abort for Intel(R) VTune(TM) tools */
32610b57cec5SDimitry Andric extern int __kmp_abort_delay;
32620b57cec5SDimitry Andric 
32630b57cec5SDimitry Andric extern int __kmp_need_register_atfork_specified;
3264fe6060f1SDimitry Andric extern int __kmp_need_register_atfork; /* At initialization, call pthread_atfork
3265fe6060f1SDimitry Andric                                           to install fork handler */
32660b57cec5SDimitry Andric extern int __kmp_gtid_mode; /* Method of getting gtid, values:
32670b57cec5SDimitry Andric                                0 - not set, will be set at runtime
32680b57cec5SDimitry Andric                                1 - using stack search
32690b57cec5SDimitry Andric                                2 - dynamic TLS (pthread_getspecific(Linux* OS/OS
32700b57cec5SDimitry Andric                                    X*) or TlsGetValue(Windows* OS))
32710b57cec5SDimitry Andric                                3 - static TLS (__declspec(thread) __kmp_gtid),
32720b57cec5SDimitry Andric                                    Linux* OS .so only.  */
32730b57cec5SDimitry Andric extern int
32740b57cec5SDimitry Andric     __kmp_adjust_gtid_mode; /* If true, adjust method based on #threads */
32750b57cec5SDimitry Andric #ifdef KMP_TDATA_GTID
32760b57cec5SDimitry Andric extern KMP_THREAD_LOCAL int __kmp_gtid;
32770b57cec5SDimitry Andric #endif
32780b57cec5SDimitry Andric extern int __kmp_tls_gtid_min; /* #threads below which use sp search for gtid */
32790b57cec5SDimitry Andric extern int __kmp_foreign_tp; // If true, separate TP var for each foreign thread
32800b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
32810b57cec5SDimitry Andric extern int __kmp_inherit_fp_control; // copy fp creg(s) parent->workers at fork
32820b57cec5SDimitry Andric extern kmp_int16 __kmp_init_x87_fpu_control_word; // init thread's FP ctrl reg
32830b57cec5SDimitry Andric extern kmp_uint32 __kmp_init_mxcsr; /* init thread's mxscr */
32840b57cec5SDimitry Andric #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
32850b57cec5SDimitry Andric 
32860b57cec5SDimitry Andric // max_active_levels for nested parallelism enabled by default via
32870b57cec5SDimitry Andric // OMP_MAX_ACTIVE_LEVELS, OMP_NESTED, OMP_NUM_THREADS, and OMP_PROC_BIND
32880b57cec5SDimitry Andric extern int __kmp_dflt_max_active_levels;
32890b57cec5SDimitry Andric // Indicates whether value of __kmp_dflt_max_active_levels was already
32900b57cec5SDimitry Andric // explicitly set by OMP_MAX_ACTIVE_LEVELS or OMP_NESTED=false
32910b57cec5SDimitry Andric extern bool __kmp_dflt_max_active_levels_set;
32920b57cec5SDimitry Andric extern int __kmp_dispatch_num_buffers; /* max possible dynamic loops in
32930b57cec5SDimitry Andric                                           concurrent execution per team */
32940b57cec5SDimitry Andric #if KMP_NESTED_HOT_TEAMS
32950b57cec5SDimitry Andric extern int __kmp_hot_teams_mode;
32960b57cec5SDimitry Andric extern int __kmp_hot_teams_max_level;
32970b57cec5SDimitry Andric #endif
32980b57cec5SDimitry Andric 
32990b57cec5SDimitry Andric #if KMP_OS_LINUX
33000b57cec5SDimitry Andric extern enum clock_function_type __kmp_clock_function;
33010b57cec5SDimitry Andric extern int __kmp_clock_function_param;
33020b57cec5SDimitry Andric #endif /* KMP_OS_LINUX */
33030b57cec5SDimitry Andric 
33040b57cec5SDimitry Andric #if KMP_MIC_SUPPORTED
33050b57cec5SDimitry Andric extern enum mic_type __kmp_mic_type;
33060b57cec5SDimitry Andric #endif
33070b57cec5SDimitry Andric 
33080b57cec5SDimitry Andric #ifdef USE_LOAD_BALANCE
33090b57cec5SDimitry Andric extern double __kmp_load_balance_interval; // load balance algorithm interval
33100b57cec5SDimitry Andric #endif /* USE_LOAD_BALANCE */
33110b57cec5SDimitry Andric 
33120b57cec5SDimitry Andric // OpenMP 3.1 - Nested num threads array
33130b57cec5SDimitry Andric typedef struct kmp_nested_nthreads_t {
33140b57cec5SDimitry Andric   int *nth;
33150b57cec5SDimitry Andric   int size;
33160b57cec5SDimitry Andric   int used;
33170b57cec5SDimitry Andric } kmp_nested_nthreads_t;
33180b57cec5SDimitry Andric 
33190b57cec5SDimitry Andric extern kmp_nested_nthreads_t __kmp_nested_nth;
33200b57cec5SDimitry Andric 
33210b57cec5SDimitry Andric #if KMP_USE_ADAPTIVE_LOCKS
33220b57cec5SDimitry Andric 
33230b57cec5SDimitry Andric // Parameters for the speculative lock backoff system.
33240b57cec5SDimitry Andric struct kmp_adaptive_backoff_params_t {
33250b57cec5SDimitry Andric   // Number of soft retries before it counts as a hard retry.
33260b57cec5SDimitry Andric   kmp_uint32 max_soft_retries;
33270b57cec5SDimitry Andric   // Badness is a bit mask : 0,1,3,7,15,... on each hard failure we move one to
33280b57cec5SDimitry Andric   // the right
33290b57cec5SDimitry Andric   kmp_uint32 max_badness;
33300b57cec5SDimitry Andric };
33310b57cec5SDimitry Andric 
33320b57cec5SDimitry Andric extern kmp_adaptive_backoff_params_t __kmp_adaptive_backoff_params;
33330b57cec5SDimitry Andric 
33340b57cec5SDimitry Andric #if KMP_DEBUG_ADAPTIVE_LOCKS
33350b57cec5SDimitry Andric extern const char *__kmp_speculative_statsfile;
33360b57cec5SDimitry Andric #endif
33370b57cec5SDimitry Andric 
33380b57cec5SDimitry Andric #endif // KMP_USE_ADAPTIVE_LOCKS
33390b57cec5SDimitry Andric 
33400b57cec5SDimitry Andric extern int __kmp_display_env; /* TRUE or FALSE */
33410b57cec5SDimitry Andric extern int __kmp_display_env_verbose; /* TRUE if OMP_DISPLAY_ENV=VERBOSE */
33420b57cec5SDimitry Andric extern int __kmp_omp_cancellation; /* TRUE or FALSE */
3343fe6060f1SDimitry Andric extern int __kmp_nteams;
3344fe6060f1SDimitry Andric extern int __kmp_teams_thread_limit;
33450b57cec5SDimitry Andric 
33460b57cec5SDimitry Andric /* ------------------------------------------------------------------------- */
33470b57cec5SDimitry Andric 
33480b57cec5SDimitry Andric /* the following are protected by the fork/join lock */
33490b57cec5SDimitry Andric /* write: lock  read: anytime */
33500b57cec5SDimitry Andric extern kmp_info_t **__kmp_threads; /* Descriptors for the threads */
335181ad6265SDimitry Andric /* Holds old arrays of __kmp_threads until library shutdown */
335281ad6265SDimitry Andric extern kmp_old_threads_list_t *__kmp_old_threads_list;
33530b57cec5SDimitry Andric /* read/write: lock */
33540b57cec5SDimitry Andric extern volatile kmp_team_t *__kmp_team_pool;
33550b57cec5SDimitry Andric extern volatile kmp_info_t *__kmp_thread_pool;
33560b57cec5SDimitry Andric extern kmp_info_t *__kmp_thread_pool_insert_pt;
33570b57cec5SDimitry Andric 
33580b57cec5SDimitry Andric // total num threads reachable from some root thread including all root threads
33590b57cec5SDimitry Andric extern volatile int __kmp_nth;
33600b57cec5SDimitry Andric /* total number of threads reachable from some root thread including all root
33610b57cec5SDimitry Andric    threads, and those in the thread pool */
33620b57cec5SDimitry Andric extern volatile int __kmp_all_nth;
33630b57cec5SDimitry Andric extern std::atomic<int> __kmp_thread_pool_active_nth;
33640b57cec5SDimitry Andric 
33650b57cec5SDimitry Andric extern kmp_root_t **__kmp_root; /* root of thread hierarchy */
33660b57cec5SDimitry Andric /* end data protected by fork/join lock */
33670b57cec5SDimitry Andric /* ------------------------------------------------------------------------- */
33680b57cec5SDimitry Andric 
33690b57cec5SDimitry Andric #define __kmp_get_gtid() __kmp_get_global_thread_id()
33700b57cec5SDimitry Andric #define __kmp_entry_gtid() __kmp_get_global_thread_id_reg()
33710b57cec5SDimitry Andric #define __kmp_get_tid() (__kmp_tid_from_gtid(__kmp_get_gtid()))
33720b57cec5SDimitry Andric #define __kmp_get_team() (__kmp_threads[(__kmp_get_gtid())]->th.th_team)
33730b57cec5SDimitry Andric #define __kmp_get_thread() (__kmp_thread_from_gtid(__kmp_get_gtid()))
33740b57cec5SDimitry Andric 
33750b57cec5SDimitry Andric // AT: Which way is correct?
33760b57cec5SDimitry Andric // AT: 1. nproc = __kmp_threads[ ( gtid ) ] -> th.th_team -> t.t_nproc;
33770b57cec5SDimitry Andric // AT: 2. nproc = __kmp_threads[ ( gtid ) ] -> th.th_team_nproc;
33780b57cec5SDimitry Andric #define __kmp_get_team_num_threads(gtid)                                       \
33790b57cec5SDimitry Andric   (__kmp_threads[(gtid)]->th.th_team->t.t_nproc)
33800b57cec5SDimitry Andric 
33810b57cec5SDimitry Andric static inline bool KMP_UBER_GTID(int gtid) {
33820b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(gtid >= KMP_GTID_MIN);
33830b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(gtid < __kmp_threads_capacity);
33840b57cec5SDimitry Andric   return (gtid >= 0 && __kmp_root[gtid] && __kmp_threads[gtid] &&
33850b57cec5SDimitry Andric           __kmp_threads[gtid] == __kmp_root[gtid]->r.r_uber_thread);
33860b57cec5SDimitry Andric }
33870b57cec5SDimitry Andric 
33880b57cec5SDimitry Andric static inline int __kmp_tid_from_gtid(int gtid) {
33890b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(gtid >= 0);
33900b57cec5SDimitry Andric   return __kmp_threads[gtid]->th.th_info.ds.ds_tid;
33910b57cec5SDimitry Andric }
33920b57cec5SDimitry Andric 
33930b57cec5SDimitry Andric static inline int __kmp_gtid_from_tid(int tid, const kmp_team_t *team) {
33940b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(tid >= 0 && team);
33950b57cec5SDimitry Andric   return team->t.t_threads[tid]->th.th_info.ds.ds_gtid;
33960b57cec5SDimitry Andric }
33970b57cec5SDimitry Andric 
33980b57cec5SDimitry Andric static inline int __kmp_gtid_from_thread(const kmp_info_t *thr) {
33990b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(thr);
34000b57cec5SDimitry Andric   return thr->th.th_info.ds.ds_gtid;
34010b57cec5SDimitry Andric }
34020b57cec5SDimitry Andric 
34030b57cec5SDimitry Andric static inline kmp_info_t *__kmp_thread_from_gtid(int gtid) {
34040b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(gtid >= 0);
34050b57cec5SDimitry Andric   return __kmp_threads[gtid];
34060b57cec5SDimitry Andric }
34070b57cec5SDimitry Andric 
34080b57cec5SDimitry Andric static inline kmp_team_t *__kmp_team_from_gtid(int gtid) {
34090b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(gtid >= 0);
34100b57cec5SDimitry Andric   return __kmp_threads[gtid]->th.th_team;
34110b57cec5SDimitry Andric }
34120b57cec5SDimitry Andric 
3413e8d8bef9SDimitry Andric static inline void __kmp_assert_valid_gtid(kmp_int32 gtid) {
3414e8d8bef9SDimitry Andric   if (UNLIKELY(gtid < 0 || gtid >= __kmp_threads_capacity))
3415e8d8bef9SDimitry Andric     KMP_FATAL(ThreadIdentInvalid);
3416e8d8bef9SDimitry Andric }
3417e8d8bef9SDimitry Andric 
3418e8d8bef9SDimitry Andric #if KMP_HAVE_MWAIT || KMP_HAVE_UMWAIT
3419e8d8bef9SDimitry Andric extern int __kmp_user_level_mwait; // TRUE or FALSE; from KMP_USER_LEVEL_MWAIT
3420e8d8bef9SDimitry Andric extern int __kmp_umwait_enabled; // Runtime check if user-level mwait enabled
3421e8d8bef9SDimitry Andric extern int __kmp_mwait_enabled; // Runtime check if ring3 mwait is enabled
3422e8d8bef9SDimitry Andric extern int __kmp_mwait_hints; // Hints to pass in to mwait
3423e8d8bef9SDimitry Andric #endif
3424e8d8bef9SDimitry Andric 
342504eeddc0SDimitry Andric #if KMP_HAVE_UMWAIT
342604eeddc0SDimitry Andric extern int __kmp_waitpkg_enabled; // Runtime check if waitpkg exists
342704eeddc0SDimitry Andric extern int __kmp_tpause_state; // 0 (default), 1=C0.1, 2=C0.2; from KMP_TPAUSE
342804eeddc0SDimitry Andric extern int __kmp_tpause_hint; // 1=C0.1 (default), 0=C0.2; from KMP_TPAUSE
342904eeddc0SDimitry Andric extern int __kmp_tpause_enabled; // 0 (default), 1 (KMP_TPAUSE is non-zero)
343004eeddc0SDimitry Andric #endif
343104eeddc0SDimitry Andric 
34320b57cec5SDimitry Andric /* ------------------------------------------------------------------------- */
34330b57cec5SDimitry Andric 
34340b57cec5SDimitry Andric extern kmp_global_t __kmp_global; /* global status */
34350b57cec5SDimitry Andric 
34360b57cec5SDimitry Andric extern kmp_info_t __kmp_monitor;
34370b57cec5SDimitry Andric // For Debugging Support Library
34380b57cec5SDimitry Andric extern std::atomic<kmp_int32> __kmp_team_counter;
34390b57cec5SDimitry Andric // For Debugging Support Library
34400b57cec5SDimitry Andric extern std::atomic<kmp_int32> __kmp_task_counter;
34410b57cec5SDimitry Andric 
34420b57cec5SDimitry Andric #if USE_DEBUGGER
34430b57cec5SDimitry Andric #define _KMP_GEN_ID(counter)                                                   \
34440b57cec5SDimitry Andric   (__kmp_debugging ? KMP_ATOMIC_INC(&counter) + 1 : ~0)
34450b57cec5SDimitry Andric #else
34460b57cec5SDimitry Andric #define _KMP_GEN_ID(counter) (~0)
34470b57cec5SDimitry Andric #endif /* USE_DEBUGGER */
34480b57cec5SDimitry Andric 
34490b57cec5SDimitry Andric #define KMP_GEN_TASK_ID() _KMP_GEN_ID(__kmp_task_counter)
34500b57cec5SDimitry Andric #define KMP_GEN_TEAM_ID() _KMP_GEN_ID(__kmp_team_counter)
34510b57cec5SDimitry Andric 
34520b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
34530b57cec5SDimitry Andric 
34540b57cec5SDimitry Andric extern void __kmp_print_storage_map_gtid(int gtid, void *p1, void *p2,
34550b57cec5SDimitry Andric                                          size_t size, char const *format, ...);
34560b57cec5SDimitry Andric 
34570b57cec5SDimitry Andric extern void __kmp_serial_initialize(void);
34580b57cec5SDimitry Andric extern void __kmp_middle_initialize(void);
34590b57cec5SDimitry Andric extern void __kmp_parallel_initialize(void);
34600b57cec5SDimitry Andric 
34610b57cec5SDimitry Andric extern void __kmp_internal_begin(void);
34620b57cec5SDimitry Andric extern void __kmp_internal_end_library(int gtid);
34630b57cec5SDimitry Andric extern void __kmp_internal_end_thread(int gtid);
34640b57cec5SDimitry Andric extern void __kmp_internal_end_atexit(void);
34650b57cec5SDimitry Andric extern void __kmp_internal_end_dtor(void);
34660b57cec5SDimitry Andric extern void __kmp_internal_end_dest(void *);
34670b57cec5SDimitry Andric 
34680b57cec5SDimitry Andric extern int __kmp_register_root(int initial_thread);
34690b57cec5SDimitry Andric extern void __kmp_unregister_root(int gtid);
3470e8d8bef9SDimitry Andric extern void __kmp_unregister_library(void); // called by __kmp_internal_end()
34710b57cec5SDimitry Andric 
34720b57cec5SDimitry Andric extern int __kmp_ignore_mppbeg(void);
34730b57cec5SDimitry Andric extern int __kmp_ignore_mppend(void);
34740b57cec5SDimitry Andric 
34750b57cec5SDimitry Andric extern int __kmp_enter_single(int gtid, ident_t *id_ref, int push_ws);
34760b57cec5SDimitry Andric extern void __kmp_exit_single(int gtid);
34770b57cec5SDimitry Andric 
34780b57cec5SDimitry Andric extern void __kmp_parallel_deo(int *gtid_ref, int *cid_ref, ident_t *loc_ref);
34790b57cec5SDimitry Andric extern void __kmp_parallel_dxo(int *gtid_ref, int *cid_ref, ident_t *loc_ref);
34800b57cec5SDimitry Andric 
34810b57cec5SDimitry Andric #ifdef USE_LOAD_BALANCE
34820b57cec5SDimitry Andric extern int __kmp_get_load_balance(int);
34830b57cec5SDimitry Andric #endif
34840b57cec5SDimitry Andric 
34850b57cec5SDimitry Andric extern int __kmp_get_global_thread_id(void);
34860b57cec5SDimitry Andric extern int __kmp_get_global_thread_id_reg(void);
34870b57cec5SDimitry Andric extern void __kmp_exit_thread(int exit_status);
34880b57cec5SDimitry Andric extern void __kmp_abort(char const *format, ...);
34890b57cec5SDimitry Andric extern void __kmp_abort_thread(void);
34900b57cec5SDimitry Andric KMP_NORETURN extern void __kmp_abort_process(void);
34910b57cec5SDimitry Andric extern void __kmp_warn(char const *format, ...);
34920b57cec5SDimitry Andric 
34930b57cec5SDimitry Andric extern void __kmp_set_num_threads(int new_nth, int gtid);
34940b57cec5SDimitry Andric 
34950b57cec5SDimitry Andric // Returns current thread (pointer to kmp_info_t). Current thread *must* be
34960b57cec5SDimitry Andric // registered.
34970b57cec5SDimitry Andric static inline kmp_info_t *__kmp_entry_thread() {
34980b57cec5SDimitry Andric   int gtid = __kmp_entry_gtid();
34990b57cec5SDimitry Andric 
35000b57cec5SDimitry Andric   return __kmp_threads[gtid];
35010b57cec5SDimitry Andric }
35020b57cec5SDimitry Andric 
35030b57cec5SDimitry Andric extern void __kmp_set_max_active_levels(int gtid, int new_max_active_levels);
35040b57cec5SDimitry Andric extern int __kmp_get_max_active_levels(int gtid);
35050b57cec5SDimitry Andric extern int __kmp_get_ancestor_thread_num(int gtid, int level);
35060b57cec5SDimitry Andric extern int __kmp_get_team_size(int gtid, int level);
35070b57cec5SDimitry Andric extern void __kmp_set_schedule(int gtid, kmp_sched_t new_sched, int chunk);
35080b57cec5SDimitry Andric extern void __kmp_get_schedule(int gtid, kmp_sched_t *sched, int *chunk);
35090b57cec5SDimitry Andric 
35100b57cec5SDimitry Andric extern unsigned short __kmp_get_random(kmp_info_t *thread);
35110b57cec5SDimitry Andric extern void __kmp_init_random(kmp_info_t *thread);
35120b57cec5SDimitry Andric 
35130b57cec5SDimitry Andric extern kmp_r_sched_t __kmp_get_schedule_global(void);
35140b57cec5SDimitry Andric extern void __kmp_adjust_num_threads(int new_nproc);
35150b57cec5SDimitry Andric extern void __kmp_check_stksize(size_t *val);
35160b57cec5SDimitry Andric 
35170b57cec5SDimitry Andric extern void *___kmp_allocate(size_t size KMP_SRC_LOC_DECL);
35180b57cec5SDimitry Andric extern void *___kmp_page_allocate(size_t size KMP_SRC_LOC_DECL);
35190b57cec5SDimitry Andric extern void ___kmp_free(void *ptr KMP_SRC_LOC_DECL);
35200b57cec5SDimitry Andric #define __kmp_allocate(size) ___kmp_allocate((size)KMP_SRC_LOC_CURR)
35210b57cec5SDimitry Andric #define __kmp_page_allocate(size) ___kmp_page_allocate((size)KMP_SRC_LOC_CURR)
35220b57cec5SDimitry Andric #define __kmp_free(ptr) ___kmp_free((ptr)KMP_SRC_LOC_CURR)
35230b57cec5SDimitry Andric 
35240b57cec5SDimitry Andric #if USE_FAST_MEMORY
35250b57cec5SDimitry Andric extern void *___kmp_fast_allocate(kmp_info_t *this_thr,
35260b57cec5SDimitry Andric                                   size_t size KMP_SRC_LOC_DECL);
35270b57cec5SDimitry Andric extern void ___kmp_fast_free(kmp_info_t *this_thr, void *ptr KMP_SRC_LOC_DECL);
35280b57cec5SDimitry Andric extern void __kmp_free_fast_memory(kmp_info_t *this_thr);
35290b57cec5SDimitry Andric extern void __kmp_initialize_fast_memory(kmp_info_t *this_thr);
35300b57cec5SDimitry Andric #define __kmp_fast_allocate(this_thr, size)                                    \
35310b57cec5SDimitry Andric   ___kmp_fast_allocate((this_thr), (size)KMP_SRC_LOC_CURR)
35320b57cec5SDimitry Andric #define __kmp_fast_free(this_thr, ptr)                                         \
35330b57cec5SDimitry Andric   ___kmp_fast_free((this_thr), (ptr)KMP_SRC_LOC_CURR)
35340b57cec5SDimitry Andric #endif
35350b57cec5SDimitry Andric 
35360b57cec5SDimitry Andric extern void *___kmp_thread_malloc(kmp_info_t *th, size_t size KMP_SRC_LOC_DECL);
35370b57cec5SDimitry Andric extern void *___kmp_thread_calloc(kmp_info_t *th, size_t nelem,
35380b57cec5SDimitry Andric                                   size_t elsize KMP_SRC_LOC_DECL);
35390b57cec5SDimitry Andric extern void *___kmp_thread_realloc(kmp_info_t *th, void *ptr,
35400b57cec5SDimitry Andric                                    size_t size KMP_SRC_LOC_DECL);
35410b57cec5SDimitry Andric extern void ___kmp_thread_free(kmp_info_t *th, void *ptr KMP_SRC_LOC_DECL);
35420b57cec5SDimitry Andric #define __kmp_thread_malloc(th, size)                                          \
35430b57cec5SDimitry Andric   ___kmp_thread_malloc((th), (size)KMP_SRC_LOC_CURR)
35440b57cec5SDimitry Andric #define __kmp_thread_calloc(th, nelem, elsize)                                 \
35450b57cec5SDimitry Andric   ___kmp_thread_calloc((th), (nelem), (elsize)KMP_SRC_LOC_CURR)
35460b57cec5SDimitry Andric #define __kmp_thread_realloc(th, ptr, size)                                    \
35470b57cec5SDimitry Andric   ___kmp_thread_realloc((th), (ptr), (size)KMP_SRC_LOC_CURR)
35480b57cec5SDimitry Andric #define __kmp_thread_free(th, ptr)                                             \
35490b57cec5SDimitry Andric   ___kmp_thread_free((th), (ptr)KMP_SRC_LOC_CURR)
35500b57cec5SDimitry Andric 
35510b57cec5SDimitry Andric extern void __kmp_push_num_threads(ident_t *loc, int gtid, int num_threads);
35520b57cec5SDimitry Andric 
35530b57cec5SDimitry Andric extern void __kmp_push_proc_bind(ident_t *loc, int gtid,
35540b57cec5SDimitry Andric                                  kmp_proc_bind_t proc_bind);
35550b57cec5SDimitry Andric extern void __kmp_push_num_teams(ident_t *loc, int gtid, int num_teams,
35560b57cec5SDimitry Andric                                  int num_threads);
3557fe6060f1SDimitry Andric extern void __kmp_push_num_teams_51(ident_t *loc, int gtid, int num_teams_lb,
3558fe6060f1SDimitry Andric                                     int num_teams_ub, int num_threads);
35590b57cec5SDimitry Andric 
35600b57cec5SDimitry Andric extern void __kmp_yield();
35610b57cec5SDimitry Andric 
35620b57cec5SDimitry Andric extern void __kmpc_dispatch_init_4(ident_t *loc, kmp_int32 gtid,
35630b57cec5SDimitry Andric                                    enum sched_type schedule, kmp_int32 lb,
35640b57cec5SDimitry Andric                                    kmp_int32 ub, kmp_int32 st, kmp_int32 chunk);
35650b57cec5SDimitry Andric extern void __kmpc_dispatch_init_4u(ident_t *loc, kmp_int32 gtid,
35660b57cec5SDimitry Andric                                     enum sched_type schedule, kmp_uint32 lb,
35670b57cec5SDimitry Andric                                     kmp_uint32 ub, kmp_int32 st,
35680b57cec5SDimitry Andric                                     kmp_int32 chunk);
35690b57cec5SDimitry Andric extern void __kmpc_dispatch_init_8(ident_t *loc, kmp_int32 gtid,
35700b57cec5SDimitry Andric                                    enum sched_type schedule, kmp_int64 lb,
35710b57cec5SDimitry Andric                                    kmp_int64 ub, kmp_int64 st, kmp_int64 chunk);
35720b57cec5SDimitry Andric extern void __kmpc_dispatch_init_8u(ident_t *loc, kmp_int32 gtid,
35730b57cec5SDimitry Andric                                     enum sched_type schedule, kmp_uint64 lb,
35740b57cec5SDimitry Andric                                     kmp_uint64 ub, kmp_int64 st,
35750b57cec5SDimitry Andric                                     kmp_int64 chunk);
35760b57cec5SDimitry Andric 
35770b57cec5SDimitry Andric extern int __kmpc_dispatch_next_4(ident_t *loc, kmp_int32 gtid,
35780b57cec5SDimitry Andric                                   kmp_int32 *p_last, kmp_int32 *p_lb,
35790b57cec5SDimitry Andric                                   kmp_int32 *p_ub, kmp_int32 *p_st);
35800b57cec5SDimitry Andric extern int __kmpc_dispatch_next_4u(ident_t *loc, kmp_int32 gtid,
35810b57cec5SDimitry Andric                                    kmp_int32 *p_last, kmp_uint32 *p_lb,
35820b57cec5SDimitry Andric                                    kmp_uint32 *p_ub, kmp_int32 *p_st);
35830b57cec5SDimitry Andric extern int __kmpc_dispatch_next_8(ident_t *loc, kmp_int32 gtid,
35840b57cec5SDimitry Andric                                   kmp_int32 *p_last, kmp_int64 *p_lb,
35850b57cec5SDimitry Andric                                   kmp_int64 *p_ub, kmp_int64 *p_st);
35860b57cec5SDimitry Andric extern int __kmpc_dispatch_next_8u(ident_t *loc, kmp_int32 gtid,
35870b57cec5SDimitry Andric                                    kmp_int32 *p_last, kmp_uint64 *p_lb,
35880b57cec5SDimitry Andric                                    kmp_uint64 *p_ub, kmp_int64 *p_st);
35890b57cec5SDimitry Andric 
35900b57cec5SDimitry Andric extern void __kmpc_dispatch_fini_4(ident_t *loc, kmp_int32 gtid);
35910b57cec5SDimitry Andric extern void __kmpc_dispatch_fini_8(ident_t *loc, kmp_int32 gtid);
35920b57cec5SDimitry Andric extern void __kmpc_dispatch_fini_4u(ident_t *loc, kmp_int32 gtid);
35930b57cec5SDimitry Andric extern void __kmpc_dispatch_fini_8u(ident_t *loc, kmp_int32 gtid);
35940b57cec5SDimitry Andric 
35950b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
35960b57cec5SDimitry Andric 
35970b57cec5SDimitry Andric extern void __kmp_aux_dispatch_init_4(ident_t *loc, kmp_int32 gtid,
35980b57cec5SDimitry Andric                                       enum sched_type schedule, kmp_int32 lb,
35990b57cec5SDimitry Andric                                       kmp_int32 ub, kmp_int32 st,
36000b57cec5SDimitry Andric                                       kmp_int32 chunk, int push_ws);
36010b57cec5SDimitry Andric extern void __kmp_aux_dispatch_init_4u(ident_t *loc, kmp_int32 gtid,
36020b57cec5SDimitry Andric                                        enum sched_type schedule, kmp_uint32 lb,
36030b57cec5SDimitry Andric                                        kmp_uint32 ub, kmp_int32 st,
36040b57cec5SDimitry Andric                                        kmp_int32 chunk, int push_ws);
36050b57cec5SDimitry Andric extern void __kmp_aux_dispatch_init_8(ident_t *loc, kmp_int32 gtid,
36060b57cec5SDimitry Andric                                       enum sched_type schedule, kmp_int64 lb,
36070b57cec5SDimitry Andric                                       kmp_int64 ub, kmp_int64 st,
36080b57cec5SDimitry Andric                                       kmp_int64 chunk, int push_ws);
36090b57cec5SDimitry Andric extern void __kmp_aux_dispatch_init_8u(ident_t *loc, kmp_int32 gtid,
36100b57cec5SDimitry Andric                                        enum sched_type schedule, kmp_uint64 lb,
36110b57cec5SDimitry Andric                                        kmp_uint64 ub, kmp_int64 st,
36120b57cec5SDimitry Andric                                        kmp_int64 chunk, int push_ws);
36130b57cec5SDimitry Andric extern void __kmp_aux_dispatch_fini_chunk_4(ident_t *loc, kmp_int32 gtid);
36140b57cec5SDimitry Andric extern void __kmp_aux_dispatch_fini_chunk_8(ident_t *loc, kmp_int32 gtid);
36150b57cec5SDimitry Andric extern void __kmp_aux_dispatch_fini_chunk_4u(ident_t *loc, kmp_int32 gtid);
36160b57cec5SDimitry Andric extern void __kmp_aux_dispatch_fini_chunk_8u(ident_t *loc, kmp_int32 gtid);
36170b57cec5SDimitry Andric 
36180b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
36190b57cec5SDimitry Andric 
36200b57cec5SDimitry Andric extern kmp_uint32 __kmp_eq_4(kmp_uint32 value, kmp_uint32 checker);
36210b57cec5SDimitry Andric extern kmp_uint32 __kmp_neq_4(kmp_uint32 value, kmp_uint32 checker);
36220b57cec5SDimitry Andric extern kmp_uint32 __kmp_lt_4(kmp_uint32 value, kmp_uint32 checker);
36230b57cec5SDimitry Andric extern kmp_uint32 __kmp_ge_4(kmp_uint32 value, kmp_uint32 checker);
36240b57cec5SDimitry Andric extern kmp_uint32 __kmp_le_4(kmp_uint32 value, kmp_uint32 checker);
36250b57cec5SDimitry Andric extern kmp_uint32 __kmp_wait_4(kmp_uint32 volatile *spinner, kmp_uint32 checker,
36260b57cec5SDimitry Andric                                kmp_uint32 (*pred)(kmp_uint32, kmp_uint32),
36270b57cec5SDimitry Andric                                void *obj);
36280b57cec5SDimitry Andric extern void __kmp_wait_4_ptr(void *spinner, kmp_uint32 checker,
36290b57cec5SDimitry Andric                              kmp_uint32 (*pred)(void *, kmp_uint32), void *obj);
36300b57cec5SDimitry Andric 
3631e8d8bef9SDimitry Andric extern void __kmp_wait_64(kmp_info_t *this_thr, kmp_flag_64<> *flag,
36320b57cec5SDimitry Andric                           int final_spin
36330b57cec5SDimitry Andric #if USE_ITT_BUILD
36340b57cec5SDimitry Andric                           ,
36350b57cec5SDimitry Andric                           void *itt_sync_obj
36360b57cec5SDimitry Andric #endif
36370b57cec5SDimitry Andric );
3638e8d8bef9SDimitry Andric extern void __kmp_release_64(kmp_flag_64<> *flag);
36390b57cec5SDimitry Andric 
36400b57cec5SDimitry Andric extern void __kmp_infinite_loop(void);
36410b57cec5SDimitry Andric 
36420b57cec5SDimitry Andric extern void __kmp_cleanup(void);
36430b57cec5SDimitry Andric 
36440b57cec5SDimitry Andric #if KMP_HANDLE_SIGNALS
36450b57cec5SDimitry Andric extern int __kmp_handle_signals;
36460b57cec5SDimitry Andric extern void __kmp_install_signals(int parallel_init);
36470b57cec5SDimitry Andric extern void __kmp_remove_signals(void);
36480b57cec5SDimitry Andric #endif
36490b57cec5SDimitry Andric 
36500b57cec5SDimitry Andric extern void __kmp_clear_system_time(void);
36510b57cec5SDimitry Andric extern void __kmp_read_system_time(double *delta);
36520b57cec5SDimitry Andric 
36530b57cec5SDimitry Andric extern void __kmp_check_stack_overlap(kmp_info_t *thr);
36540b57cec5SDimitry Andric 
36550b57cec5SDimitry Andric extern void __kmp_expand_host_name(char *buffer, size_t size);
36560b57cec5SDimitry Andric extern void __kmp_expand_file_name(char *result, size_t rlen, char *pattern);
36570b57cec5SDimitry Andric 
3658*bdd1243dSDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64 || (KMP_OS_WINDOWS && (KMP_ARCH_AARCH64 || KMP_ARCH_ARM))
36590b57cec5SDimitry Andric extern void
36600b57cec5SDimitry Andric __kmp_initialize_system_tick(void); /* Initialize timer tick value */
36610b57cec5SDimitry Andric #endif
36620b57cec5SDimitry Andric 
36630b57cec5SDimitry Andric extern void
36640b57cec5SDimitry Andric __kmp_runtime_initialize(void); /* machine specific initialization */
36650b57cec5SDimitry Andric extern void __kmp_runtime_destroy(void);
36660b57cec5SDimitry Andric 
36670b57cec5SDimitry Andric #if KMP_AFFINITY_SUPPORTED
36680b57cec5SDimitry Andric extern char *__kmp_affinity_print_mask(char *buf, int buf_len,
36690b57cec5SDimitry Andric                                        kmp_affin_mask_t *mask);
36700b57cec5SDimitry Andric extern kmp_str_buf_t *__kmp_affinity_str_buf_mask(kmp_str_buf_t *buf,
36710b57cec5SDimitry Andric                                                   kmp_affin_mask_t *mask);
3672*bdd1243dSDimitry Andric extern void __kmp_affinity_initialize(kmp_affinity_t &affinity);
36730b57cec5SDimitry Andric extern void __kmp_affinity_uninitialize(void);
36740b57cec5SDimitry Andric extern void __kmp_affinity_set_init_mask(
36750b57cec5SDimitry Andric     int gtid, int isa_root); /* set affinity according to KMP_AFFINITY */
36760b57cec5SDimitry Andric extern void __kmp_affinity_set_place(int gtid);
36770b57cec5SDimitry Andric extern void __kmp_affinity_determine_capable(const char *env_var);
36780b57cec5SDimitry Andric extern int __kmp_aux_set_affinity(void **mask);
36790b57cec5SDimitry Andric extern int __kmp_aux_get_affinity(void **mask);
36800b57cec5SDimitry Andric extern int __kmp_aux_get_affinity_max_proc();
36810b57cec5SDimitry Andric extern int __kmp_aux_set_affinity_mask_proc(int proc, void **mask);
36820b57cec5SDimitry Andric extern int __kmp_aux_unset_affinity_mask_proc(int proc, void **mask);
36830b57cec5SDimitry Andric extern int __kmp_aux_get_affinity_mask_proc(int proc, void **mask);
36840b57cec5SDimitry Andric extern void __kmp_balanced_affinity(kmp_info_t *th, int team_size);
3685489b1cf2SDimitry Andric #if KMP_OS_LINUX || KMP_OS_FREEBSD
36860b57cec5SDimitry Andric extern int kmp_set_thread_affinity_mask_initial(void);
36870b57cec5SDimitry Andric #endif
3688fe6060f1SDimitry Andric static inline void __kmp_assign_root_init_mask() {
3689fe6060f1SDimitry Andric   int gtid = __kmp_entry_gtid();
3690fe6060f1SDimitry Andric   kmp_root_t *r = __kmp_threads[gtid]->th.th_root;
3691fe6060f1SDimitry Andric   if (r->r.r_uber_thread == __kmp_threads[gtid] && !r->r.r_affinity_assigned) {
3692fe6060f1SDimitry Andric     __kmp_affinity_set_init_mask(gtid, TRUE);
3693fe6060f1SDimitry Andric     r->r.r_affinity_assigned = TRUE;
3694fe6060f1SDimitry Andric   }
3695fe6060f1SDimitry Andric }
3696fcaf7f86SDimitry Andric static inline void __kmp_reset_root_init_mask(int gtid) {
3697*bdd1243dSDimitry Andric   if (!KMP_AFFINITY_CAPABLE())
3698*bdd1243dSDimitry Andric     return;
3699fcaf7f86SDimitry Andric   kmp_info_t *th = __kmp_threads[gtid];
3700fcaf7f86SDimitry Andric   kmp_root_t *r = th->th.th_root;
3701fcaf7f86SDimitry Andric   if (r->r.r_uber_thread == th && r->r.r_affinity_assigned) {
3702fcaf7f86SDimitry Andric     __kmp_set_system_affinity(__kmp_affin_origMask, FALSE);
3703fcaf7f86SDimitry Andric     KMP_CPU_COPY(th->th.th_affin_mask, __kmp_affin_origMask);
3704fcaf7f86SDimitry Andric     r->r.r_affinity_assigned = FALSE;
3705fcaf7f86SDimitry Andric   }
3706fcaf7f86SDimitry Andric }
3707fe6060f1SDimitry Andric #else /* KMP_AFFINITY_SUPPORTED */
3708fe6060f1SDimitry Andric #define __kmp_assign_root_init_mask() /* Nothing */
3709fcaf7f86SDimitry Andric static inline void __kmp_reset_root_init_mask(int gtid) {}
37100b57cec5SDimitry Andric #endif /* KMP_AFFINITY_SUPPORTED */
37110b57cec5SDimitry Andric // No need for KMP_AFFINITY_SUPPORTED guard as only one field in the
37120b57cec5SDimitry Andric // format string is for affinity, so platforms that do not support
37130b57cec5SDimitry Andric // affinity can still use the other fields, e.g., %n for num_threads
37140b57cec5SDimitry Andric extern size_t __kmp_aux_capture_affinity(int gtid, const char *format,
37150b57cec5SDimitry Andric                                          kmp_str_buf_t *buffer);
37160b57cec5SDimitry Andric extern void __kmp_aux_display_affinity(int gtid, const char *format);
37170b57cec5SDimitry Andric 
37180b57cec5SDimitry Andric extern void __kmp_cleanup_hierarchy();
37190b57cec5SDimitry Andric extern void __kmp_get_hierarchy(kmp_uint32 nproc, kmp_bstate_t *thr_bar);
37200b57cec5SDimitry Andric 
37210b57cec5SDimitry Andric #if KMP_USE_FUTEX
37220b57cec5SDimitry Andric 
37230b57cec5SDimitry Andric extern int __kmp_futex_determine_capable(void);
37240b57cec5SDimitry Andric 
37250b57cec5SDimitry Andric #endif // KMP_USE_FUTEX
37260b57cec5SDimitry Andric 
37270b57cec5SDimitry Andric extern void __kmp_gtid_set_specific(int gtid);
37280b57cec5SDimitry Andric extern int __kmp_gtid_get_specific(void);
37290b57cec5SDimitry Andric 
37300b57cec5SDimitry Andric extern double __kmp_read_cpu_time(void);
37310b57cec5SDimitry Andric 
37320b57cec5SDimitry Andric extern int __kmp_read_system_info(struct kmp_sys_info *info);
37330b57cec5SDimitry Andric 
37340b57cec5SDimitry Andric #if KMP_USE_MONITOR
37350b57cec5SDimitry Andric extern void __kmp_create_monitor(kmp_info_t *th);
37360b57cec5SDimitry Andric #endif
37370b57cec5SDimitry Andric 
37380b57cec5SDimitry Andric extern void *__kmp_launch_thread(kmp_info_t *thr);
37390b57cec5SDimitry Andric 
37400b57cec5SDimitry Andric extern void __kmp_create_worker(int gtid, kmp_info_t *th, size_t stack_size);
37410b57cec5SDimitry Andric 
37420b57cec5SDimitry Andric #if KMP_OS_WINDOWS
37430b57cec5SDimitry Andric extern int __kmp_still_running(kmp_info_t *th);
37440b57cec5SDimitry Andric extern int __kmp_is_thread_alive(kmp_info_t *th, DWORD *exit_val);
37450b57cec5SDimitry Andric extern void __kmp_free_handle(kmp_thread_t tHandle);
37460b57cec5SDimitry Andric #endif
37470b57cec5SDimitry Andric 
37480b57cec5SDimitry Andric #if KMP_USE_MONITOR
37490b57cec5SDimitry Andric extern void __kmp_reap_monitor(kmp_info_t *th);
37500b57cec5SDimitry Andric #endif
37510b57cec5SDimitry Andric extern void __kmp_reap_worker(kmp_info_t *th);
37520b57cec5SDimitry Andric extern void __kmp_terminate_thread(int gtid);
37530b57cec5SDimitry Andric 
37540b57cec5SDimitry Andric extern int __kmp_try_suspend_mx(kmp_info_t *th);
37550b57cec5SDimitry Andric extern void __kmp_lock_suspend_mx(kmp_info_t *th);
37560b57cec5SDimitry Andric extern void __kmp_unlock_suspend_mx(kmp_info_t *th);
37570b57cec5SDimitry Andric 
37580b57cec5SDimitry Andric extern void __kmp_elapsed(double *);
37590b57cec5SDimitry Andric extern void __kmp_elapsed_tick(double *);
37600b57cec5SDimitry Andric 
37610b57cec5SDimitry Andric extern void __kmp_enable(int old_state);
37620b57cec5SDimitry Andric extern void __kmp_disable(int *old_state);
37630b57cec5SDimitry Andric 
37640b57cec5SDimitry Andric extern void __kmp_thread_sleep(int millis);
37650b57cec5SDimitry Andric 
37660b57cec5SDimitry Andric extern void __kmp_common_initialize(void);
37670b57cec5SDimitry Andric extern void __kmp_common_destroy(void);
37680b57cec5SDimitry Andric extern void __kmp_common_destroy_gtid(int gtid);
37690b57cec5SDimitry Andric 
37700b57cec5SDimitry Andric #if KMP_OS_UNIX
37710b57cec5SDimitry Andric extern void __kmp_register_atfork(void);
37720b57cec5SDimitry Andric #endif
37730b57cec5SDimitry Andric extern void __kmp_suspend_initialize(void);
37740b57cec5SDimitry Andric extern void __kmp_suspend_initialize_thread(kmp_info_t *th);
37750b57cec5SDimitry Andric extern void __kmp_suspend_uninitialize_thread(kmp_info_t *th);
37760b57cec5SDimitry Andric 
37770b57cec5SDimitry Andric extern kmp_info_t *__kmp_allocate_thread(kmp_root_t *root, kmp_team_t *team,
37780b57cec5SDimitry Andric                                          int tid);
37790b57cec5SDimitry Andric extern kmp_team_t *
37800b57cec5SDimitry Andric __kmp_allocate_team(kmp_root_t *root, int new_nproc, int max_nproc,
37810b57cec5SDimitry Andric #if OMPT_SUPPORT
37820b57cec5SDimitry Andric                     ompt_data_t ompt_parallel_data,
37830b57cec5SDimitry Andric #endif
37840b57cec5SDimitry Andric                     kmp_proc_bind_t proc_bind, kmp_internal_control_t *new_icvs,
37850b57cec5SDimitry Andric                     int argc USE_NESTED_HOT_ARG(kmp_info_t *thr));
37860b57cec5SDimitry Andric extern void __kmp_free_thread(kmp_info_t *);
37870b57cec5SDimitry Andric extern void __kmp_free_team(kmp_root_t *,
37880b57cec5SDimitry Andric                             kmp_team_t *USE_NESTED_HOT_ARG(kmp_info_t *));
37890b57cec5SDimitry Andric extern kmp_team_t *__kmp_reap_team(kmp_team_t *);
37900b57cec5SDimitry Andric 
37910b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
37920b57cec5SDimitry Andric 
37930b57cec5SDimitry Andric extern void __kmp_initialize_bget(kmp_info_t *th);
37940b57cec5SDimitry Andric extern void __kmp_finalize_bget(kmp_info_t *th);
37950b57cec5SDimitry Andric 
37960b57cec5SDimitry Andric KMP_EXPORT void *kmpc_malloc(size_t size);
37970b57cec5SDimitry Andric KMP_EXPORT void *kmpc_aligned_malloc(size_t size, size_t alignment);
37980b57cec5SDimitry Andric KMP_EXPORT void *kmpc_calloc(size_t nelem, size_t elsize);
37990b57cec5SDimitry Andric KMP_EXPORT void *kmpc_realloc(void *ptr, size_t size);
38000b57cec5SDimitry Andric KMP_EXPORT void kmpc_free(void *ptr);
38010b57cec5SDimitry Andric 
38020b57cec5SDimitry Andric /* declarations for internal use */
38030b57cec5SDimitry Andric 
38040b57cec5SDimitry Andric extern int __kmp_barrier(enum barrier_type bt, int gtid, int is_split,
38050b57cec5SDimitry Andric                          size_t reduce_size, void *reduce_data,
38060b57cec5SDimitry Andric                          void (*reduce)(void *, void *));
38070b57cec5SDimitry Andric extern void __kmp_end_split_barrier(enum barrier_type bt, int gtid);
38080b57cec5SDimitry Andric extern int __kmp_barrier_gomp_cancel(int gtid);
38090b57cec5SDimitry Andric 
38100b57cec5SDimitry Andric /*!
38110b57cec5SDimitry Andric  * Tell the fork call which compiler generated the fork call, and therefore how
38120b57cec5SDimitry Andric  * to deal with the call.
38130b57cec5SDimitry Andric  */
38140b57cec5SDimitry Andric enum fork_context_e {
38150b57cec5SDimitry Andric   fork_context_gnu, /**< Called from GNU generated code, so must not invoke the
38160b57cec5SDimitry Andric                        microtask internally. */
38170b57cec5SDimitry Andric   fork_context_intel, /**< Called from Intel generated code.  */
38180b57cec5SDimitry Andric   fork_context_last
38190b57cec5SDimitry Andric };
38200b57cec5SDimitry Andric extern int __kmp_fork_call(ident_t *loc, int gtid,
38210b57cec5SDimitry Andric                            enum fork_context_e fork_context, kmp_int32 argc,
38220b57cec5SDimitry Andric                            microtask_t microtask, launch_t invoker,
382316794618SDimitry Andric                            kmp_va_list ap);
38240b57cec5SDimitry Andric 
38250b57cec5SDimitry Andric extern void __kmp_join_call(ident_t *loc, int gtid
38260b57cec5SDimitry Andric #if OMPT_SUPPORT
38270b57cec5SDimitry Andric                             ,
38280b57cec5SDimitry Andric                             enum fork_context_e fork_context
38290b57cec5SDimitry Andric #endif
38300b57cec5SDimitry Andric                             ,
38310b57cec5SDimitry Andric                             int exit_teams = 0);
38320b57cec5SDimitry Andric 
38330b57cec5SDimitry Andric extern void __kmp_serialized_parallel(ident_t *id, kmp_int32 gtid);
38340b57cec5SDimitry Andric extern void __kmp_internal_fork(ident_t *id, int gtid, kmp_team_t *team);
38350b57cec5SDimitry Andric extern void __kmp_internal_join(ident_t *id, int gtid, kmp_team_t *team);
38360b57cec5SDimitry Andric extern int __kmp_invoke_task_func(int gtid);
38370b57cec5SDimitry Andric extern void __kmp_run_before_invoked_task(int gtid, int tid,
38380b57cec5SDimitry Andric                                           kmp_info_t *this_thr,
38390b57cec5SDimitry Andric                                           kmp_team_t *team);
38400b57cec5SDimitry Andric extern void __kmp_run_after_invoked_task(int gtid, int tid,
38410b57cec5SDimitry Andric                                          kmp_info_t *this_thr,
38420b57cec5SDimitry Andric                                          kmp_team_t *team);
38430b57cec5SDimitry Andric 
38440b57cec5SDimitry Andric // should never have been exported
38450b57cec5SDimitry Andric KMP_EXPORT int __kmpc_invoke_task_func(int gtid);
38460b57cec5SDimitry Andric extern int __kmp_invoke_teams_master(int gtid);
38470b57cec5SDimitry Andric extern void __kmp_teams_master(int gtid);
38480b57cec5SDimitry Andric extern int __kmp_aux_get_team_num();
38490b57cec5SDimitry Andric extern int __kmp_aux_get_num_teams();
38500b57cec5SDimitry Andric extern void __kmp_save_internal_controls(kmp_info_t *thread);
38510b57cec5SDimitry Andric extern void __kmp_user_set_library(enum library_type arg);
38520b57cec5SDimitry Andric extern void __kmp_aux_set_library(enum library_type arg);
38530b57cec5SDimitry Andric extern void __kmp_aux_set_stacksize(size_t arg);
38540b57cec5SDimitry Andric extern void __kmp_aux_set_blocktime(int arg, kmp_info_t *thread, int tid);
3855e8d8bef9SDimitry Andric extern void __kmp_aux_set_defaults(char const *str, size_t len);
38560b57cec5SDimitry Andric 
38570b57cec5SDimitry Andric /* Functions called from __kmp_aux_env_initialize() in kmp_settings.cpp */
38580b57cec5SDimitry Andric void kmpc_set_blocktime(int arg);
38590b57cec5SDimitry Andric void ompc_set_nested(int flag);
38600b57cec5SDimitry Andric void ompc_set_dynamic(int flag);
38610b57cec5SDimitry Andric void ompc_set_num_threads(int arg);
38620b57cec5SDimitry Andric 
38630b57cec5SDimitry Andric extern void __kmp_push_current_task_to_thread(kmp_info_t *this_thr,
38640b57cec5SDimitry Andric                                               kmp_team_t *team, int tid);
38650b57cec5SDimitry Andric extern void __kmp_pop_current_task_from_thread(kmp_info_t *this_thr);
38660b57cec5SDimitry Andric extern kmp_task_t *__kmp_task_alloc(ident_t *loc_ref, kmp_int32 gtid,
38670b57cec5SDimitry Andric                                     kmp_tasking_flags_t *flags,
38680b57cec5SDimitry Andric                                     size_t sizeof_kmp_task_t,
38690b57cec5SDimitry Andric                                     size_t sizeof_shareds,
38700b57cec5SDimitry Andric                                     kmp_routine_entry_t task_entry);
38710b57cec5SDimitry Andric extern void __kmp_init_implicit_task(ident_t *loc_ref, kmp_info_t *this_thr,
38720b57cec5SDimitry Andric                                      kmp_team_t *team, int tid,
38730b57cec5SDimitry Andric                                      int set_curr_task);
38740b57cec5SDimitry Andric extern void __kmp_finish_implicit_task(kmp_info_t *this_thr);
38750b57cec5SDimitry Andric extern void __kmp_free_implicit_task(kmp_info_t *this_thr);
38760b57cec5SDimitry Andric 
38770b57cec5SDimitry Andric extern kmp_event_t *__kmpc_task_allow_completion_event(ident_t *loc_ref,
38780b57cec5SDimitry Andric                                                        int gtid,
38790b57cec5SDimitry Andric                                                        kmp_task_t *task);
38800b57cec5SDimitry Andric extern void __kmp_fulfill_event(kmp_event_t *event);
38810b57cec5SDimitry Andric 
38820b57cec5SDimitry Andric extern void __kmp_free_task_team(kmp_info_t *thread,
38830b57cec5SDimitry Andric                                  kmp_task_team_t *task_team);
38840b57cec5SDimitry Andric extern void __kmp_reap_task_teams(void);
38850b57cec5SDimitry Andric extern void __kmp_wait_to_unref_task_teams(void);
38860b57cec5SDimitry Andric extern void __kmp_task_team_setup(kmp_info_t *this_thr, kmp_team_t *team,
38870b57cec5SDimitry Andric                                   int always);
38880b57cec5SDimitry Andric extern void __kmp_task_team_sync(kmp_info_t *this_thr, kmp_team_t *team);
38890b57cec5SDimitry Andric extern void __kmp_task_team_wait(kmp_info_t *this_thr, kmp_team_t *team
38900b57cec5SDimitry Andric #if USE_ITT_BUILD
38910b57cec5SDimitry Andric                                  ,
38920b57cec5SDimitry Andric                                  void *itt_sync_obj
38930b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */
38940b57cec5SDimitry Andric                                  ,
38950b57cec5SDimitry Andric                                  int wait = 1);
38960b57cec5SDimitry Andric extern void __kmp_tasking_barrier(kmp_team_t *team, kmp_info_t *thread,
38970b57cec5SDimitry Andric                                   int gtid);
38980b57cec5SDimitry Andric 
38990b57cec5SDimitry Andric extern int __kmp_is_address_mapped(void *addr);
39000b57cec5SDimitry Andric extern kmp_uint64 __kmp_hardware_timestamp(void);
39010b57cec5SDimitry Andric 
39020b57cec5SDimitry Andric #if KMP_OS_UNIX
39030b57cec5SDimitry Andric extern int __kmp_read_from_file(char const *path, char const *format, ...);
39040b57cec5SDimitry Andric #endif
39050b57cec5SDimitry Andric 
39060b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
39070b57cec5SDimitry Andric //
39080b57cec5SDimitry Andric // Assembly routines that have no compiler intrinsic replacement
39090b57cec5SDimitry Andric //
39100b57cec5SDimitry Andric 
39110b57cec5SDimitry Andric extern int __kmp_invoke_microtask(microtask_t pkfn, int gtid, int npr, int argc,
39120b57cec5SDimitry Andric                                   void *argv[]
39130b57cec5SDimitry Andric #if OMPT_SUPPORT
39140b57cec5SDimitry Andric                                   ,
39150b57cec5SDimitry Andric                                   void **exit_frame_ptr
39160b57cec5SDimitry Andric #endif
39170b57cec5SDimitry Andric );
39180b57cec5SDimitry Andric 
39190b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
39200b57cec5SDimitry Andric 
39210b57cec5SDimitry Andric KMP_EXPORT void __kmpc_begin(ident_t *, kmp_int32 flags);
39220b57cec5SDimitry Andric KMP_EXPORT void __kmpc_end(ident_t *);
39230b57cec5SDimitry Andric 
39240b57cec5SDimitry Andric KMP_EXPORT void __kmpc_threadprivate_register_vec(ident_t *, void *data,
39250b57cec5SDimitry Andric                                                   kmpc_ctor_vec ctor,
39260b57cec5SDimitry Andric                                                   kmpc_cctor_vec cctor,
39270b57cec5SDimitry Andric                                                   kmpc_dtor_vec dtor,
39280b57cec5SDimitry Andric                                                   size_t vector_length);
39290b57cec5SDimitry Andric KMP_EXPORT void __kmpc_threadprivate_register(ident_t *, void *data,
39300b57cec5SDimitry Andric                                               kmpc_ctor ctor, kmpc_cctor cctor,
39310b57cec5SDimitry Andric                                               kmpc_dtor dtor);
39320b57cec5SDimitry Andric KMP_EXPORT void *__kmpc_threadprivate(ident_t *, kmp_int32 global_tid,
39330b57cec5SDimitry Andric                                       void *data, size_t size);
39340b57cec5SDimitry Andric 
39350b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_global_thread_num(ident_t *);
39360b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_global_num_threads(ident_t *);
39370b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_bound_thread_num(ident_t *);
39380b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_bound_num_threads(ident_t *);
39390b57cec5SDimitry Andric 
39400b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_ok_to_fork(ident_t *);
39410b57cec5SDimitry Andric KMP_EXPORT void __kmpc_fork_call(ident_t *, kmp_int32 nargs,
39420b57cec5SDimitry Andric                                  kmpc_micro microtask, ...);
3943*bdd1243dSDimitry Andric KMP_EXPORT void __kmpc_fork_call_if(ident_t *loc, kmp_int32 nargs,
3944*bdd1243dSDimitry Andric                                     kmpc_micro microtask, kmp_int32 cond,
3945*bdd1243dSDimitry Andric                                     void *args);
39460b57cec5SDimitry Andric 
39470b57cec5SDimitry Andric KMP_EXPORT void __kmpc_serialized_parallel(ident_t *, kmp_int32 global_tid);
39480b57cec5SDimitry Andric KMP_EXPORT void __kmpc_end_serialized_parallel(ident_t *, kmp_int32 global_tid);
39490b57cec5SDimitry Andric 
39500b57cec5SDimitry Andric KMP_EXPORT void __kmpc_flush(ident_t *);
39510b57cec5SDimitry Andric KMP_EXPORT void __kmpc_barrier(ident_t *, kmp_int32 global_tid);
39520b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid);
39530b57cec5SDimitry Andric KMP_EXPORT void __kmpc_end_master(ident_t *, kmp_int32 global_tid);
3954fe6060f1SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_masked(ident_t *, kmp_int32 global_tid,
3955fe6060f1SDimitry Andric                                    kmp_int32 filter);
3956fe6060f1SDimitry Andric KMP_EXPORT void __kmpc_end_masked(ident_t *, kmp_int32 global_tid);
39570b57cec5SDimitry Andric KMP_EXPORT void __kmpc_ordered(ident_t *, kmp_int32 global_tid);
39580b57cec5SDimitry Andric KMP_EXPORT void __kmpc_end_ordered(ident_t *, kmp_int32 global_tid);
39590b57cec5SDimitry Andric KMP_EXPORT void __kmpc_critical(ident_t *, kmp_int32 global_tid,
39600b57cec5SDimitry Andric                                 kmp_critical_name *);
39610b57cec5SDimitry Andric KMP_EXPORT void __kmpc_end_critical(ident_t *, kmp_int32 global_tid,
39620b57cec5SDimitry Andric                                     kmp_critical_name *);
39630b57cec5SDimitry Andric KMP_EXPORT void __kmpc_critical_with_hint(ident_t *, kmp_int32 global_tid,
39640b57cec5SDimitry Andric                                           kmp_critical_name *, uint32_t hint);
39650b57cec5SDimitry Andric 
39660b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_barrier_master(ident_t *, kmp_int32 global_tid);
39670b57cec5SDimitry Andric KMP_EXPORT void __kmpc_end_barrier_master(ident_t *, kmp_int32 global_tid);
39680b57cec5SDimitry Andric 
39690b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_barrier_master_nowait(ident_t *,
39700b57cec5SDimitry Andric                                                   kmp_int32 global_tid);
39710b57cec5SDimitry Andric 
39720b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid);
39730b57cec5SDimitry Andric KMP_EXPORT void __kmpc_end_single(ident_t *, kmp_int32 global_tid);
39740b57cec5SDimitry Andric 
3975753f127fSDimitry Andric KMP_EXPORT kmp_int32 __kmpc_sections_init(ident_t *loc, kmp_int32 global_tid);
3976753f127fSDimitry Andric KMP_EXPORT kmp_int32 __kmpc_next_section(ident_t *loc, kmp_int32 global_tid,
3977753f127fSDimitry Andric                                          kmp_int32 numberOfSections);
3978753f127fSDimitry Andric KMP_EXPORT void __kmpc_end_sections(ident_t *loc, kmp_int32 global_tid);
3979753f127fSDimitry Andric 
39800b57cec5SDimitry Andric KMP_EXPORT void KMPC_FOR_STATIC_INIT(ident_t *loc, kmp_int32 global_tid,
39810b57cec5SDimitry Andric                                      kmp_int32 schedtype, kmp_int32 *plastiter,
39820b57cec5SDimitry Andric                                      kmp_int *plower, kmp_int *pupper,
39830b57cec5SDimitry Andric                                      kmp_int *pstride, kmp_int incr,
39840b57cec5SDimitry Andric                                      kmp_int chunk);
39850b57cec5SDimitry Andric 
39860b57cec5SDimitry Andric KMP_EXPORT void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
39870b57cec5SDimitry Andric 
39880b57cec5SDimitry Andric KMP_EXPORT void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
39890b57cec5SDimitry Andric                                    size_t cpy_size, void *cpy_data,
39900b57cec5SDimitry Andric                                    void (*cpy_func)(void *, void *),
39910b57cec5SDimitry Andric                                    kmp_int32 didit);
39920b57cec5SDimitry Andric 
3993753f127fSDimitry Andric KMP_EXPORT void *__kmpc_copyprivate_light(ident_t *loc, kmp_int32 gtid,
3994753f127fSDimitry Andric                                           void *cpy_data);
3995753f127fSDimitry Andric 
39960b57cec5SDimitry Andric extern void KMPC_SET_NUM_THREADS(int arg);
39970b57cec5SDimitry Andric extern void KMPC_SET_DYNAMIC(int flag);
39980b57cec5SDimitry Andric extern void KMPC_SET_NESTED(int flag);
39990b57cec5SDimitry Andric 
40000b57cec5SDimitry Andric /* OMP 3.0 tasking interface routines */
40010b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_omp_task(ident_t *loc_ref, kmp_int32 gtid,
40020b57cec5SDimitry Andric                                      kmp_task_t *new_task);
40030b57cec5SDimitry Andric KMP_EXPORT kmp_task_t *__kmpc_omp_task_alloc(ident_t *loc_ref, kmp_int32 gtid,
40040b57cec5SDimitry Andric                                              kmp_int32 flags,
40050b57cec5SDimitry Andric                                              size_t sizeof_kmp_task_t,
40060b57cec5SDimitry Andric                                              size_t sizeof_shareds,
40070b57cec5SDimitry Andric                                              kmp_routine_entry_t task_entry);
4008fe6060f1SDimitry Andric KMP_EXPORT kmp_task_t *__kmpc_omp_target_task_alloc(
4009fe6060f1SDimitry Andric     ident_t *loc_ref, kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t,
4010fe6060f1SDimitry Andric     size_t sizeof_shareds, kmp_routine_entry_t task_entry, kmp_int64 device_id);
40110b57cec5SDimitry Andric KMP_EXPORT void __kmpc_omp_task_begin_if0(ident_t *loc_ref, kmp_int32 gtid,
40120b57cec5SDimitry Andric                                           kmp_task_t *task);
40130b57cec5SDimitry Andric KMP_EXPORT void __kmpc_omp_task_complete_if0(ident_t *loc_ref, kmp_int32 gtid,
40140b57cec5SDimitry Andric                                              kmp_task_t *task);
40150b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_omp_task_parts(ident_t *loc_ref, kmp_int32 gtid,
40160b57cec5SDimitry Andric                                            kmp_task_t *new_task);
40170b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_omp_taskwait(ident_t *loc_ref, kmp_int32 gtid);
40180b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_omp_taskyield(ident_t *loc_ref, kmp_int32 gtid,
40190b57cec5SDimitry Andric                                           int end_part);
40200b57cec5SDimitry Andric 
40210b57cec5SDimitry Andric #if TASK_UNUSED
40220b57cec5SDimitry Andric void __kmpc_omp_task_begin(ident_t *loc_ref, kmp_int32 gtid, kmp_task_t *task);
40230b57cec5SDimitry Andric void __kmpc_omp_task_complete(ident_t *loc_ref, kmp_int32 gtid,
40240b57cec5SDimitry Andric                               kmp_task_t *task);
40250b57cec5SDimitry Andric #endif // TASK_UNUSED
40260b57cec5SDimitry Andric 
40270b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
40280b57cec5SDimitry Andric 
40290b57cec5SDimitry Andric KMP_EXPORT void __kmpc_taskgroup(ident_t *loc, int gtid);
40300b57cec5SDimitry Andric KMP_EXPORT void __kmpc_end_taskgroup(ident_t *loc, int gtid);
40310b57cec5SDimitry Andric 
40320b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_omp_task_with_deps(
40330b57cec5SDimitry Andric     ident_t *loc_ref, kmp_int32 gtid, kmp_task_t *new_task, kmp_int32 ndeps,
40340b57cec5SDimitry Andric     kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias,
40350b57cec5SDimitry Andric     kmp_depend_info_t *noalias_dep_list);
40360b57cec5SDimitry Andric KMP_EXPORT void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32 gtid,
40370b57cec5SDimitry Andric                                      kmp_int32 ndeps,
40380b57cec5SDimitry Andric                                      kmp_depend_info_t *dep_list,
40390b57cec5SDimitry Andric                                      kmp_int32 ndeps_noalias,
40400b57cec5SDimitry Andric                                      kmp_depend_info_t *noalias_dep_list);
4041*bdd1243dSDimitry Andric /* __kmpc_omp_taskwait_deps_51 : Function for OpenMP 5.1 nowait clause.
4042*bdd1243dSDimitry Andric  *                               Placeholder for taskwait with nowait clause.*/
4043*bdd1243dSDimitry Andric KMP_EXPORT void __kmpc_omp_taskwait_deps_51(ident_t *loc_ref, kmp_int32 gtid,
4044*bdd1243dSDimitry Andric                                             kmp_int32 ndeps,
4045*bdd1243dSDimitry Andric                                             kmp_depend_info_t *dep_list,
4046*bdd1243dSDimitry Andric                                             kmp_int32 ndeps_noalias,
4047*bdd1243dSDimitry Andric                                             kmp_depend_info_t *noalias_dep_list,
4048*bdd1243dSDimitry Andric                                             kmp_int32 has_no_wait);
4049*bdd1243dSDimitry Andric 
40500b57cec5SDimitry Andric extern kmp_int32 __kmp_omp_task(kmp_int32 gtid, kmp_task_t *new_task,
40510b57cec5SDimitry Andric                                 bool serialize_immediate);
40520b57cec5SDimitry Andric 
40530b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_cancel(ident_t *loc_ref, kmp_int32 gtid,
40540b57cec5SDimitry Andric                                    kmp_int32 cncl_kind);
40550b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_cancellationpoint(ident_t *loc_ref, kmp_int32 gtid,
40560b57cec5SDimitry Andric                                               kmp_int32 cncl_kind);
40570b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_cancel_barrier(ident_t *loc_ref, kmp_int32 gtid);
40580b57cec5SDimitry Andric KMP_EXPORT int __kmp_get_cancellation_status(int cancel_kind);
40590b57cec5SDimitry Andric 
40600b57cec5SDimitry Andric KMP_EXPORT void __kmpc_proxy_task_completed(kmp_int32 gtid, kmp_task_t *ptask);
40610b57cec5SDimitry Andric KMP_EXPORT void __kmpc_proxy_task_completed_ooo(kmp_task_t *ptask);
40620b57cec5SDimitry Andric KMP_EXPORT void __kmpc_taskloop(ident_t *loc, kmp_int32 gtid, kmp_task_t *task,
40630b57cec5SDimitry Andric                                 kmp_int32 if_val, kmp_uint64 *lb,
40640b57cec5SDimitry Andric                                 kmp_uint64 *ub, kmp_int64 st, kmp_int32 nogroup,
40650b57cec5SDimitry Andric                                 kmp_int32 sched, kmp_uint64 grainsize,
40660b57cec5SDimitry Andric                                 void *task_dup);
4067e8d8bef9SDimitry Andric KMP_EXPORT void __kmpc_taskloop_5(ident_t *loc, kmp_int32 gtid,
4068e8d8bef9SDimitry Andric                                   kmp_task_t *task, kmp_int32 if_val,
4069e8d8bef9SDimitry Andric                                   kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st,
4070e8d8bef9SDimitry Andric                                   kmp_int32 nogroup, kmp_int32 sched,
4071e8d8bef9SDimitry Andric                                   kmp_uint64 grainsize, kmp_int32 modifier,
4072e8d8bef9SDimitry Andric                                   void *task_dup);
40730b57cec5SDimitry Andric KMP_EXPORT void *__kmpc_task_reduction_init(int gtid, int num_data, void *data);
40740b57cec5SDimitry Andric KMP_EXPORT void *__kmpc_taskred_init(int gtid, int num_data, void *data);
40750b57cec5SDimitry Andric KMP_EXPORT void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void *d);
40760b57cec5SDimitry Andric KMP_EXPORT void *__kmpc_task_reduction_modifier_init(ident_t *loc, int gtid,
40770b57cec5SDimitry Andric                                                      int is_ws, int num,
40780b57cec5SDimitry Andric                                                      void *data);
40790b57cec5SDimitry Andric KMP_EXPORT void *__kmpc_taskred_modifier_init(ident_t *loc, int gtid, int is_ws,
40800b57cec5SDimitry Andric                                               int num, void *data);
40810b57cec5SDimitry Andric KMP_EXPORT void __kmpc_task_reduction_modifier_fini(ident_t *loc, int gtid,
40820b57cec5SDimitry Andric                                                     int is_ws);
40830b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_omp_reg_task_with_affinity(
40840b57cec5SDimitry Andric     ident_t *loc_ref, kmp_int32 gtid, kmp_task_t *new_task, kmp_int32 naffins,
40850b57cec5SDimitry Andric     kmp_task_affinity_info_t *affin_list);
4086fe6060f1SDimitry Andric KMP_EXPORT void __kmp_set_num_teams(int num_teams);
4087fe6060f1SDimitry Andric KMP_EXPORT int __kmp_get_max_teams(void);
4088fe6060f1SDimitry Andric KMP_EXPORT void __kmp_set_teams_thread_limit(int limit);
4089fe6060f1SDimitry Andric KMP_EXPORT int __kmp_get_teams_thread_limit(void);
40900b57cec5SDimitry Andric 
4091*bdd1243dSDimitry Andric /* Interface target task integration */
4092*bdd1243dSDimitry Andric KMP_EXPORT void **__kmpc_omp_get_target_async_handle_ptr(kmp_int32 gtid);
4093*bdd1243dSDimitry Andric KMP_EXPORT bool __kmpc_omp_has_task_team(kmp_int32 gtid);
4094*bdd1243dSDimitry Andric 
40950b57cec5SDimitry Andric /* Lock interface routines (fast versions with gtid passed in) */
40960b57cec5SDimitry Andric KMP_EXPORT void __kmpc_init_lock(ident_t *loc, kmp_int32 gtid,
40970b57cec5SDimitry Andric                                  void **user_lock);
40980b57cec5SDimitry Andric KMP_EXPORT void __kmpc_init_nest_lock(ident_t *loc, kmp_int32 gtid,
40990b57cec5SDimitry Andric                                       void **user_lock);
41000b57cec5SDimitry Andric KMP_EXPORT void __kmpc_destroy_lock(ident_t *loc, kmp_int32 gtid,
41010b57cec5SDimitry Andric                                     void **user_lock);
41020b57cec5SDimitry Andric KMP_EXPORT void __kmpc_destroy_nest_lock(ident_t *loc, kmp_int32 gtid,
41030b57cec5SDimitry Andric                                          void **user_lock);
41040b57cec5SDimitry Andric KMP_EXPORT void __kmpc_set_lock(ident_t *loc, kmp_int32 gtid, void **user_lock);
41050b57cec5SDimitry Andric KMP_EXPORT void __kmpc_set_nest_lock(ident_t *loc, kmp_int32 gtid,
41060b57cec5SDimitry Andric                                      void **user_lock);
41070b57cec5SDimitry Andric KMP_EXPORT void __kmpc_unset_lock(ident_t *loc, kmp_int32 gtid,
41080b57cec5SDimitry Andric                                   void **user_lock);
41090b57cec5SDimitry Andric KMP_EXPORT void __kmpc_unset_nest_lock(ident_t *loc, kmp_int32 gtid,
41100b57cec5SDimitry Andric                                        void **user_lock);
41110b57cec5SDimitry Andric KMP_EXPORT int __kmpc_test_lock(ident_t *loc, kmp_int32 gtid, void **user_lock);
41120b57cec5SDimitry Andric KMP_EXPORT int __kmpc_test_nest_lock(ident_t *loc, kmp_int32 gtid,
41130b57cec5SDimitry Andric                                      void **user_lock);
41140b57cec5SDimitry Andric 
41150b57cec5SDimitry Andric KMP_EXPORT void __kmpc_init_lock_with_hint(ident_t *loc, kmp_int32 gtid,
41160b57cec5SDimitry Andric                                            void **user_lock, uintptr_t hint);
41170b57cec5SDimitry Andric KMP_EXPORT void __kmpc_init_nest_lock_with_hint(ident_t *loc, kmp_int32 gtid,
41180b57cec5SDimitry Andric                                                 void **user_lock,
41190b57cec5SDimitry Andric                                                 uintptr_t hint);
41200b57cec5SDimitry Andric 
41210b57cec5SDimitry Andric /* Interface to fast scalable reduce methods routines */
41220b57cec5SDimitry Andric 
41230b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_reduce_nowait(
41240b57cec5SDimitry Andric     ident_t *loc, kmp_int32 global_tid, kmp_int32 num_vars, size_t reduce_size,
41250b57cec5SDimitry Andric     void *reduce_data, void (*reduce_func)(void *lhs_data, void *rhs_data),
41260b57cec5SDimitry Andric     kmp_critical_name *lck);
41270b57cec5SDimitry Andric KMP_EXPORT void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
41280b57cec5SDimitry Andric                                          kmp_critical_name *lck);
41290b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_reduce(
41300b57cec5SDimitry Andric     ident_t *loc, kmp_int32 global_tid, kmp_int32 num_vars, size_t reduce_size,
41310b57cec5SDimitry Andric     void *reduce_data, void (*reduce_func)(void *lhs_data, void *rhs_data),
41320b57cec5SDimitry Andric     kmp_critical_name *lck);
41330b57cec5SDimitry Andric KMP_EXPORT void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
41340b57cec5SDimitry Andric                                   kmp_critical_name *lck);
41350b57cec5SDimitry Andric 
41360b57cec5SDimitry Andric /* Internal fast reduction routines */
41370b57cec5SDimitry Andric 
41380b57cec5SDimitry Andric extern PACKED_REDUCTION_METHOD_T __kmp_determine_reduction_method(
41390b57cec5SDimitry Andric     ident_t *loc, kmp_int32 global_tid, kmp_int32 num_vars, size_t reduce_size,
41400b57cec5SDimitry Andric     void *reduce_data, void (*reduce_func)(void *lhs_data, void *rhs_data),
41410b57cec5SDimitry Andric     kmp_critical_name *lck);
41420b57cec5SDimitry Andric 
41430b57cec5SDimitry Andric // this function is for testing set/get/determine reduce method
41440b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmp_get_reduce_method(void);
41450b57cec5SDimitry Andric 
41460b57cec5SDimitry Andric KMP_EXPORT kmp_uint64 __kmpc_get_taskid();
41470b57cec5SDimitry Andric KMP_EXPORT kmp_uint64 __kmpc_get_parent_taskid();
41480b57cec5SDimitry Andric 
41490b57cec5SDimitry Andric // C++ port
41500b57cec5SDimitry Andric // missing 'extern "C"' declarations
41510b57cec5SDimitry Andric 
41520b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_in_parallel(ident_t *loc);
41530b57cec5SDimitry Andric KMP_EXPORT void __kmpc_pop_num_threads(ident_t *loc, kmp_int32 global_tid);
41540b57cec5SDimitry Andric KMP_EXPORT void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
41550b57cec5SDimitry Andric                                         kmp_int32 num_threads);
41560b57cec5SDimitry Andric 
41570b57cec5SDimitry Andric KMP_EXPORT void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
41580b57cec5SDimitry Andric                                       int proc_bind);
41590b57cec5SDimitry Andric KMP_EXPORT void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid,
41600b57cec5SDimitry Andric                                       kmp_int32 num_teams,
41610b57cec5SDimitry Andric                                       kmp_int32 num_threads);
4162fe6060f1SDimitry Andric /* Function for OpenMP 5.1 num_teams clause */
4163fe6060f1SDimitry Andric KMP_EXPORT void __kmpc_push_num_teams_51(ident_t *loc, kmp_int32 global_tid,
4164fe6060f1SDimitry Andric                                          kmp_int32 num_teams_lb,
4165fe6060f1SDimitry Andric                                          kmp_int32 num_teams_ub,
4166fe6060f1SDimitry Andric                                          kmp_int32 num_threads);
41670b57cec5SDimitry Andric KMP_EXPORT void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc,
41680b57cec5SDimitry Andric                                   kmpc_micro microtask, ...);
41690b57cec5SDimitry Andric struct kmp_dim { // loop bounds info casted to kmp_int64
41700b57cec5SDimitry Andric   kmp_int64 lo; // lower
41710b57cec5SDimitry Andric   kmp_int64 up; // upper
41720b57cec5SDimitry Andric   kmp_int64 st; // stride
41730b57cec5SDimitry Andric };
41740b57cec5SDimitry Andric KMP_EXPORT void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid,
41750b57cec5SDimitry Andric                                      kmp_int32 num_dims,
41760b57cec5SDimitry Andric                                      const struct kmp_dim *dims);
41770b57cec5SDimitry Andric KMP_EXPORT void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid,
41780b57cec5SDimitry Andric                                      const kmp_int64 *vec);
41790b57cec5SDimitry Andric KMP_EXPORT void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid,
41800b57cec5SDimitry Andric                                      const kmp_int64 *vec);
41810b57cec5SDimitry Andric KMP_EXPORT void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid);
41820b57cec5SDimitry Andric 
41830b57cec5SDimitry Andric KMP_EXPORT void *__kmpc_threadprivate_cached(ident_t *loc, kmp_int32 global_tid,
41840b57cec5SDimitry Andric                                              void *data, size_t size,
41850b57cec5SDimitry Andric                                              void ***cache);
41860b57cec5SDimitry Andric 
41870b57cec5SDimitry Andric // Symbols for MS mutual detection.
41880b57cec5SDimitry Andric extern int _You_must_link_with_exactly_one_OpenMP_library;
41890b57cec5SDimitry Andric extern int _You_must_link_with_Intel_OpenMP_library;
41900b57cec5SDimitry Andric #if KMP_OS_WINDOWS && (KMP_VERSION_MAJOR > 4)
41910b57cec5SDimitry Andric extern int _You_must_link_with_Microsoft_OpenMP_library;
41920b57cec5SDimitry Andric #endif
41930b57cec5SDimitry Andric 
41940b57cec5SDimitry Andric // The routines below are not exported.
41950b57cec5SDimitry Andric // Consider making them 'static' in corresponding source files.
41960b57cec5SDimitry Andric void kmp_threadprivate_insert_private_data(int gtid, void *pc_addr,
41970b57cec5SDimitry Andric                                            void *data_addr, size_t pc_size);
41980b57cec5SDimitry Andric struct private_common *kmp_threadprivate_insert(int gtid, void *pc_addr,
41990b57cec5SDimitry Andric                                                 void *data_addr,
42000b57cec5SDimitry Andric                                                 size_t pc_size);
42010b57cec5SDimitry Andric void __kmp_threadprivate_resize_cache(int newCapacity);
42020b57cec5SDimitry Andric void __kmp_cleanup_threadprivate_caches();
42030b57cec5SDimitry Andric 
42040b57cec5SDimitry Andric // ompc_, kmpc_ entries moved from omp.h.
42050b57cec5SDimitry Andric #if KMP_OS_WINDOWS
42060b57cec5SDimitry Andric #define KMPC_CONVENTION __cdecl
42070b57cec5SDimitry Andric #else
42080b57cec5SDimitry Andric #define KMPC_CONVENTION
42090b57cec5SDimitry Andric #endif
42100b57cec5SDimitry Andric 
42110b57cec5SDimitry Andric #ifndef __OMP_H
42120b57cec5SDimitry Andric typedef enum omp_sched_t {
42130b57cec5SDimitry Andric   omp_sched_static = 1,
42140b57cec5SDimitry Andric   omp_sched_dynamic = 2,
42150b57cec5SDimitry Andric   omp_sched_guided = 3,
42160b57cec5SDimitry Andric   omp_sched_auto = 4
42170b57cec5SDimitry Andric } omp_sched_t;
42180b57cec5SDimitry Andric typedef void *kmp_affinity_mask_t;
42190b57cec5SDimitry Andric #endif
42200b57cec5SDimitry Andric 
42210b57cec5SDimitry Andric KMP_EXPORT void KMPC_CONVENTION ompc_set_max_active_levels(int);
42220b57cec5SDimitry Andric KMP_EXPORT void KMPC_CONVENTION ompc_set_schedule(omp_sched_t, int);
42230b57cec5SDimitry Andric KMP_EXPORT int KMPC_CONVENTION ompc_get_ancestor_thread_num(int);
42240b57cec5SDimitry Andric KMP_EXPORT int KMPC_CONVENTION ompc_get_team_size(int);
42250b57cec5SDimitry Andric KMP_EXPORT int KMPC_CONVENTION
42260b57cec5SDimitry Andric kmpc_set_affinity_mask_proc(int, kmp_affinity_mask_t *);
42270b57cec5SDimitry Andric KMP_EXPORT int KMPC_CONVENTION
42280b57cec5SDimitry Andric kmpc_unset_affinity_mask_proc(int, kmp_affinity_mask_t *);
42290b57cec5SDimitry Andric KMP_EXPORT int KMPC_CONVENTION
42300b57cec5SDimitry Andric kmpc_get_affinity_mask_proc(int, kmp_affinity_mask_t *);
42310b57cec5SDimitry Andric 
42320b57cec5SDimitry Andric KMP_EXPORT void KMPC_CONVENTION kmpc_set_stacksize(int);
42330b57cec5SDimitry Andric KMP_EXPORT void KMPC_CONVENTION kmpc_set_stacksize_s(size_t);
42340b57cec5SDimitry Andric KMP_EXPORT void KMPC_CONVENTION kmpc_set_library(int);
42350b57cec5SDimitry Andric KMP_EXPORT void KMPC_CONVENTION kmpc_set_defaults(char const *);
42360b57cec5SDimitry Andric KMP_EXPORT void KMPC_CONVENTION kmpc_set_disp_num_buffers(int);
4237fe6060f1SDimitry Andric void KMP_EXPAND_NAME(ompc_set_affinity_format)(char const *format);
4238fe6060f1SDimitry Andric size_t KMP_EXPAND_NAME(ompc_get_affinity_format)(char *buffer, size_t size);
4239fe6060f1SDimitry Andric void KMP_EXPAND_NAME(ompc_display_affinity)(char const *format);
4240fe6060f1SDimitry Andric size_t KMP_EXPAND_NAME(ompc_capture_affinity)(char *buffer, size_t buf_size,
4241fe6060f1SDimitry Andric                                               char const *format);
42420b57cec5SDimitry Andric 
42430b57cec5SDimitry Andric enum kmp_target_offload_kind {
42440b57cec5SDimitry Andric   tgt_disabled = 0,
42450b57cec5SDimitry Andric   tgt_default = 1,
42460b57cec5SDimitry Andric   tgt_mandatory = 2
42470b57cec5SDimitry Andric };
42480b57cec5SDimitry Andric typedef enum kmp_target_offload_kind kmp_target_offload_kind_t;
42490b57cec5SDimitry Andric // Set via OMP_TARGET_OFFLOAD if specified, defaults to tgt_default otherwise
42500b57cec5SDimitry Andric extern kmp_target_offload_kind_t __kmp_target_offload;
42510b57cec5SDimitry Andric extern int __kmpc_get_target_offload();
42520b57cec5SDimitry Andric 
42530b57cec5SDimitry Andric // Constants used in libomptarget
42540b57cec5SDimitry Andric #define KMP_DEVICE_DEFAULT -1 // This is libomptarget's default device.
42550b57cec5SDimitry Andric #define KMP_DEVICE_ALL -11 // This is libomptarget's "all devices".
42560b57cec5SDimitry Andric 
42570b57cec5SDimitry Andric // OMP Pause Resource
42580b57cec5SDimitry Andric 
42590b57cec5SDimitry Andric // The following enum is used both to set the status in __kmp_pause_status, and
42600b57cec5SDimitry Andric // as the internal equivalent of the externally-visible omp_pause_resource_t.
42610b57cec5SDimitry Andric typedef enum kmp_pause_status_t {
42620b57cec5SDimitry Andric   kmp_not_paused = 0, // status is not paused, or, requesting resume
42630b57cec5SDimitry Andric   kmp_soft_paused = 1, // status is soft-paused, or, requesting soft pause
42640b57cec5SDimitry Andric   kmp_hard_paused = 2 // status is hard-paused, or, requesting hard pause
42650b57cec5SDimitry Andric } kmp_pause_status_t;
42660b57cec5SDimitry Andric 
42670b57cec5SDimitry Andric // This stores the pause state of the runtime
42680b57cec5SDimitry Andric extern kmp_pause_status_t __kmp_pause_status;
42690b57cec5SDimitry Andric extern int __kmpc_pause_resource(kmp_pause_status_t level);
42700b57cec5SDimitry Andric extern int __kmp_pause_resource(kmp_pause_status_t level);
42710b57cec5SDimitry Andric // Soft resume sets __kmp_pause_status, and wakes up all threads.
42720b57cec5SDimitry Andric extern void __kmp_resume_if_soft_paused();
42730b57cec5SDimitry Andric // Hard resume simply resets the status to not paused. Library will appear to
42740b57cec5SDimitry Andric // be uninitialized after hard pause. Let OMP constructs trigger required
42750b57cec5SDimitry Andric // initializations.
42760b57cec5SDimitry Andric static inline void __kmp_resume_if_hard_paused() {
42770b57cec5SDimitry Andric   if (__kmp_pause_status == kmp_hard_paused) {
42780b57cec5SDimitry Andric     __kmp_pause_status = kmp_not_paused;
42790b57cec5SDimitry Andric   }
42800b57cec5SDimitry Andric }
42810b57cec5SDimitry Andric 
42825ffd83dbSDimitry Andric extern void __kmp_omp_display_env(int verbose);
42835ffd83dbSDimitry Andric 
4284e8d8bef9SDimitry Andric // 1: it is initializing hidden helper team
4285e8d8bef9SDimitry Andric extern volatile int __kmp_init_hidden_helper;
4286e8d8bef9SDimitry Andric // 1: the hidden helper team is done
4287e8d8bef9SDimitry Andric extern volatile int __kmp_hidden_helper_team_done;
4288e8d8bef9SDimitry Andric // 1: enable hidden helper task
4289e8d8bef9SDimitry Andric extern kmp_int32 __kmp_enable_hidden_helper;
4290e8d8bef9SDimitry Andric // Main thread of hidden helper team
4291e8d8bef9SDimitry Andric extern kmp_info_t *__kmp_hidden_helper_main_thread;
4292e8d8bef9SDimitry Andric // Descriptors for the hidden helper threads
4293e8d8bef9SDimitry Andric extern kmp_info_t **__kmp_hidden_helper_threads;
4294e8d8bef9SDimitry Andric // Number of hidden helper threads
4295e8d8bef9SDimitry Andric extern kmp_int32 __kmp_hidden_helper_threads_num;
4296e8d8bef9SDimitry Andric // Number of hidden helper tasks that have not been executed yet
4297e8d8bef9SDimitry Andric extern std::atomic<kmp_int32> __kmp_unexecuted_hidden_helper_tasks;
4298e8d8bef9SDimitry Andric 
4299e8d8bef9SDimitry Andric extern void __kmp_hidden_helper_initialize();
4300e8d8bef9SDimitry Andric extern void __kmp_hidden_helper_threads_initz_routine();
4301e8d8bef9SDimitry Andric extern void __kmp_do_initialize_hidden_helper_threads();
4302e8d8bef9SDimitry Andric extern void __kmp_hidden_helper_threads_initz_wait();
4303e8d8bef9SDimitry Andric extern void __kmp_hidden_helper_initz_release();
4304e8d8bef9SDimitry Andric extern void __kmp_hidden_helper_threads_deinitz_wait();
4305e8d8bef9SDimitry Andric extern void __kmp_hidden_helper_threads_deinitz_release();
4306e8d8bef9SDimitry Andric extern void __kmp_hidden_helper_main_thread_wait();
4307e8d8bef9SDimitry Andric extern void __kmp_hidden_helper_worker_thread_wait();
4308e8d8bef9SDimitry Andric extern void __kmp_hidden_helper_worker_thread_signal();
4309e8d8bef9SDimitry Andric extern void __kmp_hidden_helper_main_thread_release();
4310e8d8bef9SDimitry Andric 
4311e8d8bef9SDimitry Andric // Check whether a given thread is a hidden helper thread
4312e8d8bef9SDimitry Andric #define KMP_HIDDEN_HELPER_THREAD(gtid)                                         \
4313e8d8bef9SDimitry Andric   ((gtid) >= 1 && (gtid) <= __kmp_hidden_helper_threads_num)
4314e8d8bef9SDimitry Andric 
4315e8d8bef9SDimitry Andric #define KMP_HIDDEN_HELPER_WORKER_THREAD(gtid)                                  \
4316e8d8bef9SDimitry Andric   ((gtid) > 1 && (gtid) <= __kmp_hidden_helper_threads_num)
4317e8d8bef9SDimitry Andric 
4318*bdd1243dSDimitry Andric #define KMP_HIDDEN_HELPER_MAIN_THREAD(gtid)                                    \
4319*bdd1243dSDimitry Andric   ((gtid) == 1 && (gtid) <= __kmp_hidden_helper_threads_num)
4320*bdd1243dSDimitry Andric 
4321fe6060f1SDimitry Andric #define KMP_HIDDEN_HELPER_TEAM(team)                                           \
4322fe6060f1SDimitry Andric   (team->t.t_threads[0] == __kmp_hidden_helper_main_thread)
4323fe6060f1SDimitry Andric 
4324e8d8bef9SDimitry Andric // Map a gtid to a hidden helper thread. The first hidden helper thread, a.k.a
4325e8d8bef9SDimitry Andric // main thread, is skipped.
4326e8d8bef9SDimitry Andric #define KMP_GTID_TO_SHADOW_GTID(gtid)                                          \
4327e8d8bef9SDimitry Andric   ((gtid) % (__kmp_hidden_helper_threads_num - 1) + 2)
4328e8d8bef9SDimitry Andric 
4329fe6060f1SDimitry Andric // Return the adjusted gtid value by subtracting from gtid the number
4330fe6060f1SDimitry Andric // of hidden helper threads. This adjusted value is the gtid the thread would
4331fe6060f1SDimitry Andric // have received if there were no hidden helper threads.
4332fe6060f1SDimitry Andric static inline int __kmp_adjust_gtid_for_hidden_helpers(int gtid) {
4333fe6060f1SDimitry Andric   int adjusted_gtid = gtid;
4334fe6060f1SDimitry Andric   if (__kmp_hidden_helper_threads_num > 0 && gtid > 0 &&
4335fe6060f1SDimitry Andric       gtid - __kmp_hidden_helper_threads_num >= 0) {
4336fe6060f1SDimitry Andric     adjusted_gtid -= __kmp_hidden_helper_threads_num;
4337fe6060f1SDimitry Andric   }
4338fe6060f1SDimitry Andric   return adjusted_gtid;
4339fe6060f1SDimitry Andric }
4340fe6060f1SDimitry Andric 
4341fe6060f1SDimitry Andric // Support for error directive
4342fe6060f1SDimitry Andric typedef enum kmp_severity_t {
4343fe6060f1SDimitry Andric   severity_warning = 1,
4344fe6060f1SDimitry Andric   severity_fatal = 2
4345fe6060f1SDimitry Andric } kmp_severity_t;
4346fe6060f1SDimitry Andric extern void __kmpc_error(ident_t *loc, int severity, const char *message);
4347fe6060f1SDimitry Andric 
4348349cc55cSDimitry Andric // Support for scope directive
4349349cc55cSDimitry Andric KMP_EXPORT void __kmpc_scope(ident_t *loc, kmp_int32 gtid, void *reserved);
4350349cc55cSDimitry Andric KMP_EXPORT void __kmpc_end_scope(ident_t *loc, kmp_int32 gtid, void *reserved);
4351349cc55cSDimitry Andric 
43520b57cec5SDimitry Andric #ifdef __cplusplus
43530b57cec5SDimitry Andric }
43540b57cec5SDimitry Andric #endif
43550b57cec5SDimitry Andric 
4356e8d8bef9SDimitry Andric template <bool C, bool S>
4357e8d8bef9SDimitry Andric extern void __kmp_suspend_32(int th_gtid, kmp_flag_32<C, S> *flag);
4358e8d8bef9SDimitry Andric template <bool C, bool S>
4359e8d8bef9SDimitry Andric extern void __kmp_suspend_64(int th_gtid, kmp_flag_64<C, S> *flag);
4360349cc55cSDimitry Andric template <bool C, bool S>
4361349cc55cSDimitry Andric extern void __kmp_atomic_suspend_64(int th_gtid,
4362349cc55cSDimitry Andric                                     kmp_atomic_flag_64<C, S> *flag);
4363e8d8bef9SDimitry Andric extern void __kmp_suspend_oncore(int th_gtid, kmp_flag_oncore *flag);
4364e8d8bef9SDimitry Andric #if KMP_HAVE_MWAIT || KMP_HAVE_UMWAIT
4365e8d8bef9SDimitry Andric template <bool C, bool S>
4366e8d8bef9SDimitry Andric extern void __kmp_mwait_32(int th_gtid, kmp_flag_32<C, S> *flag);
4367e8d8bef9SDimitry Andric template <bool C, bool S>
4368e8d8bef9SDimitry Andric extern void __kmp_mwait_64(int th_gtid, kmp_flag_64<C, S> *flag);
4369349cc55cSDimitry Andric template <bool C, bool S>
4370349cc55cSDimitry Andric extern void __kmp_atomic_mwait_64(int th_gtid, kmp_atomic_flag_64<C, S> *flag);
4371e8d8bef9SDimitry Andric extern void __kmp_mwait_oncore(int th_gtid, kmp_flag_oncore *flag);
4372e8d8bef9SDimitry Andric #endif
4373e8d8bef9SDimitry Andric template <bool C, bool S>
4374e8d8bef9SDimitry Andric extern void __kmp_resume_32(int target_gtid, kmp_flag_32<C, S> *flag);
4375e8d8bef9SDimitry Andric template <bool C, bool S>
4376e8d8bef9SDimitry Andric extern void __kmp_resume_64(int target_gtid, kmp_flag_64<C, S> *flag);
4377349cc55cSDimitry Andric template <bool C, bool S>
4378349cc55cSDimitry Andric extern void __kmp_atomic_resume_64(int target_gtid,
4379349cc55cSDimitry Andric                                    kmp_atomic_flag_64<C, S> *flag);
4380e8d8bef9SDimitry Andric extern void __kmp_resume_oncore(int target_gtid, kmp_flag_oncore *flag);
4381e8d8bef9SDimitry Andric 
4382e8d8bef9SDimitry Andric template <bool C, bool S>
4383e8d8bef9SDimitry Andric int __kmp_execute_tasks_32(kmp_info_t *thread, kmp_int32 gtid,
4384e8d8bef9SDimitry Andric                            kmp_flag_32<C, S> *flag, int final_spin,
4385e8d8bef9SDimitry Andric                            int *thread_finished,
4386e8d8bef9SDimitry Andric #if USE_ITT_BUILD
4387e8d8bef9SDimitry Andric                            void *itt_sync_obj,
4388e8d8bef9SDimitry Andric #endif /* USE_ITT_BUILD */
4389e8d8bef9SDimitry Andric                            kmp_int32 is_constrained);
4390e8d8bef9SDimitry Andric template <bool C, bool S>
4391e8d8bef9SDimitry Andric int __kmp_execute_tasks_64(kmp_info_t *thread, kmp_int32 gtid,
4392e8d8bef9SDimitry Andric                            kmp_flag_64<C, S> *flag, int final_spin,
4393e8d8bef9SDimitry Andric                            int *thread_finished,
4394e8d8bef9SDimitry Andric #if USE_ITT_BUILD
4395e8d8bef9SDimitry Andric                            void *itt_sync_obj,
4396e8d8bef9SDimitry Andric #endif /* USE_ITT_BUILD */
4397e8d8bef9SDimitry Andric                            kmp_int32 is_constrained);
4398349cc55cSDimitry Andric template <bool C, bool S>
4399349cc55cSDimitry Andric int __kmp_atomic_execute_tasks_64(kmp_info_t *thread, kmp_int32 gtid,
4400349cc55cSDimitry Andric                                   kmp_atomic_flag_64<C, S> *flag,
4401349cc55cSDimitry Andric                                   int final_spin, int *thread_finished,
4402349cc55cSDimitry Andric #if USE_ITT_BUILD
4403349cc55cSDimitry Andric                                   void *itt_sync_obj,
4404349cc55cSDimitry Andric #endif /* USE_ITT_BUILD */
4405349cc55cSDimitry Andric                                   kmp_int32 is_constrained);
4406e8d8bef9SDimitry Andric int __kmp_execute_tasks_oncore(kmp_info_t *thread, kmp_int32 gtid,
4407e8d8bef9SDimitry Andric                                kmp_flag_oncore *flag, int final_spin,
4408e8d8bef9SDimitry Andric                                int *thread_finished,
4409e8d8bef9SDimitry Andric #if USE_ITT_BUILD
4410e8d8bef9SDimitry Andric                                void *itt_sync_obj,
4411e8d8bef9SDimitry Andric #endif /* USE_ITT_BUILD */
4412e8d8bef9SDimitry Andric                                kmp_int32 is_constrained);
4413e8d8bef9SDimitry Andric 
4414fe6060f1SDimitry Andric extern int __kmp_nesting_mode;
4415fe6060f1SDimitry Andric extern int __kmp_nesting_mode_nlevels;
4416fe6060f1SDimitry Andric extern int *__kmp_nesting_nth_level;
4417fe6060f1SDimitry Andric extern void __kmp_init_nesting_mode();
4418fe6060f1SDimitry Andric extern void __kmp_set_nesting_mode_threads();
4419fe6060f1SDimitry Andric 
4420e8d8bef9SDimitry Andric /// This class safely opens and closes a C-style FILE* object using RAII
4421e8d8bef9SDimitry Andric /// semantics. There are also methods which allow using stdout or stderr as
4422e8d8bef9SDimitry Andric /// the underlying FILE* object. With the implicit conversion operator to
4423e8d8bef9SDimitry Andric /// FILE*, an object with this type can be used in any function which takes
4424e8d8bef9SDimitry Andric /// a FILE* object e.g., fprintf().
4425e8d8bef9SDimitry Andric /// No close method is needed at use sites.
4426e8d8bef9SDimitry Andric class kmp_safe_raii_file_t {
4427e8d8bef9SDimitry Andric   FILE *f;
4428e8d8bef9SDimitry Andric 
4429e8d8bef9SDimitry Andric   void close() {
4430e8d8bef9SDimitry Andric     if (f && f != stdout && f != stderr) {
4431e8d8bef9SDimitry Andric       fclose(f);
4432e8d8bef9SDimitry Andric       f = nullptr;
4433e8d8bef9SDimitry Andric     }
4434e8d8bef9SDimitry Andric   }
4435e8d8bef9SDimitry Andric 
4436e8d8bef9SDimitry Andric public:
4437e8d8bef9SDimitry Andric   kmp_safe_raii_file_t() : f(nullptr) {}
4438e8d8bef9SDimitry Andric   kmp_safe_raii_file_t(const char *filename, const char *mode,
4439e8d8bef9SDimitry Andric                        const char *env_var = nullptr)
4440e8d8bef9SDimitry Andric       : f(nullptr) {
4441e8d8bef9SDimitry Andric     open(filename, mode, env_var);
4442e8d8bef9SDimitry Andric   }
4443e8d8bef9SDimitry Andric   ~kmp_safe_raii_file_t() { close(); }
4444e8d8bef9SDimitry Andric 
4445e8d8bef9SDimitry Andric   /// Open filename using mode. This is automatically closed in the destructor.
4446e8d8bef9SDimitry Andric   /// The env_var parameter indicates the environment variable the filename
4447e8d8bef9SDimitry Andric   /// came from if != nullptr.
4448e8d8bef9SDimitry Andric   void open(const char *filename, const char *mode,
4449e8d8bef9SDimitry Andric             const char *env_var = nullptr) {
4450e8d8bef9SDimitry Andric     KMP_ASSERT(!f);
4451e8d8bef9SDimitry Andric     f = fopen(filename, mode);
4452e8d8bef9SDimitry Andric     if (!f) {
4453e8d8bef9SDimitry Andric       int code = errno;
4454e8d8bef9SDimitry Andric       if (env_var) {
4455e8d8bef9SDimitry Andric         __kmp_fatal(KMP_MSG(CantOpenFileForReading, filename), KMP_ERR(code),
4456e8d8bef9SDimitry Andric                     KMP_HNT(CheckEnvVar, env_var, filename), __kmp_msg_null);
4457e8d8bef9SDimitry Andric       } else {
4458e8d8bef9SDimitry Andric         __kmp_fatal(KMP_MSG(CantOpenFileForReading, filename), KMP_ERR(code),
4459e8d8bef9SDimitry Andric                     __kmp_msg_null);
4460e8d8bef9SDimitry Andric       }
4461e8d8bef9SDimitry Andric     }
4462e8d8bef9SDimitry Andric   }
4463349cc55cSDimitry Andric   /// Instead of erroring out, return non-zero when
4464349cc55cSDimitry Andric   /// unsuccessful fopen() for any reason
4465349cc55cSDimitry Andric   int try_open(const char *filename, const char *mode) {
4466349cc55cSDimitry Andric     KMP_ASSERT(!f);
4467349cc55cSDimitry Andric     f = fopen(filename, mode);
4468349cc55cSDimitry Andric     if (!f)
4469349cc55cSDimitry Andric       return errno;
4470349cc55cSDimitry Andric     return 0;
4471349cc55cSDimitry Andric   }
4472e8d8bef9SDimitry Andric   /// Set the FILE* object to stdout and output there
4473e8d8bef9SDimitry Andric   /// No open call should happen before this call.
4474e8d8bef9SDimitry Andric   void set_stdout() {
4475e8d8bef9SDimitry Andric     KMP_ASSERT(!f);
4476e8d8bef9SDimitry Andric     f = stdout;
4477e8d8bef9SDimitry Andric   }
4478e8d8bef9SDimitry Andric   /// Set the FILE* object to stderr and output there
4479e8d8bef9SDimitry Andric   /// No open call should happen before this call.
4480e8d8bef9SDimitry Andric   void set_stderr() {
4481e8d8bef9SDimitry Andric     KMP_ASSERT(!f);
4482e8d8bef9SDimitry Andric     f = stderr;
4483e8d8bef9SDimitry Andric   }
4484e8d8bef9SDimitry Andric   operator bool() { return bool(f); }
4485e8d8bef9SDimitry Andric   operator FILE *() { return f; }
4486e8d8bef9SDimitry Andric };
4487e8d8bef9SDimitry Andric 
4488e8d8bef9SDimitry Andric template <typename SourceType, typename TargetType,
4489e8d8bef9SDimitry Andric           bool isSourceSmaller = (sizeof(SourceType) < sizeof(TargetType)),
4490e8d8bef9SDimitry Andric           bool isSourceEqual = (sizeof(SourceType) == sizeof(TargetType)),
4491e8d8bef9SDimitry Andric           bool isSourceSigned = std::is_signed<SourceType>::value,
4492e8d8bef9SDimitry Andric           bool isTargetSigned = std::is_signed<TargetType>::value>
4493e8d8bef9SDimitry Andric struct kmp_convert {};
4494e8d8bef9SDimitry Andric 
4495e8d8bef9SDimitry Andric // Both types are signed; Source smaller
4496e8d8bef9SDimitry Andric template <typename SourceType, typename TargetType>
4497e8d8bef9SDimitry Andric struct kmp_convert<SourceType, TargetType, true, false, true, true> {
4498e8d8bef9SDimitry Andric   static TargetType to(SourceType src) { return (TargetType)src; }
4499e8d8bef9SDimitry Andric };
4500e8d8bef9SDimitry Andric // Source equal
4501e8d8bef9SDimitry Andric template <typename SourceType, typename TargetType>
4502e8d8bef9SDimitry Andric struct kmp_convert<SourceType, TargetType, false, true, true, true> {
4503e8d8bef9SDimitry Andric   static TargetType to(SourceType src) { return src; }
4504e8d8bef9SDimitry Andric };
4505e8d8bef9SDimitry Andric // Source bigger
4506e8d8bef9SDimitry Andric template <typename SourceType, typename TargetType>
4507e8d8bef9SDimitry Andric struct kmp_convert<SourceType, TargetType, false, false, true, true> {
4508e8d8bef9SDimitry Andric   static TargetType to(SourceType src) {
4509e8d8bef9SDimitry Andric     KMP_ASSERT(src <= static_cast<SourceType>(
4510e8d8bef9SDimitry Andric                           (std::numeric_limits<TargetType>::max)()));
4511e8d8bef9SDimitry Andric     KMP_ASSERT(src >= static_cast<SourceType>(
4512e8d8bef9SDimitry Andric                           (std::numeric_limits<TargetType>::min)()));
4513e8d8bef9SDimitry Andric     return (TargetType)src;
4514e8d8bef9SDimitry Andric   }
4515e8d8bef9SDimitry Andric };
4516e8d8bef9SDimitry Andric 
4517e8d8bef9SDimitry Andric // Source signed, Target unsigned
4518e8d8bef9SDimitry Andric // Source smaller
4519e8d8bef9SDimitry Andric template <typename SourceType, typename TargetType>
4520e8d8bef9SDimitry Andric struct kmp_convert<SourceType, TargetType, true, false, true, false> {
4521e8d8bef9SDimitry Andric   static TargetType to(SourceType src) {
4522e8d8bef9SDimitry Andric     KMP_ASSERT(src >= 0);
4523e8d8bef9SDimitry Andric     return (TargetType)src;
4524e8d8bef9SDimitry Andric   }
4525e8d8bef9SDimitry Andric };
4526e8d8bef9SDimitry Andric // Source equal
4527e8d8bef9SDimitry Andric template <typename SourceType, typename TargetType>
4528e8d8bef9SDimitry Andric struct kmp_convert<SourceType, TargetType, false, true, true, false> {
4529e8d8bef9SDimitry Andric   static TargetType to(SourceType src) {
4530e8d8bef9SDimitry Andric     KMP_ASSERT(src >= 0);
4531e8d8bef9SDimitry Andric     return (TargetType)src;
4532e8d8bef9SDimitry Andric   }
4533e8d8bef9SDimitry Andric };
4534e8d8bef9SDimitry Andric // Source bigger
4535e8d8bef9SDimitry Andric template <typename SourceType, typename TargetType>
4536e8d8bef9SDimitry Andric struct kmp_convert<SourceType, TargetType, false, false, true, false> {
4537e8d8bef9SDimitry Andric   static TargetType to(SourceType src) {
4538e8d8bef9SDimitry Andric     KMP_ASSERT(src >= 0);
4539e8d8bef9SDimitry Andric     KMP_ASSERT(src <= static_cast<SourceType>(
4540e8d8bef9SDimitry Andric                           (std::numeric_limits<TargetType>::max)()));
4541e8d8bef9SDimitry Andric     return (TargetType)src;
4542e8d8bef9SDimitry Andric   }
4543e8d8bef9SDimitry Andric };
4544e8d8bef9SDimitry Andric 
4545e8d8bef9SDimitry Andric // Source unsigned, Target signed
4546e8d8bef9SDimitry Andric // Source smaller
4547e8d8bef9SDimitry Andric template <typename SourceType, typename TargetType>
4548e8d8bef9SDimitry Andric struct kmp_convert<SourceType, TargetType, true, false, false, true> {
4549e8d8bef9SDimitry Andric   static TargetType to(SourceType src) { return (TargetType)src; }
4550e8d8bef9SDimitry Andric };
4551e8d8bef9SDimitry Andric // Source equal
4552e8d8bef9SDimitry Andric template <typename SourceType, typename TargetType>
4553e8d8bef9SDimitry Andric struct kmp_convert<SourceType, TargetType, false, true, false, true> {
4554e8d8bef9SDimitry Andric   static TargetType to(SourceType src) {
4555e8d8bef9SDimitry Andric     KMP_ASSERT(src <= static_cast<SourceType>(
4556e8d8bef9SDimitry Andric                           (std::numeric_limits<TargetType>::max)()));
4557e8d8bef9SDimitry Andric     return (TargetType)src;
4558e8d8bef9SDimitry Andric   }
4559e8d8bef9SDimitry Andric };
4560e8d8bef9SDimitry Andric // Source bigger
4561e8d8bef9SDimitry Andric template <typename SourceType, typename TargetType>
4562e8d8bef9SDimitry Andric struct kmp_convert<SourceType, TargetType, false, false, false, true> {
4563e8d8bef9SDimitry Andric   static TargetType to(SourceType src) {
4564e8d8bef9SDimitry Andric     KMP_ASSERT(src <= static_cast<SourceType>(
4565e8d8bef9SDimitry Andric                           (std::numeric_limits<TargetType>::max)()));
4566e8d8bef9SDimitry Andric     return (TargetType)src;
4567e8d8bef9SDimitry Andric   }
4568e8d8bef9SDimitry Andric };
4569e8d8bef9SDimitry Andric 
4570e8d8bef9SDimitry Andric // Source unsigned, Target unsigned
4571e8d8bef9SDimitry Andric // Source smaller
4572e8d8bef9SDimitry Andric template <typename SourceType, typename TargetType>
4573e8d8bef9SDimitry Andric struct kmp_convert<SourceType, TargetType, true, false, false, false> {
4574e8d8bef9SDimitry Andric   static TargetType to(SourceType src) { return (TargetType)src; }
4575e8d8bef9SDimitry Andric };
4576e8d8bef9SDimitry Andric // Source equal
4577e8d8bef9SDimitry Andric template <typename SourceType, typename TargetType>
4578e8d8bef9SDimitry Andric struct kmp_convert<SourceType, TargetType, false, true, false, false> {
4579e8d8bef9SDimitry Andric   static TargetType to(SourceType src) { return src; }
4580e8d8bef9SDimitry Andric };
4581e8d8bef9SDimitry Andric // Source bigger
4582e8d8bef9SDimitry Andric template <typename SourceType, typename TargetType>
4583e8d8bef9SDimitry Andric struct kmp_convert<SourceType, TargetType, false, false, false, false> {
4584e8d8bef9SDimitry Andric   static TargetType to(SourceType src) {
4585e8d8bef9SDimitry Andric     KMP_ASSERT(src <= static_cast<SourceType>(
4586e8d8bef9SDimitry Andric                           (std::numeric_limits<TargetType>::max)()));
4587e8d8bef9SDimitry Andric     return (TargetType)src;
4588e8d8bef9SDimitry Andric   }
4589e8d8bef9SDimitry Andric };
4590e8d8bef9SDimitry Andric 
4591e8d8bef9SDimitry Andric template <typename T1, typename T2>
4592e8d8bef9SDimitry Andric static inline void __kmp_type_convert(T1 src, T2 *dest) {
4593e8d8bef9SDimitry Andric   *dest = kmp_convert<T1, T2>::to(src);
4594e8d8bef9SDimitry Andric }
4595e8d8bef9SDimitry Andric 
45960b57cec5SDimitry Andric #endif /* KMP_H */
4597