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 #if HWLOC_API_VERSION >= 0x00020000 1040b57cec5SDimitry Andric // hwloc 2.0 changed type of depth of object from unsigned to int 1050b57cec5SDimitry Andric typedef int kmp_hwloc_depth_t; 1060b57cec5SDimitry Andric #else 1070b57cec5SDimitry Andric typedef unsigned int kmp_hwloc_depth_t; 1080b57cec5SDimitry Andric #endif 1090b57cec5SDimitry Andric #endif 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64 1120b57cec5SDimitry Andric #include <xmmintrin.h> 1130b57cec5SDimitry Andric #endif 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric #include "kmp_debug.h" 1160b57cec5SDimitry Andric #include "kmp_lock.h" 1170b57cec5SDimitry Andric #include "kmp_version.h" 1180b57cec5SDimitry Andric #if USE_DEBUGGER 1190b57cec5SDimitry Andric #include "kmp_debugger.h" 1200b57cec5SDimitry Andric #endif 1210b57cec5SDimitry Andric #include "kmp_i18n.h" 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric #define KMP_HANDLE_SIGNALS (KMP_OS_UNIX || KMP_OS_WINDOWS) 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric #include "kmp_wrapper_malloc.h" 1260b57cec5SDimitry Andric #if KMP_OS_UNIX 1270b57cec5SDimitry Andric #include <unistd.h> 1280b57cec5SDimitry Andric #if !defined NSIG && defined _NSIG 1290b57cec5SDimitry Andric #define NSIG _NSIG 1300b57cec5SDimitry Andric #endif 1310b57cec5SDimitry Andric #endif 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric #if KMP_OS_LINUX 1340b57cec5SDimitry Andric #pragma weak clock_gettime 1350b57cec5SDimitry Andric #endif 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric #if OMPT_SUPPORT 1380b57cec5SDimitry Andric #include "ompt-internal.h" 1390b57cec5SDimitry Andric #endif 1400b57cec5SDimitry Andric 141*fe6060f1SDimitry Andric #if OMPD_SUPPORT 142*fe6060f1SDimitry Andric #include "ompd-specific.h" 143*fe6060f1SDimitry Andric #endif 144*fe6060f1SDimitry Andric 145e8d8bef9SDimitry Andric #ifndef UNLIKELY 146e8d8bef9SDimitry Andric #define UNLIKELY(x) (x) 147e8d8bef9SDimitry Andric #endif 148e8d8bef9SDimitry Andric 1490b57cec5SDimitry Andric // Affinity format function 1500b57cec5SDimitry Andric #include "kmp_str.h" 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric // 0 - no fast memory allocation, alignment: 8-byte on x86, 16-byte on x64. 1530b57cec5SDimitry Andric // 3 - fast allocation using sync, non-sync free lists of any size, non-self 1540b57cec5SDimitry Andric // free lists of limited size. 1550b57cec5SDimitry Andric #ifndef USE_FAST_MEMORY 1560b57cec5SDimitry Andric #define USE_FAST_MEMORY 3 1570b57cec5SDimitry Andric #endif 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric #ifndef KMP_NESTED_HOT_TEAMS 1600b57cec5SDimitry Andric #define KMP_NESTED_HOT_TEAMS 0 1610b57cec5SDimitry Andric #define USE_NESTED_HOT_ARG(x) 1620b57cec5SDimitry Andric #else 1630b57cec5SDimitry Andric #if KMP_NESTED_HOT_TEAMS 1640b57cec5SDimitry Andric #define USE_NESTED_HOT_ARG(x) , x 1650b57cec5SDimitry Andric #else 1660b57cec5SDimitry Andric #define USE_NESTED_HOT_ARG(x) 1670b57cec5SDimitry Andric #endif 1680b57cec5SDimitry Andric #endif 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric // Assume using BGET compare_exchange instruction instead of lock by default. 1710b57cec5SDimitry Andric #ifndef USE_CMP_XCHG_FOR_BGET 1720b57cec5SDimitry Andric #define USE_CMP_XCHG_FOR_BGET 1 1730b57cec5SDimitry Andric #endif 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric // Test to see if queuing lock is better than bootstrap lock for bget 1760b57cec5SDimitry Andric // #ifndef USE_QUEUING_LOCK_FOR_BGET 1770b57cec5SDimitry Andric // #define USE_QUEUING_LOCK_FOR_BGET 1780b57cec5SDimitry Andric // #endif 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric #define KMP_NSEC_PER_SEC 1000000000L 1810b57cec5SDimitry Andric #define KMP_USEC_PER_SEC 1000000L 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric /*! 1840b57cec5SDimitry Andric @ingroup BASIC_TYPES 1850b57cec5SDimitry Andric @{ 1860b57cec5SDimitry Andric */ 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andric /*! 1890b57cec5SDimitry Andric Values for bit flags used in the ident_t to describe the fields. 1900b57cec5SDimitry Andric */ 1910b57cec5SDimitry Andric enum { 1920b57cec5SDimitry Andric /*! Use trampoline for internal microtasks */ 1930b57cec5SDimitry Andric KMP_IDENT_IMB = 0x01, 1940b57cec5SDimitry Andric /*! Use c-style ident structure */ 1950b57cec5SDimitry Andric KMP_IDENT_KMPC = 0x02, 1960b57cec5SDimitry Andric /* 0x04 is no longer used */ 1970b57cec5SDimitry Andric /*! Entry point generated by auto-parallelization */ 1980b57cec5SDimitry Andric KMP_IDENT_AUTOPAR = 0x08, 1990b57cec5SDimitry Andric /*! Compiler generates atomic reduction option for kmpc_reduce* */ 2000b57cec5SDimitry Andric KMP_IDENT_ATOMIC_REDUCE = 0x10, 2010b57cec5SDimitry Andric /*! To mark a 'barrier' directive in user code */ 2020b57cec5SDimitry Andric KMP_IDENT_BARRIER_EXPL = 0x20, 2030b57cec5SDimitry Andric /*! To Mark implicit barriers. */ 2040b57cec5SDimitry Andric KMP_IDENT_BARRIER_IMPL = 0x0040, 2050b57cec5SDimitry Andric KMP_IDENT_BARRIER_IMPL_MASK = 0x01C0, 2060b57cec5SDimitry Andric KMP_IDENT_BARRIER_IMPL_FOR = 0x0040, 2070b57cec5SDimitry Andric KMP_IDENT_BARRIER_IMPL_SECTIONS = 0x00C0, 2080b57cec5SDimitry Andric 2090b57cec5SDimitry Andric KMP_IDENT_BARRIER_IMPL_SINGLE = 0x0140, 2100b57cec5SDimitry Andric KMP_IDENT_BARRIER_IMPL_WORKSHARE = 0x01C0, 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric /*! To mark a static loop in OMPT callbacks */ 2130b57cec5SDimitry Andric KMP_IDENT_WORK_LOOP = 0x200, 2140b57cec5SDimitry Andric /*! To mark a sections directive in OMPT callbacks */ 2150b57cec5SDimitry Andric KMP_IDENT_WORK_SECTIONS = 0x400, 216480093f4SDimitry Andric /*! To mark a distribute construct in OMPT callbacks */ 2170b57cec5SDimitry Andric KMP_IDENT_WORK_DISTRIBUTE = 0x800, 2180b57cec5SDimitry Andric /*! Atomic hint; bottom four bits as omp_sync_hint_t. Top four reserved and 2190b57cec5SDimitry Andric not currently used. If one day we need more bits, then we can use 2200b57cec5SDimitry Andric an invalid combination of hints to mean that another, larger field 2210b57cec5SDimitry Andric should be used in a different flag. */ 2220b57cec5SDimitry Andric KMP_IDENT_ATOMIC_HINT_MASK = 0xFF0000, 2230b57cec5SDimitry Andric KMP_IDENT_ATOMIC_HINT_UNCONTENDED = 0x010000, 2240b57cec5SDimitry Andric KMP_IDENT_ATOMIC_HINT_CONTENDED = 0x020000, 2250b57cec5SDimitry Andric KMP_IDENT_ATOMIC_HINT_NONSPECULATIVE = 0x040000, 2260b57cec5SDimitry Andric KMP_IDENT_ATOMIC_HINT_SPECULATIVE = 0x080000, 227e8d8bef9SDimitry Andric KMP_IDENT_OPENMP_SPEC_VERSION_MASK = 0xFF000000 2280b57cec5SDimitry Andric }; 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric /*! 2310b57cec5SDimitry Andric * The ident structure that describes a source location. 2320b57cec5SDimitry Andric */ 2330b57cec5SDimitry Andric typedef struct ident { 2340b57cec5SDimitry Andric kmp_int32 reserved_1; /**< might be used in Fortran; see above */ 2350b57cec5SDimitry Andric kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags; KMP_IDENT_KMPC 2360b57cec5SDimitry Andric identifies this union member */ 2370b57cec5SDimitry Andric kmp_int32 reserved_2; /**< not really used in Fortran any more; see above */ 2380b57cec5SDimitry Andric #if USE_ITT_BUILD 2390b57cec5SDimitry Andric /* but currently used for storing region-specific ITT */ 2400b57cec5SDimitry Andric /* contextual information. */ 2410b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 2420b57cec5SDimitry Andric kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for C++ */ 2430b57cec5SDimitry Andric char const *psource; /**< String describing the source location. 2440b57cec5SDimitry Andric The string is composed of semi-colon separated fields 2450b57cec5SDimitry Andric which describe the source file, the function and a pair 2460b57cec5SDimitry Andric of line numbers that delimit the construct. */ 247e8d8bef9SDimitry Andric // Returns the OpenMP version in form major*10+minor (e.g., 50 for 5.0) 248e8d8bef9SDimitry Andric kmp_int32 get_openmp_version() { 249e8d8bef9SDimitry Andric return (((flags & KMP_IDENT_OPENMP_SPEC_VERSION_MASK) >> 24) & 0xFF); 250e8d8bef9SDimitry Andric } 2510b57cec5SDimitry Andric } ident_t; 2520b57cec5SDimitry Andric /*! 2530b57cec5SDimitry Andric @} 2540b57cec5SDimitry Andric */ 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric // Some forward declarations. 2570b57cec5SDimitry Andric typedef union kmp_team kmp_team_t; 2580b57cec5SDimitry Andric typedef struct kmp_taskdata kmp_taskdata_t; 2590b57cec5SDimitry Andric typedef union kmp_task_team kmp_task_team_t; 2600b57cec5SDimitry Andric typedef union kmp_team kmp_team_p; 2610b57cec5SDimitry Andric typedef union kmp_info kmp_info_p; 2620b57cec5SDimitry Andric typedef union kmp_root kmp_root_p; 2630b57cec5SDimitry Andric 264e8d8bef9SDimitry Andric template <bool C = false, bool S = true> class kmp_flag_32; 265e8d8bef9SDimitry Andric template <bool C = false, bool S = true> class kmp_flag_64; 266e8d8bef9SDimitry Andric class kmp_flag_oncore; 267e8d8bef9SDimitry Andric 2680b57cec5SDimitry Andric #ifdef __cplusplus 2690b57cec5SDimitry Andric extern "C" { 2700b57cec5SDimitry Andric #endif 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */ 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric /* Pack two 32-bit signed integers into a 64-bit signed integer */ 2750b57cec5SDimitry Andric /* ToDo: Fix word ordering for big-endian machines. */ 2760b57cec5SDimitry Andric #define KMP_PACK_64(HIGH_32, LOW_32) \ 2770b57cec5SDimitry Andric ((kmp_int64)((((kmp_uint64)(HIGH_32)) << 32) | (kmp_uint64)(LOW_32))) 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric // Generic string manipulation macros. Assume that _x is of type char * 2800b57cec5SDimitry Andric #define SKIP_WS(_x) \ 2810b57cec5SDimitry Andric { \ 2820b57cec5SDimitry Andric while (*(_x) == ' ' || *(_x) == '\t') \ 2830b57cec5SDimitry Andric (_x)++; \ 2840b57cec5SDimitry Andric } 2850b57cec5SDimitry Andric #define SKIP_DIGITS(_x) \ 2860b57cec5SDimitry Andric { \ 2870b57cec5SDimitry Andric while (*(_x) >= '0' && *(_x) <= '9') \ 2880b57cec5SDimitry Andric (_x)++; \ 2890b57cec5SDimitry Andric } 2900b57cec5SDimitry Andric #define SKIP_TOKEN(_x) \ 2910b57cec5SDimitry Andric { \ 2920b57cec5SDimitry Andric while ((*(_x) >= '0' && *(_x) <= '9') || (*(_x) >= 'a' && *(_x) <= 'z') || \ 2930b57cec5SDimitry Andric (*(_x) >= 'A' && *(_x) <= 'Z') || *(_x) == '_') \ 2940b57cec5SDimitry Andric (_x)++; \ 2950b57cec5SDimitry Andric } 2960b57cec5SDimitry Andric #define SKIP_TO(_x, _c) \ 2970b57cec5SDimitry Andric { \ 2980b57cec5SDimitry Andric while (*(_x) != '\0' && *(_x) != (_c)) \ 2990b57cec5SDimitry Andric (_x)++; \ 3000b57cec5SDimitry Andric } 3010b57cec5SDimitry Andric 3020b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */ 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andric #define KMP_MAX(x, y) ((x) > (y) ? (x) : (y)) 3050b57cec5SDimitry Andric #define KMP_MIN(x, y) ((x) < (y) ? (x) : (y)) 3060b57cec5SDimitry Andric 3070b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */ 3080b57cec5SDimitry Andric /* Enumeration types */ 3090b57cec5SDimitry Andric 3100b57cec5SDimitry Andric enum kmp_state_timer { 3110b57cec5SDimitry Andric ts_stop, 3120b57cec5SDimitry Andric ts_start, 3130b57cec5SDimitry Andric ts_pause, 3140b57cec5SDimitry Andric 3150b57cec5SDimitry Andric ts_last_state 3160b57cec5SDimitry Andric }; 3170b57cec5SDimitry Andric 3180b57cec5SDimitry Andric enum dynamic_mode { 3190b57cec5SDimitry Andric dynamic_default, 3200b57cec5SDimitry Andric #ifdef USE_LOAD_BALANCE 3210b57cec5SDimitry Andric dynamic_load_balance, 3220b57cec5SDimitry Andric #endif /* USE_LOAD_BALANCE */ 3230b57cec5SDimitry Andric dynamic_random, 3240b57cec5SDimitry Andric dynamic_thread_limit, 3250b57cec5SDimitry Andric dynamic_max 3260b57cec5SDimitry Andric }; 3270b57cec5SDimitry Andric 3280b57cec5SDimitry Andric /* external schedule constants, duplicate enum omp_sched in omp.h in order to 3290b57cec5SDimitry Andric * not include it here */ 3300b57cec5SDimitry Andric #ifndef KMP_SCHED_TYPE_DEFINED 3310b57cec5SDimitry Andric #define KMP_SCHED_TYPE_DEFINED 3320b57cec5SDimitry Andric typedef enum kmp_sched { 3330b57cec5SDimitry Andric kmp_sched_lower = 0, // lower and upper bounds are for routine parameter check 3340b57cec5SDimitry Andric // Note: need to adjust __kmp_sch_map global array in case enum is changed 3350b57cec5SDimitry Andric kmp_sched_static = 1, // mapped to kmp_sch_static_chunked (33) 3360b57cec5SDimitry Andric kmp_sched_dynamic = 2, // mapped to kmp_sch_dynamic_chunked (35) 3370b57cec5SDimitry Andric kmp_sched_guided = 3, // mapped to kmp_sch_guided_chunked (36) 3380b57cec5SDimitry Andric kmp_sched_auto = 4, // mapped to kmp_sch_auto (38) 3390b57cec5SDimitry Andric kmp_sched_upper_std = 5, // upper bound for standard schedules 3400b57cec5SDimitry Andric kmp_sched_lower_ext = 100, // lower bound of Intel extension schedules 3410b57cec5SDimitry Andric kmp_sched_trapezoidal = 101, // mapped to kmp_sch_trapezoidal (39) 3420b57cec5SDimitry Andric #if KMP_STATIC_STEAL_ENABLED 3430b57cec5SDimitry Andric kmp_sched_static_steal = 102, // mapped to kmp_sch_static_steal (44) 3440b57cec5SDimitry Andric #endif 3450b57cec5SDimitry Andric kmp_sched_upper, 3460b57cec5SDimitry Andric kmp_sched_default = kmp_sched_static, // default scheduling 3470b57cec5SDimitry Andric kmp_sched_monotonic = 0x80000000 3480b57cec5SDimitry Andric } kmp_sched_t; 3490b57cec5SDimitry Andric #endif 3500b57cec5SDimitry Andric 3510b57cec5SDimitry Andric /*! 3520b57cec5SDimitry Andric @ingroup WORK_SHARING 3530b57cec5SDimitry Andric * Describes the loop schedule to be used for a parallel for loop. 3540b57cec5SDimitry Andric */ 3550b57cec5SDimitry Andric enum sched_type : kmp_int32 { 3560b57cec5SDimitry Andric kmp_sch_lower = 32, /**< lower bound for unordered values */ 3570b57cec5SDimitry Andric kmp_sch_static_chunked = 33, 3580b57cec5SDimitry Andric kmp_sch_static = 34, /**< static unspecialized */ 3590b57cec5SDimitry Andric kmp_sch_dynamic_chunked = 35, 3600b57cec5SDimitry Andric kmp_sch_guided_chunked = 36, /**< guided unspecialized */ 3610b57cec5SDimitry Andric kmp_sch_runtime = 37, 3620b57cec5SDimitry Andric kmp_sch_auto = 38, /**< auto */ 3630b57cec5SDimitry Andric kmp_sch_trapezoidal = 39, 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric /* accessible only through KMP_SCHEDULE environment variable */ 3660b57cec5SDimitry Andric kmp_sch_static_greedy = 40, 3670b57cec5SDimitry Andric kmp_sch_static_balanced = 41, 3680b57cec5SDimitry Andric /* accessible only through KMP_SCHEDULE environment variable */ 3690b57cec5SDimitry Andric kmp_sch_guided_iterative_chunked = 42, 3700b57cec5SDimitry Andric kmp_sch_guided_analytical_chunked = 43, 3710b57cec5SDimitry Andric /* accessible only through KMP_SCHEDULE environment variable */ 3720b57cec5SDimitry Andric kmp_sch_static_steal = 44, 3730b57cec5SDimitry Andric 3740b57cec5SDimitry Andric /* static with chunk adjustment (e.g., simd) */ 3750b57cec5SDimitry Andric kmp_sch_static_balanced_chunked = 45, 3760b57cec5SDimitry Andric kmp_sch_guided_simd = 46, /**< guided with chunk adjustment */ 3770b57cec5SDimitry Andric kmp_sch_runtime_simd = 47, /**< runtime with chunk adjustment */ 3780b57cec5SDimitry Andric 3790b57cec5SDimitry Andric /* accessible only through KMP_SCHEDULE environment variable */ 3800b57cec5SDimitry Andric kmp_sch_upper, /**< upper bound for unordered values */ 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric kmp_ord_lower = 64, /**< lower bound for ordered values, must be power of 2 */ 3830b57cec5SDimitry Andric kmp_ord_static_chunked = 65, 3840b57cec5SDimitry Andric kmp_ord_static = 66, /**< ordered static unspecialized */ 3850b57cec5SDimitry Andric kmp_ord_dynamic_chunked = 67, 3860b57cec5SDimitry Andric kmp_ord_guided_chunked = 68, 3870b57cec5SDimitry Andric kmp_ord_runtime = 69, 3880b57cec5SDimitry Andric kmp_ord_auto = 70, /**< ordered auto */ 3890b57cec5SDimitry Andric kmp_ord_trapezoidal = 71, 3900b57cec5SDimitry Andric kmp_ord_upper, /**< upper bound for ordered values */ 3910b57cec5SDimitry Andric 3920b57cec5SDimitry Andric /* Schedules for Distribute construct */ 3930b57cec5SDimitry Andric kmp_distribute_static_chunked = 91, /**< distribute static chunked */ 3940b57cec5SDimitry Andric kmp_distribute_static = 92, /**< distribute static unspecialized */ 3950b57cec5SDimitry Andric 3960b57cec5SDimitry Andric /* For the "nomerge" versions, kmp_dispatch_next*() will always return a 3970b57cec5SDimitry Andric single iteration/chunk, even if the loop is serialized. For the schedule 3980b57cec5SDimitry Andric types listed above, the entire iteration vector is returned if the loop is 3990b57cec5SDimitry Andric serialized. This doesn't work for gcc/gcomp sections. */ 4000b57cec5SDimitry Andric kmp_nm_lower = 160, /**< lower bound for nomerge values */ 4010b57cec5SDimitry Andric 4020b57cec5SDimitry Andric kmp_nm_static_chunked = 4030b57cec5SDimitry Andric (kmp_sch_static_chunked - kmp_sch_lower + kmp_nm_lower), 4040b57cec5SDimitry Andric kmp_nm_static = 162, /**< static unspecialized */ 4050b57cec5SDimitry Andric kmp_nm_dynamic_chunked = 163, 4060b57cec5SDimitry Andric kmp_nm_guided_chunked = 164, /**< guided unspecialized */ 4070b57cec5SDimitry Andric kmp_nm_runtime = 165, 4080b57cec5SDimitry Andric kmp_nm_auto = 166, /**< auto */ 4090b57cec5SDimitry Andric kmp_nm_trapezoidal = 167, 4100b57cec5SDimitry Andric 4110b57cec5SDimitry Andric /* accessible only through KMP_SCHEDULE environment variable */ 4120b57cec5SDimitry Andric kmp_nm_static_greedy = 168, 4130b57cec5SDimitry Andric kmp_nm_static_balanced = 169, 4140b57cec5SDimitry Andric /* accessible only through KMP_SCHEDULE environment variable */ 4150b57cec5SDimitry Andric kmp_nm_guided_iterative_chunked = 170, 4160b57cec5SDimitry Andric kmp_nm_guided_analytical_chunked = 171, 4170b57cec5SDimitry Andric kmp_nm_static_steal = 4180b57cec5SDimitry Andric 172, /* accessible only through OMP_SCHEDULE environment variable */ 4190b57cec5SDimitry Andric 4200b57cec5SDimitry Andric kmp_nm_ord_static_chunked = 193, 4210b57cec5SDimitry Andric kmp_nm_ord_static = 194, /**< ordered static unspecialized */ 4220b57cec5SDimitry Andric kmp_nm_ord_dynamic_chunked = 195, 4230b57cec5SDimitry Andric kmp_nm_ord_guided_chunked = 196, 4240b57cec5SDimitry Andric kmp_nm_ord_runtime = 197, 4250b57cec5SDimitry Andric kmp_nm_ord_auto = 198, /**< auto */ 4260b57cec5SDimitry Andric kmp_nm_ord_trapezoidal = 199, 4270b57cec5SDimitry Andric kmp_nm_upper, /**< upper bound for nomerge values */ 4280b57cec5SDimitry Andric 4290b57cec5SDimitry Andric /* Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers. Since 4300b57cec5SDimitry Andric we need to distinguish the three possible cases (no modifier, monotonic 4310b57cec5SDimitry Andric modifier, nonmonotonic modifier), we need separate bits for each modifier. 4320b57cec5SDimitry Andric The absence of monotonic does not imply nonmonotonic, especially since 4.5 4330b57cec5SDimitry Andric says that the behaviour of the "no modifier" case is implementation defined 4340b57cec5SDimitry Andric in 4.5, but will become "nonmonotonic" in 5.0. 4350b57cec5SDimitry Andric 4360b57cec5SDimitry Andric Since we're passing a full 32 bit value, we can use a couple of high bits 4370b57cec5SDimitry Andric for these flags; out of paranoia we avoid the sign bit. 4380b57cec5SDimitry Andric 4390b57cec5SDimitry Andric These modifiers can be or-ed into non-static schedules by the compiler to 4400b57cec5SDimitry Andric pass the additional information. They will be stripped early in the 4410b57cec5SDimitry Andric processing in __kmp_dispatch_init when setting up schedules, so most of the 4420b57cec5SDimitry Andric code won't ever see schedules with these bits set. */ 4430b57cec5SDimitry Andric kmp_sch_modifier_monotonic = 4440b57cec5SDimitry Andric (1 << 29), /**< Set if the monotonic schedule modifier was present */ 4450b57cec5SDimitry Andric kmp_sch_modifier_nonmonotonic = 4460b57cec5SDimitry Andric (1 << 30), /**< Set if the nonmonotonic schedule modifier was present */ 4470b57cec5SDimitry Andric 4480b57cec5SDimitry Andric #define SCHEDULE_WITHOUT_MODIFIERS(s) \ 4490b57cec5SDimitry Andric (enum sched_type)( \ 4500b57cec5SDimitry Andric (s) & ~(kmp_sch_modifier_nonmonotonic | kmp_sch_modifier_monotonic)) 4510b57cec5SDimitry Andric #define SCHEDULE_HAS_MONOTONIC(s) (((s)&kmp_sch_modifier_monotonic) != 0) 4520b57cec5SDimitry Andric #define SCHEDULE_HAS_NONMONOTONIC(s) (((s)&kmp_sch_modifier_nonmonotonic) != 0) 4530b57cec5SDimitry Andric #define SCHEDULE_HAS_NO_MODIFIERS(s) \ 4540b57cec5SDimitry Andric (((s) & (kmp_sch_modifier_nonmonotonic | kmp_sch_modifier_monotonic)) == 0) 4550b57cec5SDimitry Andric #define SCHEDULE_GET_MODIFIERS(s) \ 4560b57cec5SDimitry Andric ((enum sched_type)( \ 4570b57cec5SDimitry Andric (s) & (kmp_sch_modifier_nonmonotonic | kmp_sch_modifier_monotonic))) 4580b57cec5SDimitry Andric #define SCHEDULE_SET_MODIFIERS(s, m) \ 4590b57cec5SDimitry Andric (s = (enum sched_type)((kmp_int32)s | (kmp_int32)m)) 4600b57cec5SDimitry Andric #define SCHEDULE_NONMONOTONIC 0 4610b57cec5SDimitry Andric #define SCHEDULE_MONOTONIC 1 4620b57cec5SDimitry Andric 4630b57cec5SDimitry Andric kmp_sch_default = kmp_sch_static /**< default scheduling algorithm */ 4640b57cec5SDimitry Andric }; 4650b57cec5SDimitry Andric 4660b57cec5SDimitry Andric // Apply modifiers on internal kind to standard kind 4670b57cec5SDimitry Andric static inline void 4680b57cec5SDimitry Andric __kmp_sched_apply_mods_stdkind(kmp_sched_t *kind, 4690b57cec5SDimitry Andric enum sched_type internal_kind) { 4700b57cec5SDimitry Andric if (SCHEDULE_HAS_MONOTONIC(internal_kind)) { 4710b57cec5SDimitry Andric *kind = (kmp_sched_t)((int)*kind | (int)kmp_sched_monotonic); 4720b57cec5SDimitry Andric } 4730b57cec5SDimitry Andric } 4740b57cec5SDimitry Andric 4750b57cec5SDimitry Andric // Apply modifiers on standard kind to internal kind 4760b57cec5SDimitry Andric static inline void 4770b57cec5SDimitry Andric __kmp_sched_apply_mods_intkind(kmp_sched_t kind, 4780b57cec5SDimitry Andric enum sched_type *internal_kind) { 4790b57cec5SDimitry Andric if ((int)kind & (int)kmp_sched_monotonic) { 4800b57cec5SDimitry Andric *internal_kind = (enum sched_type)((int)*internal_kind | 4810b57cec5SDimitry Andric (int)kmp_sch_modifier_monotonic); 4820b57cec5SDimitry Andric } 4830b57cec5SDimitry Andric } 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric // Get standard schedule without modifiers 4860b57cec5SDimitry Andric static inline kmp_sched_t __kmp_sched_without_mods(kmp_sched_t kind) { 4870b57cec5SDimitry Andric return (kmp_sched_t)((int)kind & ~((int)kmp_sched_monotonic)); 4880b57cec5SDimitry Andric } 4890b57cec5SDimitry Andric 4900b57cec5SDimitry Andric /* Type to keep runtime schedule set via OMP_SCHEDULE or omp_set_schedule() */ 4910b57cec5SDimitry Andric typedef union kmp_r_sched { 4920b57cec5SDimitry Andric struct { 4930b57cec5SDimitry Andric enum sched_type r_sched_type; 4940b57cec5SDimitry Andric int chunk; 4950b57cec5SDimitry Andric }; 4960b57cec5SDimitry Andric kmp_int64 sched; 4970b57cec5SDimitry Andric } kmp_r_sched_t; 4980b57cec5SDimitry Andric 4990b57cec5SDimitry Andric extern enum sched_type __kmp_sch_map[]; // map OMP 3.0 schedule types with our 5000b57cec5SDimitry Andric // internal schedule types 5010b57cec5SDimitry Andric 5020b57cec5SDimitry Andric enum library_type { 5030b57cec5SDimitry Andric library_none, 5040b57cec5SDimitry Andric library_serial, 5050b57cec5SDimitry Andric library_turnaround, 5060b57cec5SDimitry Andric library_throughput 5070b57cec5SDimitry Andric }; 5080b57cec5SDimitry Andric 5090b57cec5SDimitry Andric #if KMP_OS_LINUX 5100b57cec5SDimitry Andric enum clock_function_type { 5110b57cec5SDimitry Andric clock_function_gettimeofday, 5120b57cec5SDimitry Andric clock_function_clock_gettime 5130b57cec5SDimitry Andric }; 5140b57cec5SDimitry Andric #endif /* KMP_OS_LINUX */ 5150b57cec5SDimitry Andric 5160b57cec5SDimitry Andric #if KMP_MIC_SUPPORTED 5170b57cec5SDimitry Andric enum mic_type { non_mic, mic1, mic2, mic3, dummy }; 5180b57cec5SDimitry Andric #endif 5190b57cec5SDimitry Andric 5200b57cec5SDimitry Andric /* -- fast reduction stuff ------------------------------------------------ */ 5210b57cec5SDimitry Andric 5220b57cec5SDimitry Andric #undef KMP_FAST_REDUCTION_BARRIER 5230b57cec5SDimitry Andric #define KMP_FAST_REDUCTION_BARRIER 1 5240b57cec5SDimitry Andric 5250b57cec5SDimitry Andric #undef KMP_FAST_REDUCTION_CORE_DUO 5260b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64 5270b57cec5SDimitry Andric #define KMP_FAST_REDUCTION_CORE_DUO 1 5280b57cec5SDimitry Andric #endif 5290b57cec5SDimitry Andric 5300b57cec5SDimitry Andric enum _reduction_method { 5310b57cec5SDimitry Andric reduction_method_not_defined = 0, 5320b57cec5SDimitry Andric critical_reduce_block = (1 << 8), 5330b57cec5SDimitry Andric atomic_reduce_block = (2 << 8), 5340b57cec5SDimitry Andric tree_reduce_block = (3 << 8), 5350b57cec5SDimitry Andric empty_reduce_block = (4 << 8) 5360b57cec5SDimitry Andric }; 5370b57cec5SDimitry Andric 5380b57cec5SDimitry Andric // Description of the packed_reduction_method variable: 5390b57cec5SDimitry Andric // The packed_reduction_method variable consists of two enum types variables 5400b57cec5SDimitry Andric // that are packed together into 0-th byte and 1-st byte: 5410b57cec5SDimitry Andric // 0: (packed_reduction_method & 0x000000FF) is a 'enum barrier_type' value of 5420b57cec5SDimitry Andric // barrier that will be used in fast reduction: bs_plain_barrier or 5430b57cec5SDimitry Andric // bs_reduction_barrier 5440b57cec5SDimitry Andric // 1: (packed_reduction_method & 0x0000FF00) is a reduction method that will 5450b57cec5SDimitry Andric // be used in fast reduction; 5460b57cec5SDimitry Andric // Reduction method is of 'enum _reduction_method' type and it's defined the way 5470b57cec5SDimitry Andric // so that the bits of 0-th byte are empty, so no need to execute a shift 5480b57cec5SDimitry Andric // instruction while packing/unpacking 5490b57cec5SDimitry Andric 5500b57cec5SDimitry Andric #if KMP_FAST_REDUCTION_BARRIER 5510b57cec5SDimitry Andric #define PACK_REDUCTION_METHOD_AND_BARRIER(reduction_method, barrier_type) \ 5520b57cec5SDimitry Andric ((reduction_method) | (barrier_type)) 5530b57cec5SDimitry Andric 5540b57cec5SDimitry Andric #define UNPACK_REDUCTION_METHOD(packed_reduction_method) \ 5550b57cec5SDimitry Andric ((enum _reduction_method)((packed_reduction_method) & (0x0000FF00))) 5560b57cec5SDimitry Andric 5570b57cec5SDimitry Andric #define UNPACK_REDUCTION_BARRIER(packed_reduction_method) \ 5580b57cec5SDimitry Andric ((enum barrier_type)((packed_reduction_method) & (0x000000FF))) 5590b57cec5SDimitry Andric #else 5600b57cec5SDimitry Andric #define PACK_REDUCTION_METHOD_AND_BARRIER(reduction_method, barrier_type) \ 5610b57cec5SDimitry Andric (reduction_method) 5620b57cec5SDimitry Andric 5630b57cec5SDimitry Andric #define UNPACK_REDUCTION_METHOD(packed_reduction_method) \ 5640b57cec5SDimitry Andric (packed_reduction_method) 5650b57cec5SDimitry Andric 5660b57cec5SDimitry Andric #define UNPACK_REDUCTION_BARRIER(packed_reduction_method) (bs_plain_barrier) 5670b57cec5SDimitry Andric #endif 5680b57cec5SDimitry Andric 5690b57cec5SDimitry Andric #define TEST_REDUCTION_METHOD(packed_reduction_method, which_reduction_block) \ 5700b57cec5SDimitry Andric ((UNPACK_REDUCTION_METHOD(packed_reduction_method)) == \ 5710b57cec5SDimitry Andric (which_reduction_block)) 5720b57cec5SDimitry Andric 5730b57cec5SDimitry Andric #if KMP_FAST_REDUCTION_BARRIER 5740b57cec5SDimitry Andric #define TREE_REDUCE_BLOCK_WITH_REDUCTION_BARRIER \ 5750b57cec5SDimitry Andric (PACK_REDUCTION_METHOD_AND_BARRIER(tree_reduce_block, bs_reduction_barrier)) 5760b57cec5SDimitry Andric 5770b57cec5SDimitry Andric #define TREE_REDUCE_BLOCK_WITH_PLAIN_BARRIER \ 5780b57cec5SDimitry Andric (PACK_REDUCTION_METHOD_AND_BARRIER(tree_reduce_block, bs_plain_barrier)) 5790b57cec5SDimitry Andric #endif 5800b57cec5SDimitry Andric 5810b57cec5SDimitry Andric typedef int PACKED_REDUCTION_METHOD_T; 5820b57cec5SDimitry Andric 5830b57cec5SDimitry Andric /* -- end of fast reduction stuff ----------------------------------------- */ 5840b57cec5SDimitry Andric 5850b57cec5SDimitry Andric #if KMP_OS_WINDOWS 5860b57cec5SDimitry Andric #define USE_CBLKDATA 5870b57cec5SDimitry Andric #if KMP_MSVC_COMPAT 5880b57cec5SDimitry Andric #pragma warning(push) 5890b57cec5SDimitry Andric #pragma warning(disable : 271 310) 5900b57cec5SDimitry Andric #endif 5910b57cec5SDimitry Andric #include <windows.h> 5920b57cec5SDimitry Andric #if KMP_MSVC_COMPAT 5930b57cec5SDimitry Andric #pragma warning(pop) 5940b57cec5SDimitry Andric #endif 5950b57cec5SDimitry Andric #endif 5960b57cec5SDimitry Andric 5970b57cec5SDimitry Andric #if KMP_OS_UNIX 5980b57cec5SDimitry Andric #include <dlfcn.h> 5990b57cec5SDimitry Andric #include <pthread.h> 6000b57cec5SDimitry Andric #endif 6010b57cec5SDimitry Andric 602*fe6060f1SDimitry Andric enum kmp_hw_t : int { 603*fe6060f1SDimitry Andric KMP_HW_UNKNOWN = -1, 604*fe6060f1SDimitry Andric KMP_HW_SOCKET = 0, 605*fe6060f1SDimitry Andric KMP_HW_PROC_GROUP, 606*fe6060f1SDimitry Andric KMP_HW_NUMA, 607*fe6060f1SDimitry Andric KMP_HW_DIE, 608*fe6060f1SDimitry Andric KMP_HW_LLC, 609*fe6060f1SDimitry Andric KMP_HW_L3, 610*fe6060f1SDimitry Andric KMP_HW_TILE, 611*fe6060f1SDimitry Andric KMP_HW_MODULE, 612*fe6060f1SDimitry Andric KMP_HW_L2, 613*fe6060f1SDimitry Andric KMP_HW_L1, 614*fe6060f1SDimitry Andric KMP_HW_CORE, 615*fe6060f1SDimitry Andric KMP_HW_THREAD, 616*fe6060f1SDimitry Andric KMP_HW_LAST 617*fe6060f1SDimitry Andric }; 618*fe6060f1SDimitry Andric 619*fe6060f1SDimitry Andric #define KMP_DEBUG_ASSERT_VALID_HW_TYPE(type) \ 620*fe6060f1SDimitry Andric KMP_DEBUG_ASSERT(type >= (kmp_hw_t)0 && type < KMP_HW_LAST) 621*fe6060f1SDimitry Andric #define KMP_ASSERT_VALID_HW_TYPE(type) \ 622*fe6060f1SDimitry Andric KMP_ASSERT(type >= (kmp_hw_t)0 && type < KMP_HW_LAST) 623*fe6060f1SDimitry Andric 624*fe6060f1SDimitry Andric #define KMP_FOREACH_HW_TYPE(type) \ 625*fe6060f1SDimitry Andric for (kmp_hw_t type = (kmp_hw_t)0; type < KMP_HW_LAST; \ 626*fe6060f1SDimitry Andric type = (kmp_hw_t)((int)type + 1)) 627*fe6060f1SDimitry Andric 628*fe6060f1SDimitry Andric const char *__kmp_hw_get_keyword(kmp_hw_t type, bool plural = false); 629*fe6060f1SDimitry Andric const char *__kmp_hw_get_catalog_string(kmp_hw_t type, bool plural = false); 630*fe6060f1SDimitry Andric 6310b57cec5SDimitry Andric /* Only Linux* OS and Windows* OS support thread affinity. */ 6320b57cec5SDimitry Andric #if KMP_AFFINITY_SUPPORTED 6330b57cec5SDimitry Andric 6340b57cec5SDimitry Andric // GROUP_AFFINITY is already defined for _MSC_VER>=1600 (VS2010 and later). 6350b57cec5SDimitry Andric #if KMP_OS_WINDOWS 6360b57cec5SDimitry Andric #if _MSC_VER < 1600 && KMP_MSVC_COMPAT 6370b57cec5SDimitry Andric typedef struct GROUP_AFFINITY { 6380b57cec5SDimitry Andric KAFFINITY Mask; 6390b57cec5SDimitry Andric WORD Group; 6400b57cec5SDimitry Andric WORD Reserved[3]; 6410b57cec5SDimitry Andric } GROUP_AFFINITY; 6420b57cec5SDimitry Andric #endif /* _MSC_VER < 1600 */ 6430b57cec5SDimitry Andric #if KMP_GROUP_AFFINITY 6440b57cec5SDimitry Andric extern int __kmp_num_proc_groups; 6450b57cec5SDimitry Andric #else 6460b57cec5SDimitry Andric static const int __kmp_num_proc_groups = 1; 6470b57cec5SDimitry Andric #endif /* KMP_GROUP_AFFINITY */ 6480b57cec5SDimitry Andric typedef DWORD (*kmp_GetActiveProcessorCount_t)(WORD); 6490b57cec5SDimitry Andric extern kmp_GetActiveProcessorCount_t __kmp_GetActiveProcessorCount; 6500b57cec5SDimitry Andric 6510b57cec5SDimitry Andric typedef WORD (*kmp_GetActiveProcessorGroupCount_t)(void); 6520b57cec5SDimitry Andric extern kmp_GetActiveProcessorGroupCount_t __kmp_GetActiveProcessorGroupCount; 6530b57cec5SDimitry Andric 6540b57cec5SDimitry Andric typedef BOOL (*kmp_GetThreadGroupAffinity_t)(HANDLE, GROUP_AFFINITY *); 6550b57cec5SDimitry Andric extern kmp_GetThreadGroupAffinity_t __kmp_GetThreadGroupAffinity; 6560b57cec5SDimitry Andric 6570b57cec5SDimitry Andric typedef BOOL (*kmp_SetThreadGroupAffinity_t)(HANDLE, const GROUP_AFFINITY *, 6580b57cec5SDimitry Andric GROUP_AFFINITY *); 6590b57cec5SDimitry Andric extern kmp_SetThreadGroupAffinity_t __kmp_SetThreadGroupAffinity; 6600b57cec5SDimitry Andric #endif /* KMP_OS_WINDOWS */ 6610b57cec5SDimitry Andric 6620b57cec5SDimitry Andric #if KMP_USE_HWLOC 6630b57cec5SDimitry Andric extern hwloc_topology_t __kmp_hwloc_topology; 6640b57cec5SDimitry Andric extern int __kmp_hwloc_error; 6650b57cec5SDimitry Andric #endif 6660b57cec5SDimitry Andric 6670b57cec5SDimitry Andric extern size_t __kmp_affin_mask_size; 6680b57cec5SDimitry Andric #define KMP_AFFINITY_CAPABLE() (__kmp_affin_mask_size > 0) 6690b57cec5SDimitry Andric #define KMP_AFFINITY_DISABLE() (__kmp_affin_mask_size = 0) 6700b57cec5SDimitry Andric #define KMP_AFFINITY_ENABLE(mask_size) (__kmp_affin_mask_size = mask_size) 6710b57cec5SDimitry Andric #define KMP_CPU_SET_ITERATE(i, mask) \ 6720b57cec5SDimitry Andric for (i = (mask)->begin(); (int)i != (mask)->end(); i = (mask)->next(i)) 6730b57cec5SDimitry Andric #define KMP_CPU_SET(i, mask) (mask)->set(i) 6740b57cec5SDimitry Andric #define KMP_CPU_ISSET(i, mask) (mask)->is_set(i) 6750b57cec5SDimitry Andric #define KMP_CPU_CLR(i, mask) (mask)->clear(i) 6760b57cec5SDimitry Andric #define KMP_CPU_ZERO(mask) (mask)->zero() 6770b57cec5SDimitry Andric #define KMP_CPU_COPY(dest, src) (dest)->copy(src) 6780b57cec5SDimitry Andric #define KMP_CPU_AND(dest, src) (dest)->bitwise_and(src) 6790b57cec5SDimitry Andric #define KMP_CPU_COMPLEMENT(max_bit_number, mask) (mask)->bitwise_not() 6800b57cec5SDimitry Andric #define KMP_CPU_UNION(dest, src) (dest)->bitwise_or(src) 6810b57cec5SDimitry Andric #define KMP_CPU_ALLOC(ptr) (ptr = __kmp_affinity_dispatch->allocate_mask()) 6820b57cec5SDimitry Andric #define KMP_CPU_FREE(ptr) __kmp_affinity_dispatch->deallocate_mask(ptr) 6830b57cec5SDimitry Andric #define KMP_CPU_ALLOC_ON_STACK(ptr) KMP_CPU_ALLOC(ptr) 6840b57cec5SDimitry Andric #define KMP_CPU_FREE_FROM_STACK(ptr) KMP_CPU_FREE(ptr) 6850b57cec5SDimitry Andric #define KMP_CPU_INTERNAL_ALLOC(ptr) KMP_CPU_ALLOC(ptr) 6860b57cec5SDimitry Andric #define KMP_CPU_INTERNAL_FREE(ptr) KMP_CPU_FREE(ptr) 6870b57cec5SDimitry Andric #define KMP_CPU_INDEX(arr, i) __kmp_affinity_dispatch->index_mask_array(arr, i) 6880b57cec5SDimitry Andric #define KMP_CPU_ALLOC_ARRAY(arr, n) \ 6890b57cec5SDimitry Andric (arr = __kmp_affinity_dispatch->allocate_mask_array(n)) 6900b57cec5SDimitry Andric #define KMP_CPU_FREE_ARRAY(arr, n) \ 6910b57cec5SDimitry Andric __kmp_affinity_dispatch->deallocate_mask_array(arr) 6920b57cec5SDimitry Andric #define KMP_CPU_INTERNAL_ALLOC_ARRAY(arr, n) KMP_CPU_ALLOC_ARRAY(arr, n) 6930b57cec5SDimitry Andric #define KMP_CPU_INTERNAL_FREE_ARRAY(arr, n) KMP_CPU_FREE_ARRAY(arr, n) 6940b57cec5SDimitry Andric #define __kmp_get_system_affinity(mask, abort_bool) \ 6950b57cec5SDimitry Andric (mask)->get_system_affinity(abort_bool) 6960b57cec5SDimitry Andric #define __kmp_set_system_affinity(mask, abort_bool) \ 6970b57cec5SDimitry Andric (mask)->set_system_affinity(abort_bool) 6980b57cec5SDimitry Andric #define __kmp_get_proc_group(mask) (mask)->get_proc_group() 6990b57cec5SDimitry Andric 7000b57cec5SDimitry Andric class KMPAffinity { 7010b57cec5SDimitry Andric public: 7020b57cec5SDimitry Andric class Mask { 7030b57cec5SDimitry Andric public: 7040b57cec5SDimitry Andric void *operator new(size_t n); 7050b57cec5SDimitry Andric void operator delete(void *p); 7060b57cec5SDimitry Andric void *operator new[](size_t n); 7070b57cec5SDimitry Andric void operator delete[](void *p); 7080b57cec5SDimitry Andric virtual ~Mask() {} 7090b57cec5SDimitry Andric // Set bit i to 1 7100b57cec5SDimitry Andric virtual void set(int i) {} 7110b57cec5SDimitry Andric // Return bit i 7120b57cec5SDimitry Andric virtual bool is_set(int i) const { return false; } 7130b57cec5SDimitry Andric // Set bit i to 0 7140b57cec5SDimitry Andric virtual void clear(int i) {} 7150b57cec5SDimitry Andric // Zero out entire mask 7160b57cec5SDimitry Andric virtual void zero() {} 7170b57cec5SDimitry Andric // Copy src into this mask 7180b57cec5SDimitry Andric virtual void copy(const Mask *src) {} 7190b57cec5SDimitry Andric // this &= rhs 7200b57cec5SDimitry Andric virtual void bitwise_and(const Mask *rhs) {} 7210b57cec5SDimitry Andric // this |= rhs 7220b57cec5SDimitry Andric virtual void bitwise_or(const Mask *rhs) {} 7230b57cec5SDimitry Andric // this = ~this 7240b57cec5SDimitry Andric virtual void bitwise_not() {} 7250b57cec5SDimitry Andric // API for iterating over an affinity mask 7260b57cec5SDimitry Andric // for (int i = mask->begin(); i != mask->end(); i = mask->next(i)) 7270b57cec5SDimitry Andric virtual int begin() const { return 0; } 7280b57cec5SDimitry Andric virtual int end() const { return 0; } 7290b57cec5SDimitry Andric virtual int next(int previous) const { return 0; } 730e8d8bef9SDimitry Andric #if KMP_OS_WINDOWS 731e8d8bef9SDimitry Andric virtual int set_process_affinity(bool abort_on_error) const { return -1; } 732e8d8bef9SDimitry Andric #endif 7330b57cec5SDimitry Andric // Set the system's affinity to this affinity mask's value 7340b57cec5SDimitry Andric virtual int set_system_affinity(bool abort_on_error) const { return -1; } 7350b57cec5SDimitry Andric // Set this affinity mask to the current system affinity 7360b57cec5SDimitry Andric virtual int get_system_affinity(bool abort_on_error) { return -1; } 7370b57cec5SDimitry Andric // Only 1 DWORD in the mask should have any procs set. 7380b57cec5SDimitry Andric // Return the appropriate index, or -1 for an invalid mask. 7390b57cec5SDimitry Andric virtual int get_proc_group() const { return -1; } 7400b57cec5SDimitry Andric }; 7410b57cec5SDimitry Andric void *operator new(size_t n); 7420b57cec5SDimitry Andric void operator delete(void *p); 7430b57cec5SDimitry Andric // Need virtual destructor 7440b57cec5SDimitry Andric virtual ~KMPAffinity() = default; 7450b57cec5SDimitry Andric // Determine if affinity is capable 7460b57cec5SDimitry Andric virtual void determine_capable(const char *env_var) {} 7470b57cec5SDimitry Andric // Bind the current thread to os proc 7480b57cec5SDimitry Andric virtual void bind_thread(int proc) {} 7490b57cec5SDimitry Andric // Factory functions to allocate/deallocate a mask 7500b57cec5SDimitry Andric virtual Mask *allocate_mask() { return nullptr; } 7510b57cec5SDimitry Andric virtual void deallocate_mask(Mask *m) {} 7520b57cec5SDimitry Andric virtual Mask *allocate_mask_array(int num) { return nullptr; } 7530b57cec5SDimitry Andric virtual void deallocate_mask_array(Mask *m) {} 7540b57cec5SDimitry Andric virtual Mask *index_mask_array(Mask *m, int index) { return nullptr; } 7550b57cec5SDimitry Andric static void pick_api(); 7560b57cec5SDimitry Andric static void destroy_api(); 7570b57cec5SDimitry Andric enum api_type { 7580b57cec5SDimitry Andric NATIVE_OS 7590b57cec5SDimitry Andric #if KMP_USE_HWLOC 7600b57cec5SDimitry Andric , 7610b57cec5SDimitry Andric HWLOC 7620b57cec5SDimitry Andric #endif 7630b57cec5SDimitry Andric }; 7640b57cec5SDimitry Andric virtual api_type get_api_type() const { 7650b57cec5SDimitry Andric KMP_ASSERT(0); 7660b57cec5SDimitry Andric return NATIVE_OS; 7670b57cec5SDimitry Andric } 7680b57cec5SDimitry Andric 7690b57cec5SDimitry Andric private: 7700b57cec5SDimitry Andric static bool picked_api; 7710b57cec5SDimitry Andric }; 7720b57cec5SDimitry Andric 7730b57cec5SDimitry Andric typedef KMPAffinity::Mask kmp_affin_mask_t; 7740b57cec5SDimitry Andric extern KMPAffinity *__kmp_affinity_dispatch; 7750b57cec5SDimitry Andric 7760b57cec5SDimitry Andric // Declare local char buffers with this size for printing debug and info 7770b57cec5SDimitry Andric // messages, using __kmp_affinity_print_mask(). 7780b57cec5SDimitry Andric #define KMP_AFFIN_MASK_PRINT_LEN 1024 7790b57cec5SDimitry Andric 7800b57cec5SDimitry Andric enum affinity_type { 7810b57cec5SDimitry Andric affinity_none = 0, 7820b57cec5SDimitry Andric affinity_physical, 7830b57cec5SDimitry Andric affinity_logical, 7840b57cec5SDimitry Andric affinity_compact, 7850b57cec5SDimitry Andric affinity_scatter, 7860b57cec5SDimitry Andric affinity_explicit, 7870b57cec5SDimitry Andric affinity_balanced, 7880b57cec5SDimitry Andric affinity_disabled, // not used outsize the env var parser 7890b57cec5SDimitry Andric affinity_default 7900b57cec5SDimitry Andric }; 7910b57cec5SDimitry Andric 7920b57cec5SDimitry Andric enum affinity_top_method { 7930b57cec5SDimitry Andric affinity_top_method_all = 0, // try all (supported) methods, in order 7940b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64 7950b57cec5SDimitry Andric affinity_top_method_apicid, 7960b57cec5SDimitry Andric affinity_top_method_x2apicid, 797*fe6060f1SDimitry Andric affinity_top_method_x2apicid_1f, 7980b57cec5SDimitry Andric #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */ 7990b57cec5SDimitry Andric affinity_top_method_cpuinfo, // KMP_CPUINFO_FILE is usable on Windows* OS, too 8000b57cec5SDimitry Andric #if KMP_GROUP_AFFINITY 8010b57cec5SDimitry Andric affinity_top_method_group, 8020b57cec5SDimitry Andric #endif /* KMP_GROUP_AFFINITY */ 8030b57cec5SDimitry Andric affinity_top_method_flat, 8040b57cec5SDimitry Andric #if KMP_USE_HWLOC 8050b57cec5SDimitry Andric affinity_top_method_hwloc, 8060b57cec5SDimitry Andric #endif 8070b57cec5SDimitry Andric affinity_top_method_default 8080b57cec5SDimitry Andric }; 8090b57cec5SDimitry Andric 8100b57cec5SDimitry Andric #define affinity_respect_mask_default (-1) 8110b57cec5SDimitry Andric 8120b57cec5SDimitry Andric extern enum affinity_type __kmp_affinity_type; /* Affinity type */ 813*fe6060f1SDimitry Andric extern kmp_hw_t __kmp_affinity_gran; /* Affinity granularity */ 8140b57cec5SDimitry Andric extern int __kmp_affinity_gran_levels; /* corresponding int value */ 8150b57cec5SDimitry Andric extern int __kmp_affinity_dups; /* Affinity duplicate masks */ 8160b57cec5SDimitry Andric extern enum affinity_top_method __kmp_affinity_top_method; 8170b57cec5SDimitry Andric extern int __kmp_affinity_compact; /* Affinity 'compact' value */ 8180b57cec5SDimitry Andric extern int __kmp_affinity_offset; /* Affinity offset value */ 8190b57cec5SDimitry Andric extern int __kmp_affinity_verbose; /* Was verbose specified for KMP_AFFINITY? */ 8200b57cec5SDimitry Andric extern int __kmp_affinity_warnings; /* KMP_AFFINITY warnings enabled ? */ 8210b57cec5SDimitry Andric extern int __kmp_affinity_respect_mask; // Respect process' init affinity mask? 8220b57cec5SDimitry Andric extern char *__kmp_affinity_proclist; /* proc ID list */ 8230b57cec5SDimitry Andric extern kmp_affin_mask_t *__kmp_affinity_masks; 8240b57cec5SDimitry Andric extern unsigned __kmp_affinity_num_masks; 8250b57cec5SDimitry Andric extern void __kmp_affinity_bind_thread(int which); 8260b57cec5SDimitry Andric 8270b57cec5SDimitry Andric extern kmp_affin_mask_t *__kmp_affin_fullMask; 8280b57cec5SDimitry Andric extern char *__kmp_cpuinfo_file; 8290b57cec5SDimitry Andric 8300b57cec5SDimitry Andric #endif /* KMP_AFFINITY_SUPPORTED */ 8310b57cec5SDimitry Andric 8320b57cec5SDimitry Andric // This needs to be kept in sync with the values in omp.h !!! 8330b57cec5SDimitry Andric typedef enum kmp_proc_bind_t { 8340b57cec5SDimitry Andric proc_bind_false = 0, 8350b57cec5SDimitry Andric proc_bind_true, 836*fe6060f1SDimitry Andric proc_bind_primary, 8370b57cec5SDimitry Andric proc_bind_close, 8380b57cec5SDimitry Andric proc_bind_spread, 8390b57cec5SDimitry Andric proc_bind_intel, // use KMP_AFFINITY interface 8400b57cec5SDimitry Andric proc_bind_default 8410b57cec5SDimitry Andric } kmp_proc_bind_t; 8420b57cec5SDimitry Andric 8430b57cec5SDimitry Andric typedef struct kmp_nested_proc_bind_t { 8440b57cec5SDimitry Andric kmp_proc_bind_t *bind_types; 8450b57cec5SDimitry Andric int size; 8460b57cec5SDimitry Andric int used; 8470b57cec5SDimitry Andric } kmp_nested_proc_bind_t; 8480b57cec5SDimitry Andric 8490b57cec5SDimitry Andric extern kmp_nested_proc_bind_t __kmp_nested_proc_bind; 8500b57cec5SDimitry Andric 8510b57cec5SDimitry Andric extern int __kmp_display_affinity; 8520b57cec5SDimitry Andric extern char *__kmp_affinity_format; 8530b57cec5SDimitry Andric static const size_t KMP_AFFINITY_FORMAT_SIZE = 512; 854*fe6060f1SDimitry Andric #if OMPT_SUPPORT 855*fe6060f1SDimitry Andric extern int __kmp_tool; 856*fe6060f1SDimitry Andric extern char *__kmp_tool_libraries; 857*fe6060f1SDimitry Andric #endif // OMPT_SUPPORT 8580b57cec5SDimitry Andric 8590b57cec5SDimitry Andric #if KMP_AFFINITY_SUPPORTED 8600b57cec5SDimitry Andric #define KMP_PLACE_ALL (-1) 8610b57cec5SDimitry Andric #define KMP_PLACE_UNDEFINED (-2) 8620b57cec5SDimitry Andric // Is KMP_AFFINITY is being used instead of OMP_PROC_BIND/OMP_PLACES? 8630b57cec5SDimitry Andric #define KMP_AFFINITY_NON_PROC_BIND \ 8640b57cec5SDimitry Andric ((__kmp_nested_proc_bind.bind_types[0] == proc_bind_false || \ 8650b57cec5SDimitry Andric __kmp_nested_proc_bind.bind_types[0] == proc_bind_intel) && \ 8660b57cec5SDimitry Andric (__kmp_affinity_num_masks > 0 || __kmp_affinity_type == affinity_balanced)) 8670b57cec5SDimitry Andric #endif /* KMP_AFFINITY_SUPPORTED */ 8680b57cec5SDimitry Andric 8690b57cec5SDimitry Andric extern int __kmp_affinity_num_places; 8700b57cec5SDimitry Andric 8710b57cec5SDimitry Andric typedef enum kmp_cancel_kind_t { 8720b57cec5SDimitry Andric cancel_noreq = 0, 8730b57cec5SDimitry Andric cancel_parallel = 1, 8740b57cec5SDimitry Andric cancel_loop = 2, 8750b57cec5SDimitry Andric cancel_sections = 3, 8760b57cec5SDimitry Andric cancel_taskgroup = 4 8770b57cec5SDimitry Andric } kmp_cancel_kind_t; 8780b57cec5SDimitry Andric 8790b57cec5SDimitry Andric // KMP_HW_SUBSET support: 8800b57cec5SDimitry Andric typedef struct kmp_hws_item { 8810b57cec5SDimitry Andric int num; 8820b57cec5SDimitry Andric int offset; 8830b57cec5SDimitry Andric } kmp_hws_item_t; 8840b57cec5SDimitry Andric 8850b57cec5SDimitry Andric extern kmp_hws_item_t __kmp_hws_socket; 886*fe6060f1SDimitry Andric extern kmp_hws_item_t __kmp_hws_die; 8870b57cec5SDimitry Andric extern kmp_hws_item_t __kmp_hws_node; 8880b57cec5SDimitry Andric extern kmp_hws_item_t __kmp_hws_tile; 8890b57cec5SDimitry Andric extern kmp_hws_item_t __kmp_hws_core; 8900b57cec5SDimitry Andric extern kmp_hws_item_t __kmp_hws_proc; 8910b57cec5SDimitry Andric extern int __kmp_hws_requested; 8920b57cec5SDimitry Andric extern int __kmp_hws_abs_flag; // absolute or per-item number requested 8930b57cec5SDimitry Andric 8940b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */ 8950b57cec5SDimitry Andric 8960b57cec5SDimitry Andric #define KMP_PAD(type, sz) \ 8970b57cec5SDimitry Andric (sizeof(type) + (sz - ((sizeof(type) - 1) % (sz)) - 1)) 8980b57cec5SDimitry Andric 8990b57cec5SDimitry Andric // We need to avoid using -1 as a GTID as +1 is added to the gtid 9000b57cec5SDimitry Andric // when storing it in a lock, and the value 0 is reserved. 9010b57cec5SDimitry Andric #define KMP_GTID_DNE (-2) /* Does not exist */ 9020b57cec5SDimitry Andric #define KMP_GTID_SHUTDOWN (-3) /* Library is shutting down */ 9030b57cec5SDimitry Andric #define KMP_GTID_MONITOR (-4) /* Monitor thread ID */ 9040b57cec5SDimitry Andric #define KMP_GTID_UNKNOWN (-5) /* Is not known */ 9050b57cec5SDimitry Andric #define KMP_GTID_MIN (-6) /* Minimal gtid for low bound check in DEBUG */ 9060b57cec5SDimitry Andric 9070b57cec5SDimitry Andric /* OpenMP 5.0 Memory Management support */ 9080b57cec5SDimitry Andric 9090b57cec5SDimitry Andric #ifndef __OMP_H 910480093f4SDimitry Andric // Duplicate type definitions from omp.h 9110b57cec5SDimitry Andric typedef uintptr_t omp_uintptr_t; 9120b57cec5SDimitry Andric 9130b57cec5SDimitry Andric typedef enum { 914e8d8bef9SDimitry Andric omp_atk_sync_hint = 1, 9155ffd83dbSDimitry Andric omp_atk_alignment = 2, 9165ffd83dbSDimitry Andric omp_atk_access = 3, 9175ffd83dbSDimitry Andric omp_atk_pool_size = 4, 9185ffd83dbSDimitry Andric omp_atk_fallback = 5, 9195ffd83dbSDimitry Andric omp_atk_fb_data = 6, 9205ffd83dbSDimitry Andric omp_atk_pinned = 7, 9215ffd83dbSDimitry Andric omp_atk_partition = 8 9220b57cec5SDimitry Andric } omp_alloctrait_key_t; 9230b57cec5SDimitry Andric 9240b57cec5SDimitry Andric typedef enum { 9255ffd83dbSDimitry Andric omp_atv_false = 0, 9265ffd83dbSDimitry Andric omp_atv_true = 1, 9275ffd83dbSDimitry Andric omp_atv_contended = 3, 9285ffd83dbSDimitry Andric omp_atv_uncontended = 4, 929e8d8bef9SDimitry Andric omp_atv_serialized = 5, 930e8d8bef9SDimitry Andric omp_atv_sequential = omp_atv_serialized, // (deprecated) 9315ffd83dbSDimitry Andric omp_atv_private = 6, 9325ffd83dbSDimitry Andric omp_atv_all = 7, 9335ffd83dbSDimitry Andric omp_atv_thread = 8, 9345ffd83dbSDimitry Andric omp_atv_pteam = 9, 9355ffd83dbSDimitry Andric omp_atv_cgroup = 10, 9365ffd83dbSDimitry Andric omp_atv_default_mem_fb = 11, 9375ffd83dbSDimitry Andric omp_atv_null_fb = 12, 9385ffd83dbSDimitry Andric omp_atv_abort_fb = 13, 9395ffd83dbSDimitry Andric omp_atv_allocator_fb = 14, 9405ffd83dbSDimitry Andric omp_atv_environment = 15, 9415ffd83dbSDimitry Andric omp_atv_nearest = 16, 9425ffd83dbSDimitry Andric omp_atv_blocked = 17, 9435ffd83dbSDimitry Andric omp_atv_interleaved = 18 9440b57cec5SDimitry Andric } omp_alloctrait_value_t; 945e8d8bef9SDimitry Andric #define omp_atv_default ((omp_uintptr_t)-1) 9460b57cec5SDimitry Andric 9470b57cec5SDimitry Andric typedef void *omp_memspace_handle_t; 9480b57cec5SDimitry Andric extern omp_memspace_handle_t const omp_default_mem_space; 9490b57cec5SDimitry Andric extern omp_memspace_handle_t const omp_large_cap_mem_space; 9500b57cec5SDimitry Andric extern omp_memspace_handle_t const omp_const_mem_space; 9510b57cec5SDimitry Andric extern omp_memspace_handle_t const omp_high_bw_mem_space; 9520b57cec5SDimitry Andric extern omp_memspace_handle_t const omp_low_lat_mem_space; 953*fe6060f1SDimitry Andric // Preview of target memory support 954*fe6060f1SDimitry Andric extern omp_memspace_handle_t const llvm_omp_target_host_mem_space; 955*fe6060f1SDimitry Andric extern omp_memspace_handle_t const llvm_omp_target_shared_mem_space; 956*fe6060f1SDimitry Andric extern omp_memspace_handle_t const llvm_omp_target_device_mem_space; 9570b57cec5SDimitry Andric 9580b57cec5SDimitry Andric typedef struct { 9590b57cec5SDimitry Andric omp_alloctrait_key_t key; 9600b57cec5SDimitry Andric omp_uintptr_t value; 9610b57cec5SDimitry Andric } omp_alloctrait_t; 9620b57cec5SDimitry Andric 9630b57cec5SDimitry Andric typedef void *omp_allocator_handle_t; 9640b57cec5SDimitry Andric extern omp_allocator_handle_t const omp_null_allocator; 9650b57cec5SDimitry Andric extern omp_allocator_handle_t const omp_default_mem_alloc; 9660b57cec5SDimitry Andric extern omp_allocator_handle_t const omp_large_cap_mem_alloc; 9670b57cec5SDimitry Andric extern omp_allocator_handle_t const omp_const_mem_alloc; 9680b57cec5SDimitry Andric extern omp_allocator_handle_t const omp_high_bw_mem_alloc; 9690b57cec5SDimitry Andric extern omp_allocator_handle_t const omp_low_lat_mem_alloc; 9700b57cec5SDimitry Andric extern omp_allocator_handle_t const omp_cgroup_mem_alloc; 9710b57cec5SDimitry Andric extern omp_allocator_handle_t const omp_pteam_mem_alloc; 9720b57cec5SDimitry Andric extern omp_allocator_handle_t const omp_thread_mem_alloc; 973*fe6060f1SDimitry Andric // Preview of target memory support 974*fe6060f1SDimitry Andric extern omp_allocator_handle_t const llvm_omp_target_host_mem_alloc; 975*fe6060f1SDimitry Andric extern omp_allocator_handle_t const llvm_omp_target_shared_mem_alloc; 976*fe6060f1SDimitry Andric extern omp_allocator_handle_t const llvm_omp_target_device_mem_alloc; 9770b57cec5SDimitry Andric extern omp_allocator_handle_t const kmp_max_mem_alloc; 9780b57cec5SDimitry Andric extern omp_allocator_handle_t __kmp_def_allocator; 9790b57cec5SDimitry Andric 980480093f4SDimitry Andric // end of duplicate type definitions from omp.h 9810b57cec5SDimitry Andric #endif 9820b57cec5SDimitry Andric 9830b57cec5SDimitry Andric extern int __kmp_memkind_available; 9840b57cec5SDimitry Andric 9850b57cec5SDimitry Andric typedef omp_memspace_handle_t kmp_memspace_t; // placeholder 9860b57cec5SDimitry Andric 9870b57cec5SDimitry Andric typedef struct kmp_allocator_t { 9880b57cec5SDimitry Andric omp_memspace_handle_t memspace; 9890b57cec5SDimitry Andric void **memkind; // pointer to memkind 9900b57cec5SDimitry Andric int alignment; 9910b57cec5SDimitry Andric omp_alloctrait_value_t fb; 9920b57cec5SDimitry Andric kmp_allocator_t *fb_data; 9930b57cec5SDimitry Andric kmp_uint64 pool_size; 9940b57cec5SDimitry Andric kmp_uint64 pool_used; 9950b57cec5SDimitry Andric } kmp_allocator_t; 9960b57cec5SDimitry Andric 9970b57cec5SDimitry Andric extern omp_allocator_handle_t __kmpc_init_allocator(int gtid, 9980b57cec5SDimitry Andric omp_memspace_handle_t, 9990b57cec5SDimitry Andric int ntraits, 10000b57cec5SDimitry Andric omp_alloctrait_t traits[]); 10010b57cec5SDimitry Andric extern void __kmpc_destroy_allocator(int gtid, omp_allocator_handle_t al); 10020b57cec5SDimitry Andric extern void __kmpc_set_default_allocator(int gtid, omp_allocator_handle_t al); 10030b57cec5SDimitry Andric extern omp_allocator_handle_t __kmpc_get_default_allocator(int gtid); 10040b57cec5SDimitry Andric extern void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t al); 1005e8d8bef9SDimitry Andric extern void *__kmpc_calloc(int gtid, size_t nmemb, size_t sz, 1006e8d8bef9SDimitry Andric omp_allocator_handle_t al); 1007e8d8bef9SDimitry Andric extern void *__kmpc_realloc(int gtid, void *ptr, size_t sz, 1008e8d8bef9SDimitry Andric omp_allocator_handle_t al, 1009e8d8bef9SDimitry Andric omp_allocator_handle_t free_al); 10100b57cec5SDimitry Andric extern void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t al); 10110b57cec5SDimitry Andric 10120b57cec5SDimitry Andric extern void __kmp_init_memkind(); 10130b57cec5SDimitry Andric extern void __kmp_fini_memkind(); 1014*fe6060f1SDimitry Andric extern void __kmp_init_target_mem(); 10150b57cec5SDimitry Andric 10160b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */ 10170b57cec5SDimitry Andric 10180b57cec5SDimitry Andric #define KMP_UINT64_MAX \ 10190b57cec5SDimitry Andric (~((kmp_uint64)1 << ((sizeof(kmp_uint64) * (1 << 3)) - 1))) 10200b57cec5SDimitry Andric 10210b57cec5SDimitry Andric #define KMP_MIN_NTH 1 10220b57cec5SDimitry Andric 10230b57cec5SDimitry Andric #ifndef KMP_MAX_NTH 10240b57cec5SDimitry Andric #if defined(PTHREAD_THREADS_MAX) && PTHREAD_THREADS_MAX < INT_MAX 10250b57cec5SDimitry Andric #define KMP_MAX_NTH PTHREAD_THREADS_MAX 10260b57cec5SDimitry Andric #else 10270b57cec5SDimitry Andric #define KMP_MAX_NTH INT_MAX 10280b57cec5SDimitry Andric #endif 10290b57cec5SDimitry Andric #endif /* KMP_MAX_NTH */ 10300b57cec5SDimitry Andric 10310b57cec5SDimitry Andric #ifdef PTHREAD_STACK_MIN 10320b57cec5SDimitry Andric #define KMP_MIN_STKSIZE PTHREAD_STACK_MIN 10330b57cec5SDimitry Andric #else 10340b57cec5SDimitry Andric #define KMP_MIN_STKSIZE ((size_t)(32 * 1024)) 10350b57cec5SDimitry Andric #endif 10360b57cec5SDimitry Andric 10370b57cec5SDimitry Andric #define KMP_MAX_STKSIZE (~((size_t)1 << ((sizeof(size_t) * (1 << 3)) - 1))) 10380b57cec5SDimitry Andric 10390b57cec5SDimitry Andric #if KMP_ARCH_X86 10400b57cec5SDimitry Andric #define KMP_DEFAULT_STKSIZE ((size_t)(2 * 1024 * 1024)) 10410b57cec5SDimitry Andric #elif KMP_ARCH_X86_64 10420b57cec5SDimitry Andric #define KMP_DEFAULT_STKSIZE ((size_t)(4 * 1024 * 1024)) 10430b57cec5SDimitry Andric #define KMP_BACKUP_STKSIZE ((size_t)(2 * 1024 * 1024)) 10440b57cec5SDimitry Andric #else 10450b57cec5SDimitry Andric #define KMP_DEFAULT_STKSIZE ((size_t)(1024 * 1024)) 10460b57cec5SDimitry Andric #endif 10470b57cec5SDimitry Andric 10480b57cec5SDimitry Andric #define KMP_DEFAULT_MALLOC_POOL_INCR ((size_t)(1024 * 1024)) 10490b57cec5SDimitry Andric #define KMP_MIN_MALLOC_POOL_INCR ((size_t)(4 * 1024)) 10500b57cec5SDimitry Andric #define KMP_MAX_MALLOC_POOL_INCR \ 10510b57cec5SDimitry Andric (~((size_t)1 << ((sizeof(size_t) * (1 << 3)) - 1))) 10520b57cec5SDimitry Andric 10530b57cec5SDimitry Andric #define KMP_MIN_STKOFFSET (0) 10540b57cec5SDimitry Andric #define KMP_MAX_STKOFFSET KMP_MAX_STKSIZE 10550b57cec5SDimitry Andric #if KMP_OS_DARWIN 10560b57cec5SDimitry Andric #define KMP_DEFAULT_STKOFFSET KMP_MIN_STKOFFSET 10570b57cec5SDimitry Andric #else 10580b57cec5SDimitry Andric #define KMP_DEFAULT_STKOFFSET CACHE_LINE 10590b57cec5SDimitry Andric #endif 10600b57cec5SDimitry Andric 10610b57cec5SDimitry Andric #define KMP_MIN_STKPADDING (0) 10620b57cec5SDimitry Andric #define KMP_MAX_STKPADDING (2 * 1024 * 1024) 10630b57cec5SDimitry Andric 10640b57cec5SDimitry Andric #define KMP_BLOCKTIME_MULTIPLIER \ 10650b57cec5SDimitry Andric (1000) /* number of blocktime units per second */ 10660b57cec5SDimitry Andric #define KMP_MIN_BLOCKTIME (0) 10670b57cec5SDimitry Andric #define KMP_MAX_BLOCKTIME \ 10680b57cec5SDimitry Andric (INT_MAX) /* Must be this for "infinite" setting the work */ 10690b57cec5SDimitry Andric #define KMP_DEFAULT_BLOCKTIME (200) /* __kmp_blocktime is in milliseconds */ 10700b57cec5SDimitry Andric 10710b57cec5SDimitry Andric #if KMP_USE_MONITOR 10720b57cec5SDimitry Andric #define KMP_DEFAULT_MONITOR_STKSIZE ((size_t)(64 * 1024)) 10730b57cec5SDimitry Andric #define KMP_MIN_MONITOR_WAKEUPS (1) // min times monitor wakes up per second 10740b57cec5SDimitry Andric #define KMP_MAX_MONITOR_WAKEUPS (1000) // max times monitor can wake up per sec 10750b57cec5SDimitry Andric 10760b57cec5SDimitry Andric /* Calculate new number of monitor wakeups for a specific block time based on 10770b57cec5SDimitry Andric previous monitor_wakeups. Only allow increasing number of wakeups */ 10780b57cec5SDimitry Andric #define KMP_WAKEUPS_FROM_BLOCKTIME(blocktime, monitor_wakeups) \ 1079*fe6060f1SDimitry Andric (((blocktime) == KMP_MAX_BLOCKTIME) ? (monitor_wakeups) \ 1080*fe6060f1SDimitry Andric : ((blocktime) == KMP_MIN_BLOCKTIME) ? KMP_MAX_MONITOR_WAKEUPS \ 10810b57cec5SDimitry Andric : ((monitor_wakeups) > (KMP_BLOCKTIME_MULTIPLIER / (blocktime))) \ 10820b57cec5SDimitry Andric ? (monitor_wakeups) \ 10830b57cec5SDimitry Andric : (KMP_BLOCKTIME_MULTIPLIER) / (blocktime)) 10840b57cec5SDimitry Andric 10850b57cec5SDimitry Andric /* Calculate number of intervals for a specific block time based on 10860b57cec5SDimitry Andric monitor_wakeups */ 10870b57cec5SDimitry Andric #define KMP_INTERVALS_FROM_BLOCKTIME(blocktime, monitor_wakeups) \ 10880b57cec5SDimitry Andric (((blocktime) + (KMP_BLOCKTIME_MULTIPLIER / (monitor_wakeups)) - 1) / \ 10890b57cec5SDimitry Andric (KMP_BLOCKTIME_MULTIPLIER / (monitor_wakeups))) 10900b57cec5SDimitry Andric #else 10910b57cec5SDimitry Andric #define KMP_BLOCKTIME(team, tid) \ 10920b57cec5SDimitry Andric (get__bt_set(team, tid) ? get__blocktime(team, tid) : __kmp_dflt_blocktime) 10930b57cec5SDimitry Andric #if KMP_OS_UNIX && (KMP_ARCH_X86 || KMP_ARCH_X86_64) 10940b57cec5SDimitry Andric // HW TSC is used to reduce overhead (clock tick instead of nanosecond). 10950b57cec5SDimitry Andric extern kmp_uint64 __kmp_ticks_per_msec; 10960b57cec5SDimitry Andric #if KMP_COMPILER_ICC 10970b57cec5SDimitry Andric #define KMP_NOW() ((kmp_uint64)_rdtsc()) 10980b57cec5SDimitry Andric #else 10990b57cec5SDimitry Andric #define KMP_NOW() __kmp_hardware_timestamp() 11000b57cec5SDimitry Andric #endif 11010b57cec5SDimitry Andric #define KMP_NOW_MSEC() (KMP_NOW() / __kmp_ticks_per_msec) 11020b57cec5SDimitry Andric #define KMP_BLOCKTIME_INTERVAL(team, tid) \ 11030b57cec5SDimitry Andric (KMP_BLOCKTIME(team, tid) * __kmp_ticks_per_msec) 11040b57cec5SDimitry Andric #define KMP_BLOCKING(goal, count) ((goal) > KMP_NOW()) 11050b57cec5SDimitry Andric #else 11060b57cec5SDimitry Andric // System time is retrieved sporadically while blocking. 11070b57cec5SDimitry Andric extern kmp_uint64 __kmp_now_nsec(); 11080b57cec5SDimitry Andric #define KMP_NOW() __kmp_now_nsec() 11090b57cec5SDimitry Andric #define KMP_NOW_MSEC() (KMP_NOW() / KMP_USEC_PER_SEC) 11100b57cec5SDimitry Andric #define KMP_BLOCKTIME_INTERVAL(team, tid) \ 11110b57cec5SDimitry Andric (KMP_BLOCKTIME(team, tid) * KMP_USEC_PER_SEC) 11120b57cec5SDimitry Andric #define KMP_BLOCKING(goal, count) ((count) % 1000 != 0 || (goal) > KMP_NOW()) 11130b57cec5SDimitry Andric #endif 11140b57cec5SDimitry Andric #endif // KMP_USE_MONITOR 11150b57cec5SDimitry Andric 11160b57cec5SDimitry Andric #define KMP_MIN_STATSCOLS 40 11170b57cec5SDimitry Andric #define KMP_MAX_STATSCOLS 4096 11180b57cec5SDimitry Andric #define KMP_DEFAULT_STATSCOLS 80 11190b57cec5SDimitry Andric 11200b57cec5SDimitry Andric #define KMP_MIN_INTERVAL 0 11210b57cec5SDimitry Andric #define KMP_MAX_INTERVAL (INT_MAX - 1) 11220b57cec5SDimitry Andric #define KMP_DEFAULT_INTERVAL 0 11230b57cec5SDimitry Andric 11240b57cec5SDimitry Andric #define KMP_MIN_CHUNK 1 11250b57cec5SDimitry Andric #define KMP_MAX_CHUNK (INT_MAX - 1) 11260b57cec5SDimitry Andric #define KMP_DEFAULT_CHUNK 1 11270b57cec5SDimitry Andric 1128*fe6060f1SDimitry Andric #define KMP_MIN_DISP_NUM_BUFF 1 11290b57cec5SDimitry Andric #define KMP_DFLT_DISP_NUM_BUFF 7 1130*fe6060f1SDimitry Andric #define KMP_MAX_DISP_NUM_BUFF 4096 1131*fe6060f1SDimitry Andric 11320b57cec5SDimitry Andric #define KMP_MAX_ORDERED 8 11330b57cec5SDimitry Andric 11340b57cec5SDimitry Andric #define KMP_MAX_FIELDS 32 11350b57cec5SDimitry Andric 11360b57cec5SDimitry Andric #define KMP_MAX_BRANCH_BITS 31 11370b57cec5SDimitry Andric 11380b57cec5SDimitry Andric #define KMP_MAX_ACTIVE_LEVELS_LIMIT INT_MAX 11390b57cec5SDimitry Andric 11400b57cec5SDimitry Andric #define KMP_MAX_DEFAULT_DEVICE_LIMIT INT_MAX 11410b57cec5SDimitry Andric 11420b57cec5SDimitry Andric #define KMP_MAX_TASK_PRIORITY_LIMIT INT_MAX 11430b57cec5SDimitry Andric 11440b57cec5SDimitry Andric /* Minimum number of threads before switch to TLS gtid (experimentally 11450b57cec5SDimitry Andric determined) */ 11460b57cec5SDimitry Andric /* josh TODO: what about OS X* tuning? */ 11470b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64 11480b57cec5SDimitry Andric #define KMP_TLS_GTID_MIN 5 11490b57cec5SDimitry Andric #else 11500b57cec5SDimitry Andric #define KMP_TLS_GTID_MIN INT_MAX 11510b57cec5SDimitry Andric #endif 11520b57cec5SDimitry Andric 1153e8d8bef9SDimitry Andric #define KMP_MASTER_TID(tid) (0 == (tid)) 1154e8d8bef9SDimitry Andric #define KMP_WORKER_TID(tid) (0 != (tid)) 11550b57cec5SDimitry Andric 1156e8d8bef9SDimitry Andric #define KMP_MASTER_GTID(gtid) (0 == __kmp_tid_from_gtid((gtid))) 1157e8d8bef9SDimitry Andric #define KMP_WORKER_GTID(gtid) (0 != __kmp_tid_from_gtid((gtid))) 1158e8d8bef9SDimitry Andric #define KMP_INITIAL_GTID(gtid) (0 == (gtid)) 11590b57cec5SDimitry Andric 11600b57cec5SDimitry Andric #ifndef TRUE 11610b57cec5SDimitry Andric #define FALSE 0 11620b57cec5SDimitry Andric #define TRUE (!FALSE) 11630b57cec5SDimitry Andric #endif 11640b57cec5SDimitry Andric 11650b57cec5SDimitry Andric /* NOTE: all of the following constants must be even */ 11660b57cec5SDimitry Andric 11670b57cec5SDimitry Andric #if KMP_OS_WINDOWS 11680b57cec5SDimitry Andric #define KMP_INIT_WAIT 64U /* initial number of spin-tests */ 11690b57cec5SDimitry Andric #define KMP_NEXT_WAIT 32U /* susequent number of spin-tests */ 11700b57cec5SDimitry Andric #elif KMP_OS_LINUX 11710b57cec5SDimitry Andric #define KMP_INIT_WAIT 1024U /* initial number of spin-tests */ 11720b57cec5SDimitry Andric #define KMP_NEXT_WAIT 512U /* susequent number of spin-tests */ 11730b57cec5SDimitry Andric #elif KMP_OS_DARWIN 11740b57cec5SDimitry Andric /* TODO: tune for KMP_OS_DARWIN */ 11750b57cec5SDimitry Andric #define KMP_INIT_WAIT 1024U /* initial number of spin-tests */ 11760b57cec5SDimitry Andric #define KMP_NEXT_WAIT 512U /* susequent number of spin-tests */ 11770b57cec5SDimitry Andric #elif KMP_OS_DRAGONFLY 11780b57cec5SDimitry Andric /* TODO: tune for KMP_OS_DRAGONFLY */ 11790b57cec5SDimitry Andric #define KMP_INIT_WAIT 1024U /* initial number of spin-tests */ 11800b57cec5SDimitry Andric #define KMP_NEXT_WAIT 512U /* susequent number of spin-tests */ 11810b57cec5SDimitry Andric #elif KMP_OS_FREEBSD 11820b57cec5SDimitry Andric /* TODO: tune for KMP_OS_FREEBSD */ 11830b57cec5SDimitry Andric #define KMP_INIT_WAIT 1024U /* initial number of spin-tests */ 11840b57cec5SDimitry Andric #define KMP_NEXT_WAIT 512U /* susequent number of spin-tests */ 11850b57cec5SDimitry Andric #elif KMP_OS_NETBSD 11860b57cec5SDimitry Andric /* TODO: tune for KMP_OS_NETBSD */ 11870b57cec5SDimitry Andric #define KMP_INIT_WAIT 1024U /* initial number of spin-tests */ 11880b57cec5SDimitry Andric #define KMP_NEXT_WAIT 512U /* susequent number of spin-tests */ 11890b57cec5SDimitry Andric #elif KMP_OS_HURD 11900b57cec5SDimitry Andric /* TODO: tune for KMP_OS_HURD */ 11910b57cec5SDimitry Andric #define KMP_INIT_WAIT 1024U /* initial number of spin-tests */ 11920b57cec5SDimitry Andric #define KMP_NEXT_WAIT 512U /* susequent number of spin-tests */ 11930b57cec5SDimitry Andric #elif KMP_OS_OPENBSD 11940b57cec5SDimitry Andric /* TODO: tune for KMP_OS_OPENBSD */ 11950b57cec5SDimitry Andric #define KMP_INIT_WAIT 1024U /* initial number of spin-tests */ 11960b57cec5SDimitry Andric #define KMP_NEXT_WAIT 512U /* susequent number of spin-tests */ 11970b57cec5SDimitry Andric #endif 11980b57cec5SDimitry Andric 11990b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64 12000b57cec5SDimitry Andric typedef struct kmp_cpuid { 12010b57cec5SDimitry Andric kmp_uint32 eax; 12020b57cec5SDimitry Andric kmp_uint32 ebx; 12030b57cec5SDimitry Andric kmp_uint32 ecx; 12040b57cec5SDimitry Andric kmp_uint32 edx; 12050b57cec5SDimitry Andric } kmp_cpuid_t; 12060b57cec5SDimitry Andric 12070b57cec5SDimitry Andric typedef struct kmp_cpuinfo { 12080b57cec5SDimitry Andric int initialized; // If 0, other fields are not initialized. 12090b57cec5SDimitry Andric int signature; // CPUID(1).EAX 12100b57cec5SDimitry Andric int family; // CPUID(1).EAX[27:20]+CPUID(1).EAX[11:8] (Extended Family+Family) 12110b57cec5SDimitry Andric int model; // ( CPUID(1).EAX[19:16] << 4 ) + CPUID(1).EAX[7:4] ( ( Extended 12120b57cec5SDimitry Andric // Model << 4 ) + Model) 12130b57cec5SDimitry Andric int stepping; // CPUID(1).EAX[3:0] ( Stepping ) 12140b57cec5SDimitry Andric int sse2; // 0 if SSE2 instructions are not supported, 1 otherwise. 12150b57cec5SDimitry Andric int rtm; // 0 if RTM instructions are not supported, 1 otherwise. 12160b57cec5SDimitry Andric int apic_id; 12170b57cec5SDimitry Andric int physical_id; 12180b57cec5SDimitry Andric int logical_id; 12190b57cec5SDimitry Andric kmp_uint64 frequency; // Nominal CPU frequency in Hz. 12200b57cec5SDimitry Andric char name[3 * sizeof(kmp_cpuid_t)]; // CPUID(0x80000002,0x80000003,0x80000004) 12210b57cec5SDimitry Andric } kmp_cpuinfo_t; 12220b57cec5SDimitry Andric 12230b57cec5SDimitry Andric extern void __kmp_query_cpuid(kmp_cpuinfo_t *p); 12240b57cec5SDimitry Andric 12250b57cec5SDimitry Andric #if KMP_OS_UNIX 12260b57cec5SDimitry Andric // subleaf is only needed for cache and topology discovery and can be set to 12270b57cec5SDimitry Andric // zero in most cases 12280b57cec5SDimitry Andric static inline void __kmp_x86_cpuid(int leaf, int subleaf, struct kmp_cpuid *p) { 12290b57cec5SDimitry Andric __asm__ __volatile__("cpuid" 12300b57cec5SDimitry Andric : "=a"(p->eax), "=b"(p->ebx), "=c"(p->ecx), "=d"(p->edx) 12310b57cec5SDimitry Andric : "a"(leaf), "c"(subleaf)); 12320b57cec5SDimitry Andric } 12330b57cec5SDimitry Andric // Load p into FPU control word 12340b57cec5SDimitry Andric static inline void __kmp_load_x87_fpu_control_word(const kmp_int16 *p) { 12350b57cec5SDimitry Andric __asm__ __volatile__("fldcw %0" : : "m"(*p)); 12360b57cec5SDimitry Andric } 12370b57cec5SDimitry Andric // Store FPU control word into p 12380b57cec5SDimitry Andric static inline void __kmp_store_x87_fpu_control_word(kmp_int16 *p) { 12390b57cec5SDimitry Andric __asm__ __volatile__("fstcw %0" : "=m"(*p)); 12400b57cec5SDimitry Andric } 12410b57cec5SDimitry Andric static inline void __kmp_clear_x87_fpu_status_word() { 12420b57cec5SDimitry Andric #if KMP_MIC 12430b57cec5SDimitry Andric // 32-bit protected mode x87 FPU state 12440b57cec5SDimitry Andric struct x87_fpu_state { 12450b57cec5SDimitry Andric unsigned cw; 12460b57cec5SDimitry Andric unsigned sw; 12470b57cec5SDimitry Andric unsigned tw; 12480b57cec5SDimitry Andric unsigned fip; 12490b57cec5SDimitry Andric unsigned fips; 12500b57cec5SDimitry Andric unsigned fdp; 12510b57cec5SDimitry Andric unsigned fds; 12520b57cec5SDimitry Andric }; 12530b57cec5SDimitry Andric struct x87_fpu_state fpu_state = {0, 0, 0, 0, 0, 0, 0}; 12540b57cec5SDimitry Andric __asm__ __volatile__("fstenv %0\n\t" // store FP env 12550b57cec5SDimitry Andric "andw $0x7f00, %1\n\t" // clear 0-7,15 bits of FP SW 12560b57cec5SDimitry Andric "fldenv %0\n\t" // load FP env back 12570b57cec5SDimitry Andric : "+m"(fpu_state), "+m"(fpu_state.sw)); 12580b57cec5SDimitry Andric #else 12590b57cec5SDimitry Andric __asm__ __volatile__("fnclex"); 12600b57cec5SDimitry Andric #endif // KMP_MIC 12610b57cec5SDimitry Andric } 12620b57cec5SDimitry Andric #if __SSE__ 12630b57cec5SDimitry Andric static inline void __kmp_load_mxcsr(const kmp_uint32 *p) { _mm_setcsr(*p); } 12640b57cec5SDimitry Andric static inline void __kmp_store_mxcsr(kmp_uint32 *p) { *p = _mm_getcsr(); } 12650b57cec5SDimitry Andric #else 12660b57cec5SDimitry Andric static inline void __kmp_load_mxcsr(const kmp_uint32 *p) {} 12670b57cec5SDimitry Andric static inline void __kmp_store_mxcsr(kmp_uint32 *p) { *p = 0; } 12680b57cec5SDimitry Andric #endif 12690b57cec5SDimitry Andric #else 12700b57cec5SDimitry Andric // Windows still has these as external functions in assembly file 12710b57cec5SDimitry Andric extern void __kmp_x86_cpuid(int mode, int mode2, struct kmp_cpuid *p); 12720b57cec5SDimitry Andric extern void __kmp_load_x87_fpu_control_word(const kmp_int16 *p); 12730b57cec5SDimitry Andric extern void __kmp_store_x87_fpu_control_word(kmp_int16 *p); 12740b57cec5SDimitry Andric extern void __kmp_clear_x87_fpu_status_word(); 12750b57cec5SDimitry Andric static inline void __kmp_load_mxcsr(const kmp_uint32 *p) { _mm_setcsr(*p); } 12760b57cec5SDimitry Andric static inline void __kmp_store_mxcsr(kmp_uint32 *p) { *p = _mm_getcsr(); } 12770b57cec5SDimitry Andric #endif // KMP_OS_UNIX 12780b57cec5SDimitry Andric 12790b57cec5SDimitry Andric #define KMP_X86_MXCSR_MASK 0xffffffc0 /* ignore status flags (6 lsb) */ 12800b57cec5SDimitry Andric 12810b57cec5SDimitry Andric #if KMP_ARCH_X86 12820b57cec5SDimitry Andric extern void __kmp_x86_pause(void); 12830b57cec5SDimitry Andric #elif KMP_MIC 12840b57cec5SDimitry Andric // Performance testing on KNC (C0QS-7120 P/A/X/D, 61-core, 16 GB Memory) showed 12850b57cec5SDimitry Andric // regression after removal of extra PAUSE from spin loops. Changing 12860b57cec5SDimitry Andric // the delay from 100 to 300 showed even better performance than double PAUSE 12870b57cec5SDimitry Andric // on Spec OMP2001 and LCPC tasking tests, no regressions on EPCC. 12880b57cec5SDimitry Andric static inline void __kmp_x86_pause(void) { _mm_delay_32(300); } 12890b57cec5SDimitry Andric #else 12900b57cec5SDimitry Andric static inline void __kmp_x86_pause(void) { _mm_pause(); } 12910b57cec5SDimitry Andric #endif 12920b57cec5SDimitry Andric #define KMP_CPU_PAUSE() __kmp_x86_pause() 12930b57cec5SDimitry Andric #elif KMP_ARCH_PPC64 12940b57cec5SDimitry Andric #define KMP_PPC64_PRI_LOW() __asm__ volatile("or 1, 1, 1") 12950b57cec5SDimitry Andric #define KMP_PPC64_PRI_MED() __asm__ volatile("or 2, 2, 2") 12960b57cec5SDimitry Andric #define KMP_PPC64_PRI_LOC_MB() __asm__ volatile("" : : : "memory") 12970b57cec5SDimitry Andric #define KMP_CPU_PAUSE() \ 12980b57cec5SDimitry Andric do { \ 12990b57cec5SDimitry Andric KMP_PPC64_PRI_LOW(); \ 13000b57cec5SDimitry Andric KMP_PPC64_PRI_MED(); \ 13010b57cec5SDimitry Andric KMP_PPC64_PRI_LOC_MB(); \ 13020b57cec5SDimitry Andric } while (0) 13030b57cec5SDimitry Andric #else 13040b57cec5SDimitry Andric #define KMP_CPU_PAUSE() /* nothing to do */ 13050b57cec5SDimitry Andric #endif 13060b57cec5SDimitry Andric 13070b57cec5SDimitry Andric #define KMP_INIT_YIELD(count) \ 13080b57cec5SDimitry Andric { (count) = __kmp_yield_init; } 13090b57cec5SDimitry Andric 13100b57cec5SDimitry Andric #define KMP_OVERSUBSCRIBED \ 13110b57cec5SDimitry Andric (TCR_4(__kmp_nth) > (__kmp_avail_proc ? __kmp_avail_proc : __kmp_xproc)) 13120b57cec5SDimitry Andric 13130b57cec5SDimitry Andric #define KMP_TRY_YIELD \ 13140b57cec5SDimitry Andric ((__kmp_use_yield == 1) || (__kmp_use_yield == 2 && (KMP_OVERSUBSCRIBED))) 13150b57cec5SDimitry Andric 13160b57cec5SDimitry Andric #define KMP_TRY_YIELD_OVERSUB \ 13170b57cec5SDimitry Andric ((__kmp_use_yield == 1 || __kmp_use_yield == 2) && (KMP_OVERSUBSCRIBED)) 13180b57cec5SDimitry Andric 13190b57cec5SDimitry Andric #define KMP_YIELD(cond) \ 13200b57cec5SDimitry Andric { \ 13210b57cec5SDimitry Andric KMP_CPU_PAUSE(); \ 13220b57cec5SDimitry Andric if ((cond) && (KMP_TRY_YIELD)) \ 13230b57cec5SDimitry Andric __kmp_yield(); \ 13240b57cec5SDimitry Andric } 13250b57cec5SDimitry Andric 13260b57cec5SDimitry Andric #define KMP_YIELD_OVERSUB() \ 13270b57cec5SDimitry Andric { \ 13280b57cec5SDimitry Andric KMP_CPU_PAUSE(); \ 13290b57cec5SDimitry Andric if ((KMP_TRY_YIELD_OVERSUB)) \ 13300b57cec5SDimitry Andric __kmp_yield(); \ 13310b57cec5SDimitry Andric } 13320b57cec5SDimitry Andric 13330b57cec5SDimitry Andric // Note the decrement of 2 in the following Macros. With KMP_LIBRARY=turnaround, 13340b57cec5SDimitry Andric // there should be no yielding since initial value from KMP_INIT_YIELD() is odd. 13350b57cec5SDimitry Andric #define KMP_YIELD_SPIN(count) \ 13360b57cec5SDimitry Andric { \ 13370b57cec5SDimitry Andric KMP_CPU_PAUSE(); \ 13380b57cec5SDimitry Andric if (KMP_TRY_YIELD) { \ 13390b57cec5SDimitry Andric (count) -= 2; \ 13400b57cec5SDimitry Andric if (!(count)) { \ 13410b57cec5SDimitry Andric __kmp_yield(); \ 13420b57cec5SDimitry Andric (count) = __kmp_yield_next; \ 13430b57cec5SDimitry Andric } \ 13440b57cec5SDimitry Andric } \ 13450b57cec5SDimitry Andric } 13460b57cec5SDimitry Andric 13470b57cec5SDimitry Andric #define KMP_YIELD_OVERSUB_ELSE_SPIN(count) \ 13480b57cec5SDimitry Andric { \ 13490b57cec5SDimitry Andric KMP_CPU_PAUSE(); \ 13500b57cec5SDimitry Andric if ((KMP_TRY_YIELD_OVERSUB)) \ 13510b57cec5SDimitry Andric __kmp_yield(); \ 13520b57cec5SDimitry Andric else if (__kmp_use_yield == 1) { \ 13530b57cec5SDimitry Andric (count) -= 2; \ 13540b57cec5SDimitry Andric if (!(count)) { \ 13550b57cec5SDimitry Andric __kmp_yield(); \ 13560b57cec5SDimitry Andric (count) = __kmp_yield_next; \ 13570b57cec5SDimitry Andric } \ 13580b57cec5SDimitry Andric } \ 13590b57cec5SDimitry Andric } 13600b57cec5SDimitry Andric 1361e8d8bef9SDimitry Andric // User-level Monitor/Mwait 1362e8d8bef9SDimitry Andric #if KMP_HAVE_UMWAIT 1363e8d8bef9SDimitry Andric // We always try for UMWAIT first 1364e8d8bef9SDimitry Andric #if KMP_HAVE_WAITPKG_INTRINSICS 1365e8d8bef9SDimitry Andric #if KMP_HAVE_IMMINTRIN_H 1366e8d8bef9SDimitry Andric #include <immintrin.h> 1367e8d8bef9SDimitry Andric #elif KMP_HAVE_INTRIN_H 1368e8d8bef9SDimitry Andric #include <intrin.h> 1369e8d8bef9SDimitry Andric #endif 1370e8d8bef9SDimitry Andric #endif // KMP_HAVE_WAITPKG_INTRINSICS 1371e8d8bef9SDimitry Andric KMP_ATTRIBUTE_TARGET_WAITPKG 1372*fe6060f1SDimitry Andric static inline int __kmp_tpause(uint32_t hint, uint64_t counter) { 1373e8d8bef9SDimitry Andric #if !KMP_HAVE_WAITPKG_INTRINSICS 1374e8d8bef9SDimitry Andric uint32_t timeHi = uint32_t(counter >> 32); 1375e8d8bef9SDimitry Andric uint32_t timeLo = uint32_t(counter & 0xffffffff); 1376e8d8bef9SDimitry Andric char flag; 1377e8d8bef9SDimitry Andric __asm__ volatile("#tpause\n.byte 0x66, 0x0F, 0xAE, 0xF1\n" 1378e8d8bef9SDimitry Andric "setb %0" 1379e8d8bef9SDimitry Andric : "=r"(flag) 1380e8d8bef9SDimitry Andric : "a"(timeLo), "d"(timeHi), "c"(hint) 1381e8d8bef9SDimitry Andric :); 1382e8d8bef9SDimitry Andric return flag; 1383e8d8bef9SDimitry Andric #else 1384e8d8bef9SDimitry Andric return _tpause(hint, counter); 1385e8d8bef9SDimitry Andric #endif 1386e8d8bef9SDimitry Andric } 1387e8d8bef9SDimitry Andric KMP_ATTRIBUTE_TARGET_WAITPKG 1388*fe6060f1SDimitry Andric static inline void __kmp_umonitor(void *cacheline) { 1389e8d8bef9SDimitry Andric #if !KMP_HAVE_WAITPKG_INTRINSICS 1390e8d8bef9SDimitry Andric __asm__ volatile("# umonitor\n.byte 0xF3, 0x0F, 0xAE, 0x01 " 1391e8d8bef9SDimitry Andric : 1392e8d8bef9SDimitry Andric : "a"(cacheline) 1393e8d8bef9SDimitry Andric :); 1394e8d8bef9SDimitry Andric #else 1395e8d8bef9SDimitry Andric _umonitor(cacheline); 1396e8d8bef9SDimitry Andric #endif 1397e8d8bef9SDimitry Andric } 1398e8d8bef9SDimitry Andric KMP_ATTRIBUTE_TARGET_WAITPKG 1399*fe6060f1SDimitry Andric static inline int __kmp_umwait(uint32_t hint, uint64_t counter) { 1400e8d8bef9SDimitry Andric #if !KMP_HAVE_WAITPKG_INTRINSICS 1401e8d8bef9SDimitry Andric uint32_t timeHi = uint32_t(counter >> 32); 1402e8d8bef9SDimitry Andric uint32_t timeLo = uint32_t(counter & 0xffffffff); 1403e8d8bef9SDimitry Andric char flag; 1404e8d8bef9SDimitry Andric __asm__ volatile("#umwait\n.byte 0xF2, 0x0F, 0xAE, 0xF1\n" 1405e8d8bef9SDimitry Andric "setb %0" 1406e8d8bef9SDimitry Andric : "=r"(flag) 1407e8d8bef9SDimitry Andric : "a"(timeLo), "d"(timeHi), "c"(hint) 1408e8d8bef9SDimitry Andric :); 1409e8d8bef9SDimitry Andric return flag; 1410e8d8bef9SDimitry Andric #else 1411e8d8bef9SDimitry Andric return _umwait(hint, counter); 1412e8d8bef9SDimitry Andric #endif 1413e8d8bef9SDimitry Andric } 1414e8d8bef9SDimitry Andric #elif KMP_HAVE_MWAIT 1415e8d8bef9SDimitry Andric #if KMP_OS_UNIX 1416e8d8bef9SDimitry Andric #include <pmmintrin.h> 1417e8d8bef9SDimitry Andric #else 1418e8d8bef9SDimitry Andric #include <intrin.h> 1419e8d8bef9SDimitry Andric #endif 1420e8d8bef9SDimitry Andric #if KMP_OS_UNIX 1421e8d8bef9SDimitry Andric __attribute__((target("sse3"))) 1422e8d8bef9SDimitry Andric #endif 1423e8d8bef9SDimitry Andric static inline void 1424e8d8bef9SDimitry Andric __kmp_mm_monitor(void *cacheline, unsigned extensions, unsigned hints) { 1425e8d8bef9SDimitry Andric _mm_monitor(cacheline, extensions, hints); 1426e8d8bef9SDimitry Andric } 1427e8d8bef9SDimitry Andric #if KMP_OS_UNIX 1428e8d8bef9SDimitry Andric __attribute__((target("sse3"))) 1429e8d8bef9SDimitry Andric #endif 1430e8d8bef9SDimitry Andric static inline void 1431e8d8bef9SDimitry Andric __kmp_mm_mwait(unsigned extensions, unsigned hints) { 1432e8d8bef9SDimitry Andric _mm_mwait(extensions, hints); 1433e8d8bef9SDimitry Andric } 1434e8d8bef9SDimitry Andric #endif // KMP_HAVE_UMWAIT 1435e8d8bef9SDimitry Andric 14360b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */ 14370b57cec5SDimitry Andric /* Support datatypes for the orphaned construct nesting checks. */ 14380b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */ 14390b57cec5SDimitry Andric 14400b57cec5SDimitry Andric enum cons_type { 14410b57cec5SDimitry Andric ct_none, 14420b57cec5SDimitry Andric ct_parallel, 14430b57cec5SDimitry Andric ct_pdo, 14440b57cec5SDimitry Andric ct_pdo_ordered, 14450b57cec5SDimitry Andric ct_psections, 14460b57cec5SDimitry Andric ct_psingle, 14470b57cec5SDimitry Andric ct_critical, 14480b57cec5SDimitry Andric ct_ordered_in_parallel, 14490b57cec5SDimitry Andric ct_ordered_in_pdo, 14500b57cec5SDimitry Andric ct_master, 14510b57cec5SDimitry Andric ct_reduce, 1452*fe6060f1SDimitry Andric ct_barrier, 1453*fe6060f1SDimitry Andric ct_masked 14540b57cec5SDimitry Andric }; 14550b57cec5SDimitry Andric 14560b57cec5SDimitry Andric #define IS_CONS_TYPE_ORDERED(ct) ((ct) == ct_pdo_ordered) 14570b57cec5SDimitry Andric 14580b57cec5SDimitry Andric struct cons_data { 14590b57cec5SDimitry Andric ident_t const *ident; 14600b57cec5SDimitry Andric enum cons_type type; 14610b57cec5SDimitry Andric int prev; 14620b57cec5SDimitry Andric kmp_user_lock_p 14630b57cec5SDimitry Andric name; /* address exclusively for critical section name comparison */ 14640b57cec5SDimitry Andric }; 14650b57cec5SDimitry Andric 14660b57cec5SDimitry Andric struct cons_header { 14670b57cec5SDimitry Andric int p_top, w_top, s_top; 14680b57cec5SDimitry Andric int stack_size, stack_top; 14690b57cec5SDimitry Andric struct cons_data *stack_data; 14700b57cec5SDimitry Andric }; 14710b57cec5SDimitry Andric 14720b57cec5SDimitry Andric struct kmp_region_info { 14730b57cec5SDimitry Andric char *text; 14740b57cec5SDimitry Andric int offset[KMP_MAX_FIELDS]; 14750b57cec5SDimitry Andric int length[KMP_MAX_FIELDS]; 14760b57cec5SDimitry Andric }; 14770b57cec5SDimitry Andric 14780b57cec5SDimitry Andric /* ---------------------------------------------------------------------- */ 14790b57cec5SDimitry Andric /* ---------------------------------------------------------------------- */ 14800b57cec5SDimitry Andric 14810b57cec5SDimitry Andric #if KMP_OS_WINDOWS 14820b57cec5SDimitry Andric typedef HANDLE kmp_thread_t; 14830b57cec5SDimitry Andric typedef DWORD kmp_key_t; 14840b57cec5SDimitry Andric #endif /* KMP_OS_WINDOWS */ 14850b57cec5SDimitry Andric 14860b57cec5SDimitry Andric #if KMP_OS_UNIX 14870b57cec5SDimitry Andric typedef pthread_t kmp_thread_t; 14880b57cec5SDimitry Andric typedef pthread_key_t kmp_key_t; 14890b57cec5SDimitry Andric #endif 14900b57cec5SDimitry Andric 14910b57cec5SDimitry Andric extern kmp_key_t __kmp_gtid_threadprivate_key; 14920b57cec5SDimitry Andric 14930b57cec5SDimitry Andric typedef struct kmp_sys_info { 14940b57cec5SDimitry Andric long maxrss; /* the maximum resident set size utilized (in kilobytes) */ 14950b57cec5SDimitry Andric long minflt; /* the number of page faults serviced without any I/O */ 14960b57cec5SDimitry Andric long majflt; /* the number of page faults serviced that required I/O */ 14970b57cec5SDimitry Andric long nswap; /* the number of times a process was "swapped" out of memory */ 14980b57cec5SDimitry Andric long inblock; /* the number of times the file system had to perform input */ 14990b57cec5SDimitry Andric long oublock; /* the number of times the file system had to perform output */ 15000b57cec5SDimitry Andric long nvcsw; /* the number of times a context switch was voluntarily */ 15010b57cec5SDimitry Andric long nivcsw; /* the number of times a context switch was forced */ 15020b57cec5SDimitry Andric } kmp_sys_info_t; 15030b57cec5SDimitry Andric 15040b57cec5SDimitry Andric #if USE_ITT_BUILD 15050b57cec5SDimitry Andric // We cannot include "kmp_itt.h" due to circular dependency. Declare the only 15060b57cec5SDimitry Andric // required type here. Later we will check the type meets requirements. 15070b57cec5SDimitry Andric typedef int kmp_itt_mark_t; 15080b57cec5SDimitry Andric #define KMP_ITT_DEBUG 0 15090b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 15100b57cec5SDimitry Andric 15110b57cec5SDimitry Andric typedef kmp_int32 kmp_critical_name[8]; 15120b57cec5SDimitry Andric 15130b57cec5SDimitry Andric /*! 15140b57cec5SDimitry Andric @ingroup PARALLEL 15150b57cec5SDimitry Andric The type for a microtask which gets passed to @ref __kmpc_fork_call(). 15160b57cec5SDimitry Andric The arguments to the outlined function are 15170b57cec5SDimitry Andric @param global_tid the global thread identity of the thread executing the 15180b57cec5SDimitry Andric function. 1519480093f4SDimitry Andric @param bound_tid the local identity of the thread executing the function 15200b57cec5SDimitry Andric @param ... pointers to shared variables accessed by the function. 15210b57cec5SDimitry Andric */ 15220b57cec5SDimitry Andric typedef void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid, ...); 15230b57cec5SDimitry Andric typedef void (*kmpc_micro_bound)(kmp_int32 *bound_tid, kmp_int32 *bound_nth, 15240b57cec5SDimitry Andric ...); 15250b57cec5SDimitry Andric 15260b57cec5SDimitry Andric /*! 15270b57cec5SDimitry Andric @ingroup THREADPRIVATE 15280b57cec5SDimitry Andric @{ 15290b57cec5SDimitry Andric */ 15300b57cec5SDimitry Andric /* --------------------------------------------------------------------------- 15310b57cec5SDimitry Andric */ 15320b57cec5SDimitry Andric /* Threadprivate initialization/finalization function declarations */ 15330b57cec5SDimitry Andric 15340b57cec5SDimitry Andric /* for non-array objects: __kmpc_threadprivate_register() */ 15350b57cec5SDimitry Andric 15360b57cec5SDimitry Andric /*! 15370b57cec5SDimitry Andric Pointer to the constructor function. 15380b57cec5SDimitry Andric The first argument is the <tt>this</tt> pointer 15390b57cec5SDimitry Andric */ 15400b57cec5SDimitry Andric typedef void *(*kmpc_ctor)(void *); 15410b57cec5SDimitry Andric 15420b57cec5SDimitry Andric /*! 15430b57cec5SDimitry Andric Pointer to the destructor function. 15440b57cec5SDimitry Andric The first argument is the <tt>this</tt> pointer 15450b57cec5SDimitry Andric */ 15460b57cec5SDimitry Andric typedef void (*kmpc_dtor)( 15470b57cec5SDimitry Andric void * /*, size_t */); /* 2nd arg: magic number for KCC unused by Intel 15480b57cec5SDimitry Andric compiler */ 15490b57cec5SDimitry Andric /*! 15500b57cec5SDimitry Andric Pointer to an alternate constructor. 15510b57cec5SDimitry Andric The first argument is the <tt>this</tt> pointer. 15520b57cec5SDimitry Andric */ 15530b57cec5SDimitry Andric typedef void *(*kmpc_cctor)(void *, void *); 15540b57cec5SDimitry Andric 15550b57cec5SDimitry Andric /* for array objects: __kmpc_threadprivate_register_vec() */ 15560b57cec5SDimitry Andric /* First arg: "this" pointer */ 15570b57cec5SDimitry Andric /* Last arg: number of array elements */ 15580b57cec5SDimitry Andric /*! 15590b57cec5SDimitry Andric Array constructor. 15600b57cec5SDimitry Andric First argument is the <tt>this</tt> pointer 15610b57cec5SDimitry Andric Second argument the number of array elements. 15620b57cec5SDimitry Andric */ 15630b57cec5SDimitry Andric typedef void *(*kmpc_ctor_vec)(void *, size_t); 15640b57cec5SDimitry Andric /*! 15650b57cec5SDimitry Andric Pointer to the array destructor function. 15660b57cec5SDimitry Andric The first argument is the <tt>this</tt> pointer 15670b57cec5SDimitry Andric Second argument the number of array elements. 15680b57cec5SDimitry Andric */ 15690b57cec5SDimitry Andric typedef void (*kmpc_dtor_vec)(void *, size_t); 15700b57cec5SDimitry Andric /*! 15710b57cec5SDimitry Andric Array constructor. 15720b57cec5SDimitry Andric First argument is the <tt>this</tt> pointer 15730b57cec5SDimitry Andric Third argument the number of array elements. 15740b57cec5SDimitry Andric */ 15750b57cec5SDimitry Andric typedef void *(*kmpc_cctor_vec)(void *, void *, 15760b57cec5SDimitry Andric size_t); /* function unused by compiler */ 15770b57cec5SDimitry Andric 15780b57cec5SDimitry Andric /*! 15790b57cec5SDimitry Andric @} 15800b57cec5SDimitry Andric */ 15810b57cec5SDimitry Andric 15820b57cec5SDimitry Andric /* keeps tracked of threadprivate cache allocations for cleanup later */ 15830b57cec5SDimitry Andric typedef struct kmp_cached_addr { 15840b57cec5SDimitry Andric void **addr; /* address of allocated cache */ 15850b57cec5SDimitry Andric void ***compiler_cache; /* pointer to compiler's cache */ 15860b57cec5SDimitry Andric void *data; /* pointer to global data */ 15870b57cec5SDimitry Andric struct kmp_cached_addr *next; /* pointer to next cached address */ 15880b57cec5SDimitry Andric } kmp_cached_addr_t; 15890b57cec5SDimitry Andric 15900b57cec5SDimitry Andric struct private_data { 15910b57cec5SDimitry Andric struct private_data *next; /* The next descriptor in the list */ 15920b57cec5SDimitry Andric void *data; /* The data buffer for this descriptor */ 15930b57cec5SDimitry Andric int more; /* The repeat count for this descriptor */ 15940b57cec5SDimitry Andric size_t size; /* The data size for this descriptor */ 15950b57cec5SDimitry Andric }; 15960b57cec5SDimitry Andric 15970b57cec5SDimitry Andric struct private_common { 15980b57cec5SDimitry Andric struct private_common *next; 15990b57cec5SDimitry Andric struct private_common *link; 16000b57cec5SDimitry Andric void *gbl_addr; 1601*fe6060f1SDimitry Andric void *par_addr; /* par_addr == gbl_addr for PRIMARY thread */ 16020b57cec5SDimitry Andric size_t cmn_size; 16030b57cec5SDimitry Andric }; 16040b57cec5SDimitry Andric 16050b57cec5SDimitry Andric struct shared_common { 16060b57cec5SDimitry Andric struct shared_common *next; 16070b57cec5SDimitry Andric struct private_data *pod_init; 16080b57cec5SDimitry Andric void *obj_init; 16090b57cec5SDimitry Andric void *gbl_addr; 16100b57cec5SDimitry Andric union { 16110b57cec5SDimitry Andric kmpc_ctor ctor; 16120b57cec5SDimitry Andric kmpc_ctor_vec ctorv; 16130b57cec5SDimitry Andric } ct; 16140b57cec5SDimitry Andric union { 16150b57cec5SDimitry Andric kmpc_cctor cctor; 16160b57cec5SDimitry Andric kmpc_cctor_vec cctorv; 16170b57cec5SDimitry Andric } cct; 16180b57cec5SDimitry Andric union { 16190b57cec5SDimitry Andric kmpc_dtor dtor; 16200b57cec5SDimitry Andric kmpc_dtor_vec dtorv; 16210b57cec5SDimitry Andric } dt; 16220b57cec5SDimitry Andric size_t vec_len; 16230b57cec5SDimitry Andric int is_vec; 16240b57cec5SDimitry Andric size_t cmn_size; 16250b57cec5SDimitry Andric }; 16260b57cec5SDimitry Andric 16270b57cec5SDimitry Andric #define KMP_HASH_TABLE_LOG2 9 /* log2 of the hash table size */ 16280b57cec5SDimitry Andric #define KMP_HASH_TABLE_SIZE \ 16290b57cec5SDimitry Andric (1 << KMP_HASH_TABLE_LOG2) /* size of the hash table */ 16300b57cec5SDimitry Andric #define KMP_HASH_SHIFT 3 /* throw away this many low bits from the address */ 16310b57cec5SDimitry Andric #define KMP_HASH(x) \ 16320b57cec5SDimitry Andric ((((kmp_uintptr_t)x) >> KMP_HASH_SHIFT) & (KMP_HASH_TABLE_SIZE - 1)) 16330b57cec5SDimitry Andric 16340b57cec5SDimitry Andric struct common_table { 16350b57cec5SDimitry Andric struct private_common *data[KMP_HASH_TABLE_SIZE]; 16360b57cec5SDimitry Andric }; 16370b57cec5SDimitry Andric 16380b57cec5SDimitry Andric struct shared_table { 16390b57cec5SDimitry Andric struct shared_common *data[KMP_HASH_TABLE_SIZE]; 16400b57cec5SDimitry Andric }; 16410b57cec5SDimitry Andric 16420b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */ 16430b57cec5SDimitry Andric 16440b57cec5SDimitry Andric #if KMP_USE_HIER_SCHED 16450b57cec5SDimitry Andric // Shared barrier data that exists inside a single unit of the scheduling 16460b57cec5SDimitry Andric // hierarchy 16470b57cec5SDimitry Andric typedef struct kmp_hier_private_bdata_t { 16480b57cec5SDimitry Andric kmp_int32 num_active; 16490b57cec5SDimitry Andric kmp_uint64 index; 16500b57cec5SDimitry Andric kmp_uint64 wait_val[2]; 16510b57cec5SDimitry Andric } kmp_hier_private_bdata_t; 16520b57cec5SDimitry Andric #endif 16530b57cec5SDimitry Andric 16540b57cec5SDimitry Andric typedef struct kmp_sched_flags { 16550b57cec5SDimitry Andric unsigned ordered : 1; 16560b57cec5SDimitry Andric unsigned nomerge : 1; 16570b57cec5SDimitry Andric unsigned contains_last : 1; 16580b57cec5SDimitry Andric #if KMP_USE_HIER_SCHED 16590b57cec5SDimitry Andric unsigned use_hier : 1; 16600b57cec5SDimitry Andric unsigned unused : 28; 16610b57cec5SDimitry Andric #else 16620b57cec5SDimitry Andric unsigned unused : 29; 16630b57cec5SDimitry Andric #endif 16640b57cec5SDimitry Andric } kmp_sched_flags_t; 16650b57cec5SDimitry Andric 16660b57cec5SDimitry Andric KMP_BUILD_ASSERT(sizeof(kmp_sched_flags_t) == 4); 16670b57cec5SDimitry Andric 16680b57cec5SDimitry Andric #if KMP_STATIC_STEAL_ENABLED 16690b57cec5SDimitry Andric typedef struct KMP_ALIGN_CACHE dispatch_private_info32 { 16700b57cec5SDimitry Andric kmp_int32 count; 16710b57cec5SDimitry Andric kmp_int32 ub; 16720b57cec5SDimitry Andric /* Adding KMP_ALIGN_CACHE here doesn't help / can hurt performance */ 16730b57cec5SDimitry Andric kmp_int32 lb; 16740b57cec5SDimitry Andric kmp_int32 st; 16750b57cec5SDimitry Andric kmp_int32 tc; 1676*fe6060f1SDimitry Andric kmp_lock_t *steal_lock; // lock used for chunk stealing 1677*fe6060f1SDimitry Andric // KMP_ALIGN(32) ensures (if the KMP_ALIGN macro is turned on) 16780b57cec5SDimitry Andric // a) parm3 is properly aligned and 1679*fe6060f1SDimitry Andric // b) all parm1-4 are on the same cache line. 16800b57cec5SDimitry Andric // Because of parm1-4 are used together, performance seems to be better 1681*fe6060f1SDimitry Andric // if they are on the same cache line (not measured though). 16820b57cec5SDimitry Andric 16830b57cec5SDimitry Andric struct KMP_ALIGN(32) { // AC: changed 16 to 32 in order to simplify template 16840b57cec5SDimitry Andric kmp_int32 parm1; // structures in kmp_dispatch.cpp. This should 16850b57cec5SDimitry Andric kmp_int32 parm2; // make no real change at least while padding is off. 16860b57cec5SDimitry Andric kmp_int32 parm3; 16870b57cec5SDimitry Andric kmp_int32 parm4; 16880b57cec5SDimitry Andric }; 16890b57cec5SDimitry Andric 16900b57cec5SDimitry Andric kmp_uint32 ordered_lower; 16910b57cec5SDimitry Andric kmp_uint32 ordered_upper; 16920b57cec5SDimitry Andric #if KMP_OS_WINDOWS 16930b57cec5SDimitry Andric kmp_int32 last_upper; 16940b57cec5SDimitry Andric #endif /* KMP_OS_WINDOWS */ 16950b57cec5SDimitry Andric } dispatch_private_info32_t; 16960b57cec5SDimitry Andric 16970b57cec5SDimitry Andric typedef struct KMP_ALIGN_CACHE dispatch_private_info64 { 16980b57cec5SDimitry Andric kmp_int64 count; // current chunk number for static & static-steal scheduling 16990b57cec5SDimitry Andric kmp_int64 ub; /* upper-bound */ 17000b57cec5SDimitry Andric /* Adding KMP_ALIGN_CACHE here doesn't help / can hurt performance */ 17010b57cec5SDimitry Andric kmp_int64 lb; /* lower-bound */ 17020b57cec5SDimitry Andric kmp_int64 st; /* stride */ 17030b57cec5SDimitry Andric kmp_int64 tc; /* trip count (number of iterations) */ 1704*fe6060f1SDimitry Andric kmp_lock_t *steal_lock; // lock used for chunk stealing 17050b57cec5SDimitry Andric /* parm[1-4] are used in different ways by different scheduling algorithms */ 17060b57cec5SDimitry Andric 17070b57cec5SDimitry Andric // KMP_ALIGN( 32 ) ensures ( if the KMP_ALIGN macro is turned on ) 17080b57cec5SDimitry Andric // a) parm3 is properly aligned and 17090b57cec5SDimitry Andric // b) all parm1-4 are in the same cache line. 17100b57cec5SDimitry Andric // Because of parm1-4 are used together, performance seems to be better 17110b57cec5SDimitry Andric // if they are in the same line (not measured though). 17120b57cec5SDimitry Andric 17130b57cec5SDimitry Andric struct KMP_ALIGN(32) { 17140b57cec5SDimitry Andric kmp_int64 parm1; 17150b57cec5SDimitry Andric kmp_int64 parm2; 17160b57cec5SDimitry Andric kmp_int64 parm3; 17170b57cec5SDimitry Andric kmp_int64 parm4; 17180b57cec5SDimitry Andric }; 17190b57cec5SDimitry Andric 17200b57cec5SDimitry Andric kmp_uint64 ordered_lower; 17210b57cec5SDimitry Andric kmp_uint64 ordered_upper; 17220b57cec5SDimitry Andric #if KMP_OS_WINDOWS 17230b57cec5SDimitry Andric kmp_int64 last_upper; 17240b57cec5SDimitry Andric #endif /* KMP_OS_WINDOWS */ 17250b57cec5SDimitry Andric } dispatch_private_info64_t; 17260b57cec5SDimitry Andric #else /* KMP_STATIC_STEAL_ENABLED */ 17270b57cec5SDimitry Andric typedef struct KMP_ALIGN_CACHE dispatch_private_info32 { 17280b57cec5SDimitry Andric kmp_int32 lb; 17290b57cec5SDimitry Andric kmp_int32 ub; 17300b57cec5SDimitry Andric kmp_int32 st; 17310b57cec5SDimitry Andric kmp_int32 tc; 17320b57cec5SDimitry Andric 17330b57cec5SDimitry Andric kmp_int32 parm1; 17340b57cec5SDimitry Andric kmp_int32 parm2; 17350b57cec5SDimitry Andric kmp_int32 parm3; 17360b57cec5SDimitry Andric kmp_int32 parm4; 17370b57cec5SDimitry Andric 17380b57cec5SDimitry Andric kmp_int32 count; 17390b57cec5SDimitry Andric 17400b57cec5SDimitry Andric kmp_uint32 ordered_lower; 17410b57cec5SDimitry Andric kmp_uint32 ordered_upper; 17420b57cec5SDimitry Andric #if KMP_OS_WINDOWS 17430b57cec5SDimitry Andric kmp_int32 last_upper; 17440b57cec5SDimitry Andric #endif /* KMP_OS_WINDOWS */ 17450b57cec5SDimitry Andric } dispatch_private_info32_t; 17460b57cec5SDimitry Andric 17470b57cec5SDimitry Andric typedef struct KMP_ALIGN_CACHE dispatch_private_info64 { 17480b57cec5SDimitry Andric kmp_int64 lb; /* lower-bound */ 17490b57cec5SDimitry Andric kmp_int64 ub; /* upper-bound */ 17500b57cec5SDimitry Andric kmp_int64 st; /* stride */ 17510b57cec5SDimitry Andric kmp_int64 tc; /* trip count (number of iterations) */ 17520b57cec5SDimitry Andric 17530b57cec5SDimitry Andric /* parm[1-4] are used in different ways by different scheduling algorithms */ 17540b57cec5SDimitry Andric kmp_int64 parm1; 17550b57cec5SDimitry Andric kmp_int64 parm2; 17560b57cec5SDimitry Andric kmp_int64 parm3; 17570b57cec5SDimitry Andric kmp_int64 parm4; 17580b57cec5SDimitry Andric 17590b57cec5SDimitry Andric kmp_int64 count; /* current chunk number for static scheduling */ 17600b57cec5SDimitry Andric 17610b57cec5SDimitry Andric kmp_uint64 ordered_lower; 17620b57cec5SDimitry Andric kmp_uint64 ordered_upper; 17630b57cec5SDimitry Andric #if KMP_OS_WINDOWS 17640b57cec5SDimitry Andric kmp_int64 last_upper; 17650b57cec5SDimitry Andric #endif /* KMP_OS_WINDOWS */ 17660b57cec5SDimitry Andric } dispatch_private_info64_t; 17670b57cec5SDimitry Andric #endif /* KMP_STATIC_STEAL_ENABLED */ 17680b57cec5SDimitry Andric 17690b57cec5SDimitry Andric typedef struct KMP_ALIGN_CACHE dispatch_private_info { 17700b57cec5SDimitry Andric union private_info { 17710b57cec5SDimitry Andric dispatch_private_info32_t p32; 17720b57cec5SDimitry Andric dispatch_private_info64_t p64; 17730b57cec5SDimitry Andric } u; 17740b57cec5SDimitry Andric enum sched_type schedule; /* scheduling algorithm */ 17750b57cec5SDimitry Andric kmp_sched_flags_t flags; /* flags (e.g., ordered, nomerge, etc.) */ 1776*fe6060f1SDimitry Andric std::atomic<kmp_uint32> steal_flag; // static_steal only, state of a buffer 17770b57cec5SDimitry Andric kmp_int32 ordered_bumped; 17780b57cec5SDimitry Andric // Stack of buffers for nest of serial regions 17790b57cec5SDimitry Andric struct dispatch_private_info *next; 17800b57cec5SDimitry Andric kmp_int32 type_size; /* the size of types in private_info */ 17810b57cec5SDimitry Andric #if KMP_USE_HIER_SCHED 17820b57cec5SDimitry Andric kmp_int32 hier_id; 17830b57cec5SDimitry Andric void *parent; /* hierarchical scheduling parent pointer */ 17840b57cec5SDimitry Andric #endif 17850b57cec5SDimitry Andric enum cons_type pushed_ws; 17860b57cec5SDimitry Andric } dispatch_private_info_t; 17870b57cec5SDimitry Andric 17880b57cec5SDimitry Andric typedef struct dispatch_shared_info32 { 17890b57cec5SDimitry Andric /* chunk index under dynamic, number of idle threads under static-steal; 17900b57cec5SDimitry Andric iteration index otherwise */ 17910b57cec5SDimitry Andric volatile kmp_uint32 iteration; 1792*fe6060f1SDimitry Andric volatile kmp_int32 num_done; 17930b57cec5SDimitry Andric volatile kmp_uint32 ordered_iteration; 17940b57cec5SDimitry Andric // Dummy to retain the structure size after making ordered_iteration scalar 17950b57cec5SDimitry Andric kmp_int32 ordered_dummy[KMP_MAX_ORDERED - 1]; 17960b57cec5SDimitry Andric } dispatch_shared_info32_t; 17970b57cec5SDimitry Andric 17980b57cec5SDimitry Andric typedef struct dispatch_shared_info64 { 17990b57cec5SDimitry Andric /* chunk index under dynamic, number of idle threads under static-steal; 18000b57cec5SDimitry Andric iteration index otherwise */ 18010b57cec5SDimitry Andric volatile kmp_uint64 iteration; 1802*fe6060f1SDimitry Andric volatile kmp_int64 num_done; 18030b57cec5SDimitry Andric volatile kmp_uint64 ordered_iteration; 18040b57cec5SDimitry Andric // Dummy to retain the structure size after making ordered_iteration scalar 18050b57cec5SDimitry Andric kmp_int64 ordered_dummy[KMP_MAX_ORDERED - 3]; 18060b57cec5SDimitry Andric } dispatch_shared_info64_t; 18070b57cec5SDimitry Andric 18080b57cec5SDimitry Andric typedef struct dispatch_shared_info { 18090b57cec5SDimitry Andric union shared_info { 18100b57cec5SDimitry Andric dispatch_shared_info32_t s32; 18110b57cec5SDimitry Andric dispatch_shared_info64_t s64; 18120b57cec5SDimitry Andric } u; 18130b57cec5SDimitry Andric volatile kmp_uint32 buffer_index; 18140b57cec5SDimitry Andric volatile kmp_int32 doacross_buf_idx; // teamwise index 18150b57cec5SDimitry Andric volatile kmp_uint32 *doacross_flags; // shared array of iteration flags (0/1) 18160b57cec5SDimitry Andric kmp_int32 doacross_num_done; // count finished threads 18170b57cec5SDimitry Andric #if KMP_USE_HIER_SCHED 18180b57cec5SDimitry Andric void *hier; 18190b57cec5SDimitry Andric #endif 18200b57cec5SDimitry Andric #if KMP_USE_HWLOC 18210b57cec5SDimitry Andric // When linking with libhwloc, the ORDERED EPCC test slows down on big 18220b57cec5SDimitry Andric // machines (> 48 cores). Performance analysis showed that a cache thrash 18230b57cec5SDimitry Andric // was occurring and this padding helps alleviate the problem. 18240b57cec5SDimitry Andric char padding[64]; 18250b57cec5SDimitry Andric #endif 18260b57cec5SDimitry Andric } dispatch_shared_info_t; 18270b57cec5SDimitry Andric 18280b57cec5SDimitry Andric typedef struct kmp_disp { 18290b57cec5SDimitry Andric /* Vector for ORDERED SECTION */ 18300b57cec5SDimitry Andric void (*th_deo_fcn)(int *gtid, int *cid, ident_t *); 18310b57cec5SDimitry Andric /* Vector for END ORDERED SECTION */ 18320b57cec5SDimitry Andric void (*th_dxo_fcn)(int *gtid, int *cid, ident_t *); 18330b57cec5SDimitry Andric 18340b57cec5SDimitry Andric dispatch_shared_info_t *th_dispatch_sh_current; 18350b57cec5SDimitry Andric dispatch_private_info_t *th_dispatch_pr_current; 18360b57cec5SDimitry Andric 18370b57cec5SDimitry Andric dispatch_private_info_t *th_disp_buffer; 1838*fe6060f1SDimitry Andric kmp_uint32 th_disp_index; 18390b57cec5SDimitry Andric kmp_int32 th_doacross_buf_idx; // thread's doacross buffer index 18400b57cec5SDimitry Andric volatile kmp_uint32 *th_doacross_flags; // pointer to shared array of flags 18410b57cec5SDimitry Andric kmp_int64 *th_doacross_info; // info on loop bounds 18420b57cec5SDimitry Andric #if KMP_USE_INTERNODE_ALIGNMENT 18430b57cec5SDimitry Andric char more_padding[INTERNODE_CACHE_LINE]; 18440b57cec5SDimitry Andric #endif 18450b57cec5SDimitry Andric } kmp_disp_t; 18460b57cec5SDimitry Andric 18470b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */ 18480b57cec5SDimitry Andric /* Barrier stuff */ 18490b57cec5SDimitry Andric 18500b57cec5SDimitry Andric /* constants for barrier state update */ 18510b57cec5SDimitry Andric #define KMP_INIT_BARRIER_STATE 0 /* should probably start from zero */ 18520b57cec5SDimitry Andric #define KMP_BARRIER_SLEEP_BIT 0 /* bit used for suspend/sleep part of state */ 18530b57cec5SDimitry Andric #define KMP_BARRIER_UNUSED_BIT 1 // bit that must never be set for valid state 18540b57cec5SDimitry Andric #define KMP_BARRIER_BUMP_BIT 2 /* lsb used for bump of go/arrived state */ 18550b57cec5SDimitry Andric 18560b57cec5SDimitry Andric #define KMP_BARRIER_SLEEP_STATE (1 << KMP_BARRIER_SLEEP_BIT) 18570b57cec5SDimitry Andric #define KMP_BARRIER_UNUSED_STATE (1 << KMP_BARRIER_UNUSED_BIT) 18580b57cec5SDimitry Andric #define KMP_BARRIER_STATE_BUMP (1 << KMP_BARRIER_BUMP_BIT) 18590b57cec5SDimitry Andric 18600b57cec5SDimitry Andric #if (KMP_BARRIER_SLEEP_BIT >= KMP_BARRIER_BUMP_BIT) 18610b57cec5SDimitry Andric #error "Barrier sleep bit must be smaller than barrier bump bit" 18620b57cec5SDimitry Andric #endif 18630b57cec5SDimitry Andric #if (KMP_BARRIER_UNUSED_BIT >= KMP_BARRIER_BUMP_BIT) 18640b57cec5SDimitry Andric #error "Barrier unused bit must be smaller than barrier bump bit" 18650b57cec5SDimitry Andric #endif 18660b57cec5SDimitry Andric 18670b57cec5SDimitry Andric // Constants for release barrier wait state: currently, hierarchical only 18680b57cec5SDimitry Andric #define KMP_BARRIER_NOT_WAITING 0 // Normal state; worker not in wait_sleep 18690b57cec5SDimitry Andric #define KMP_BARRIER_OWN_FLAG \ 18700b57cec5SDimitry Andric 1 // Normal state; worker waiting on own b_go flag in release 18710b57cec5SDimitry Andric #define KMP_BARRIER_PARENT_FLAG \ 18720b57cec5SDimitry Andric 2 // Special state; worker waiting on parent's b_go flag in release 18730b57cec5SDimitry Andric #define KMP_BARRIER_SWITCH_TO_OWN_FLAG \ 18740b57cec5SDimitry Andric 3 // Special state; tells worker to shift from parent to own b_go 18750b57cec5SDimitry Andric #define KMP_BARRIER_SWITCHING \ 18760b57cec5SDimitry Andric 4 // Special state; worker resets appropriate flag on wake-up 18770b57cec5SDimitry Andric 18780b57cec5SDimitry Andric #define KMP_NOT_SAFE_TO_REAP \ 18790b57cec5SDimitry Andric 0 // Thread th_reap_state: not safe to reap (tasking) 18800b57cec5SDimitry Andric #define KMP_SAFE_TO_REAP 1 // Thread th_reap_state: safe to reap (not tasking) 18810b57cec5SDimitry Andric 18820b57cec5SDimitry Andric enum barrier_type { 18830b57cec5SDimitry Andric bs_plain_barrier = 0, /* 0, All non-fork/join barriers (except reduction 18840b57cec5SDimitry Andric barriers if enabled) */ 18850b57cec5SDimitry Andric bs_forkjoin_barrier, /* 1, All fork/join (parallel region) barriers */ 18860b57cec5SDimitry Andric #if KMP_FAST_REDUCTION_BARRIER 18870b57cec5SDimitry Andric bs_reduction_barrier, /* 2, All barriers that are used in reduction */ 18880b57cec5SDimitry Andric #endif // KMP_FAST_REDUCTION_BARRIER 18890b57cec5SDimitry Andric bs_last_barrier /* Just a placeholder to mark the end */ 18900b57cec5SDimitry Andric }; 18910b57cec5SDimitry Andric 18920b57cec5SDimitry Andric // to work with reduction barriers just like with plain barriers 18930b57cec5SDimitry Andric #if !KMP_FAST_REDUCTION_BARRIER 18940b57cec5SDimitry Andric #define bs_reduction_barrier bs_plain_barrier 18950b57cec5SDimitry Andric #endif // KMP_FAST_REDUCTION_BARRIER 18960b57cec5SDimitry Andric 18970b57cec5SDimitry Andric typedef enum kmp_bar_pat { /* Barrier communication patterns */ 18980b57cec5SDimitry Andric bp_linear_bar = 18990b57cec5SDimitry Andric 0, /* Single level (degenerate) tree */ 19000b57cec5SDimitry Andric bp_tree_bar = 19010b57cec5SDimitry Andric 1, /* Balanced tree with branching factor 2^n */ 1902*fe6060f1SDimitry Andric bp_hyper_bar = 2, /* Hypercube-embedded tree with min 1903*fe6060f1SDimitry Andric branching factor 2^n */ 19040b57cec5SDimitry Andric bp_hierarchical_bar = 3, /* Machine hierarchy tree */ 19050b57cec5SDimitry Andric bp_last_bar /* Placeholder to mark the end */ 19060b57cec5SDimitry Andric } kmp_bar_pat_e; 19070b57cec5SDimitry Andric 19080b57cec5SDimitry Andric #define KMP_BARRIER_ICV_PUSH 1 19090b57cec5SDimitry Andric 19100b57cec5SDimitry Andric /* Record for holding the values of the internal controls stack records */ 19110b57cec5SDimitry Andric typedef struct kmp_internal_control { 19120b57cec5SDimitry Andric int serial_nesting_level; /* corresponds to the value of the 19130b57cec5SDimitry Andric th_team_serialized field */ 19140b57cec5SDimitry Andric kmp_int8 dynamic; /* internal control for dynamic adjustment of threads (per 19150b57cec5SDimitry Andric thread) */ 19160b57cec5SDimitry Andric kmp_int8 19170b57cec5SDimitry Andric bt_set; /* internal control for whether blocktime is explicitly set */ 19180b57cec5SDimitry Andric int blocktime; /* internal control for blocktime */ 19190b57cec5SDimitry Andric #if KMP_USE_MONITOR 19200b57cec5SDimitry Andric int bt_intervals; /* internal control for blocktime intervals */ 19210b57cec5SDimitry Andric #endif 19220b57cec5SDimitry Andric int nproc; /* internal control for #threads for next parallel region (per 19230b57cec5SDimitry Andric thread) */ 19240b57cec5SDimitry Andric int thread_limit; /* internal control for thread-limit-var */ 19250b57cec5SDimitry Andric int max_active_levels; /* internal control for max_active_levels */ 19260b57cec5SDimitry Andric kmp_r_sched_t 19270b57cec5SDimitry Andric sched; /* internal control for runtime schedule {sched,chunk} pair */ 19280b57cec5SDimitry Andric kmp_proc_bind_t proc_bind; /* internal control for affinity */ 19290b57cec5SDimitry Andric kmp_int32 default_device; /* internal control for default device */ 19300b57cec5SDimitry Andric struct kmp_internal_control *next; 19310b57cec5SDimitry Andric } kmp_internal_control_t; 19320b57cec5SDimitry Andric 19330b57cec5SDimitry Andric static inline void copy_icvs(kmp_internal_control_t *dst, 19340b57cec5SDimitry Andric kmp_internal_control_t *src) { 19350b57cec5SDimitry Andric *dst = *src; 19360b57cec5SDimitry Andric } 19370b57cec5SDimitry Andric 19380b57cec5SDimitry Andric /* Thread barrier needs volatile barrier fields */ 19390b57cec5SDimitry Andric typedef struct KMP_ALIGN_CACHE kmp_bstate { 19400b57cec5SDimitry Andric // th_fixed_icvs is aligned by virtue of kmp_bstate being aligned (and all 19410b57cec5SDimitry Andric // uses of it). It is not explicitly aligned below, because we *don't* want 19420b57cec5SDimitry Andric // it to be padded -- instead, we fit b_go into the same cache line with 19430b57cec5SDimitry Andric // th_fixed_icvs, enabling NGO cache lines stores in the hierarchical barrier. 19440b57cec5SDimitry Andric kmp_internal_control_t th_fixed_icvs; // Initial ICVs for the thread 19450b57cec5SDimitry Andric // Tuck b_go into end of th_fixed_icvs cache line, so it can be stored with 19460b57cec5SDimitry Andric // same NGO store 19470b57cec5SDimitry Andric volatile kmp_uint64 b_go; // STATE => task should proceed (hierarchical) 19480b57cec5SDimitry Andric KMP_ALIGN_CACHE volatile kmp_uint64 19490b57cec5SDimitry Andric b_arrived; // STATE => task reached synch point. 19500b57cec5SDimitry Andric kmp_uint32 *skip_per_level; 19510b57cec5SDimitry Andric kmp_uint32 my_level; 19520b57cec5SDimitry Andric kmp_int32 parent_tid; 19530b57cec5SDimitry Andric kmp_int32 old_tid; 19540b57cec5SDimitry Andric kmp_uint32 depth; 19550b57cec5SDimitry Andric struct kmp_bstate *parent_bar; 19560b57cec5SDimitry Andric kmp_team_t *team; 19570b57cec5SDimitry Andric kmp_uint64 leaf_state; 19580b57cec5SDimitry Andric kmp_uint32 nproc; 19590b57cec5SDimitry Andric kmp_uint8 base_leaf_kids; 19600b57cec5SDimitry Andric kmp_uint8 leaf_kids; 19610b57cec5SDimitry Andric kmp_uint8 offset; 19620b57cec5SDimitry Andric kmp_uint8 wait_flag; 19630b57cec5SDimitry Andric kmp_uint8 use_oncore_barrier; 19640b57cec5SDimitry Andric #if USE_DEBUGGER 19650b57cec5SDimitry Andric // The following field is intended for the debugger solely. Only the worker 19660b57cec5SDimitry Andric // thread itself accesses this field: the worker increases it by 1 when it 19670b57cec5SDimitry Andric // arrives to a barrier. 19680b57cec5SDimitry Andric KMP_ALIGN_CACHE kmp_uint b_worker_arrived; 19690b57cec5SDimitry Andric #endif /* USE_DEBUGGER */ 19700b57cec5SDimitry Andric } kmp_bstate_t; 19710b57cec5SDimitry Andric 19720b57cec5SDimitry Andric union KMP_ALIGN_CACHE kmp_barrier_union { 19730b57cec5SDimitry Andric double b_align; /* use worst case alignment */ 19740b57cec5SDimitry Andric char b_pad[KMP_PAD(kmp_bstate_t, CACHE_LINE)]; 19750b57cec5SDimitry Andric kmp_bstate_t bb; 19760b57cec5SDimitry Andric }; 19770b57cec5SDimitry Andric 19780b57cec5SDimitry Andric typedef union kmp_barrier_union kmp_balign_t; 19790b57cec5SDimitry Andric 19800b57cec5SDimitry Andric /* Team barrier needs only non-volatile arrived counter */ 19810b57cec5SDimitry Andric union KMP_ALIGN_CACHE kmp_barrier_team_union { 19820b57cec5SDimitry Andric double b_align; /* use worst case alignment */ 19830b57cec5SDimitry Andric char b_pad[CACHE_LINE]; 19840b57cec5SDimitry Andric struct { 19850b57cec5SDimitry Andric kmp_uint64 b_arrived; /* STATE => task reached synch point. */ 19860b57cec5SDimitry Andric #if USE_DEBUGGER 19870b57cec5SDimitry Andric // The following two fields are indended for the debugger solely. Only 1988*fe6060f1SDimitry Andric // primary thread of the team accesses these fields: the first one is 1989*fe6060f1SDimitry Andric // increased by 1 when the primary thread arrives to a barrier, the second 1990*fe6060f1SDimitry Andric // one is increased by one when all the threads arrived. 19910b57cec5SDimitry Andric kmp_uint b_master_arrived; 19920b57cec5SDimitry Andric kmp_uint b_team_arrived; 19930b57cec5SDimitry Andric #endif 19940b57cec5SDimitry Andric }; 19950b57cec5SDimitry Andric }; 19960b57cec5SDimitry Andric 19970b57cec5SDimitry Andric typedef union kmp_barrier_team_union kmp_balign_team_t; 19980b57cec5SDimitry Andric 19990b57cec5SDimitry Andric /* Padding for Linux* OS pthreads condition variables and mutexes used to signal 20000b57cec5SDimitry Andric threads when a condition changes. This is to workaround an NPTL bug where 20010b57cec5SDimitry Andric padding was added to pthread_cond_t which caused the initialization routine 20020b57cec5SDimitry Andric to write outside of the structure if compiled on pre-NPTL threads. */ 20030b57cec5SDimitry Andric #if KMP_OS_WINDOWS 20040b57cec5SDimitry Andric typedef struct kmp_win32_mutex { 20050b57cec5SDimitry Andric /* The Lock */ 20060b57cec5SDimitry Andric CRITICAL_SECTION cs; 20070b57cec5SDimitry Andric } kmp_win32_mutex_t; 20080b57cec5SDimitry Andric 20090b57cec5SDimitry Andric typedef struct kmp_win32_cond { 20100b57cec5SDimitry Andric /* Count of the number of waiters. */ 20110b57cec5SDimitry Andric int waiters_count_; 20120b57cec5SDimitry Andric 20130b57cec5SDimitry Andric /* Serialize access to <waiters_count_> */ 20140b57cec5SDimitry Andric kmp_win32_mutex_t waiters_count_lock_; 20150b57cec5SDimitry Andric 20160b57cec5SDimitry Andric /* Number of threads to release via a <cond_broadcast> or a <cond_signal> */ 20170b57cec5SDimitry Andric int release_count_; 20180b57cec5SDimitry Andric 20190b57cec5SDimitry Andric /* Keeps track of the current "generation" so that we don't allow */ 20200b57cec5SDimitry Andric /* one thread to steal all the "releases" from the broadcast. */ 20210b57cec5SDimitry Andric int wait_generation_count_; 20220b57cec5SDimitry Andric 20230b57cec5SDimitry Andric /* A manual-reset event that's used to block and release waiting threads. */ 20240b57cec5SDimitry Andric HANDLE event_; 20250b57cec5SDimitry Andric } kmp_win32_cond_t; 20260b57cec5SDimitry Andric #endif 20270b57cec5SDimitry Andric 20280b57cec5SDimitry Andric #if KMP_OS_UNIX 20290b57cec5SDimitry Andric 20300b57cec5SDimitry Andric union KMP_ALIGN_CACHE kmp_cond_union { 20310b57cec5SDimitry Andric double c_align; 20320b57cec5SDimitry Andric char c_pad[CACHE_LINE]; 20330b57cec5SDimitry Andric pthread_cond_t c_cond; 20340b57cec5SDimitry Andric }; 20350b57cec5SDimitry Andric 20360b57cec5SDimitry Andric typedef union kmp_cond_union kmp_cond_align_t; 20370b57cec5SDimitry Andric 20380b57cec5SDimitry Andric union KMP_ALIGN_CACHE kmp_mutex_union { 20390b57cec5SDimitry Andric double m_align; 20400b57cec5SDimitry Andric char m_pad[CACHE_LINE]; 20410b57cec5SDimitry Andric pthread_mutex_t m_mutex; 20420b57cec5SDimitry Andric }; 20430b57cec5SDimitry Andric 20440b57cec5SDimitry Andric typedef union kmp_mutex_union kmp_mutex_align_t; 20450b57cec5SDimitry Andric 20460b57cec5SDimitry Andric #endif /* KMP_OS_UNIX */ 20470b57cec5SDimitry Andric 20480b57cec5SDimitry Andric typedef struct kmp_desc_base { 20490b57cec5SDimitry Andric void *ds_stackbase; 20500b57cec5SDimitry Andric size_t ds_stacksize; 20510b57cec5SDimitry Andric int ds_stackgrow; 20520b57cec5SDimitry Andric kmp_thread_t ds_thread; 20530b57cec5SDimitry Andric volatile int ds_tid; 20540b57cec5SDimitry Andric int ds_gtid; 20550b57cec5SDimitry Andric #if KMP_OS_WINDOWS 20560b57cec5SDimitry Andric volatile int ds_alive; 20570b57cec5SDimitry Andric DWORD ds_thread_id; 20580b57cec5SDimitry Andric /* ds_thread keeps thread handle on Windows* OS. It is enough for RTL purposes. 20590b57cec5SDimitry Andric However, debugger support (libomp_db) cannot work with handles, because they 20600b57cec5SDimitry Andric uncomparable. For example, debugger requests info about thread with handle h. 20610b57cec5SDimitry Andric h is valid within debugger process, and meaningless within debugee process. 20620b57cec5SDimitry Andric Even if h is duped by call to DuplicateHandle(), so the result h' is valid 20630b57cec5SDimitry Andric within debugee process, but it is a *new* handle which does *not* equal to 20640b57cec5SDimitry Andric any other handle in debugee... The only way to compare handles is convert 20650b57cec5SDimitry Andric them to system-wide ids. GetThreadId() function is available only in 20660b57cec5SDimitry Andric Longhorn and Server 2003. :-( In contrast, GetCurrentThreadId() is available 20670b57cec5SDimitry Andric on all Windows* OS flavours (including Windows* 95). Thus, we have to get 20680b57cec5SDimitry Andric thread id by call to GetCurrentThreadId() from within the thread and save it 20690b57cec5SDimitry Andric to let libomp_db identify threads. */ 20700b57cec5SDimitry Andric #endif /* KMP_OS_WINDOWS */ 20710b57cec5SDimitry Andric } kmp_desc_base_t; 20720b57cec5SDimitry Andric 20730b57cec5SDimitry Andric typedef union KMP_ALIGN_CACHE kmp_desc { 20740b57cec5SDimitry Andric double ds_align; /* use worst case alignment */ 20750b57cec5SDimitry Andric char ds_pad[KMP_PAD(kmp_desc_base_t, CACHE_LINE)]; 20760b57cec5SDimitry Andric kmp_desc_base_t ds; 20770b57cec5SDimitry Andric } kmp_desc_t; 20780b57cec5SDimitry Andric 20790b57cec5SDimitry Andric typedef struct kmp_local { 20800b57cec5SDimitry Andric volatile int this_construct; /* count of single's encountered by thread */ 20810b57cec5SDimitry Andric void *reduce_data; 20820b57cec5SDimitry Andric #if KMP_USE_BGET 20830b57cec5SDimitry Andric void *bget_data; 20840b57cec5SDimitry Andric void *bget_list; 20850b57cec5SDimitry Andric #if !USE_CMP_XCHG_FOR_BGET 20860b57cec5SDimitry Andric #ifdef USE_QUEUING_LOCK_FOR_BGET 20870b57cec5SDimitry Andric kmp_lock_t bget_lock; /* Lock for accessing bget free list */ 20880b57cec5SDimitry Andric #else 20890b57cec5SDimitry Andric kmp_bootstrap_lock_t bget_lock; // Lock for accessing bget free list. Must be 20900b57cec5SDimitry Andric // bootstrap lock so we can use it at library 20910b57cec5SDimitry Andric // shutdown. 20920b57cec5SDimitry Andric #endif /* USE_LOCK_FOR_BGET */ 20930b57cec5SDimitry Andric #endif /* ! USE_CMP_XCHG_FOR_BGET */ 20940b57cec5SDimitry Andric #endif /* KMP_USE_BGET */ 20950b57cec5SDimitry Andric 20960b57cec5SDimitry Andric PACKED_REDUCTION_METHOD_T 20970b57cec5SDimitry Andric packed_reduction_method; /* stored by __kmpc_reduce*(), used by 20980b57cec5SDimitry Andric __kmpc_end_reduce*() */ 20990b57cec5SDimitry Andric 21000b57cec5SDimitry Andric } kmp_local_t; 21010b57cec5SDimitry Andric 21020b57cec5SDimitry Andric #define KMP_CHECK_UPDATE(a, b) \ 21030b57cec5SDimitry Andric if ((a) != (b)) \ 21040b57cec5SDimitry Andric (a) = (b) 21050b57cec5SDimitry Andric #define KMP_CHECK_UPDATE_SYNC(a, b) \ 21060b57cec5SDimitry Andric if ((a) != (b)) \ 21070b57cec5SDimitry Andric TCW_SYNC_PTR((a), (b)) 21080b57cec5SDimitry Andric 21090b57cec5SDimitry Andric #define get__blocktime(xteam, xtid) \ 21100b57cec5SDimitry Andric ((xteam)->t.t_threads[(xtid)]->th.th_current_task->td_icvs.blocktime) 21110b57cec5SDimitry Andric #define get__bt_set(xteam, xtid) \ 21120b57cec5SDimitry Andric ((xteam)->t.t_threads[(xtid)]->th.th_current_task->td_icvs.bt_set) 21130b57cec5SDimitry Andric #if KMP_USE_MONITOR 21140b57cec5SDimitry Andric #define get__bt_intervals(xteam, xtid) \ 21150b57cec5SDimitry Andric ((xteam)->t.t_threads[(xtid)]->th.th_current_task->td_icvs.bt_intervals) 21160b57cec5SDimitry Andric #endif 21170b57cec5SDimitry Andric 21180b57cec5SDimitry Andric #define get__dynamic_2(xteam, xtid) \ 21190b57cec5SDimitry Andric ((xteam)->t.t_threads[(xtid)]->th.th_current_task->td_icvs.dynamic) 21200b57cec5SDimitry Andric #define get__nproc_2(xteam, xtid) \ 21210b57cec5SDimitry Andric ((xteam)->t.t_threads[(xtid)]->th.th_current_task->td_icvs.nproc) 21220b57cec5SDimitry Andric #define get__sched_2(xteam, xtid) \ 21230b57cec5SDimitry Andric ((xteam)->t.t_threads[(xtid)]->th.th_current_task->td_icvs.sched) 21240b57cec5SDimitry Andric 21250b57cec5SDimitry Andric #define set__blocktime_team(xteam, xtid, xval) \ 21260b57cec5SDimitry Andric (((xteam)->t.t_threads[(xtid)]->th.th_current_task->td_icvs.blocktime) = \ 21270b57cec5SDimitry Andric (xval)) 21280b57cec5SDimitry Andric 21290b57cec5SDimitry Andric #if KMP_USE_MONITOR 21300b57cec5SDimitry Andric #define set__bt_intervals_team(xteam, xtid, xval) \ 21310b57cec5SDimitry Andric (((xteam)->t.t_threads[(xtid)]->th.th_current_task->td_icvs.bt_intervals) = \ 21320b57cec5SDimitry Andric (xval)) 21330b57cec5SDimitry Andric #endif 21340b57cec5SDimitry Andric 21350b57cec5SDimitry Andric #define set__bt_set_team(xteam, xtid, xval) \ 21360b57cec5SDimitry Andric (((xteam)->t.t_threads[(xtid)]->th.th_current_task->td_icvs.bt_set) = (xval)) 21370b57cec5SDimitry Andric 21380b57cec5SDimitry Andric #define set__dynamic(xthread, xval) \ 21390b57cec5SDimitry Andric (((xthread)->th.th_current_task->td_icvs.dynamic) = (xval)) 21400b57cec5SDimitry Andric #define get__dynamic(xthread) \ 21410b57cec5SDimitry Andric (((xthread)->th.th_current_task->td_icvs.dynamic) ? (FTN_TRUE) : (FTN_FALSE)) 21420b57cec5SDimitry Andric 21430b57cec5SDimitry Andric #define set__nproc(xthread, xval) \ 21440b57cec5SDimitry Andric (((xthread)->th.th_current_task->td_icvs.nproc) = (xval)) 21450b57cec5SDimitry Andric 21460b57cec5SDimitry Andric #define set__thread_limit(xthread, xval) \ 21470b57cec5SDimitry Andric (((xthread)->th.th_current_task->td_icvs.thread_limit) = (xval)) 21480b57cec5SDimitry Andric 21490b57cec5SDimitry Andric #define set__max_active_levels(xthread, xval) \ 21500b57cec5SDimitry Andric (((xthread)->th.th_current_task->td_icvs.max_active_levels) = (xval)) 21510b57cec5SDimitry Andric 21520b57cec5SDimitry Andric #define get__max_active_levels(xthread) \ 21530b57cec5SDimitry Andric ((xthread)->th.th_current_task->td_icvs.max_active_levels) 21540b57cec5SDimitry Andric 21550b57cec5SDimitry Andric #define set__sched(xthread, xval) \ 21560b57cec5SDimitry Andric (((xthread)->th.th_current_task->td_icvs.sched) = (xval)) 21570b57cec5SDimitry Andric 21580b57cec5SDimitry Andric #define set__proc_bind(xthread, xval) \ 21590b57cec5SDimitry Andric (((xthread)->th.th_current_task->td_icvs.proc_bind) = (xval)) 21600b57cec5SDimitry Andric #define get__proc_bind(xthread) \ 21610b57cec5SDimitry Andric ((xthread)->th.th_current_task->td_icvs.proc_bind) 21620b57cec5SDimitry Andric 21630b57cec5SDimitry Andric // OpenMP tasking data structures 21640b57cec5SDimitry Andric 21650b57cec5SDimitry Andric typedef enum kmp_tasking_mode { 21660b57cec5SDimitry Andric tskm_immediate_exec = 0, 21670b57cec5SDimitry Andric tskm_extra_barrier = 1, 21680b57cec5SDimitry Andric tskm_task_teams = 2, 21690b57cec5SDimitry Andric tskm_max = 2 21700b57cec5SDimitry Andric } kmp_tasking_mode_t; 21710b57cec5SDimitry Andric 21720b57cec5SDimitry Andric extern kmp_tasking_mode_t 21730b57cec5SDimitry Andric __kmp_tasking_mode; /* determines how/when to execute tasks */ 21740b57cec5SDimitry Andric extern int __kmp_task_stealing_constraint; 21750b57cec5SDimitry Andric extern int __kmp_enable_task_throttling; 21760b57cec5SDimitry Andric extern kmp_int32 __kmp_default_device; // Set via OMP_DEFAULT_DEVICE if 21770b57cec5SDimitry Andric // specified, defaults to 0 otherwise 21780b57cec5SDimitry Andric // Set via OMP_MAX_TASK_PRIORITY if specified, defaults to 0 otherwise 21790b57cec5SDimitry Andric extern kmp_int32 __kmp_max_task_priority; 21800b57cec5SDimitry Andric // Set via KMP_TASKLOOP_MIN_TASKS if specified, defaults to 0 otherwise 21810b57cec5SDimitry Andric extern kmp_uint64 __kmp_taskloop_min_tasks; 21820b57cec5SDimitry Andric 21830b57cec5SDimitry Andric /* NOTE: kmp_taskdata_t and kmp_task_t structures allocated in single block with 21840b57cec5SDimitry Andric taskdata first */ 21850b57cec5SDimitry Andric #define KMP_TASK_TO_TASKDATA(task) (((kmp_taskdata_t *)task) - 1) 21860b57cec5SDimitry Andric #define KMP_TASKDATA_TO_TASK(taskdata) (kmp_task_t *)(taskdata + 1) 21870b57cec5SDimitry Andric 21880b57cec5SDimitry Andric // The tt_found_tasks flag is a signal to all threads in the team that tasks 21890b57cec5SDimitry Andric // were spawned and queued since the previous barrier release. 21900b57cec5SDimitry Andric #define KMP_TASKING_ENABLED(task_team) \ 2191e8d8bef9SDimitry Andric (TRUE == TCR_SYNC_4((task_team)->tt.tt_found_tasks)) 21920b57cec5SDimitry Andric /*! 21930b57cec5SDimitry Andric @ingroup BASIC_TYPES 21940b57cec5SDimitry Andric @{ 21950b57cec5SDimitry Andric */ 21960b57cec5SDimitry Andric 21970b57cec5SDimitry Andric /*! 21980b57cec5SDimitry Andric */ 21990b57cec5SDimitry Andric typedef kmp_int32 (*kmp_routine_entry_t)(kmp_int32, void *); 22000b57cec5SDimitry Andric 22010b57cec5SDimitry Andric typedef union kmp_cmplrdata { 22020b57cec5SDimitry Andric kmp_int32 priority; /**< priority specified by user for the task */ 22030b57cec5SDimitry Andric kmp_routine_entry_t 22040b57cec5SDimitry Andric destructors; /* pointer to function to invoke deconstructors of 22050b57cec5SDimitry Andric firstprivate C++ objects */ 22060b57cec5SDimitry Andric /* future data */ 22070b57cec5SDimitry Andric } kmp_cmplrdata_t; 22080b57cec5SDimitry Andric 22090b57cec5SDimitry Andric /* sizeof_kmp_task_t passed as arg to kmpc_omp_task call */ 22100b57cec5SDimitry Andric /*! 22110b57cec5SDimitry Andric */ 22120b57cec5SDimitry Andric typedef struct kmp_task { /* GEH: Shouldn't this be aligned somehow? */ 22130b57cec5SDimitry Andric void *shareds; /**< pointer to block of pointers to shared vars */ 22140b57cec5SDimitry Andric kmp_routine_entry_t 22150b57cec5SDimitry Andric routine; /**< pointer to routine to call for executing task */ 22160b57cec5SDimitry Andric kmp_int32 part_id; /**< part id for the task */ 22170b57cec5SDimitry Andric kmp_cmplrdata_t 22180b57cec5SDimitry Andric data1; /* Two known optional additions: destructors and priority */ 22190b57cec5SDimitry Andric kmp_cmplrdata_t data2; /* Process destructors first, priority second */ 22200b57cec5SDimitry Andric /* future data */ 22210b57cec5SDimitry Andric /* private vars */ 22220b57cec5SDimitry Andric } kmp_task_t; 22230b57cec5SDimitry Andric 22240b57cec5SDimitry Andric /*! 22250b57cec5SDimitry Andric @} 22260b57cec5SDimitry Andric */ 22270b57cec5SDimitry Andric 22280b57cec5SDimitry Andric typedef struct kmp_taskgroup { 22290b57cec5SDimitry Andric std::atomic<kmp_int32> count; // number of allocated and incomplete tasks 22300b57cec5SDimitry Andric std::atomic<kmp_int32> 22310b57cec5SDimitry Andric cancel_request; // request for cancellation of this taskgroup 22320b57cec5SDimitry Andric struct kmp_taskgroup *parent; // parent taskgroup 22330b57cec5SDimitry Andric // Block of data to perform task reduction 22340b57cec5SDimitry Andric void *reduce_data; // reduction related info 22350b57cec5SDimitry Andric kmp_int32 reduce_num_data; // number of data items to reduce 2236*fe6060f1SDimitry Andric uintptr_t *gomp_data; // gomp reduction data 22370b57cec5SDimitry Andric } kmp_taskgroup_t; 22380b57cec5SDimitry Andric 22390b57cec5SDimitry Andric // forward declarations 22400b57cec5SDimitry Andric typedef union kmp_depnode kmp_depnode_t; 22410b57cec5SDimitry Andric typedef struct kmp_depnode_list kmp_depnode_list_t; 22420b57cec5SDimitry Andric typedef struct kmp_dephash_entry kmp_dephash_entry_t; 22430b57cec5SDimitry Andric 2244*fe6060f1SDimitry Andric #define KMP_DEP_IN 0x1 2245*fe6060f1SDimitry Andric #define KMP_DEP_OUT 0x2 2246*fe6060f1SDimitry Andric #define KMP_DEP_INOUT 0x3 2247*fe6060f1SDimitry Andric #define KMP_DEP_MTX 0x4 2248*fe6060f1SDimitry Andric #define KMP_DEP_SET 0x8 22490b57cec5SDimitry Andric // Compiler sends us this info: 22500b57cec5SDimitry Andric typedef struct kmp_depend_info { 22510b57cec5SDimitry Andric kmp_intptr_t base_addr; 22520b57cec5SDimitry Andric size_t len; 2253*fe6060f1SDimitry Andric union { 2254*fe6060f1SDimitry Andric kmp_uint8 flag; 22550b57cec5SDimitry Andric struct { 2256*fe6060f1SDimitry Andric unsigned in : 1; 2257*fe6060f1SDimitry Andric unsigned out : 1; 2258*fe6060f1SDimitry Andric unsigned mtx : 1; 2259*fe6060f1SDimitry Andric unsigned set : 1; 22600b57cec5SDimitry Andric } flags; 2261*fe6060f1SDimitry Andric }; 22620b57cec5SDimitry Andric } kmp_depend_info_t; 22630b57cec5SDimitry Andric 22640b57cec5SDimitry Andric // Internal structures to work with task dependencies: 22650b57cec5SDimitry Andric struct kmp_depnode_list { 22660b57cec5SDimitry Andric kmp_depnode_t *node; 22670b57cec5SDimitry Andric kmp_depnode_list_t *next; 22680b57cec5SDimitry Andric }; 22690b57cec5SDimitry Andric 22700b57cec5SDimitry Andric // Max number of mutexinoutset dependencies per node 22710b57cec5SDimitry Andric #define MAX_MTX_DEPS 4 22720b57cec5SDimitry Andric 22730b57cec5SDimitry Andric typedef struct kmp_base_depnode { 22740b57cec5SDimitry Andric kmp_depnode_list_t *successors; /* used under lock */ 22750b57cec5SDimitry Andric kmp_task_t *task; /* non-NULL if depnode is active, used under lock */ 22760b57cec5SDimitry Andric kmp_lock_t *mtx_locks[MAX_MTX_DEPS]; /* lock mutexinoutset dependent tasks */ 22770b57cec5SDimitry Andric kmp_int32 mtx_num_locks; /* number of locks in mtx_locks array */ 22780b57cec5SDimitry Andric kmp_lock_t lock; /* guards shared fields: task, successors */ 22790b57cec5SDimitry Andric #if KMP_SUPPORT_GRAPH_OUTPUT 22800b57cec5SDimitry Andric kmp_uint32 id; 22810b57cec5SDimitry Andric #endif 22820b57cec5SDimitry Andric std::atomic<kmp_int32> npredecessors; 22830b57cec5SDimitry Andric std::atomic<kmp_int32> nrefs; 22840b57cec5SDimitry Andric } kmp_base_depnode_t; 22850b57cec5SDimitry Andric 22860b57cec5SDimitry Andric union KMP_ALIGN_CACHE kmp_depnode { 22870b57cec5SDimitry Andric double dn_align; /* use worst case alignment */ 22880b57cec5SDimitry Andric char dn_pad[KMP_PAD(kmp_base_depnode_t, CACHE_LINE)]; 22890b57cec5SDimitry Andric kmp_base_depnode_t dn; 22900b57cec5SDimitry Andric }; 22910b57cec5SDimitry Andric 22920b57cec5SDimitry Andric struct kmp_dephash_entry { 22930b57cec5SDimitry Andric kmp_intptr_t addr; 22940b57cec5SDimitry Andric kmp_depnode_t *last_out; 2295*fe6060f1SDimitry Andric kmp_depnode_list_t *last_set; 2296*fe6060f1SDimitry Andric kmp_depnode_list_t *prev_set; 2297*fe6060f1SDimitry Andric kmp_uint8 last_flag; 22980b57cec5SDimitry Andric kmp_lock_t *mtx_lock; /* is referenced by depnodes w/mutexinoutset dep */ 22990b57cec5SDimitry Andric kmp_dephash_entry_t *next_in_bucket; 23000b57cec5SDimitry Andric }; 23010b57cec5SDimitry Andric 23020b57cec5SDimitry Andric typedef struct kmp_dephash { 23030b57cec5SDimitry Andric kmp_dephash_entry_t **buckets; 23040b57cec5SDimitry Andric size_t size; 2305489b1cf2SDimitry Andric size_t generation; 23060b57cec5SDimitry Andric kmp_uint32 nelements; 23070b57cec5SDimitry Andric kmp_uint32 nconflicts; 23080b57cec5SDimitry Andric } kmp_dephash_t; 23090b57cec5SDimitry Andric 23100b57cec5SDimitry Andric typedef struct kmp_task_affinity_info { 23110b57cec5SDimitry Andric kmp_intptr_t base_addr; 23120b57cec5SDimitry Andric size_t len; 23130b57cec5SDimitry Andric struct { 23140b57cec5SDimitry Andric bool flag1 : 1; 23150b57cec5SDimitry Andric bool flag2 : 1; 23160b57cec5SDimitry Andric kmp_int32 reserved : 30; 23170b57cec5SDimitry Andric } flags; 23180b57cec5SDimitry Andric } kmp_task_affinity_info_t; 23190b57cec5SDimitry Andric 23200b57cec5SDimitry Andric typedef enum kmp_event_type_t { 23210b57cec5SDimitry Andric KMP_EVENT_UNINITIALIZED = 0, 23220b57cec5SDimitry Andric KMP_EVENT_ALLOW_COMPLETION = 1 23230b57cec5SDimitry Andric } kmp_event_type_t; 23240b57cec5SDimitry Andric 23250b57cec5SDimitry Andric typedef struct { 23260b57cec5SDimitry Andric kmp_event_type_t type; 23270b57cec5SDimitry Andric kmp_tas_lock_t lock; 23280b57cec5SDimitry Andric union { 23290b57cec5SDimitry Andric kmp_task_t *task; 23300b57cec5SDimitry Andric } ed; 23310b57cec5SDimitry Andric } kmp_event_t; 23320b57cec5SDimitry Andric 23330b57cec5SDimitry Andric #ifdef BUILD_TIED_TASK_STACK 23340b57cec5SDimitry Andric 23350b57cec5SDimitry Andric /* Tied Task stack definitions */ 23360b57cec5SDimitry Andric typedef struct kmp_stack_block { 23370b57cec5SDimitry Andric kmp_taskdata_t *sb_block[TASK_STACK_BLOCK_SIZE]; 23380b57cec5SDimitry Andric struct kmp_stack_block *sb_next; 23390b57cec5SDimitry Andric struct kmp_stack_block *sb_prev; 23400b57cec5SDimitry Andric } kmp_stack_block_t; 23410b57cec5SDimitry Andric 23420b57cec5SDimitry Andric typedef struct kmp_task_stack { 23430b57cec5SDimitry Andric kmp_stack_block_t ts_first_block; // first block of stack entries 23440b57cec5SDimitry Andric kmp_taskdata_t **ts_top; // pointer to the top of stack 23450b57cec5SDimitry Andric kmp_int32 ts_entries; // number of entries on the stack 23460b57cec5SDimitry Andric } kmp_task_stack_t; 23470b57cec5SDimitry Andric 23480b57cec5SDimitry Andric #endif // BUILD_TIED_TASK_STACK 23490b57cec5SDimitry Andric 23500b57cec5SDimitry Andric typedef struct kmp_tasking_flags { /* Total struct must be exactly 32 bits */ 23510b57cec5SDimitry Andric /* Compiler flags */ /* Total compiler flags must be 16 bits */ 23520b57cec5SDimitry Andric unsigned tiedness : 1; /* task is either tied (1) or untied (0) */ 23530b57cec5SDimitry Andric unsigned final : 1; /* task is final(1) so execute immediately */ 23540b57cec5SDimitry Andric unsigned merged_if0 : 1; /* no __kmpc_task_{begin/complete}_if0 calls in if0 23550b57cec5SDimitry Andric code path */ 23560b57cec5SDimitry Andric unsigned destructors_thunk : 1; /* set if the compiler creates a thunk to 23570b57cec5SDimitry Andric invoke destructors from the runtime */ 23580b57cec5SDimitry Andric unsigned proxy : 1; /* task is a proxy task (it will be executed outside the 23590b57cec5SDimitry Andric context of the RTL) */ 23600b57cec5SDimitry Andric unsigned priority_specified : 1; /* set if the compiler provides priority 23610b57cec5SDimitry Andric setting for the task */ 23620b57cec5SDimitry Andric unsigned detachable : 1; /* 1 == can detach */ 2363e8d8bef9SDimitry Andric unsigned hidden_helper : 1; /* 1 == hidden helper task */ 2364e8d8bef9SDimitry Andric unsigned reserved : 8; /* reserved for compiler use */ 23650b57cec5SDimitry Andric 23660b57cec5SDimitry Andric /* Library flags */ /* Total library flags must be 16 bits */ 23670b57cec5SDimitry Andric unsigned tasktype : 1; /* task is either explicit(1) or implicit (0) */ 23680b57cec5SDimitry Andric unsigned task_serial : 1; // task is executed immediately (1) or deferred (0) 23690b57cec5SDimitry Andric unsigned tasking_ser : 1; // all tasks in team are either executed immediately 23700b57cec5SDimitry Andric // (1) or may be deferred (0) 23710b57cec5SDimitry Andric unsigned team_serial : 1; // entire team is serial (1) [1 thread] or parallel 23720b57cec5SDimitry Andric // (0) [>= 2 threads] 23730b57cec5SDimitry Andric /* If either team_serial or tasking_ser is set, task team may be NULL */ 23740b57cec5SDimitry Andric /* Task State Flags: */ 23750b57cec5SDimitry Andric unsigned started : 1; /* 1==started, 0==not started */ 23760b57cec5SDimitry Andric unsigned executing : 1; /* 1==executing, 0==not executing */ 23770b57cec5SDimitry Andric unsigned complete : 1; /* 1==complete, 0==not complete */ 2378480093f4SDimitry Andric unsigned freed : 1; /* 1==freed, 0==allocated */ 23790b57cec5SDimitry Andric unsigned native : 1; /* 1==gcc-compiled task, 0==intel */ 23800b57cec5SDimitry Andric unsigned reserved31 : 7; /* reserved for library use */ 23810b57cec5SDimitry Andric 23820b57cec5SDimitry Andric } kmp_tasking_flags_t; 23830b57cec5SDimitry Andric 23840b57cec5SDimitry Andric struct kmp_taskdata { /* aligned during dynamic allocation */ 23850b57cec5SDimitry Andric kmp_int32 td_task_id; /* id, assigned by debugger */ 23860b57cec5SDimitry Andric kmp_tasking_flags_t td_flags; /* task flags */ 23870b57cec5SDimitry Andric kmp_team_t *td_team; /* team for this task */ 23880b57cec5SDimitry Andric kmp_info_p *td_alloc_thread; /* thread that allocated data structures */ 23890b57cec5SDimitry Andric /* Currently not used except for perhaps IDB */ 23900b57cec5SDimitry Andric kmp_taskdata_t *td_parent; /* parent task */ 23910b57cec5SDimitry Andric kmp_int32 td_level; /* task nesting level */ 23920b57cec5SDimitry Andric std::atomic<kmp_int32> td_untied_count; // untied task active parts counter 23930b57cec5SDimitry Andric ident_t *td_ident; /* task identifier */ 23940b57cec5SDimitry Andric // Taskwait data. 23950b57cec5SDimitry Andric ident_t *td_taskwait_ident; 23960b57cec5SDimitry Andric kmp_uint32 td_taskwait_counter; 23970b57cec5SDimitry Andric kmp_int32 td_taskwait_thread; /* gtid + 1 of thread encountered taskwait */ 23980b57cec5SDimitry Andric KMP_ALIGN_CACHE kmp_internal_control_t 23990b57cec5SDimitry Andric td_icvs; /* Internal control variables for the task */ 24000b57cec5SDimitry Andric KMP_ALIGN_CACHE std::atomic<kmp_int32> 24010b57cec5SDimitry Andric td_allocated_child_tasks; /* Child tasks (+ current task) not yet 24020b57cec5SDimitry Andric deallocated */ 24030b57cec5SDimitry Andric std::atomic<kmp_int32> 24040b57cec5SDimitry Andric td_incomplete_child_tasks; /* Child tasks not yet complete */ 24050b57cec5SDimitry Andric kmp_taskgroup_t 24060b57cec5SDimitry Andric *td_taskgroup; // Each task keeps pointer to its current taskgroup 24070b57cec5SDimitry Andric kmp_dephash_t 24080b57cec5SDimitry Andric *td_dephash; // Dependencies for children tasks are tracked from here 24090b57cec5SDimitry Andric kmp_depnode_t 24100b57cec5SDimitry Andric *td_depnode; // Pointer to graph node if this task has dependencies 24110b57cec5SDimitry Andric kmp_task_team_t *td_task_team; 2412e8d8bef9SDimitry Andric // The global thread id of the encountering thread. We need it because when a 2413e8d8bef9SDimitry Andric // regular task depends on a hidden helper task, and the hidden helper task 2414e8d8bef9SDimitry Andric // is finished on a hidden helper thread, it will call __kmp_release_deps to 2415e8d8bef9SDimitry Andric // release all dependences. If now the task is a regular task, we need to pass 2416e8d8bef9SDimitry Andric // the encountering gtid such that the task will be picked up and executed by 2417e8d8bef9SDimitry Andric // its encountering team instead of hidden helper team. 2418e8d8bef9SDimitry Andric kmp_int32 encountering_gtid; 2419e8d8bef9SDimitry Andric size_t td_size_alloc; // Size of task structure, including shareds etc. 24200b57cec5SDimitry Andric #if defined(KMP_GOMP_COMPAT) 24210b57cec5SDimitry Andric // 4 or 8 byte integers for the loop bounds in GOMP_taskloop 24220b57cec5SDimitry Andric kmp_int32 td_size_loop_bounds; 24230b57cec5SDimitry Andric #endif 24240b57cec5SDimitry Andric kmp_taskdata_t *td_last_tied; // keep tied task for task scheduling constraint 24250b57cec5SDimitry Andric #if defined(KMP_GOMP_COMPAT) 24260b57cec5SDimitry Andric // GOMP sends in a copy function for copy constructors 24270b57cec5SDimitry Andric void (*td_copy_func)(void *, void *); 24280b57cec5SDimitry Andric #endif 24290b57cec5SDimitry Andric kmp_event_t td_allow_completion_event; 24300b57cec5SDimitry Andric #if OMPT_SUPPORT 24310b57cec5SDimitry Andric ompt_task_info_t ompt_task_info; 24320b57cec5SDimitry Andric #endif 24330b57cec5SDimitry Andric }; // struct kmp_taskdata 24340b57cec5SDimitry Andric 24350b57cec5SDimitry Andric // Make sure padding above worked 24360b57cec5SDimitry Andric KMP_BUILD_ASSERT(sizeof(kmp_taskdata_t) % sizeof(void *) == 0); 24370b57cec5SDimitry Andric 24380b57cec5SDimitry Andric // Data for task team but per thread 24390b57cec5SDimitry Andric typedef struct kmp_base_thread_data { 24400b57cec5SDimitry Andric kmp_info_p *td_thr; // Pointer back to thread info 24410b57cec5SDimitry Andric // Used only in __kmp_execute_tasks_template, maybe not avail until task is 24420b57cec5SDimitry Andric // queued? 24430b57cec5SDimitry Andric kmp_bootstrap_lock_t td_deque_lock; // Lock for accessing deque 24440b57cec5SDimitry Andric kmp_taskdata_t * 24450b57cec5SDimitry Andric *td_deque; // Deque of tasks encountered by td_thr, dynamically allocated 24460b57cec5SDimitry Andric kmp_int32 td_deque_size; // Size of deck 24470b57cec5SDimitry Andric kmp_uint32 td_deque_head; // Head of deque (will wrap) 24480b57cec5SDimitry Andric kmp_uint32 td_deque_tail; // Tail of deque (will wrap) 24490b57cec5SDimitry Andric kmp_int32 td_deque_ntasks; // Number of tasks in deque 24500b57cec5SDimitry Andric // GEH: shouldn't this be volatile since used in while-spin? 24510b57cec5SDimitry Andric kmp_int32 td_deque_last_stolen; // Thread number of last successful steal 24520b57cec5SDimitry Andric #ifdef BUILD_TIED_TASK_STACK 24530b57cec5SDimitry Andric kmp_task_stack_t td_susp_tied_tasks; // Stack of suspended tied tasks for task 24540b57cec5SDimitry Andric // scheduling constraint 24550b57cec5SDimitry Andric #endif // BUILD_TIED_TASK_STACK 24560b57cec5SDimitry Andric } kmp_base_thread_data_t; 24570b57cec5SDimitry Andric 24580b57cec5SDimitry Andric #define TASK_DEQUE_BITS 8 // Used solely to define INITIAL_TASK_DEQUE_SIZE 24590b57cec5SDimitry Andric #define INITIAL_TASK_DEQUE_SIZE (1 << TASK_DEQUE_BITS) 24600b57cec5SDimitry Andric 24610b57cec5SDimitry Andric #define TASK_DEQUE_SIZE(td) ((td).td_deque_size) 24620b57cec5SDimitry Andric #define TASK_DEQUE_MASK(td) ((td).td_deque_size - 1) 24630b57cec5SDimitry Andric 24640b57cec5SDimitry Andric typedef union KMP_ALIGN_CACHE kmp_thread_data { 24650b57cec5SDimitry Andric kmp_base_thread_data_t td; 24660b57cec5SDimitry Andric double td_align; /* use worst case alignment */ 24670b57cec5SDimitry Andric char td_pad[KMP_PAD(kmp_base_thread_data_t, CACHE_LINE)]; 24680b57cec5SDimitry Andric } kmp_thread_data_t; 24690b57cec5SDimitry Andric 24700b57cec5SDimitry Andric // Data for task teams which are used when tasking is enabled for the team 24710b57cec5SDimitry Andric typedef struct kmp_base_task_team { 24720b57cec5SDimitry Andric kmp_bootstrap_lock_t 24730b57cec5SDimitry Andric tt_threads_lock; /* Lock used to allocate per-thread part of task team */ 24740b57cec5SDimitry Andric /* must be bootstrap lock since used at library shutdown*/ 24750b57cec5SDimitry Andric kmp_task_team_t *tt_next; /* For linking the task team free list */ 24760b57cec5SDimitry Andric kmp_thread_data_t 24770b57cec5SDimitry Andric *tt_threads_data; /* Array of per-thread structures for task team */ 24780b57cec5SDimitry Andric /* Data survives task team deallocation */ 24790b57cec5SDimitry Andric kmp_int32 tt_found_tasks; /* Have we found tasks and queued them while 24800b57cec5SDimitry Andric executing this team? */ 24810b57cec5SDimitry Andric /* TRUE means tt_threads_data is set up and initialized */ 24820b57cec5SDimitry Andric kmp_int32 tt_nproc; /* #threads in team */ 24830b57cec5SDimitry Andric kmp_int32 tt_max_threads; // # entries allocated for threads_data array 24840b57cec5SDimitry Andric kmp_int32 tt_found_proxy_tasks; // found proxy tasks since last barrier 24850b57cec5SDimitry Andric kmp_int32 tt_untied_task_encountered; 2486e8d8bef9SDimitry Andric // There is hidden helper thread encountered in this task team so that we must 2487e8d8bef9SDimitry Andric // wait when waiting on task team 2488e8d8bef9SDimitry Andric kmp_int32 tt_hidden_helper_task_encountered; 24890b57cec5SDimitry Andric 24900b57cec5SDimitry Andric KMP_ALIGN_CACHE 24910b57cec5SDimitry Andric std::atomic<kmp_int32> tt_unfinished_threads; /* #threads still active */ 24920b57cec5SDimitry Andric 24930b57cec5SDimitry Andric KMP_ALIGN_CACHE 24940b57cec5SDimitry Andric volatile kmp_uint32 24950b57cec5SDimitry Andric tt_active; /* is the team still actively executing tasks */ 24960b57cec5SDimitry Andric } kmp_base_task_team_t; 24970b57cec5SDimitry Andric 24980b57cec5SDimitry Andric union KMP_ALIGN_CACHE kmp_task_team { 24990b57cec5SDimitry Andric kmp_base_task_team_t tt; 25000b57cec5SDimitry Andric double tt_align; /* use worst case alignment */ 25010b57cec5SDimitry Andric char tt_pad[KMP_PAD(kmp_base_task_team_t, CACHE_LINE)]; 25020b57cec5SDimitry Andric }; 25030b57cec5SDimitry Andric 25040b57cec5SDimitry Andric #if (USE_FAST_MEMORY == 3) || (USE_FAST_MEMORY == 5) 25050b57cec5SDimitry Andric // Free lists keep same-size free memory slots for fast memory allocation 25060b57cec5SDimitry Andric // routines 25070b57cec5SDimitry Andric typedef struct kmp_free_list { 25080b57cec5SDimitry Andric void *th_free_list_self; // Self-allocated tasks free list 25090b57cec5SDimitry Andric void *th_free_list_sync; // Self-allocated tasks stolen/returned by other 25100b57cec5SDimitry Andric // threads 25110b57cec5SDimitry Andric void *th_free_list_other; // Non-self free list (to be returned to owner's 25120b57cec5SDimitry Andric // sync list) 25130b57cec5SDimitry Andric } kmp_free_list_t; 25140b57cec5SDimitry Andric #endif 25150b57cec5SDimitry Andric #if KMP_NESTED_HOT_TEAMS 25160b57cec5SDimitry Andric // Hot teams array keeps hot teams and their sizes for given thread. Hot teams 25170b57cec5SDimitry Andric // are not put in teams pool, and they don't put threads in threads pool. 25180b57cec5SDimitry Andric typedef struct kmp_hot_team_ptr { 25190b57cec5SDimitry Andric kmp_team_p *hot_team; // pointer to hot_team of given nesting level 25200b57cec5SDimitry Andric kmp_int32 hot_team_nth; // number of threads allocated for the hot_team 25210b57cec5SDimitry Andric } kmp_hot_team_ptr_t; 25220b57cec5SDimitry Andric #endif 25230b57cec5SDimitry Andric typedef struct kmp_teams_size { 25240b57cec5SDimitry Andric kmp_int32 nteams; // number of teams in a league 25250b57cec5SDimitry Andric kmp_int32 nth; // number of threads in each team of the league 25260b57cec5SDimitry Andric } kmp_teams_size_t; 25270b57cec5SDimitry Andric 25280b57cec5SDimitry Andric // This struct stores a thread that acts as a "root" for a contention 25290b57cec5SDimitry Andric // group. Contention groups are rooted at kmp_root threads, but also at 2530*fe6060f1SDimitry Andric // each primary thread of each team created in the teams construct. 25310b57cec5SDimitry Andric // This struct therefore also stores a thread_limit associated with 25320b57cec5SDimitry Andric // that contention group, and a counter to track the number of threads 25330b57cec5SDimitry Andric // active in that contention group. Each thread has a list of these: CG 25340b57cec5SDimitry Andric // root threads have an entry in their list in which cg_root refers to 25350b57cec5SDimitry Andric // the thread itself, whereas other workers in the CG will have a 25360b57cec5SDimitry Andric // single entry where cg_root is same as the entry containing their CG 25370b57cec5SDimitry Andric // root. When a thread encounters a teams construct, it will add a new 25380b57cec5SDimitry Andric // entry to the front of its list, because it now roots a new CG. 25390b57cec5SDimitry Andric typedef struct kmp_cg_root { 25400b57cec5SDimitry Andric kmp_info_p *cg_root; // "root" thread for a contention group 25410b57cec5SDimitry Andric // The CG root's limit comes from OMP_THREAD_LIMIT for root threads, or 2542*fe6060f1SDimitry Andric // thread_limit clause for teams primary threads 25430b57cec5SDimitry Andric kmp_int32 cg_thread_limit; 25440b57cec5SDimitry Andric kmp_int32 cg_nthreads; // Count of active threads in CG rooted at cg_root 25450b57cec5SDimitry Andric struct kmp_cg_root *up; // pointer to higher level CG root in list 25460b57cec5SDimitry Andric } kmp_cg_root_t; 25470b57cec5SDimitry Andric 25480b57cec5SDimitry Andric // OpenMP thread data structures 25490b57cec5SDimitry Andric 25500b57cec5SDimitry Andric typedef struct KMP_ALIGN_CACHE kmp_base_info { 25510b57cec5SDimitry Andric /* Start with the readonly data which is cache aligned and padded. This is 2552*fe6060f1SDimitry Andric written before the thread starts working by the primary thread. Uber 2553*fe6060f1SDimitry Andric masters may update themselves later. Usage does not consider serialized 2554*fe6060f1SDimitry Andric regions. */ 25550b57cec5SDimitry Andric kmp_desc_t th_info; 25560b57cec5SDimitry Andric kmp_team_p *th_team; /* team we belong to */ 25570b57cec5SDimitry Andric kmp_root_p *th_root; /* pointer to root of task hierarchy */ 25580b57cec5SDimitry Andric kmp_info_p *th_next_pool; /* next available thread in the pool */ 25590b57cec5SDimitry Andric kmp_disp_t *th_dispatch; /* thread's dispatch data */ 25600b57cec5SDimitry Andric int th_in_pool; /* in thread pool (32 bits for TCR/TCW) */ 25610b57cec5SDimitry Andric 25620b57cec5SDimitry Andric /* The following are cached from the team info structure */ 25630b57cec5SDimitry Andric /* TODO use these in more places as determined to be needed via profiling */ 25640b57cec5SDimitry Andric int th_team_nproc; /* number of threads in a team */ 2565*fe6060f1SDimitry Andric kmp_info_p *th_team_master; /* the team's primary thread */ 25660b57cec5SDimitry Andric int th_team_serialized; /* team is serialized */ 25670b57cec5SDimitry Andric microtask_t th_teams_microtask; /* save entry address for teams construct */ 25680b57cec5SDimitry Andric int th_teams_level; /* save initial level of teams construct */ 25690b57cec5SDimitry Andric /* it is 0 on device but may be any on host */ 25700b57cec5SDimitry Andric 25715ffd83dbSDimitry Andric /* The blocktime info is copied from the team struct to the thread struct */ 25720b57cec5SDimitry Andric /* at the start of a barrier, and the values stored in the team are used */ 25730b57cec5SDimitry Andric /* at points in the code where the team struct is no longer guaranteed */ 25740b57cec5SDimitry Andric /* to exist (from the POV of worker threads). */ 25750b57cec5SDimitry Andric #if KMP_USE_MONITOR 25760b57cec5SDimitry Andric int th_team_bt_intervals; 25770b57cec5SDimitry Andric int th_team_bt_set; 25780b57cec5SDimitry Andric #else 25790b57cec5SDimitry Andric kmp_uint64 th_team_bt_intervals; 25800b57cec5SDimitry Andric #endif 25810b57cec5SDimitry Andric 25820b57cec5SDimitry Andric #if KMP_AFFINITY_SUPPORTED 25830b57cec5SDimitry Andric kmp_affin_mask_t *th_affin_mask; /* thread's current affinity mask */ 25840b57cec5SDimitry Andric #endif 25850b57cec5SDimitry Andric omp_allocator_handle_t th_def_allocator; /* default allocator */ 2586*fe6060f1SDimitry Andric /* The data set by the primary thread at reinit, then R/W by the worker */ 25870b57cec5SDimitry Andric KMP_ALIGN_CACHE int 25880b57cec5SDimitry Andric th_set_nproc; /* if > 0, then only use this request for the next fork */ 25890b57cec5SDimitry Andric #if KMP_NESTED_HOT_TEAMS 25900b57cec5SDimitry Andric kmp_hot_team_ptr_t *th_hot_teams; /* array of hot teams */ 25910b57cec5SDimitry Andric #endif 25920b57cec5SDimitry Andric kmp_proc_bind_t 25930b57cec5SDimitry Andric th_set_proc_bind; /* if != proc_bind_default, use request for next fork */ 25940b57cec5SDimitry Andric kmp_teams_size_t 25950b57cec5SDimitry Andric th_teams_size; /* number of teams/threads in teams construct */ 25960b57cec5SDimitry Andric #if KMP_AFFINITY_SUPPORTED 25970b57cec5SDimitry Andric int th_current_place; /* place currently bound to */ 25980b57cec5SDimitry Andric int th_new_place; /* place to bind to in par reg */ 25990b57cec5SDimitry Andric int th_first_place; /* first place in partition */ 26000b57cec5SDimitry Andric int th_last_place; /* last place in partition */ 26010b57cec5SDimitry Andric #endif 26020b57cec5SDimitry Andric int th_prev_level; /* previous level for affinity format */ 26030b57cec5SDimitry Andric int th_prev_num_threads; /* previous num_threads for affinity format */ 26040b57cec5SDimitry Andric #if USE_ITT_BUILD 26050b57cec5SDimitry Andric kmp_uint64 th_bar_arrive_time; /* arrival to barrier timestamp */ 26060b57cec5SDimitry Andric kmp_uint64 th_bar_min_time; /* minimum arrival time at the barrier */ 26070b57cec5SDimitry Andric kmp_uint64 th_frame_time; /* frame timestamp */ 26080b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 26090b57cec5SDimitry Andric kmp_local_t th_local; 26100b57cec5SDimitry Andric struct private_common *th_pri_head; 26110b57cec5SDimitry Andric 26120b57cec5SDimitry Andric /* Now the data only used by the worker (after initial allocation) */ 26130b57cec5SDimitry Andric /* TODO the first serial team should actually be stored in the info_t 26140b57cec5SDimitry Andric structure. this will help reduce initial allocation overhead */ 26150b57cec5SDimitry Andric KMP_ALIGN_CACHE kmp_team_p 26160b57cec5SDimitry Andric *th_serial_team; /*serialized team held in reserve*/ 26170b57cec5SDimitry Andric 26180b57cec5SDimitry Andric #if OMPT_SUPPORT 26190b57cec5SDimitry Andric ompt_thread_info_t ompt_thread_info; 26200b57cec5SDimitry Andric #endif 26210b57cec5SDimitry Andric 2622*fe6060f1SDimitry Andric /* The following are also read by the primary thread during reinit */ 26230b57cec5SDimitry Andric struct common_table *th_pri_common; 26240b57cec5SDimitry Andric 26250b57cec5SDimitry Andric volatile kmp_uint32 th_spin_here; /* thread-local location for spinning */ 26260b57cec5SDimitry Andric /* while awaiting queuing lock acquire */ 26270b57cec5SDimitry Andric 26280b57cec5SDimitry Andric volatile void *th_sleep_loc; // this points at a kmp_flag<T> 26290b57cec5SDimitry Andric 26300b57cec5SDimitry Andric ident_t *th_ident; 26310b57cec5SDimitry Andric unsigned th_x; // Random number generator data 26320b57cec5SDimitry Andric unsigned th_a; // Random number generator data 26330b57cec5SDimitry Andric 26340b57cec5SDimitry Andric /* Tasking-related data for the thread */ 26350b57cec5SDimitry Andric kmp_task_team_t *th_task_team; // Task team struct 26360b57cec5SDimitry Andric kmp_taskdata_t *th_current_task; // Innermost Task being executed 26370b57cec5SDimitry Andric kmp_uint8 th_task_state; // alternating 0/1 for task team identification 26380b57cec5SDimitry Andric kmp_uint8 *th_task_state_memo_stack; // Stack holding memos of th_task_state 26390b57cec5SDimitry Andric // at nested levels 26400b57cec5SDimitry Andric kmp_uint32 th_task_state_top; // Top element of th_task_state_memo_stack 26410b57cec5SDimitry Andric kmp_uint32 th_task_state_stack_sz; // Size of th_task_state_memo_stack 26420b57cec5SDimitry Andric kmp_uint32 th_reap_state; // Non-zero indicates thread is not 26430b57cec5SDimitry Andric // tasking, thus safe to reap 26440b57cec5SDimitry Andric 26450b57cec5SDimitry Andric /* More stuff for keeping track of active/sleeping threads (this part is 26460b57cec5SDimitry Andric written by the worker thread) */ 26470b57cec5SDimitry Andric kmp_uint8 th_active_in_pool; // included in count of #active threads in pool 26480b57cec5SDimitry Andric int th_active; // ! sleeping; 32 bits for TCR/TCW 26490b57cec5SDimitry Andric struct cons_header *th_cons; // used for consistency check 26500b57cec5SDimitry Andric #if KMP_USE_HIER_SCHED 26510b57cec5SDimitry Andric // used for hierarchical scheduling 26520b57cec5SDimitry Andric kmp_hier_private_bdata_t *th_hier_bar_data; 26530b57cec5SDimitry Andric #endif 26540b57cec5SDimitry Andric 26550b57cec5SDimitry Andric /* Add the syncronizing data which is cache aligned and padded. */ 26560b57cec5SDimitry Andric KMP_ALIGN_CACHE kmp_balign_t th_bar[bs_last_barrier]; 26570b57cec5SDimitry Andric 26580b57cec5SDimitry Andric KMP_ALIGN_CACHE volatile kmp_int32 26590b57cec5SDimitry Andric th_next_waiting; /* gtid+1 of next thread on lock wait queue, 0 if none */ 26600b57cec5SDimitry Andric 26610b57cec5SDimitry Andric #if (USE_FAST_MEMORY == 3) || (USE_FAST_MEMORY == 5) 26620b57cec5SDimitry Andric #define NUM_LISTS 4 26630b57cec5SDimitry Andric kmp_free_list_t th_free_lists[NUM_LISTS]; // Free lists for fast memory 26640b57cec5SDimitry Andric // allocation routines 26650b57cec5SDimitry Andric #endif 26660b57cec5SDimitry Andric 26670b57cec5SDimitry Andric #if KMP_OS_WINDOWS 26680b57cec5SDimitry Andric kmp_win32_cond_t th_suspend_cv; 26690b57cec5SDimitry Andric kmp_win32_mutex_t th_suspend_mx; 26700b57cec5SDimitry Andric std::atomic<int> th_suspend_init; 26710b57cec5SDimitry Andric #endif 26720b57cec5SDimitry Andric #if KMP_OS_UNIX 26730b57cec5SDimitry Andric kmp_cond_align_t th_suspend_cv; 26740b57cec5SDimitry Andric kmp_mutex_align_t th_suspend_mx; 26750b57cec5SDimitry Andric std::atomic<int> th_suspend_init_count; 26760b57cec5SDimitry Andric #endif 26770b57cec5SDimitry Andric 26780b57cec5SDimitry Andric #if USE_ITT_BUILD 26790b57cec5SDimitry Andric kmp_itt_mark_t th_itt_mark_single; 26800b57cec5SDimitry Andric // alignment ??? 26810b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 26820b57cec5SDimitry Andric #if KMP_STATS_ENABLED 26830b57cec5SDimitry Andric kmp_stats_list *th_stats; 26840b57cec5SDimitry Andric #endif 26850b57cec5SDimitry Andric #if KMP_OS_UNIX 26860b57cec5SDimitry Andric std::atomic<bool> th_blocking; 26870b57cec5SDimitry Andric #endif 26880b57cec5SDimitry Andric kmp_cg_root_t *th_cg_roots; // list of cg_roots associated with this thread 26890b57cec5SDimitry Andric } kmp_base_info_t; 26900b57cec5SDimitry Andric 26910b57cec5SDimitry Andric typedef union KMP_ALIGN_CACHE kmp_info { 26920b57cec5SDimitry Andric double th_align; /* use worst case alignment */ 26930b57cec5SDimitry Andric char th_pad[KMP_PAD(kmp_base_info_t, CACHE_LINE)]; 26940b57cec5SDimitry Andric kmp_base_info_t th; 26950b57cec5SDimitry Andric } kmp_info_t; 26960b57cec5SDimitry Andric 26970b57cec5SDimitry Andric // OpenMP thread team data structures 26980b57cec5SDimitry Andric 2699*fe6060f1SDimitry Andric typedef struct kmp_base_data { 2700*fe6060f1SDimitry Andric volatile kmp_uint32 t_value; 2701*fe6060f1SDimitry Andric } kmp_base_data_t; 27020b57cec5SDimitry Andric 27030b57cec5SDimitry Andric typedef union KMP_ALIGN_CACHE kmp_sleep_team { 27040b57cec5SDimitry Andric double dt_align; /* use worst case alignment */ 27050b57cec5SDimitry Andric char dt_pad[KMP_PAD(kmp_base_data_t, CACHE_LINE)]; 27060b57cec5SDimitry Andric kmp_base_data_t dt; 27070b57cec5SDimitry Andric } kmp_sleep_team_t; 27080b57cec5SDimitry Andric 27090b57cec5SDimitry Andric typedef union KMP_ALIGN_CACHE kmp_ordered_team { 27100b57cec5SDimitry Andric double dt_align; /* use worst case alignment */ 27110b57cec5SDimitry Andric char dt_pad[KMP_PAD(kmp_base_data_t, CACHE_LINE)]; 27120b57cec5SDimitry Andric kmp_base_data_t dt; 27130b57cec5SDimitry Andric } kmp_ordered_team_t; 27140b57cec5SDimitry Andric 27150b57cec5SDimitry Andric typedef int (*launch_t)(int gtid); 27160b57cec5SDimitry Andric 27170b57cec5SDimitry Andric /* Minimum number of ARGV entries to malloc if necessary */ 27180b57cec5SDimitry Andric #define KMP_MIN_MALLOC_ARGV_ENTRIES 100 27190b57cec5SDimitry Andric 27200b57cec5SDimitry Andric // Set up how many argv pointers will fit in cache lines containing 27210b57cec5SDimitry Andric // t_inline_argv. Historically, we have supported at least 96 bytes. Using a 2722*fe6060f1SDimitry Andric // larger value for more space between the primary write/worker read section and 27230b57cec5SDimitry Andric // read/write by all section seems to buy more performance on EPCC PARALLEL. 27240b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64 27250b57cec5SDimitry Andric #define KMP_INLINE_ARGV_BYTES \ 27260b57cec5SDimitry Andric (4 * CACHE_LINE - \ 27270b57cec5SDimitry Andric ((3 * KMP_PTR_SKIP + 2 * sizeof(int) + 2 * sizeof(kmp_int8) + \ 27280b57cec5SDimitry Andric sizeof(kmp_int16) + sizeof(kmp_uint32)) % \ 27290b57cec5SDimitry Andric CACHE_LINE)) 27300b57cec5SDimitry Andric #else 27310b57cec5SDimitry Andric #define KMP_INLINE_ARGV_BYTES \ 27320b57cec5SDimitry Andric (2 * CACHE_LINE - ((3 * KMP_PTR_SKIP + 2 * sizeof(int)) % CACHE_LINE)) 27330b57cec5SDimitry Andric #endif 27340b57cec5SDimitry Andric #define KMP_INLINE_ARGV_ENTRIES (int)(KMP_INLINE_ARGV_BYTES / KMP_PTR_SKIP) 27350b57cec5SDimitry Andric 27360b57cec5SDimitry Andric typedef struct KMP_ALIGN_CACHE kmp_base_team { 27370b57cec5SDimitry Andric // Synchronization Data 27380b57cec5SDimitry Andric // --------------------------------------------------------------------------- 27390b57cec5SDimitry Andric KMP_ALIGN_CACHE kmp_ordered_team_t t_ordered; 27400b57cec5SDimitry Andric kmp_balign_team_t t_bar[bs_last_barrier]; 27410b57cec5SDimitry Andric std::atomic<int> t_construct; // count of single directive encountered by team 27420b57cec5SDimitry Andric char pad[sizeof(kmp_lock_t)]; // padding to maintain performance on big iron 27430b57cec5SDimitry Andric 27440b57cec5SDimitry Andric // [0] - parallel / [1] - worksharing task reduction data shared by taskgroups 27450b57cec5SDimitry Andric std::atomic<void *> t_tg_reduce_data[2]; // to support task modifier 27460b57cec5SDimitry Andric std::atomic<int> t_tg_fini_counter[2]; // sync end of task reductions 27470b57cec5SDimitry Andric 2748*fe6060f1SDimitry Andric // Primary thread only 27490b57cec5SDimitry Andric // --------------------------------------------------------------------------- 2750*fe6060f1SDimitry Andric KMP_ALIGN_CACHE int t_master_tid; // tid of primary thread in parent team 2751*fe6060f1SDimitry Andric int t_master_this_cons; // "this_construct" single counter of primary thread 2752*fe6060f1SDimitry Andric // in parent team 27530b57cec5SDimitry Andric ident_t *t_ident; // if volatile, have to change too much other crud to 27540b57cec5SDimitry Andric // volatile too 27550b57cec5SDimitry Andric kmp_team_p *t_parent; // parent team 27560b57cec5SDimitry Andric kmp_team_p *t_next_pool; // next free team in the team pool 27570b57cec5SDimitry Andric kmp_disp_t *t_dispatch; // thread's dispatch data 27580b57cec5SDimitry Andric kmp_task_team_t *t_task_team[2]; // Task team struct; switch between 2 27590b57cec5SDimitry Andric kmp_proc_bind_t t_proc_bind; // bind type for par region 27600b57cec5SDimitry Andric #if USE_ITT_BUILD 27610b57cec5SDimitry Andric kmp_uint64 t_region_time; // region begin timestamp 27620b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 27630b57cec5SDimitry Andric 2764*fe6060f1SDimitry Andric // Primary thread write, workers read 27650b57cec5SDimitry Andric // -------------------------------------------------------------------------- 27660b57cec5SDimitry Andric KMP_ALIGN_CACHE void **t_argv; 27670b57cec5SDimitry Andric int t_argc; 27680b57cec5SDimitry Andric int t_nproc; // number of threads in team 27690b57cec5SDimitry Andric microtask_t t_pkfn; 27700b57cec5SDimitry Andric launch_t t_invoke; // procedure to launch the microtask 27710b57cec5SDimitry Andric 27720b57cec5SDimitry Andric #if OMPT_SUPPORT 27730b57cec5SDimitry Andric ompt_team_info_t ompt_team_info; 27740b57cec5SDimitry Andric ompt_lw_taskteam_t *ompt_serialized_team_info; 27750b57cec5SDimitry Andric #endif 27760b57cec5SDimitry Andric 27770b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64 27780b57cec5SDimitry Andric kmp_int8 t_fp_control_saved; 27790b57cec5SDimitry Andric kmp_int8 t_pad2b; 27800b57cec5SDimitry Andric kmp_int16 t_x87_fpu_control_word; // FP control regs 27810b57cec5SDimitry Andric kmp_uint32 t_mxcsr; 27820b57cec5SDimitry Andric #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */ 27830b57cec5SDimitry Andric 27840b57cec5SDimitry Andric void *t_inline_argv[KMP_INLINE_ARGV_ENTRIES]; 27850b57cec5SDimitry Andric 27860b57cec5SDimitry Andric KMP_ALIGN_CACHE kmp_info_t **t_threads; 27870b57cec5SDimitry Andric kmp_taskdata_t 27880b57cec5SDimitry Andric *t_implicit_task_taskdata; // Taskdata for the thread's implicit task 27890b57cec5SDimitry Andric int t_level; // nested parallel level 27900b57cec5SDimitry Andric 27910b57cec5SDimitry Andric KMP_ALIGN_CACHE int t_max_argc; 2792480093f4SDimitry Andric int t_max_nproc; // max threads this team can handle (dynamically expandable) 27930b57cec5SDimitry Andric int t_serialized; // levels deep of serialized teams 27940b57cec5SDimitry Andric dispatch_shared_info_t *t_disp_buffer; // buffers for dispatch system 27950b57cec5SDimitry Andric int t_id; // team's id, assigned by debugger. 27960b57cec5SDimitry Andric int t_active_level; // nested active parallel level 27970b57cec5SDimitry Andric kmp_r_sched_t t_sched; // run-time schedule for the team 27980b57cec5SDimitry Andric #if KMP_AFFINITY_SUPPORTED 27990b57cec5SDimitry Andric int t_first_place; // first & last place in parent thread's partition. 2800*fe6060f1SDimitry Andric int t_last_place; // Restore these values to primary thread after par region. 28010b57cec5SDimitry Andric #endif // KMP_AFFINITY_SUPPORTED 28020b57cec5SDimitry Andric int t_display_affinity; 28030b57cec5SDimitry Andric int t_size_changed; // team size was changed?: 0: no, 1: yes, -1: changed via 28040b57cec5SDimitry Andric // omp_set_num_threads() call 28050b57cec5SDimitry Andric omp_allocator_handle_t t_def_allocator; /* default allocator */ 28060b57cec5SDimitry Andric 28070b57cec5SDimitry Andric // Read/write by workers as well 28080b57cec5SDimitry Andric #if (KMP_ARCH_X86 || KMP_ARCH_X86_64) 28090b57cec5SDimitry Andric // Using CACHE_LINE=64 reduces memory footprint, but causes a big perf 28100b57cec5SDimitry Andric // regression of epcc 'parallel' and 'barrier' on fxe256lin01. This extra 28110b57cec5SDimitry Andric // padding serves to fix the performance of epcc 'parallel' and 'barrier' when 28120b57cec5SDimitry Andric // CACHE_LINE=64. TODO: investigate more and get rid if this padding. 28130b57cec5SDimitry Andric char dummy_padding[1024]; 28140b57cec5SDimitry Andric #endif 28150b57cec5SDimitry Andric // Internal control stack for additional nested teams. 28160b57cec5SDimitry Andric KMP_ALIGN_CACHE kmp_internal_control_t *t_control_stack_top; 28170b57cec5SDimitry Andric // for SERIALIZED teams nested 2 or more levels deep 28180b57cec5SDimitry Andric // typed flag to store request state of cancellation 28190b57cec5SDimitry Andric std::atomic<kmp_int32> t_cancel_request; 28200b57cec5SDimitry Andric int t_master_active; // save on fork, restore on join 28210b57cec5SDimitry Andric void *t_copypriv_data; // team specific pointer to copyprivate data array 28220b57cec5SDimitry Andric #if KMP_OS_WINDOWS 28230b57cec5SDimitry Andric std::atomic<kmp_uint32> t_copyin_counter; 28240b57cec5SDimitry Andric #endif 28250b57cec5SDimitry Andric #if USE_ITT_BUILD 28260b57cec5SDimitry Andric void *t_stack_id; // team specific stack stitching id (for ittnotify) 28270b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 28280b57cec5SDimitry Andric } kmp_base_team_t; 28290b57cec5SDimitry Andric 28300b57cec5SDimitry Andric union KMP_ALIGN_CACHE kmp_team { 28310b57cec5SDimitry Andric kmp_base_team_t t; 28320b57cec5SDimitry Andric double t_align; /* use worst case alignment */ 28330b57cec5SDimitry Andric char t_pad[KMP_PAD(kmp_base_team_t, CACHE_LINE)]; 28340b57cec5SDimitry Andric }; 28350b57cec5SDimitry Andric 28360b57cec5SDimitry Andric typedef union KMP_ALIGN_CACHE kmp_time_global { 28370b57cec5SDimitry Andric double dt_align; /* use worst case alignment */ 28380b57cec5SDimitry Andric char dt_pad[KMP_PAD(kmp_base_data_t, CACHE_LINE)]; 28390b57cec5SDimitry Andric kmp_base_data_t dt; 28400b57cec5SDimitry Andric } kmp_time_global_t; 28410b57cec5SDimitry Andric 28420b57cec5SDimitry Andric typedef struct kmp_base_global { 28430b57cec5SDimitry Andric /* cache-aligned */ 28440b57cec5SDimitry Andric kmp_time_global_t g_time; 28450b57cec5SDimitry Andric 28460b57cec5SDimitry Andric /* non cache-aligned */ 28470b57cec5SDimitry Andric volatile int g_abort; 28480b57cec5SDimitry Andric volatile int g_done; 28490b57cec5SDimitry Andric 28500b57cec5SDimitry Andric int g_dynamic; 28510b57cec5SDimitry Andric enum dynamic_mode g_dynamic_mode; 28520b57cec5SDimitry Andric } kmp_base_global_t; 28530b57cec5SDimitry Andric 28540b57cec5SDimitry Andric typedef union KMP_ALIGN_CACHE kmp_global { 28550b57cec5SDimitry Andric kmp_base_global_t g; 28560b57cec5SDimitry Andric double g_align; /* use worst case alignment */ 28570b57cec5SDimitry Andric char g_pad[KMP_PAD(kmp_base_global_t, CACHE_LINE)]; 28580b57cec5SDimitry Andric } kmp_global_t; 28590b57cec5SDimitry Andric 28600b57cec5SDimitry Andric typedef struct kmp_base_root { 28610b57cec5SDimitry Andric // TODO: GEH - combine r_active with r_in_parallel then r_active == 28620b57cec5SDimitry Andric // (r_in_parallel>= 0) 28630b57cec5SDimitry Andric // TODO: GEH - then replace r_active with t_active_levels if we can to reduce 28640b57cec5SDimitry Andric // the synch overhead or keeping r_active 28650b57cec5SDimitry Andric volatile int r_active; /* TRUE if some region in a nest has > 1 thread */ 28660b57cec5SDimitry Andric // keeps a count of active parallel regions per root 28670b57cec5SDimitry Andric std::atomic<int> r_in_parallel; 28680b57cec5SDimitry Andric // GEH: This is misnamed, should be r_active_levels 28690b57cec5SDimitry Andric kmp_team_t *r_root_team; 28700b57cec5SDimitry Andric kmp_team_t *r_hot_team; 28710b57cec5SDimitry Andric kmp_info_t *r_uber_thread; 28720b57cec5SDimitry Andric kmp_lock_t r_begin_lock; 28730b57cec5SDimitry Andric volatile int r_begin; 28740b57cec5SDimitry Andric int r_blocktime; /* blocktime for this root and descendants */ 2875*fe6060f1SDimitry Andric #if KMP_AFFINITY_SUPPORTED 2876*fe6060f1SDimitry Andric int r_affinity_assigned; 2877*fe6060f1SDimitry Andric #endif // KMP_AFFINITY_SUPPORTED 28780b57cec5SDimitry Andric } kmp_base_root_t; 28790b57cec5SDimitry Andric 28800b57cec5SDimitry Andric typedef union KMP_ALIGN_CACHE kmp_root { 28810b57cec5SDimitry Andric kmp_base_root_t r; 28820b57cec5SDimitry Andric double r_align; /* use worst case alignment */ 28830b57cec5SDimitry Andric char r_pad[KMP_PAD(kmp_base_root_t, CACHE_LINE)]; 28840b57cec5SDimitry Andric } kmp_root_t; 28850b57cec5SDimitry Andric 28860b57cec5SDimitry Andric struct fortran_inx_info { 28870b57cec5SDimitry Andric kmp_int32 data; 28880b57cec5SDimitry Andric }; 28890b57cec5SDimitry Andric 28900b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */ 28910b57cec5SDimitry Andric 28920b57cec5SDimitry Andric extern int __kmp_settings; 28930b57cec5SDimitry Andric extern int __kmp_duplicate_library_ok; 28940b57cec5SDimitry Andric #if USE_ITT_BUILD 28950b57cec5SDimitry Andric extern int __kmp_forkjoin_frames; 28960b57cec5SDimitry Andric extern int __kmp_forkjoin_frames_mode; 28970b57cec5SDimitry Andric #endif 28980b57cec5SDimitry Andric extern PACKED_REDUCTION_METHOD_T __kmp_force_reduction_method; 28990b57cec5SDimitry Andric extern int __kmp_determ_red; 29000b57cec5SDimitry Andric 29010b57cec5SDimitry Andric #ifdef KMP_DEBUG 29020b57cec5SDimitry Andric extern int kmp_a_debug; 29030b57cec5SDimitry Andric extern int kmp_b_debug; 29040b57cec5SDimitry Andric extern int kmp_c_debug; 29050b57cec5SDimitry Andric extern int kmp_d_debug; 29060b57cec5SDimitry Andric extern int kmp_e_debug; 29070b57cec5SDimitry Andric extern int kmp_f_debug; 29080b57cec5SDimitry Andric #endif /* KMP_DEBUG */ 29090b57cec5SDimitry Andric 29100b57cec5SDimitry Andric /* For debug information logging using rotating buffer */ 29110b57cec5SDimitry Andric #define KMP_DEBUG_BUF_LINES_INIT 512 29120b57cec5SDimitry Andric #define KMP_DEBUG_BUF_LINES_MIN 1 29130b57cec5SDimitry Andric 29140b57cec5SDimitry Andric #define KMP_DEBUG_BUF_CHARS_INIT 128 29150b57cec5SDimitry Andric #define KMP_DEBUG_BUF_CHARS_MIN 2 29160b57cec5SDimitry Andric 29170b57cec5SDimitry Andric extern int 29180b57cec5SDimitry Andric __kmp_debug_buf; /* TRUE means use buffer, FALSE means print to stderr */ 29190b57cec5SDimitry Andric extern int __kmp_debug_buf_lines; /* How many lines of debug stored in buffer */ 29200b57cec5SDimitry Andric extern int 29210b57cec5SDimitry Andric __kmp_debug_buf_chars; /* How many characters allowed per line in buffer */ 29220b57cec5SDimitry Andric extern int __kmp_debug_buf_atomic; /* TRUE means use atomic update of buffer 29230b57cec5SDimitry Andric entry pointer */ 29240b57cec5SDimitry Andric 29250b57cec5SDimitry Andric extern char *__kmp_debug_buffer; /* Debug buffer itself */ 29260b57cec5SDimitry Andric extern std::atomic<int> __kmp_debug_count; /* Counter for number of lines 29270b57cec5SDimitry Andric printed in buffer so far */ 29280b57cec5SDimitry Andric extern int __kmp_debug_buf_warn_chars; /* Keep track of char increase 29290b57cec5SDimitry Andric recommended in warnings */ 29300b57cec5SDimitry Andric /* end rotating debug buffer */ 29310b57cec5SDimitry Andric 29320b57cec5SDimitry Andric #ifdef KMP_DEBUG 29330b57cec5SDimitry Andric extern int __kmp_par_range; /* +1 => only go par for constructs in range */ 29340b57cec5SDimitry Andric 29350b57cec5SDimitry Andric #define KMP_PAR_RANGE_ROUTINE_LEN 1024 29360b57cec5SDimitry Andric extern char __kmp_par_range_routine[KMP_PAR_RANGE_ROUTINE_LEN]; 29370b57cec5SDimitry Andric #define KMP_PAR_RANGE_FILENAME_LEN 1024 29380b57cec5SDimitry Andric extern char __kmp_par_range_filename[KMP_PAR_RANGE_FILENAME_LEN]; 29390b57cec5SDimitry Andric extern int __kmp_par_range_lb; 29400b57cec5SDimitry Andric extern int __kmp_par_range_ub; 29410b57cec5SDimitry Andric #endif 29420b57cec5SDimitry Andric 29430b57cec5SDimitry Andric /* For printing out dynamic storage map for threads and teams */ 29440b57cec5SDimitry Andric extern int 29450b57cec5SDimitry Andric __kmp_storage_map; /* True means print storage map for threads and teams */ 29460b57cec5SDimitry Andric extern int __kmp_storage_map_verbose; /* True means storage map includes 29470b57cec5SDimitry Andric placement info */ 29480b57cec5SDimitry Andric extern int __kmp_storage_map_verbose_specified; 29490b57cec5SDimitry Andric 29500b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64 29510b57cec5SDimitry Andric extern kmp_cpuinfo_t __kmp_cpuinfo; 29520b57cec5SDimitry Andric #endif 29530b57cec5SDimitry Andric 29540b57cec5SDimitry Andric extern volatile int __kmp_init_serial; 29550b57cec5SDimitry Andric extern volatile int __kmp_init_gtid; 29560b57cec5SDimitry Andric extern volatile int __kmp_init_common; 29570b57cec5SDimitry Andric extern volatile int __kmp_init_middle; 29580b57cec5SDimitry Andric extern volatile int __kmp_init_parallel; 29590b57cec5SDimitry Andric #if KMP_USE_MONITOR 29600b57cec5SDimitry Andric extern volatile int __kmp_init_monitor; 29610b57cec5SDimitry Andric #endif 29620b57cec5SDimitry Andric extern volatile int __kmp_init_user_locks; 2963e8d8bef9SDimitry Andric extern volatile int __kmp_init_hidden_helper_threads; 29640b57cec5SDimitry Andric extern int __kmp_init_counter; 29650b57cec5SDimitry Andric extern int __kmp_root_counter; 29660b57cec5SDimitry Andric extern int __kmp_version; 29670b57cec5SDimitry Andric 29680b57cec5SDimitry Andric /* list of address of allocated caches for commons */ 29690b57cec5SDimitry Andric extern kmp_cached_addr_t *__kmp_threadpriv_cache_list; 29700b57cec5SDimitry Andric 29710b57cec5SDimitry Andric /* Barrier algorithm types and options */ 29720b57cec5SDimitry Andric extern kmp_uint32 __kmp_barrier_gather_bb_dflt; 29730b57cec5SDimitry Andric extern kmp_uint32 __kmp_barrier_release_bb_dflt; 29740b57cec5SDimitry Andric extern kmp_bar_pat_e __kmp_barrier_gather_pat_dflt; 29750b57cec5SDimitry Andric extern kmp_bar_pat_e __kmp_barrier_release_pat_dflt; 29760b57cec5SDimitry Andric extern kmp_uint32 __kmp_barrier_gather_branch_bits[bs_last_barrier]; 29770b57cec5SDimitry Andric extern kmp_uint32 __kmp_barrier_release_branch_bits[bs_last_barrier]; 29780b57cec5SDimitry Andric extern kmp_bar_pat_e __kmp_barrier_gather_pattern[bs_last_barrier]; 29790b57cec5SDimitry Andric extern kmp_bar_pat_e __kmp_barrier_release_pattern[bs_last_barrier]; 29800b57cec5SDimitry Andric extern char const *__kmp_barrier_branch_bit_env_name[bs_last_barrier]; 29810b57cec5SDimitry Andric extern char const *__kmp_barrier_pattern_env_name[bs_last_barrier]; 29820b57cec5SDimitry Andric extern char const *__kmp_barrier_type_name[bs_last_barrier]; 29830b57cec5SDimitry Andric extern char const *__kmp_barrier_pattern_name[bp_last_bar]; 29840b57cec5SDimitry Andric 29850b57cec5SDimitry Andric /* Global Locks */ 29860b57cec5SDimitry Andric extern kmp_bootstrap_lock_t __kmp_initz_lock; /* control initialization */ 29870b57cec5SDimitry Andric extern kmp_bootstrap_lock_t __kmp_forkjoin_lock; /* control fork/join access */ 29880b57cec5SDimitry Andric extern kmp_bootstrap_lock_t __kmp_task_team_lock; 29890b57cec5SDimitry Andric extern kmp_bootstrap_lock_t 29900b57cec5SDimitry Andric __kmp_exit_lock; /* exit() is not always thread-safe */ 29910b57cec5SDimitry Andric #if KMP_USE_MONITOR 29920b57cec5SDimitry Andric extern kmp_bootstrap_lock_t 29930b57cec5SDimitry Andric __kmp_monitor_lock; /* control monitor thread creation */ 29940b57cec5SDimitry Andric #endif 29950b57cec5SDimitry Andric extern kmp_bootstrap_lock_t 29960b57cec5SDimitry Andric __kmp_tp_cached_lock; /* used for the hack to allow threadprivate cache and 29970b57cec5SDimitry Andric __kmp_threads expansion to co-exist */ 29980b57cec5SDimitry Andric 29990b57cec5SDimitry Andric extern kmp_lock_t __kmp_global_lock; /* control OS/global access */ 30000b57cec5SDimitry Andric extern kmp_queuing_lock_t __kmp_dispatch_lock; /* control dispatch access */ 30010b57cec5SDimitry Andric extern kmp_lock_t __kmp_debug_lock; /* control I/O access for KMP_DEBUG */ 30020b57cec5SDimitry Andric 30030b57cec5SDimitry Andric extern enum library_type __kmp_library; 30040b57cec5SDimitry Andric 30050b57cec5SDimitry Andric extern enum sched_type __kmp_sched; /* default runtime scheduling */ 30060b57cec5SDimitry Andric extern enum sched_type __kmp_static; /* default static scheduling method */ 30070b57cec5SDimitry Andric extern enum sched_type __kmp_guided; /* default guided scheduling method */ 30080b57cec5SDimitry Andric extern enum sched_type __kmp_auto; /* default auto scheduling method */ 30090b57cec5SDimitry Andric extern int __kmp_chunk; /* default runtime chunk size */ 3010*fe6060f1SDimitry Andric extern int __kmp_force_monotonic; /* whether monotonic scheduling forced */ 30110b57cec5SDimitry Andric 30120b57cec5SDimitry Andric extern size_t __kmp_stksize; /* stack size per thread */ 30130b57cec5SDimitry Andric #if KMP_USE_MONITOR 30140b57cec5SDimitry Andric extern size_t __kmp_monitor_stksize; /* stack size for monitor thread */ 30150b57cec5SDimitry Andric #endif 30160b57cec5SDimitry Andric extern size_t __kmp_stkoffset; /* stack offset per thread */ 30170b57cec5SDimitry Andric extern int __kmp_stkpadding; /* Should we pad root thread(s) stack */ 30180b57cec5SDimitry Andric 30190b57cec5SDimitry Andric extern size_t 30200b57cec5SDimitry Andric __kmp_malloc_pool_incr; /* incremental size of pool for kmp_malloc() */ 30210b57cec5SDimitry Andric extern int __kmp_env_stksize; /* was KMP_STACKSIZE specified? */ 30220b57cec5SDimitry Andric extern int __kmp_env_blocktime; /* was KMP_BLOCKTIME specified? */ 30230b57cec5SDimitry Andric extern int __kmp_env_checks; /* was KMP_CHECKS specified? */ 30240b57cec5SDimitry Andric extern int __kmp_env_consistency_check; // was KMP_CONSISTENCY_CHECK specified? 30250b57cec5SDimitry Andric extern int __kmp_generate_warnings; /* should we issue warnings? */ 30260b57cec5SDimitry Andric extern int __kmp_reserve_warn; /* have we issued reserve_threads warning? */ 30270b57cec5SDimitry Andric 30280b57cec5SDimitry Andric #ifdef DEBUG_SUSPEND 30290b57cec5SDimitry Andric extern int __kmp_suspend_count; /* count inside __kmp_suspend_template() */ 30300b57cec5SDimitry Andric #endif 30310b57cec5SDimitry Andric 30320b57cec5SDimitry Andric extern kmp_int32 __kmp_use_yield; 30330b57cec5SDimitry Andric extern kmp_int32 __kmp_use_yield_exp_set; 30340b57cec5SDimitry Andric extern kmp_uint32 __kmp_yield_init; 30350b57cec5SDimitry Andric extern kmp_uint32 __kmp_yield_next; 30360b57cec5SDimitry Andric 30370b57cec5SDimitry Andric /* ------------------------------------------------------------------------- */ 30380b57cec5SDimitry Andric extern int __kmp_allThreadsSpecified; 30390b57cec5SDimitry Andric 30400b57cec5SDimitry Andric extern size_t __kmp_align_alloc; 30410b57cec5SDimitry Andric /* following data protected by initialization routines */ 30420b57cec5SDimitry Andric extern int __kmp_xproc; /* number of processors in the system */ 30430b57cec5SDimitry Andric extern int __kmp_avail_proc; /* number of processors available to the process */ 30440b57cec5SDimitry Andric extern size_t __kmp_sys_min_stksize; /* system-defined minimum stack size */ 30450b57cec5SDimitry Andric extern int __kmp_sys_max_nth; /* system-imposed maximum number of threads */ 30460b57cec5SDimitry Andric // maximum total number of concurrently-existing threads on device 30470b57cec5SDimitry Andric extern int __kmp_max_nth; 30480b57cec5SDimitry Andric // maximum total number of concurrently-existing threads in a contention group 30490b57cec5SDimitry Andric extern int __kmp_cg_max_nth; 30500b57cec5SDimitry Andric extern int __kmp_teams_max_nth; // max threads used in a teams construct 30510b57cec5SDimitry Andric extern int __kmp_threads_capacity; /* capacity of the arrays __kmp_threads and 30520b57cec5SDimitry Andric __kmp_root */ 30530b57cec5SDimitry Andric extern int __kmp_dflt_team_nth; /* default number of threads in a parallel 30540b57cec5SDimitry Andric region a la OMP_NUM_THREADS */ 30550b57cec5SDimitry Andric extern int __kmp_dflt_team_nth_ub; /* upper bound on "" determined at serial 30560b57cec5SDimitry Andric initialization */ 30570b57cec5SDimitry Andric extern int __kmp_tp_capacity; /* capacity of __kmp_threads if threadprivate is 30580b57cec5SDimitry Andric used (fixed) */ 30590b57cec5SDimitry Andric extern int __kmp_tp_cached; /* whether threadprivate cache has been created 30600b57cec5SDimitry Andric (__kmpc_threadprivate_cached()) */ 30610b57cec5SDimitry Andric extern int __kmp_dflt_blocktime; /* number of milliseconds to wait before 30620b57cec5SDimitry Andric blocking (env setting) */ 30630b57cec5SDimitry Andric #if KMP_USE_MONITOR 30640b57cec5SDimitry Andric extern int 30650b57cec5SDimitry Andric __kmp_monitor_wakeups; /* number of times monitor wakes up per second */ 30660b57cec5SDimitry Andric extern int __kmp_bt_intervals; /* number of monitor timestamp intervals before 30670b57cec5SDimitry Andric blocking */ 30680b57cec5SDimitry Andric #endif 30690b57cec5SDimitry Andric #ifdef KMP_ADJUST_BLOCKTIME 30700b57cec5SDimitry Andric extern int __kmp_zero_bt; /* whether blocktime has been forced to zero */ 30710b57cec5SDimitry Andric #endif /* KMP_ADJUST_BLOCKTIME */ 30720b57cec5SDimitry Andric #ifdef KMP_DFLT_NTH_CORES 30730b57cec5SDimitry Andric extern int __kmp_ncores; /* Total number of cores for threads placement */ 30740b57cec5SDimitry Andric #endif 30750b57cec5SDimitry Andric /* Number of millisecs to delay on abort for Intel(R) VTune(TM) tools */ 30760b57cec5SDimitry Andric extern int __kmp_abort_delay; 30770b57cec5SDimitry Andric 30780b57cec5SDimitry Andric extern int __kmp_need_register_atfork_specified; 3079*fe6060f1SDimitry Andric extern int __kmp_need_register_atfork; /* At initialization, call pthread_atfork 3080*fe6060f1SDimitry Andric to install fork handler */ 30810b57cec5SDimitry Andric extern int __kmp_gtid_mode; /* Method of getting gtid, values: 30820b57cec5SDimitry Andric 0 - not set, will be set at runtime 30830b57cec5SDimitry Andric 1 - using stack search 30840b57cec5SDimitry Andric 2 - dynamic TLS (pthread_getspecific(Linux* OS/OS 30850b57cec5SDimitry Andric X*) or TlsGetValue(Windows* OS)) 30860b57cec5SDimitry Andric 3 - static TLS (__declspec(thread) __kmp_gtid), 30870b57cec5SDimitry Andric Linux* OS .so only. */ 30880b57cec5SDimitry Andric extern int 30890b57cec5SDimitry Andric __kmp_adjust_gtid_mode; /* If true, adjust method based on #threads */ 30900b57cec5SDimitry Andric #ifdef KMP_TDATA_GTID 30910b57cec5SDimitry Andric extern KMP_THREAD_LOCAL int __kmp_gtid; 30920b57cec5SDimitry Andric #endif 30930b57cec5SDimitry Andric extern int __kmp_tls_gtid_min; /* #threads below which use sp search for gtid */ 30940b57cec5SDimitry Andric extern int __kmp_foreign_tp; // If true, separate TP var for each foreign thread 30950b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64 30960b57cec5SDimitry Andric extern int __kmp_inherit_fp_control; // copy fp creg(s) parent->workers at fork 30970b57cec5SDimitry Andric extern kmp_int16 __kmp_init_x87_fpu_control_word; // init thread's FP ctrl reg 30980b57cec5SDimitry Andric extern kmp_uint32 __kmp_init_mxcsr; /* init thread's mxscr */ 30990b57cec5SDimitry Andric #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */ 31000b57cec5SDimitry Andric 31010b57cec5SDimitry Andric // max_active_levels for nested parallelism enabled by default via 31020b57cec5SDimitry Andric // OMP_MAX_ACTIVE_LEVELS, OMP_NESTED, OMP_NUM_THREADS, and OMP_PROC_BIND 31030b57cec5SDimitry Andric extern int __kmp_dflt_max_active_levels; 31040b57cec5SDimitry Andric // Indicates whether value of __kmp_dflt_max_active_levels was already 31050b57cec5SDimitry Andric // explicitly set by OMP_MAX_ACTIVE_LEVELS or OMP_NESTED=false 31060b57cec5SDimitry Andric extern bool __kmp_dflt_max_active_levels_set; 31070b57cec5SDimitry Andric extern int __kmp_dispatch_num_buffers; /* max possible dynamic loops in 31080b57cec5SDimitry Andric concurrent execution per team */ 31090b57cec5SDimitry Andric #if KMP_NESTED_HOT_TEAMS 31100b57cec5SDimitry Andric extern int __kmp_hot_teams_mode; 31110b57cec5SDimitry Andric extern int __kmp_hot_teams_max_level; 31120b57cec5SDimitry Andric #endif 31130b57cec5SDimitry Andric 31140b57cec5SDimitry Andric #if KMP_OS_LINUX 31150b57cec5SDimitry Andric extern enum clock_function_type __kmp_clock_function; 31160b57cec5SDimitry Andric extern int __kmp_clock_function_param; 31170b57cec5SDimitry Andric #endif /* KMP_OS_LINUX */ 31180b57cec5SDimitry Andric 31190b57cec5SDimitry Andric #if KMP_MIC_SUPPORTED 31200b57cec5SDimitry Andric extern enum mic_type __kmp_mic_type; 31210b57cec5SDimitry Andric #endif 31220b57cec5SDimitry Andric 31230b57cec5SDimitry Andric #ifdef USE_LOAD_BALANCE 31240b57cec5SDimitry Andric extern double __kmp_load_balance_interval; // load balance algorithm interval 31250b57cec5SDimitry Andric #endif /* USE_LOAD_BALANCE */ 31260b57cec5SDimitry Andric 31270b57cec5SDimitry Andric // OpenMP 3.1 - Nested num threads array 31280b57cec5SDimitry Andric typedef struct kmp_nested_nthreads_t { 31290b57cec5SDimitry Andric int *nth; 31300b57cec5SDimitry Andric int size; 31310b57cec5SDimitry Andric int used; 31320b57cec5SDimitry Andric } kmp_nested_nthreads_t; 31330b57cec5SDimitry Andric 31340b57cec5SDimitry Andric extern kmp_nested_nthreads_t __kmp_nested_nth; 31350b57cec5SDimitry Andric 31360b57cec5SDimitry Andric #if KMP_USE_ADAPTIVE_LOCKS 31370b57cec5SDimitry Andric 31380b57cec5SDimitry Andric // Parameters for the speculative lock backoff system. 31390b57cec5SDimitry Andric struct kmp_adaptive_backoff_params_t { 31400b57cec5SDimitry Andric // Number of soft retries before it counts as a hard retry. 31410b57cec5SDimitry Andric kmp_uint32 max_soft_retries; 31420b57cec5SDimitry Andric // Badness is a bit mask : 0,1,3,7,15,... on each hard failure we move one to 31430b57cec5SDimitry Andric // the right 31440b57cec5SDimitry Andric kmp_uint32 max_badness; 31450b57cec5SDimitry Andric }; 31460b57cec5SDimitry Andric 31470b57cec5SDimitry Andric extern kmp_adaptive_backoff_params_t __kmp_adaptive_backoff_params; 31480b57cec5SDimitry Andric 31490b57cec5SDimitry Andric #if KMP_DEBUG_ADAPTIVE_LOCKS 31500b57cec5SDimitry Andric extern const char *__kmp_speculative_statsfile; 31510b57cec5SDimitry Andric #endif 31520b57cec5SDimitry Andric 31530b57cec5SDimitry Andric #endif // KMP_USE_ADAPTIVE_LOCKS 31540b57cec5SDimitry Andric 31550b57cec5SDimitry Andric extern int __kmp_display_env; /* TRUE or FALSE */ 31560b57cec5SDimitry Andric extern int __kmp_display_env_verbose; /* TRUE if OMP_DISPLAY_ENV=VERBOSE */ 31570b57cec5SDimitry Andric extern int __kmp_omp_cancellation; /* TRUE or FALSE */ 3158*fe6060f1SDimitry Andric extern int __kmp_nteams; 3159*fe6060f1SDimitry Andric extern int __kmp_teams_thread_limit; 31600b57cec5SDimitry Andric 31610b57cec5SDimitry Andric /* ------------------------------------------------------------------------- */ 31620b57cec5SDimitry Andric 31630b57cec5SDimitry Andric /* the following are protected by the fork/join lock */ 31640b57cec5SDimitry Andric /* write: lock read: anytime */ 31650b57cec5SDimitry Andric extern kmp_info_t **__kmp_threads; /* Descriptors for the threads */ 31660b57cec5SDimitry Andric /* read/write: lock */ 31670b57cec5SDimitry Andric extern volatile kmp_team_t *__kmp_team_pool; 31680b57cec5SDimitry Andric extern volatile kmp_info_t *__kmp_thread_pool; 31690b57cec5SDimitry Andric extern kmp_info_t *__kmp_thread_pool_insert_pt; 31700b57cec5SDimitry Andric 31710b57cec5SDimitry Andric // total num threads reachable from some root thread including all root threads 31720b57cec5SDimitry Andric extern volatile int __kmp_nth; 31730b57cec5SDimitry Andric /* total number of threads reachable from some root thread including all root 31740b57cec5SDimitry Andric threads, and those in the thread pool */ 31750b57cec5SDimitry Andric extern volatile int __kmp_all_nth; 31760b57cec5SDimitry Andric extern std::atomic<int> __kmp_thread_pool_active_nth; 31770b57cec5SDimitry Andric 31780b57cec5SDimitry Andric extern kmp_root_t **__kmp_root; /* root of thread hierarchy */ 31790b57cec5SDimitry Andric /* end data protected by fork/join lock */ 31800b57cec5SDimitry Andric /* ------------------------------------------------------------------------- */ 31810b57cec5SDimitry Andric 31820b57cec5SDimitry Andric #define __kmp_get_gtid() __kmp_get_global_thread_id() 31830b57cec5SDimitry Andric #define __kmp_entry_gtid() __kmp_get_global_thread_id_reg() 31840b57cec5SDimitry Andric #define __kmp_get_tid() (__kmp_tid_from_gtid(__kmp_get_gtid())) 31850b57cec5SDimitry Andric #define __kmp_get_team() (__kmp_threads[(__kmp_get_gtid())]->th.th_team) 31860b57cec5SDimitry Andric #define __kmp_get_thread() (__kmp_thread_from_gtid(__kmp_get_gtid())) 31870b57cec5SDimitry Andric 31880b57cec5SDimitry Andric // AT: Which way is correct? 31890b57cec5SDimitry Andric // AT: 1. nproc = __kmp_threads[ ( gtid ) ] -> th.th_team -> t.t_nproc; 31900b57cec5SDimitry Andric // AT: 2. nproc = __kmp_threads[ ( gtid ) ] -> th.th_team_nproc; 31910b57cec5SDimitry Andric #define __kmp_get_team_num_threads(gtid) \ 31920b57cec5SDimitry Andric (__kmp_threads[(gtid)]->th.th_team->t.t_nproc) 31930b57cec5SDimitry Andric 31940b57cec5SDimitry Andric static inline bool KMP_UBER_GTID(int gtid) { 31950b57cec5SDimitry Andric KMP_DEBUG_ASSERT(gtid >= KMP_GTID_MIN); 31960b57cec5SDimitry Andric KMP_DEBUG_ASSERT(gtid < __kmp_threads_capacity); 31970b57cec5SDimitry Andric return (gtid >= 0 && __kmp_root[gtid] && __kmp_threads[gtid] && 31980b57cec5SDimitry Andric __kmp_threads[gtid] == __kmp_root[gtid]->r.r_uber_thread); 31990b57cec5SDimitry Andric } 32000b57cec5SDimitry Andric 32010b57cec5SDimitry Andric static inline int __kmp_tid_from_gtid(int gtid) { 32020b57cec5SDimitry Andric KMP_DEBUG_ASSERT(gtid >= 0); 32030b57cec5SDimitry Andric return __kmp_threads[gtid]->th.th_info.ds.ds_tid; 32040b57cec5SDimitry Andric } 32050b57cec5SDimitry Andric 32060b57cec5SDimitry Andric static inline int __kmp_gtid_from_tid(int tid, const kmp_team_t *team) { 32070b57cec5SDimitry Andric KMP_DEBUG_ASSERT(tid >= 0 && team); 32080b57cec5SDimitry Andric return team->t.t_threads[tid]->th.th_info.ds.ds_gtid; 32090b57cec5SDimitry Andric } 32100b57cec5SDimitry Andric 32110b57cec5SDimitry Andric static inline int __kmp_gtid_from_thread(const kmp_info_t *thr) { 32120b57cec5SDimitry Andric KMP_DEBUG_ASSERT(thr); 32130b57cec5SDimitry Andric return thr->th.th_info.ds.ds_gtid; 32140b57cec5SDimitry Andric } 32150b57cec5SDimitry Andric 32160b57cec5SDimitry Andric static inline kmp_info_t *__kmp_thread_from_gtid(int gtid) { 32170b57cec5SDimitry Andric KMP_DEBUG_ASSERT(gtid >= 0); 32180b57cec5SDimitry Andric return __kmp_threads[gtid]; 32190b57cec5SDimitry Andric } 32200b57cec5SDimitry Andric 32210b57cec5SDimitry Andric static inline kmp_team_t *__kmp_team_from_gtid(int gtid) { 32220b57cec5SDimitry Andric KMP_DEBUG_ASSERT(gtid >= 0); 32230b57cec5SDimitry Andric return __kmp_threads[gtid]->th.th_team; 32240b57cec5SDimitry Andric } 32250b57cec5SDimitry Andric 3226e8d8bef9SDimitry Andric static inline void __kmp_assert_valid_gtid(kmp_int32 gtid) { 3227e8d8bef9SDimitry Andric if (UNLIKELY(gtid < 0 || gtid >= __kmp_threads_capacity)) 3228e8d8bef9SDimitry Andric KMP_FATAL(ThreadIdentInvalid); 3229e8d8bef9SDimitry Andric } 3230e8d8bef9SDimitry Andric 3231e8d8bef9SDimitry Andric #if KMP_HAVE_MWAIT || KMP_HAVE_UMWAIT 3232e8d8bef9SDimitry Andric extern int __kmp_user_level_mwait; // TRUE or FALSE; from KMP_USER_LEVEL_MWAIT 3233e8d8bef9SDimitry Andric extern int __kmp_umwait_enabled; // Runtime check if user-level mwait enabled 3234e8d8bef9SDimitry Andric extern int __kmp_mwait_enabled; // Runtime check if ring3 mwait is enabled 3235e8d8bef9SDimitry Andric extern int __kmp_mwait_hints; // Hints to pass in to mwait 3236e8d8bef9SDimitry Andric #endif 3237e8d8bef9SDimitry Andric 32380b57cec5SDimitry Andric /* ------------------------------------------------------------------------- */ 32390b57cec5SDimitry Andric 32400b57cec5SDimitry Andric extern kmp_global_t __kmp_global; /* global status */ 32410b57cec5SDimitry Andric 32420b57cec5SDimitry Andric extern kmp_info_t __kmp_monitor; 32430b57cec5SDimitry Andric // For Debugging Support Library 32440b57cec5SDimitry Andric extern std::atomic<kmp_int32> __kmp_team_counter; 32450b57cec5SDimitry Andric // For Debugging Support Library 32460b57cec5SDimitry Andric extern std::atomic<kmp_int32> __kmp_task_counter; 32470b57cec5SDimitry Andric 32480b57cec5SDimitry Andric #if USE_DEBUGGER 32490b57cec5SDimitry Andric #define _KMP_GEN_ID(counter) \ 32500b57cec5SDimitry Andric (__kmp_debugging ? KMP_ATOMIC_INC(&counter) + 1 : ~0) 32510b57cec5SDimitry Andric #else 32520b57cec5SDimitry Andric #define _KMP_GEN_ID(counter) (~0) 32530b57cec5SDimitry Andric #endif /* USE_DEBUGGER */ 32540b57cec5SDimitry Andric 32550b57cec5SDimitry Andric #define KMP_GEN_TASK_ID() _KMP_GEN_ID(__kmp_task_counter) 32560b57cec5SDimitry Andric #define KMP_GEN_TEAM_ID() _KMP_GEN_ID(__kmp_team_counter) 32570b57cec5SDimitry Andric 32580b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */ 32590b57cec5SDimitry Andric 32600b57cec5SDimitry Andric extern void __kmp_print_storage_map_gtid(int gtid, void *p1, void *p2, 32610b57cec5SDimitry Andric size_t size, char const *format, ...); 32620b57cec5SDimitry Andric 32630b57cec5SDimitry Andric extern void __kmp_serial_initialize(void); 32640b57cec5SDimitry Andric extern void __kmp_middle_initialize(void); 32650b57cec5SDimitry Andric extern void __kmp_parallel_initialize(void); 32660b57cec5SDimitry Andric 32670b57cec5SDimitry Andric extern void __kmp_internal_begin(void); 32680b57cec5SDimitry Andric extern void __kmp_internal_end_library(int gtid); 32690b57cec5SDimitry Andric extern void __kmp_internal_end_thread(int gtid); 32700b57cec5SDimitry Andric extern void __kmp_internal_end_atexit(void); 32710b57cec5SDimitry Andric extern void __kmp_internal_end_dtor(void); 32720b57cec5SDimitry Andric extern void __kmp_internal_end_dest(void *); 32730b57cec5SDimitry Andric 32740b57cec5SDimitry Andric extern int __kmp_register_root(int initial_thread); 32750b57cec5SDimitry Andric extern void __kmp_unregister_root(int gtid); 3276e8d8bef9SDimitry Andric extern void __kmp_unregister_library(void); // called by __kmp_internal_end() 32770b57cec5SDimitry Andric 32780b57cec5SDimitry Andric extern int __kmp_ignore_mppbeg(void); 32790b57cec5SDimitry Andric extern int __kmp_ignore_mppend(void); 32800b57cec5SDimitry Andric 32810b57cec5SDimitry Andric extern int __kmp_enter_single(int gtid, ident_t *id_ref, int push_ws); 32820b57cec5SDimitry Andric extern void __kmp_exit_single(int gtid); 32830b57cec5SDimitry Andric 32840b57cec5SDimitry Andric extern void __kmp_parallel_deo(int *gtid_ref, int *cid_ref, ident_t *loc_ref); 32850b57cec5SDimitry Andric extern void __kmp_parallel_dxo(int *gtid_ref, int *cid_ref, ident_t *loc_ref); 32860b57cec5SDimitry Andric 32870b57cec5SDimitry Andric #ifdef USE_LOAD_BALANCE 32880b57cec5SDimitry Andric extern int __kmp_get_load_balance(int); 32890b57cec5SDimitry Andric #endif 32900b57cec5SDimitry Andric 32910b57cec5SDimitry Andric extern int __kmp_get_global_thread_id(void); 32920b57cec5SDimitry Andric extern int __kmp_get_global_thread_id_reg(void); 32930b57cec5SDimitry Andric extern void __kmp_exit_thread(int exit_status); 32940b57cec5SDimitry Andric extern void __kmp_abort(char const *format, ...); 32950b57cec5SDimitry Andric extern void __kmp_abort_thread(void); 32960b57cec5SDimitry Andric KMP_NORETURN extern void __kmp_abort_process(void); 32970b57cec5SDimitry Andric extern void __kmp_warn(char const *format, ...); 32980b57cec5SDimitry Andric 32990b57cec5SDimitry Andric extern void __kmp_set_num_threads(int new_nth, int gtid); 33000b57cec5SDimitry Andric 33010b57cec5SDimitry Andric // Returns current thread (pointer to kmp_info_t). Current thread *must* be 33020b57cec5SDimitry Andric // registered. 33030b57cec5SDimitry Andric static inline kmp_info_t *__kmp_entry_thread() { 33040b57cec5SDimitry Andric int gtid = __kmp_entry_gtid(); 33050b57cec5SDimitry Andric 33060b57cec5SDimitry Andric return __kmp_threads[gtid]; 33070b57cec5SDimitry Andric } 33080b57cec5SDimitry Andric 33090b57cec5SDimitry Andric extern void __kmp_set_max_active_levels(int gtid, int new_max_active_levels); 33100b57cec5SDimitry Andric extern int __kmp_get_max_active_levels(int gtid); 33110b57cec5SDimitry Andric extern int __kmp_get_ancestor_thread_num(int gtid, int level); 33120b57cec5SDimitry Andric extern int __kmp_get_team_size(int gtid, int level); 33130b57cec5SDimitry Andric extern void __kmp_set_schedule(int gtid, kmp_sched_t new_sched, int chunk); 33140b57cec5SDimitry Andric extern void __kmp_get_schedule(int gtid, kmp_sched_t *sched, int *chunk); 33150b57cec5SDimitry Andric 33160b57cec5SDimitry Andric extern unsigned short __kmp_get_random(kmp_info_t *thread); 33170b57cec5SDimitry Andric extern void __kmp_init_random(kmp_info_t *thread); 33180b57cec5SDimitry Andric 33190b57cec5SDimitry Andric extern kmp_r_sched_t __kmp_get_schedule_global(void); 33200b57cec5SDimitry Andric extern void __kmp_adjust_num_threads(int new_nproc); 33210b57cec5SDimitry Andric extern void __kmp_check_stksize(size_t *val); 33220b57cec5SDimitry Andric 33230b57cec5SDimitry Andric extern void *___kmp_allocate(size_t size KMP_SRC_LOC_DECL); 33240b57cec5SDimitry Andric extern void *___kmp_page_allocate(size_t size KMP_SRC_LOC_DECL); 33250b57cec5SDimitry Andric extern void ___kmp_free(void *ptr KMP_SRC_LOC_DECL); 33260b57cec5SDimitry Andric #define __kmp_allocate(size) ___kmp_allocate((size)KMP_SRC_LOC_CURR) 33270b57cec5SDimitry Andric #define __kmp_page_allocate(size) ___kmp_page_allocate((size)KMP_SRC_LOC_CURR) 33280b57cec5SDimitry Andric #define __kmp_free(ptr) ___kmp_free((ptr)KMP_SRC_LOC_CURR) 33290b57cec5SDimitry Andric 33300b57cec5SDimitry Andric #if USE_FAST_MEMORY 33310b57cec5SDimitry Andric extern void *___kmp_fast_allocate(kmp_info_t *this_thr, 33320b57cec5SDimitry Andric size_t size KMP_SRC_LOC_DECL); 33330b57cec5SDimitry Andric extern void ___kmp_fast_free(kmp_info_t *this_thr, void *ptr KMP_SRC_LOC_DECL); 33340b57cec5SDimitry Andric extern void __kmp_free_fast_memory(kmp_info_t *this_thr); 33350b57cec5SDimitry Andric extern void __kmp_initialize_fast_memory(kmp_info_t *this_thr); 33360b57cec5SDimitry Andric #define __kmp_fast_allocate(this_thr, size) \ 33370b57cec5SDimitry Andric ___kmp_fast_allocate((this_thr), (size)KMP_SRC_LOC_CURR) 33380b57cec5SDimitry Andric #define __kmp_fast_free(this_thr, ptr) \ 33390b57cec5SDimitry Andric ___kmp_fast_free((this_thr), (ptr)KMP_SRC_LOC_CURR) 33400b57cec5SDimitry Andric #endif 33410b57cec5SDimitry Andric 33420b57cec5SDimitry Andric extern void *___kmp_thread_malloc(kmp_info_t *th, size_t size KMP_SRC_LOC_DECL); 33430b57cec5SDimitry Andric extern void *___kmp_thread_calloc(kmp_info_t *th, size_t nelem, 33440b57cec5SDimitry Andric size_t elsize KMP_SRC_LOC_DECL); 33450b57cec5SDimitry Andric extern void *___kmp_thread_realloc(kmp_info_t *th, void *ptr, 33460b57cec5SDimitry Andric size_t size KMP_SRC_LOC_DECL); 33470b57cec5SDimitry Andric extern void ___kmp_thread_free(kmp_info_t *th, void *ptr KMP_SRC_LOC_DECL); 33480b57cec5SDimitry Andric #define __kmp_thread_malloc(th, size) \ 33490b57cec5SDimitry Andric ___kmp_thread_malloc((th), (size)KMP_SRC_LOC_CURR) 33500b57cec5SDimitry Andric #define __kmp_thread_calloc(th, nelem, elsize) \ 33510b57cec5SDimitry Andric ___kmp_thread_calloc((th), (nelem), (elsize)KMP_SRC_LOC_CURR) 33520b57cec5SDimitry Andric #define __kmp_thread_realloc(th, ptr, size) \ 33530b57cec5SDimitry Andric ___kmp_thread_realloc((th), (ptr), (size)KMP_SRC_LOC_CURR) 33540b57cec5SDimitry Andric #define __kmp_thread_free(th, ptr) \ 33550b57cec5SDimitry Andric ___kmp_thread_free((th), (ptr)KMP_SRC_LOC_CURR) 33560b57cec5SDimitry Andric 33570b57cec5SDimitry Andric #define KMP_INTERNAL_MALLOC(sz) malloc(sz) 33580b57cec5SDimitry Andric #define KMP_INTERNAL_FREE(p) free(p) 33590b57cec5SDimitry Andric #define KMP_INTERNAL_REALLOC(p, sz) realloc((p), (sz)) 33600b57cec5SDimitry Andric #define KMP_INTERNAL_CALLOC(n, sz) calloc((n), (sz)) 33610b57cec5SDimitry Andric 33620b57cec5SDimitry Andric extern void __kmp_push_num_threads(ident_t *loc, int gtid, int num_threads); 33630b57cec5SDimitry Andric 33640b57cec5SDimitry Andric extern void __kmp_push_proc_bind(ident_t *loc, int gtid, 33650b57cec5SDimitry Andric kmp_proc_bind_t proc_bind); 33660b57cec5SDimitry Andric extern void __kmp_push_num_teams(ident_t *loc, int gtid, int num_teams, 33670b57cec5SDimitry Andric int num_threads); 3368*fe6060f1SDimitry Andric extern void __kmp_push_num_teams_51(ident_t *loc, int gtid, int num_teams_lb, 3369*fe6060f1SDimitry Andric int num_teams_ub, int num_threads); 33700b57cec5SDimitry Andric 33710b57cec5SDimitry Andric extern void __kmp_yield(); 33720b57cec5SDimitry Andric 33730b57cec5SDimitry Andric extern void __kmpc_dispatch_init_4(ident_t *loc, kmp_int32 gtid, 33740b57cec5SDimitry Andric enum sched_type schedule, kmp_int32 lb, 33750b57cec5SDimitry Andric kmp_int32 ub, kmp_int32 st, kmp_int32 chunk); 33760b57cec5SDimitry Andric extern void __kmpc_dispatch_init_4u(ident_t *loc, kmp_int32 gtid, 33770b57cec5SDimitry Andric enum sched_type schedule, kmp_uint32 lb, 33780b57cec5SDimitry Andric kmp_uint32 ub, kmp_int32 st, 33790b57cec5SDimitry Andric kmp_int32 chunk); 33800b57cec5SDimitry Andric extern void __kmpc_dispatch_init_8(ident_t *loc, kmp_int32 gtid, 33810b57cec5SDimitry Andric enum sched_type schedule, kmp_int64 lb, 33820b57cec5SDimitry Andric kmp_int64 ub, kmp_int64 st, kmp_int64 chunk); 33830b57cec5SDimitry Andric extern void __kmpc_dispatch_init_8u(ident_t *loc, kmp_int32 gtid, 33840b57cec5SDimitry Andric enum sched_type schedule, kmp_uint64 lb, 33850b57cec5SDimitry Andric kmp_uint64 ub, kmp_int64 st, 33860b57cec5SDimitry Andric kmp_int64 chunk); 33870b57cec5SDimitry Andric 33880b57cec5SDimitry Andric extern int __kmpc_dispatch_next_4(ident_t *loc, kmp_int32 gtid, 33890b57cec5SDimitry Andric kmp_int32 *p_last, kmp_int32 *p_lb, 33900b57cec5SDimitry Andric kmp_int32 *p_ub, kmp_int32 *p_st); 33910b57cec5SDimitry Andric extern int __kmpc_dispatch_next_4u(ident_t *loc, kmp_int32 gtid, 33920b57cec5SDimitry Andric kmp_int32 *p_last, kmp_uint32 *p_lb, 33930b57cec5SDimitry Andric kmp_uint32 *p_ub, kmp_int32 *p_st); 33940b57cec5SDimitry Andric extern int __kmpc_dispatch_next_8(ident_t *loc, kmp_int32 gtid, 33950b57cec5SDimitry Andric kmp_int32 *p_last, kmp_int64 *p_lb, 33960b57cec5SDimitry Andric kmp_int64 *p_ub, kmp_int64 *p_st); 33970b57cec5SDimitry Andric extern int __kmpc_dispatch_next_8u(ident_t *loc, kmp_int32 gtid, 33980b57cec5SDimitry Andric kmp_int32 *p_last, kmp_uint64 *p_lb, 33990b57cec5SDimitry Andric kmp_uint64 *p_ub, kmp_int64 *p_st); 34000b57cec5SDimitry Andric 34010b57cec5SDimitry Andric extern void __kmpc_dispatch_fini_4(ident_t *loc, kmp_int32 gtid); 34020b57cec5SDimitry Andric extern void __kmpc_dispatch_fini_8(ident_t *loc, kmp_int32 gtid); 34030b57cec5SDimitry Andric extern void __kmpc_dispatch_fini_4u(ident_t *loc, kmp_int32 gtid); 34040b57cec5SDimitry Andric extern void __kmpc_dispatch_fini_8u(ident_t *loc, kmp_int32 gtid); 34050b57cec5SDimitry Andric 34060b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT 34070b57cec5SDimitry Andric 34080b57cec5SDimitry Andric extern void __kmp_aux_dispatch_init_4(ident_t *loc, kmp_int32 gtid, 34090b57cec5SDimitry Andric enum sched_type schedule, kmp_int32 lb, 34100b57cec5SDimitry Andric kmp_int32 ub, kmp_int32 st, 34110b57cec5SDimitry Andric kmp_int32 chunk, int push_ws); 34120b57cec5SDimitry Andric extern void __kmp_aux_dispatch_init_4u(ident_t *loc, kmp_int32 gtid, 34130b57cec5SDimitry Andric enum sched_type schedule, kmp_uint32 lb, 34140b57cec5SDimitry Andric kmp_uint32 ub, kmp_int32 st, 34150b57cec5SDimitry Andric kmp_int32 chunk, int push_ws); 34160b57cec5SDimitry Andric extern void __kmp_aux_dispatch_init_8(ident_t *loc, kmp_int32 gtid, 34170b57cec5SDimitry Andric enum sched_type schedule, kmp_int64 lb, 34180b57cec5SDimitry Andric kmp_int64 ub, kmp_int64 st, 34190b57cec5SDimitry Andric kmp_int64 chunk, int push_ws); 34200b57cec5SDimitry Andric extern void __kmp_aux_dispatch_init_8u(ident_t *loc, kmp_int32 gtid, 34210b57cec5SDimitry Andric enum sched_type schedule, kmp_uint64 lb, 34220b57cec5SDimitry Andric kmp_uint64 ub, kmp_int64 st, 34230b57cec5SDimitry Andric kmp_int64 chunk, int push_ws); 34240b57cec5SDimitry Andric extern void __kmp_aux_dispatch_fini_chunk_4(ident_t *loc, kmp_int32 gtid); 34250b57cec5SDimitry Andric extern void __kmp_aux_dispatch_fini_chunk_8(ident_t *loc, kmp_int32 gtid); 34260b57cec5SDimitry Andric extern void __kmp_aux_dispatch_fini_chunk_4u(ident_t *loc, kmp_int32 gtid); 34270b57cec5SDimitry Andric extern void __kmp_aux_dispatch_fini_chunk_8u(ident_t *loc, kmp_int32 gtid); 34280b57cec5SDimitry Andric 34290b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */ 34300b57cec5SDimitry Andric 34310b57cec5SDimitry Andric extern kmp_uint32 __kmp_eq_4(kmp_uint32 value, kmp_uint32 checker); 34320b57cec5SDimitry Andric extern kmp_uint32 __kmp_neq_4(kmp_uint32 value, kmp_uint32 checker); 34330b57cec5SDimitry Andric extern kmp_uint32 __kmp_lt_4(kmp_uint32 value, kmp_uint32 checker); 34340b57cec5SDimitry Andric extern kmp_uint32 __kmp_ge_4(kmp_uint32 value, kmp_uint32 checker); 34350b57cec5SDimitry Andric extern kmp_uint32 __kmp_le_4(kmp_uint32 value, kmp_uint32 checker); 34360b57cec5SDimitry Andric extern kmp_uint32 __kmp_wait_4(kmp_uint32 volatile *spinner, kmp_uint32 checker, 34370b57cec5SDimitry Andric kmp_uint32 (*pred)(kmp_uint32, kmp_uint32), 34380b57cec5SDimitry Andric void *obj); 34390b57cec5SDimitry Andric extern void __kmp_wait_4_ptr(void *spinner, kmp_uint32 checker, 34400b57cec5SDimitry Andric kmp_uint32 (*pred)(void *, kmp_uint32), void *obj); 34410b57cec5SDimitry Andric 3442e8d8bef9SDimitry Andric extern void __kmp_wait_64(kmp_info_t *this_thr, kmp_flag_64<> *flag, 34430b57cec5SDimitry Andric int final_spin 34440b57cec5SDimitry Andric #if USE_ITT_BUILD 34450b57cec5SDimitry Andric , 34460b57cec5SDimitry Andric void *itt_sync_obj 34470b57cec5SDimitry Andric #endif 34480b57cec5SDimitry Andric ); 3449e8d8bef9SDimitry Andric extern void __kmp_release_64(kmp_flag_64<> *flag); 34500b57cec5SDimitry Andric 34510b57cec5SDimitry Andric extern void __kmp_infinite_loop(void); 34520b57cec5SDimitry Andric 34530b57cec5SDimitry Andric extern void __kmp_cleanup(void); 34540b57cec5SDimitry Andric 34550b57cec5SDimitry Andric #if KMP_HANDLE_SIGNALS 34560b57cec5SDimitry Andric extern int __kmp_handle_signals; 34570b57cec5SDimitry Andric extern void __kmp_install_signals(int parallel_init); 34580b57cec5SDimitry Andric extern void __kmp_remove_signals(void); 34590b57cec5SDimitry Andric #endif 34600b57cec5SDimitry Andric 34610b57cec5SDimitry Andric extern void __kmp_clear_system_time(void); 34620b57cec5SDimitry Andric extern void __kmp_read_system_time(double *delta); 34630b57cec5SDimitry Andric 34640b57cec5SDimitry Andric extern void __kmp_check_stack_overlap(kmp_info_t *thr); 34650b57cec5SDimitry Andric 34660b57cec5SDimitry Andric extern void __kmp_expand_host_name(char *buffer, size_t size); 34670b57cec5SDimitry Andric extern void __kmp_expand_file_name(char *result, size_t rlen, char *pattern); 34680b57cec5SDimitry Andric 3469*fe6060f1SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64 || (KMP_OS_WINDOWS && KMP_ARCH_AARCH64) 34700b57cec5SDimitry Andric extern void 34710b57cec5SDimitry Andric __kmp_initialize_system_tick(void); /* Initialize timer tick value */ 34720b57cec5SDimitry Andric #endif 34730b57cec5SDimitry Andric 34740b57cec5SDimitry Andric extern void 34750b57cec5SDimitry Andric __kmp_runtime_initialize(void); /* machine specific initialization */ 34760b57cec5SDimitry Andric extern void __kmp_runtime_destroy(void); 34770b57cec5SDimitry Andric 34780b57cec5SDimitry Andric #if KMP_AFFINITY_SUPPORTED 34790b57cec5SDimitry Andric extern char *__kmp_affinity_print_mask(char *buf, int buf_len, 34800b57cec5SDimitry Andric kmp_affin_mask_t *mask); 34810b57cec5SDimitry Andric extern kmp_str_buf_t *__kmp_affinity_str_buf_mask(kmp_str_buf_t *buf, 34820b57cec5SDimitry Andric kmp_affin_mask_t *mask); 34830b57cec5SDimitry Andric extern void __kmp_affinity_initialize(void); 34840b57cec5SDimitry Andric extern void __kmp_affinity_uninitialize(void); 34850b57cec5SDimitry Andric extern void __kmp_affinity_set_init_mask( 34860b57cec5SDimitry Andric int gtid, int isa_root); /* set affinity according to KMP_AFFINITY */ 34870b57cec5SDimitry Andric extern void __kmp_affinity_set_place(int gtid); 34880b57cec5SDimitry Andric extern void __kmp_affinity_determine_capable(const char *env_var); 34890b57cec5SDimitry Andric extern int __kmp_aux_set_affinity(void **mask); 34900b57cec5SDimitry Andric extern int __kmp_aux_get_affinity(void **mask); 34910b57cec5SDimitry Andric extern int __kmp_aux_get_affinity_max_proc(); 34920b57cec5SDimitry Andric extern int __kmp_aux_set_affinity_mask_proc(int proc, void **mask); 34930b57cec5SDimitry Andric extern int __kmp_aux_unset_affinity_mask_proc(int proc, void **mask); 34940b57cec5SDimitry Andric extern int __kmp_aux_get_affinity_mask_proc(int proc, void **mask); 34950b57cec5SDimitry Andric extern void __kmp_balanced_affinity(kmp_info_t *th, int team_size); 3496489b1cf2SDimitry Andric #if KMP_OS_LINUX || KMP_OS_FREEBSD 34970b57cec5SDimitry Andric extern int kmp_set_thread_affinity_mask_initial(void); 34980b57cec5SDimitry Andric #endif 3499*fe6060f1SDimitry Andric static inline void __kmp_assign_root_init_mask() { 3500*fe6060f1SDimitry Andric int gtid = __kmp_entry_gtid(); 3501*fe6060f1SDimitry Andric kmp_root_t *r = __kmp_threads[gtid]->th.th_root; 3502*fe6060f1SDimitry Andric if (r->r.r_uber_thread == __kmp_threads[gtid] && !r->r.r_affinity_assigned) { 3503*fe6060f1SDimitry Andric __kmp_affinity_set_init_mask(gtid, TRUE); 3504*fe6060f1SDimitry Andric r->r.r_affinity_assigned = TRUE; 3505*fe6060f1SDimitry Andric } 3506*fe6060f1SDimitry Andric } 3507*fe6060f1SDimitry Andric #else /* KMP_AFFINITY_SUPPORTED */ 3508*fe6060f1SDimitry Andric #define __kmp_assign_root_init_mask() /* Nothing */ 35090b57cec5SDimitry Andric #endif /* KMP_AFFINITY_SUPPORTED */ 35100b57cec5SDimitry Andric // No need for KMP_AFFINITY_SUPPORTED guard as only one field in the 35110b57cec5SDimitry Andric // format string is for affinity, so platforms that do not support 35120b57cec5SDimitry Andric // affinity can still use the other fields, e.g., %n for num_threads 35130b57cec5SDimitry Andric extern size_t __kmp_aux_capture_affinity(int gtid, const char *format, 35140b57cec5SDimitry Andric kmp_str_buf_t *buffer); 35150b57cec5SDimitry Andric extern void __kmp_aux_display_affinity(int gtid, const char *format); 35160b57cec5SDimitry Andric 35170b57cec5SDimitry Andric extern void __kmp_cleanup_hierarchy(); 35180b57cec5SDimitry Andric extern void __kmp_get_hierarchy(kmp_uint32 nproc, kmp_bstate_t *thr_bar); 35190b57cec5SDimitry Andric 35200b57cec5SDimitry Andric #if KMP_USE_FUTEX 35210b57cec5SDimitry Andric 35220b57cec5SDimitry Andric extern int __kmp_futex_determine_capable(void); 35230b57cec5SDimitry Andric 35240b57cec5SDimitry Andric #endif // KMP_USE_FUTEX 35250b57cec5SDimitry Andric 35260b57cec5SDimitry Andric extern void __kmp_gtid_set_specific(int gtid); 35270b57cec5SDimitry Andric extern int __kmp_gtid_get_specific(void); 35280b57cec5SDimitry Andric 35290b57cec5SDimitry Andric extern double __kmp_read_cpu_time(void); 35300b57cec5SDimitry Andric 35310b57cec5SDimitry Andric extern int __kmp_read_system_info(struct kmp_sys_info *info); 35320b57cec5SDimitry Andric 35330b57cec5SDimitry Andric #if KMP_USE_MONITOR 35340b57cec5SDimitry Andric extern void __kmp_create_monitor(kmp_info_t *th); 35350b57cec5SDimitry Andric #endif 35360b57cec5SDimitry Andric 35370b57cec5SDimitry Andric extern void *__kmp_launch_thread(kmp_info_t *thr); 35380b57cec5SDimitry Andric 35390b57cec5SDimitry Andric extern void __kmp_create_worker(int gtid, kmp_info_t *th, size_t stack_size); 35400b57cec5SDimitry Andric 35410b57cec5SDimitry Andric #if KMP_OS_WINDOWS 35420b57cec5SDimitry Andric extern int __kmp_still_running(kmp_info_t *th); 35430b57cec5SDimitry Andric extern int __kmp_is_thread_alive(kmp_info_t *th, DWORD *exit_val); 35440b57cec5SDimitry Andric extern void __kmp_free_handle(kmp_thread_t tHandle); 35450b57cec5SDimitry Andric #endif 35460b57cec5SDimitry Andric 35470b57cec5SDimitry Andric #if KMP_USE_MONITOR 35480b57cec5SDimitry Andric extern void __kmp_reap_monitor(kmp_info_t *th); 35490b57cec5SDimitry Andric #endif 35500b57cec5SDimitry Andric extern void __kmp_reap_worker(kmp_info_t *th); 35510b57cec5SDimitry Andric extern void __kmp_terminate_thread(int gtid); 35520b57cec5SDimitry Andric 35530b57cec5SDimitry Andric extern int __kmp_try_suspend_mx(kmp_info_t *th); 35540b57cec5SDimitry Andric extern void __kmp_lock_suspend_mx(kmp_info_t *th); 35550b57cec5SDimitry Andric extern void __kmp_unlock_suspend_mx(kmp_info_t *th); 35560b57cec5SDimitry Andric 35570b57cec5SDimitry Andric extern void __kmp_elapsed(double *); 35580b57cec5SDimitry Andric extern void __kmp_elapsed_tick(double *); 35590b57cec5SDimitry Andric 35600b57cec5SDimitry Andric extern void __kmp_enable(int old_state); 35610b57cec5SDimitry Andric extern void __kmp_disable(int *old_state); 35620b57cec5SDimitry Andric 35630b57cec5SDimitry Andric extern void __kmp_thread_sleep(int millis); 35640b57cec5SDimitry Andric 35650b57cec5SDimitry Andric extern void __kmp_common_initialize(void); 35660b57cec5SDimitry Andric extern void __kmp_common_destroy(void); 35670b57cec5SDimitry Andric extern void __kmp_common_destroy_gtid(int gtid); 35680b57cec5SDimitry Andric 35690b57cec5SDimitry Andric #if KMP_OS_UNIX 35700b57cec5SDimitry Andric extern void __kmp_register_atfork(void); 35710b57cec5SDimitry Andric #endif 35720b57cec5SDimitry Andric extern void __kmp_suspend_initialize(void); 35730b57cec5SDimitry Andric extern void __kmp_suspend_initialize_thread(kmp_info_t *th); 35740b57cec5SDimitry Andric extern void __kmp_suspend_uninitialize_thread(kmp_info_t *th); 35750b57cec5SDimitry Andric 35760b57cec5SDimitry Andric extern kmp_info_t *__kmp_allocate_thread(kmp_root_t *root, kmp_team_t *team, 35770b57cec5SDimitry Andric int tid); 35780b57cec5SDimitry Andric extern kmp_team_t * 35790b57cec5SDimitry Andric __kmp_allocate_team(kmp_root_t *root, int new_nproc, int max_nproc, 35800b57cec5SDimitry Andric #if OMPT_SUPPORT 35810b57cec5SDimitry Andric ompt_data_t ompt_parallel_data, 35820b57cec5SDimitry Andric #endif 35830b57cec5SDimitry Andric kmp_proc_bind_t proc_bind, kmp_internal_control_t *new_icvs, 35840b57cec5SDimitry Andric int argc USE_NESTED_HOT_ARG(kmp_info_t *thr)); 35850b57cec5SDimitry Andric extern void __kmp_free_thread(kmp_info_t *); 35860b57cec5SDimitry Andric extern void __kmp_free_team(kmp_root_t *, 35870b57cec5SDimitry Andric kmp_team_t *USE_NESTED_HOT_ARG(kmp_info_t *)); 35880b57cec5SDimitry Andric extern kmp_team_t *__kmp_reap_team(kmp_team_t *); 35890b57cec5SDimitry Andric 35900b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */ 35910b57cec5SDimitry Andric 35920b57cec5SDimitry Andric extern void __kmp_initialize_bget(kmp_info_t *th); 35930b57cec5SDimitry Andric extern void __kmp_finalize_bget(kmp_info_t *th); 35940b57cec5SDimitry Andric 35950b57cec5SDimitry Andric KMP_EXPORT void *kmpc_malloc(size_t size); 35960b57cec5SDimitry Andric KMP_EXPORT void *kmpc_aligned_malloc(size_t size, size_t alignment); 35970b57cec5SDimitry Andric KMP_EXPORT void *kmpc_calloc(size_t nelem, size_t elsize); 35980b57cec5SDimitry Andric KMP_EXPORT void *kmpc_realloc(void *ptr, size_t size); 35990b57cec5SDimitry Andric KMP_EXPORT void kmpc_free(void *ptr); 36000b57cec5SDimitry Andric 36010b57cec5SDimitry Andric /* declarations for internal use */ 36020b57cec5SDimitry Andric 36030b57cec5SDimitry Andric extern int __kmp_barrier(enum barrier_type bt, int gtid, int is_split, 36040b57cec5SDimitry Andric size_t reduce_size, void *reduce_data, 36050b57cec5SDimitry Andric void (*reduce)(void *, void *)); 36060b57cec5SDimitry Andric extern void __kmp_end_split_barrier(enum barrier_type bt, int gtid); 36070b57cec5SDimitry Andric extern int __kmp_barrier_gomp_cancel(int gtid); 36080b57cec5SDimitry Andric 36090b57cec5SDimitry Andric /*! 36100b57cec5SDimitry Andric * Tell the fork call which compiler generated the fork call, and therefore how 36110b57cec5SDimitry Andric * to deal with the call. 36120b57cec5SDimitry Andric */ 36130b57cec5SDimitry Andric enum fork_context_e { 36140b57cec5SDimitry Andric fork_context_gnu, /**< Called from GNU generated code, so must not invoke the 36150b57cec5SDimitry Andric microtask internally. */ 36160b57cec5SDimitry Andric fork_context_intel, /**< Called from Intel generated code. */ 36170b57cec5SDimitry Andric fork_context_last 36180b57cec5SDimitry Andric }; 36190b57cec5SDimitry Andric extern int __kmp_fork_call(ident_t *loc, int gtid, 36200b57cec5SDimitry Andric enum fork_context_e fork_context, kmp_int32 argc, 36210b57cec5SDimitry Andric microtask_t microtask, launch_t invoker, 362216794618SDimitry Andric kmp_va_list ap); 36230b57cec5SDimitry Andric 36240b57cec5SDimitry Andric extern void __kmp_join_call(ident_t *loc, int gtid 36250b57cec5SDimitry Andric #if OMPT_SUPPORT 36260b57cec5SDimitry Andric , 36270b57cec5SDimitry Andric enum fork_context_e fork_context 36280b57cec5SDimitry Andric #endif 36290b57cec5SDimitry Andric , 36300b57cec5SDimitry Andric int exit_teams = 0); 36310b57cec5SDimitry Andric 36320b57cec5SDimitry Andric extern void __kmp_serialized_parallel(ident_t *id, kmp_int32 gtid); 36330b57cec5SDimitry Andric extern void __kmp_internal_fork(ident_t *id, int gtid, kmp_team_t *team); 36340b57cec5SDimitry Andric extern void __kmp_internal_join(ident_t *id, int gtid, kmp_team_t *team); 36350b57cec5SDimitry Andric extern int __kmp_invoke_task_func(int gtid); 36360b57cec5SDimitry Andric extern void __kmp_run_before_invoked_task(int gtid, int tid, 36370b57cec5SDimitry Andric kmp_info_t *this_thr, 36380b57cec5SDimitry Andric kmp_team_t *team); 36390b57cec5SDimitry Andric extern void __kmp_run_after_invoked_task(int gtid, int tid, 36400b57cec5SDimitry Andric kmp_info_t *this_thr, 36410b57cec5SDimitry Andric kmp_team_t *team); 36420b57cec5SDimitry Andric 36430b57cec5SDimitry Andric // should never have been exported 36440b57cec5SDimitry Andric KMP_EXPORT int __kmpc_invoke_task_func(int gtid); 36450b57cec5SDimitry Andric extern int __kmp_invoke_teams_master(int gtid); 36460b57cec5SDimitry Andric extern void __kmp_teams_master(int gtid); 36470b57cec5SDimitry Andric extern int __kmp_aux_get_team_num(); 36480b57cec5SDimitry Andric extern int __kmp_aux_get_num_teams(); 36490b57cec5SDimitry Andric extern void __kmp_save_internal_controls(kmp_info_t *thread); 36500b57cec5SDimitry Andric extern void __kmp_user_set_library(enum library_type arg); 36510b57cec5SDimitry Andric extern void __kmp_aux_set_library(enum library_type arg); 36520b57cec5SDimitry Andric extern void __kmp_aux_set_stacksize(size_t arg); 36530b57cec5SDimitry Andric extern void __kmp_aux_set_blocktime(int arg, kmp_info_t *thread, int tid); 3654e8d8bef9SDimitry Andric extern void __kmp_aux_set_defaults(char const *str, size_t len); 36550b57cec5SDimitry Andric 36560b57cec5SDimitry Andric /* Functions called from __kmp_aux_env_initialize() in kmp_settings.cpp */ 36570b57cec5SDimitry Andric void kmpc_set_blocktime(int arg); 36580b57cec5SDimitry Andric void ompc_set_nested(int flag); 36590b57cec5SDimitry Andric void ompc_set_dynamic(int flag); 36600b57cec5SDimitry Andric void ompc_set_num_threads(int arg); 36610b57cec5SDimitry Andric 36620b57cec5SDimitry Andric extern void __kmp_push_current_task_to_thread(kmp_info_t *this_thr, 36630b57cec5SDimitry Andric kmp_team_t *team, int tid); 36640b57cec5SDimitry Andric extern void __kmp_pop_current_task_from_thread(kmp_info_t *this_thr); 36650b57cec5SDimitry Andric extern kmp_task_t *__kmp_task_alloc(ident_t *loc_ref, kmp_int32 gtid, 36660b57cec5SDimitry Andric kmp_tasking_flags_t *flags, 36670b57cec5SDimitry Andric size_t sizeof_kmp_task_t, 36680b57cec5SDimitry Andric size_t sizeof_shareds, 36690b57cec5SDimitry Andric kmp_routine_entry_t task_entry); 36700b57cec5SDimitry Andric extern void __kmp_init_implicit_task(ident_t *loc_ref, kmp_info_t *this_thr, 36710b57cec5SDimitry Andric kmp_team_t *team, int tid, 36720b57cec5SDimitry Andric int set_curr_task); 36730b57cec5SDimitry Andric extern void __kmp_finish_implicit_task(kmp_info_t *this_thr); 36740b57cec5SDimitry Andric extern void __kmp_free_implicit_task(kmp_info_t *this_thr); 36750b57cec5SDimitry Andric 36760b57cec5SDimitry Andric extern kmp_event_t *__kmpc_task_allow_completion_event(ident_t *loc_ref, 36770b57cec5SDimitry Andric int gtid, 36780b57cec5SDimitry Andric kmp_task_t *task); 36790b57cec5SDimitry Andric extern void __kmp_fulfill_event(kmp_event_t *event); 36800b57cec5SDimitry Andric 36810b57cec5SDimitry Andric extern void __kmp_free_task_team(kmp_info_t *thread, 36820b57cec5SDimitry Andric kmp_task_team_t *task_team); 36830b57cec5SDimitry Andric extern void __kmp_reap_task_teams(void); 36840b57cec5SDimitry Andric extern void __kmp_wait_to_unref_task_teams(void); 36850b57cec5SDimitry Andric extern void __kmp_task_team_setup(kmp_info_t *this_thr, kmp_team_t *team, 36860b57cec5SDimitry Andric int always); 36870b57cec5SDimitry Andric extern void __kmp_task_team_sync(kmp_info_t *this_thr, kmp_team_t *team); 36880b57cec5SDimitry Andric extern void __kmp_task_team_wait(kmp_info_t *this_thr, kmp_team_t *team 36890b57cec5SDimitry Andric #if USE_ITT_BUILD 36900b57cec5SDimitry Andric , 36910b57cec5SDimitry Andric void *itt_sync_obj 36920b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 36930b57cec5SDimitry Andric , 36940b57cec5SDimitry Andric int wait = 1); 36950b57cec5SDimitry Andric extern void __kmp_tasking_barrier(kmp_team_t *team, kmp_info_t *thread, 36960b57cec5SDimitry Andric int gtid); 36970b57cec5SDimitry Andric 36980b57cec5SDimitry Andric extern int __kmp_is_address_mapped(void *addr); 36990b57cec5SDimitry Andric extern kmp_uint64 __kmp_hardware_timestamp(void); 37000b57cec5SDimitry Andric 37010b57cec5SDimitry Andric #if KMP_OS_UNIX 37020b57cec5SDimitry Andric extern int __kmp_read_from_file(char const *path, char const *format, ...); 37030b57cec5SDimitry Andric #endif 37040b57cec5SDimitry Andric 37050b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */ 37060b57cec5SDimitry Andric // 37070b57cec5SDimitry Andric // Assembly routines that have no compiler intrinsic replacement 37080b57cec5SDimitry Andric // 37090b57cec5SDimitry Andric 37100b57cec5SDimitry Andric extern int __kmp_invoke_microtask(microtask_t pkfn, int gtid, int npr, int argc, 37110b57cec5SDimitry Andric void *argv[] 37120b57cec5SDimitry Andric #if OMPT_SUPPORT 37130b57cec5SDimitry Andric , 37140b57cec5SDimitry Andric void **exit_frame_ptr 37150b57cec5SDimitry Andric #endif 37160b57cec5SDimitry Andric ); 37170b57cec5SDimitry Andric 37180b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */ 37190b57cec5SDimitry Andric 37200b57cec5SDimitry Andric KMP_EXPORT void __kmpc_begin(ident_t *, kmp_int32 flags); 37210b57cec5SDimitry Andric KMP_EXPORT void __kmpc_end(ident_t *); 37220b57cec5SDimitry Andric 37230b57cec5SDimitry Andric KMP_EXPORT void __kmpc_threadprivate_register_vec(ident_t *, void *data, 37240b57cec5SDimitry Andric kmpc_ctor_vec ctor, 37250b57cec5SDimitry Andric kmpc_cctor_vec cctor, 37260b57cec5SDimitry Andric kmpc_dtor_vec dtor, 37270b57cec5SDimitry Andric size_t vector_length); 37280b57cec5SDimitry Andric KMP_EXPORT void __kmpc_threadprivate_register(ident_t *, void *data, 37290b57cec5SDimitry Andric kmpc_ctor ctor, kmpc_cctor cctor, 37300b57cec5SDimitry Andric kmpc_dtor dtor); 37310b57cec5SDimitry Andric KMP_EXPORT void *__kmpc_threadprivate(ident_t *, kmp_int32 global_tid, 37320b57cec5SDimitry Andric void *data, size_t size); 37330b57cec5SDimitry Andric 37340b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_global_thread_num(ident_t *); 37350b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_global_num_threads(ident_t *); 37360b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_bound_thread_num(ident_t *); 37370b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_bound_num_threads(ident_t *); 37380b57cec5SDimitry Andric 37390b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_ok_to_fork(ident_t *); 37400b57cec5SDimitry Andric KMP_EXPORT void __kmpc_fork_call(ident_t *, kmp_int32 nargs, 37410b57cec5SDimitry Andric kmpc_micro microtask, ...); 37420b57cec5SDimitry Andric 37430b57cec5SDimitry Andric KMP_EXPORT void __kmpc_serialized_parallel(ident_t *, kmp_int32 global_tid); 37440b57cec5SDimitry Andric KMP_EXPORT void __kmpc_end_serialized_parallel(ident_t *, kmp_int32 global_tid); 37450b57cec5SDimitry Andric 37460b57cec5SDimitry Andric KMP_EXPORT void __kmpc_flush(ident_t *); 37470b57cec5SDimitry Andric KMP_EXPORT void __kmpc_barrier(ident_t *, kmp_int32 global_tid); 37480b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid); 37490b57cec5SDimitry Andric KMP_EXPORT void __kmpc_end_master(ident_t *, kmp_int32 global_tid); 3750*fe6060f1SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_masked(ident_t *, kmp_int32 global_tid, 3751*fe6060f1SDimitry Andric kmp_int32 filter); 3752*fe6060f1SDimitry Andric KMP_EXPORT void __kmpc_end_masked(ident_t *, kmp_int32 global_tid); 37530b57cec5SDimitry Andric KMP_EXPORT void __kmpc_ordered(ident_t *, kmp_int32 global_tid); 37540b57cec5SDimitry Andric KMP_EXPORT void __kmpc_end_ordered(ident_t *, kmp_int32 global_tid); 37550b57cec5SDimitry Andric KMP_EXPORT void __kmpc_critical(ident_t *, kmp_int32 global_tid, 37560b57cec5SDimitry Andric kmp_critical_name *); 37570b57cec5SDimitry Andric KMP_EXPORT void __kmpc_end_critical(ident_t *, kmp_int32 global_tid, 37580b57cec5SDimitry Andric kmp_critical_name *); 37590b57cec5SDimitry Andric KMP_EXPORT void __kmpc_critical_with_hint(ident_t *, kmp_int32 global_tid, 37600b57cec5SDimitry Andric kmp_critical_name *, uint32_t hint); 37610b57cec5SDimitry Andric 37620b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_barrier_master(ident_t *, kmp_int32 global_tid); 37630b57cec5SDimitry Andric KMP_EXPORT void __kmpc_end_barrier_master(ident_t *, kmp_int32 global_tid); 37640b57cec5SDimitry Andric 37650b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_barrier_master_nowait(ident_t *, 37660b57cec5SDimitry Andric kmp_int32 global_tid); 37670b57cec5SDimitry Andric 37680b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid); 37690b57cec5SDimitry Andric KMP_EXPORT void __kmpc_end_single(ident_t *, kmp_int32 global_tid); 37700b57cec5SDimitry Andric 37710b57cec5SDimitry Andric KMP_EXPORT void KMPC_FOR_STATIC_INIT(ident_t *loc, kmp_int32 global_tid, 37720b57cec5SDimitry Andric kmp_int32 schedtype, kmp_int32 *plastiter, 37730b57cec5SDimitry Andric kmp_int *plower, kmp_int *pupper, 37740b57cec5SDimitry Andric kmp_int *pstride, kmp_int incr, 37750b57cec5SDimitry Andric kmp_int chunk); 37760b57cec5SDimitry Andric 37770b57cec5SDimitry Andric KMP_EXPORT void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 37780b57cec5SDimitry Andric 37790b57cec5SDimitry Andric KMP_EXPORT void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 37800b57cec5SDimitry Andric size_t cpy_size, void *cpy_data, 37810b57cec5SDimitry Andric void (*cpy_func)(void *, void *), 37820b57cec5SDimitry Andric kmp_int32 didit); 37830b57cec5SDimitry Andric 37840b57cec5SDimitry Andric extern void KMPC_SET_NUM_THREADS(int arg); 37850b57cec5SDimitry Andric extern void KMPC_SET_DYNAMIC(int flag); 37860b57cec5SDimitry Andric extern void KMPC_SET_NESTED(int flag); 37870b57cec5SDimitry Andric 37880b57cec5SDimitry Andric /* OMP 3.0 tasking interface routines */ 37890b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_omp_task(ident_t *loc_ref, kmp_int32 gtid, 37900b57cec5SDimitry Andric kmp_task_t *new_task); 37910b57cec5SDimitry Andric KMP_EXPORT kmp_task_t *__kmpc_omp_task_alloc(ident_t *loc_ref, kmp_int32 gtid, 37920b57cec5SDimitry Andric kmp_int32 flags, 37930b57cec5SDimitry Andric size_t sizeof_kmp_task_t, 37940b57cec5SDimitry Andric size_t sizeof_shareds, 37950b57cec5SDimitry Andric kmp_routine_entry_t task_entry); 3796*fe6060f1SDimitry Andric KMP_EXPORT kmp_task_t *__kmpc_omp_target_task_alloc( 3797*fe6060f1SDimitry Andric ident_t *loc_ref, kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, 3798*fe6060f1SDimitry Andric size_t sizeof_shareds, kmp_routine_entry_t task_entry, kmp_int64 device_id); 37990b57cec5SDimitry Andric KMP_EXPORT void __kmpc_omp_task_begin_if0(ident_t *loc_ref, kmp_int32 gtid, 38000b57cec5SDimitry Andric kmp_task_t *task); 38010b57cec5SDimitry Andric KMP_EXPORT void __kmpc_omp_task_complete_if0(ident_t *loc_ref, kmp_int32 gtid, 38020b57cec5SDimitry Andric kmp_task_t *task); 38030b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_omp_task_parts(ident_t *loc_ref, kmp_int32 gtid, 38040b57cec5SDimitry Andric kmp_task_t *new_task); 38050b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_omp_taskwait(ident_t *loc_ref, kmp_int32 gtid); 38060b57cec5SDimitry Andric 38070b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_omp_taskyield(ident_t *loc_ref, kmp_int32 gtid, 38080b57cec5SDimitry Andric int end_part); 38090b57cec5SDimitry Andric 38100b57cec5SDimitry Andric #if TASK_UNUSED 38110b57cec5SDimitry Andric void __kmpc_omp_task_begin(ident_t *loc_ref, kmp_int32 gtid, kmp_task_t *task); 38120b57cec5SDimitry Andric void __kmpc_omp_task_complete(ident_t *loc_ref, kmp_int32 gtid, 38130b57cec5SDimitry Andric kmp_task_t *task); 38140b57cec5SDimitry Andric #endif // TASK_UNUSED 38150b57cec5SDimitry Andric 38160b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */ 38170b57cec5SDimitry Andric 38180b57cec5SDimitry Andric KMP_EXPORT void __kmpc_taskgroup(ident_t *loc, int gtid); 38190b57cec5SDimitry Andric KMP_EXPORT void __kmpc_end_taskgroup(ident_t *loc, int gtid); 38200b57cec5SDimitry Andric 38210b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_omp_task_with_deps( 38220b57cec5SDimitry Andric ident_t *loc_ref, kmp_int32 gtid, kmp_task_t *new_task, kmp_int32 ndeps, 38230b57cec5SDimitry Andric kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias, 38240b57cec5SDimitry Andric kmp_depend_info_t *noalias_dep_list); 38250b57cec5SDimitry Andric KMP_EXPORT void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32 gtid, 38260b57cec5SDimitry Andric kmp_int32 ndeps, 38270b57cec5SDimitry Andric kmp_depend_info_t *dep_list, 38280b57cec5SDimitry Andric kmp_int32 ndeps_noalias, 38290b57cec5SDimitry Andric kmp_depend_info_t *noalias_dep_list); 38300b57cec5SDimitry Andric extern kmp_int32 __kmp_omp_task(kmp_int32 gtid, kmp_task_t *new_task, 38310b57cec5SDimitry Andric bool serialize_immediate); 38320b57cec5SDimitry Andric 38330b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_cancel(ident_t *loc_ref, kmp_int32 gtid, 38340b57cec5SDimitry Andric kmp_int32 cncl_kind); 38350b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_cancellationpoint(ident_t *loc_ref, kmp_int32 gtid, 38360b57cec5SDimitry Andric kmp_int32 cncl_kind); 38370b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_cancel_barrier(ident_t *loc_ref, kmp_int32 gtid); 38380b57cec5SDimitry Andric KMP_EXPORT int __kmp_get_cancellation_status(int cancel_kind); 38390b57cec5SDimitry Andric 38400b57cec5SDimitry Andric KMP_EXPORT void __kmpc_proxy_task_completed(kmp_int32 gtid, kmp_task_t *ptask); 38410b57cec5SDimitry Andric KMP_EXPORT void __kmpc_proxy_task_completed_ooo(kmp_task_t *ptask); 38420b57cec5SDimitry Andric KMP_EXPORT void __kmpc_taskloop(ident_t *loc, kmp_int32 gtid, kmp_task_t *task, 38430b57cec5SDimitry Andric kmp_int32 if_val, kmp_uint64 *lb, 38440b57cec5SDimitry Andric kmp_uint64 *ub, kmp_int64 st, kmp_int32 nogroup, 38450b57cec5SDimitry Andric kmp_int32 sched, kmp_uint64 grainsize, 38460b57cec5SDimitry Andric void *task_dup); 3847e8d8bef9SDimitry Andric KMP_EXPORT void __kmpc_taskloop_5(ident_t *loc, kmp_int32 gtid, 3848e8d8bef9SDimitry Andric kmp_task_t *task, kmp_int32 if_val, 3849e8d8bef9SDimitry Andric kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, 3850e8d8bef9SDimitry Andric kmp_int32 nogroup, kmp_int32 sched, 3851e8d8bef9SDimitry Andric kmp_uint64 grainsize, kmp_int32 modifier, 3852e8d8bef9SDimitry Andric void *task_dup); 38530b57cec5SDimitry Andric KMP_EXPORT void *__kmpc_task_reduction_init(int gtid, int num_data, void *data); 38540b57cec5SDimitry Andric KMP_EXPORT void *__kmpc_taskred_init(int gtid, int num_data, void *data); 38550b57cec5SDimitry Andric KMP_EXPORT void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void *d); 38560b57cec5SDimitry Andric KMP_EXPORT void *__kmpc_task_reduction_modifier_init(ident_t *loc, int gtid, 38570b57cec5SDimitry Andric int is_ws, int num, 38580b57cec5SDimitry Andric void *data); 38590b57cec5SDimitry Andric KMP_EXPORT void *__kmpc_taskred_modifier_init(ident_t *loc, int gtid, int is_ws, 38600b57cec5SDimitry Andric int num, void *data); 38610b57cec5SDimitry Andric KMP_EXPORT void __kmpc_task_reduction_modifier_fini(ident_t *loc, int gtid, 38620b57cec5SDimitry Andric int is_ws); 38630b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_omp_reg_task_with_affinity( 38640b57cec5SDimitry Andric ident_t *loc_ref, kmp_int32 gtid, kmp_task_t *new_task, kmp_int32 naffins, 38650b57cec5SDimitry Andric kmp_task_affinity_info_t *affin_list); 3866*fe6060f1SDimitry Andric KMP_EXPORT void __kmp_set_num_teams(int num_teams); 3867*fe6060f1SDimitry Andric KMP_EXPORT int __kmp_get_max_teams(void); 3868*fe6060f1SDimitry Andric KMP_EXPORT void __kmp_set_teams_thread_limit(int limit); 3869*fe6060f1SDimitry Andric KMP_EXPORT int __kmp_get_teams_thread_limit(void); 38700b57cec5SDimitry Andric 38710b57cec5SDimitry Andric /* Lock interface routines (fast versions with gtid passed in) */ 38720b57cec5SDimitry Andric KMP_EXPORT void __kmpc_init_lock(ident_t *loc, kmp_int32 gtid, 38730b57cec5SDimitry Andric void **user_lock); 38740b57cec5SDimitry Andric KMP_EXPORT void __kmpc_init_nest_lock(ident_t *loc, kmp_int32 gtid, 38750b57cec5SDimitry Andric void **user_lock); 38760b57cec5SDimitry Andric KMP_EXPORT void __kmpc_destroy_lock(ident_t *loc, kmp_int32 gtid, 38770b57cec5SDimitry Andric void **user_lock); 38780b57cec5SDimitry Andric KMP_EXPORT void __kmpc_destroy_nest_lock(ident_t *loc, kmp_int32 gtid, 38790b57cec5SDimitry Andric void **user_lock); 38800b57cec5SDimitry Andric KMP_EXPORT void __kmpc_set_lock(ident_t *loc, kmp_int32 gtid, void **user_lock); 38810b57cec5SDimitry Andric KMP_EXPORT void __kmpc_set_nest_lock(ident_t *loc, kmp_int32 gtid, 38820b57cec5SDimitry Andric void **user_lock); 38830b57cec5SDimitry Andric KMP_EXPORT void __kmpc_unset_lock(ident_t *loc, kmp_int32 gtid, 38840b57cec5SDimitry Andric void **user_lock); 38850b57cec5SDimitry Andric KMP_EXPORT void __kmpc_unset_nest_lock(ident_t *loc, kmp_int32 gtid, 38860b57cec5SDimitry Andric void **user_lock); 38870b57cec5SDimitry Andric KMP_EXPORT int __kmpc_test_lock(ident_t *loc, kmp_int32 gtid, void **user_lock); 38880b57cec5SDimitry Andric KMP_EXPORT int __kmpc_test_nest_lock(ident_t *loc, kmp_int32 gtid, 38890b57cec5SDimitry Andric void **user_lock); 38900b57cec5SDimitry Andric 38910b57cec5SDimitry Andric KMP_EXPORT void __kmpc_init_lock_with_hint(ident_t *loc, kmp_int32 gtid, 38920b57cec5SDimitry Andric void **user_lock, uintptr_t hint); 38930b57cec5SDimitry Andric KMP_EXPORT void __kmpc_init_nest_lock_with_hint(ident_t *loc, kmp_int32 gtid, 38940b57cec5SDimitry Andric void **user_lock, 38950b57cec5SDimitry Andric uintptr_t hint); 38960b57cec5SDimitry Andric 38970b57cec5SDimitry Andric /* Interface to fast scalable reduce methods routines */ 38980b57cec5SDimitry Andric 38990b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_reduce_nowait( 39000b57cec5SDimitry Andric ident_t *loc, kmp_int32 global_tid, kmp_int32 num_vars, size_t reduce_size, 39010b57cec5SDimitry Andric void *reduce_data, void (*reduce_func)(void *lhs_data, void *rhs_data), 39020b57cec5SDimitry Andric kmp_critical_name *lck); 39030b57cec5SDimitry Andric KMP_EXPORT void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 39040b57cec5SDimitry Andric kmp_critical_name *lck); 39050b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_reduce( 39060b57cec5SDimitry Andric ident_t *loc, kmp_int32 global_tid, kmp_int32 num_vars, size_t reduce_size, 39070b57cec5SDimitry Andric void *reduce_data, void (*reduce_func)(void *lhs_data, void *rhs_data), 39080b57cec5SDimitry Andric kmp_critical_name *lck); 39090b57cec5SDimitry Andric KMP_EXPORT void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 39100b57cec5SDimitry Andric kmp_critical_name *lck); 39110b57cec5SDimitry Andric 39120b57cec5SDimitry Andric /* Internal fast reduction routines */ 39130b57cec5SDimitry Andric 39140b57cec5SDimitry Andric extern PACKED_REDUCTION_METHOD_T __kmp_determine_reduction_method( 39150b57cec5SDimitry Andric ident_t *loc, kmp_int32 global_tid, kmp_int32 num_vars, size_t reduce_size, 39160b57cec5SDimitry Andric void *reduce_data, void (*reduce_func)(void *lhs_data, void *rhs_data), 39170b57cec5SDimitry Andric kmp_critical_name *lck); 39180b57cec5SDimitry Andric 39190b57cec5SDimitry Andric // this function is for testing set/get/determine reduce method 39200b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmp_get_reduce_method(void); 39210b57cec5SDimitry Andric 39220b57cec5SDimitry Andric KMP_EXPORT kmp_uint64 __kmpc_get_taskid(); 39230b57cec5SDimitry Andric KMP_EXPORT kmp_uint64 __kmpc_get_parent_taskid(); 39240b57cec5SDimitry Andric 39250b57cec5SDimitry Andric // C++ port 39260b57cec5SDimitry Andric // missing 'extern "C"' declarations 39270b57cec5SDimitry Andric 39280b57cec5SDimitry Andric KMP_EXPORT kmp_int32 __kmpc_in_parallel(ident_t *loc); 39290b57cec5SDimitry Andric KMP_EXPORT void __kmpc_pop_num_threads(ident_t *loc, kmp_int32 global_tid); 39300b57cec5SDimitry Andric KMP_EXPORT void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 39310b57cec5SDimitry Andric kmp_int32 num_threads); 39320b57cec5SDimitry Andric 39330b57cec5SDimitry Andric KMP_EXPORT void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 39340b57cec5SDimitry Andric int proc_bind); 39350b57cec5SDimitry Andric KMP_EXPORT void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid, 39360b57cec5SDimitry Andric kmp_int32 num_teams, 39370b57cec5SDimitry Andric kmp_int32 num_threads); 3938*fe6060f1SDimitry Andric /* Function for OpenMP 5.1 num_teams clause */ 3939*fe6060f1SDimitry Andric KMP_EXPORT void __kmpc_push_num_teams_51(ident_t *loc, kmp_int32 global_tid, 3940*fe6060f1SDimitry Andric kmp_int32 num_teams_lb, 3941*fe6060f1SDimitry Andric kmp_int32 num_teams_ub, 3942*fe6060f1SDimitry Andric kmp_int32 num_threads); 39430b57cec5SDimitry Andric KMP_EXPORT void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, 39440b57cec5SDimitry Andric kmpc_micro microtask, ...); 39450b57cec5SDimitry Andric struct kmp_dim { // loop bounds info casted to kmp_int64 39460b57cec5SDimitry Andric kmp_int64 lo; // lower 39470b57cec5SDimitry Andric kmp_int64 up; // upper 39480b57cec5SDimitry Andric kmp_int64 st; // stride 39490b57cec5SDimitry Andric }; 39500b57cec5SDimitry Andric KMP_EXPORT void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, 39510b57cec5SDimitry Andric kmp_int32 num_dims, 39520b57cec5SDimitry Andric const struct kmp_dim *dims); 39530b57cec5SDimitry Andric KMP_EXPORT void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, 39540b57cec5SDimitry Andric const kmp_int64 *vec); 39550b57cec5SDimitry Andric KMP_EXPORT void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, 39560b57cec5SDimitry Andric const kmp_int64 *vec); 39570b57cec5SDimitry Andric KMP_EXPORT void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); 39580b57cec5SDimitry Andric 39590b57cec5SDimitry Andric KMP_EXPORT void *__kmpc_threadprivate_cached(ident_t *loc, kmp_int32 global_tid, 39600b57cec5SDimitry Andric void *data, size_t size, 39610b57cec5SDimitry Andric void ***cache); 39620b57cec5SDimitry Andric 39630b57cec5SDimitry Andric // Symbols for MS mutual detection. 39640b57cec5SDimitry Andric extern int _You_must_link_with_exactly_one_OpenMP_library; 39650b57cec5SDimitry Andric extern int _You_must_link_with_Intel_OpenMP_library; 39660b57cec5SDimitry Andric #if KMP_OS_WINDOWS && (KMP_VERSION_MAJOR > 4) 39670b57cec5SDimitry Andric extern int _You_must_link_with_Microsoft_OpenMP_library; 39680b57cec5SDimitry Andric #endif 39690b57cec5SDimitry Andric 39700b57cec5SDimitry Andric // The routines below are not exported. 39710b57cec5SDimitry Andric // Consider making them 'static' in corresponding source files. 39720b57cec5SDimitry Andric void kmp_threadprivate_insert_private_data(int gtid, void *pc_addr, 39730b57cec5SDimitry Andric void *data_addr, size_t pc_size); 39740b57cec5SDimitry Andric struct private_common *kmp_threadprivate_insert(int gtid, void *pc_addr, 39750b57cec5SDimitry Andric void *data_addr, 39760b57cec5SDimitry Andric size_t pc_size); 39770b57cec5SDimitry Andric void __kmp_threadprivate_resize_cache(int newCapacity); 39780b57cec5SDimitry Andric void __kmp_cleanup_threadprivate_caches(); 39790b57cec5SDimitry Andric 39800b57cec5SDimitry Andric // ompc_, kmpc_ entries moved from omp.h. 39810b57cec5SDimitry Andric #if KMP_OS_WINDOWS 39820b57cec5SDimitry Andric #define KMPC_CONVENTION __cdecl 39830b57cec5SDimitry Andric #else 39840b57cec5SDimitry Andric #define KMPC_CONVENTION 39850b57cec5SDimitry Andric #endif 39860b57cec5SDimitry Andric 39870b57cec5SDimitry Andric #ifndef __OMP_H 39880b57cec5SDimitry Andric typedef enum omp_sched_t { 39890b57cec5SDimitry Andric omp_sched_static = 1, 39900b57cec5SDimitry Andric omp_sched_dynamic = 2, 39910b57cec5SDimitry Andric omp_sched_guided = 3, 39920b57cec5SDimitry Andric omp_sched_auto = 4 39930b57cec5SDimitry Andric } omp_sched_t; 39940b57cec5SDimitry Andric typedef void *kmp_affinity_mask_t; 39950b57cec5SDimitry Andric #endif 39960b57cec5SDimitry Andric 39970b57cec5SDimitry Andric KMP_EXPORT void KMPC_CONVENTION ompc_set_max_active_levels(int); 39980b57cec5SDimitry Andric KMP_EXPORT void KMPC_CONVENTION ompc_set_schedule(omp_sched_t, int); 39990b57cec5SDimitry Andric KMP_EXPORT int KMPC_CONVENTION ompc_get_ancestor_thread_num(int); 40000b57cec5SDimitry Andric KMP_EXPORT int KMPC_CONVENTION ompc_get_team_size(int); 40010b57cec5SDimitry Andric KMP_EXPORT int KMPC_CONVENTION 40020b57cec5SDimitry Andric kmpc_set_affinity_mask_proc(int, kmp_affinity_mask_t *); 40030b57cec5SDimitry Andric KMP_EXPORT int KMPC_CONVENTION 40040b57cec5SDimitry Andric kmpc_unset_affinity_mask_proc(int, kmp_affinity_mask_t *); 40050b57cec5SDimitry Andric KMP_EXPORT int KMPC_CONVENTION 40060b57cec5SDimitry Andric kmpc_get_affinity_mask_proc(int, kmp_affinity_mask_t *); 40070b57cec5SDimitry Andric 40080b57cec5SDimitry Andric KMP_EXPORT void KMPC_CONVENTION kmpc_set_stacksize(int); 40090b57cec5SDimitry Andric KMP_EXPORT void KMPC_CONVENTION kmpc_set_stacksize_s(size_t); 40100b57cec5SDimitry Andric KMP_EXPORT void KMPC_CONVENTION kmpc_set_library(int); 40110b57cec5SDimitry Andric KMP_EXPORT void KMPC_CONVENTION kmpc_set_defaults(char const *); 40120b57cec5SDimitry Andric KMP_EXPORT void KMPC_CONVENTION kmpc_set_disp_num_buffers(int); 4013*fe6060f1SDimitry Andric void KMP_EXPAND_NAME(ompc_set_affinity_format)(char const *format); 4014*fe6060f1SDimitry Andric size_t KMP_EXPAND_NAME(ompc_get_affinity_format)(char *buffer, size_t size); 4015*fe6060f1SDimitry Andric void KMP_EXPAND_NAME(ompc_display_affinity)(char const *format); 4016*fe6060f1SDimitry Andric size_t KMP_EXPAND_NAME(ompc_capture_affinity)(char *buffer, size_t buf_size, 4017*fe6060f1SDimitry Andric char const *format); 40180b57cec5SDimitry Andric 40190b57cec5SDimitry Andric enum kmp_target_offload_kind { 40200b57cec5SDimitry Andric tgt_disabled = 0, 40210b57cec5SDimitry Andric tgt_default = 1, 40220b57cec5SDimitry Andric tgt_mandatory = 2 40230b57cec5SDimitry Andric }; 40240b57cec5SDimitry Andric typedef enum kmp_target_offload_kind kmp_target_offload_kind_t; 40250b57cec5SDimitry Andric // Set via OMP_TARGET_OFFLOAD if specified, defaults to tgt_default otherwise 40260b57cec5SDimitry Andric extern kmp_target_offload_kind_t __kmp_target_offload; 40270b57cec5SDimitry Andric extern int __kmpc_get_target_offload(); 40280b57cec5SDimitry Andric 40290b57cec5SDimitry Andric // Constants used in libomptarget 40300b57cec5SDimitry Andric #define KMP_DEVICE_DEFAULT -1 // This is libomptarget's default device. 40310b57cec5SDimitry Andric #define KMP_DEVICE_ALL -11 // This is libomptarget's "all devices". 40320b57cec5SDimitry Andric 40330b57cec5SDimitry Andric // OMP Pause Resource 40340b57cec5SDimitry Andric 40350b57cec5SDimitry Andric // The following enum is used both to set the status in __kmp_pause_status, and 40360b57cec5SDimitry Andric // as the internal equivalent of the externally-visible omp_pause_resource_t. 40370b57cec5SDimitry Andric typedef enum kmp_pause_status_t { 40380b57cec5SDimitry Andric kmp_not_paused = 0, // status is not paused, or, requesting resume 40390b57cec5SDimitry Andric kmp_soft_paused = 1, // status is soft-paused, or, requesting soft pause 40400b57cec5SDimitry Andric kmp_hard_paused = 2 // status is hard-paused, or, requesting hard pause 40410b57cec5SDimitry Andric } kmp_pause_status_t; 40420b57cec5SDimitry Andric 40430b57cec5SDimitry Andric // This stores the pause state of the runtime 40440b57cec5SDimitry Andric extern kmp_pause_status_t __kmp_pause_status; 40450b57cec5SDimitry Andric extern int __kmpc_pause_resource(kmp_pause_status_t level); 40460b57cec5SDimitry Andric extern int __kmp_pause_resource(kmp_pause_status_t level); 40470b57cec5SDimitry Andric // Soft resume sets __kmp_pause_status, and wakes up all threads. 40480b57cec5SDimitry Andric extern void __kmp_resume_if_soft_paused(); 40490b57cec5SDimitry Andric // Hard resume simply resets the status to not paused. Library will appear to 40500b57cec5SDimitry Andric // be uninitialized after hard pause. Let OMP constructs trigger required 40510b57cec5SDimitry Andric // initializations. 40520b57cec5SDimitry Andric static inline void __kmp_resume_if_hard_paused() { 40530b57cec5SDimitry Andric if (__kmp_pause_status == kmp_hard_paused) { 40540b57cec5SDimitry Andric __kmp_pause_status = kmp_not_paused; 40550b57cec5SDimitry Andric } 40560b57cec5SDimitry Andric } 40570b57cec5SDimitry Andric 40585ffd83dbSDimitry Andric extern void __kmp_omp_display_env(int verbose); 40595ffd83dbSDimitry Andric 4060e8d8bef9SDimitry Andric // 1: it is initializing hidden helper team 4061e8d8bef9SDimitry Andric extern volatile int __kmp_init_hidden_helper; 4062e8d8bef9SDimitry Andric // 1: the hidden helper team is done 4063e8d8bef9SDimitry Andric extern volatile int __kmp_hidden_helper_team_done; 4064e8d8bef9SDimitry Andric // 1: enable hidden helper task 4065e8d8bef9SDimitry Andric extern kmp_int32 __kmp_enable_hidden_helper; 4066e8d8bef9SDimitry Andric // Main thread of hidden helper team 4067e8d8bef9SDimitry Andric extern kmp_info_t *__kmp_hidden_helper_main_thread; 4068e8d8bef9SDimitry Andric // Descriptors for the hidden helper threads 4069e8d8bef9SDimitry Andric extern kmp_info_t **__kmp_hidden_helper_threads; 4070e8d8bef9SDimitry Andric // Number of hidden helper threads 4071e8d8bef9SDimitry Andric extern kmp_int32 __kmp_hidden_helper_threads_num; 4072e8d8bef9SDimitry Andric // Number of hidden helper tasks that have not been executed yet 4073e8d8bef9SDimitry Andric extern std::atomic<kmp_int32> __kmp_unexecuted_hidden_helper_tasks; 4074e8d8bef9SDimitry Andric 4075e8d8bef9SDimitry Andric extern void __kmp_hidden_helper_initialize(); 4076e8d8bef9SDimitry Andric extern void __kmp_hidden_helper_threads_initz_routine(); 4077e8d8bef9SDimitry Andric extern void __kmp_do_initialize_hidden_helper_threads(); 4078e8d8bef9SDimitry Andric extern void __kmp_hidden_helper_threads_initz_wait(); 4079e8d8bef9SDimitry Andric extern void __kmp_hidden_helper_initz_release(); 4080e8d8bef9SDimitry Andric extern void __kmp_hidden_helper_threads_deinitz_wait(); 4081e8d8bef9SDimitry Andric extern void __kmp_hidden_helper_threads_deinitz_release(); 4082e8d8bef9SDimitry Andric extern void __kmp_hidden_helper_main_thread_wait(); 4083e8d8bef9SDimitry Andric extern void __kmp_hidden_helper_worker_thread_wait(); 4084e8d8bef9SDimitry Andric extern void __kmp_hidden_helper_worker_thread_signal(); 4085e8d8bef9SDimitry Andric extern void __kmp_hidden_helper_main_thread_release(); 4086e8d8bef9SDimitry Andric 4087e8d8bef9SDimitry Andric // Check whether a given thread is a hidden helper thread 4088e8d8bef9SDimitry Andric #define KMP_HIDDEN_HELPER_THREAD(gtid) \ 4089e8d8bef9SDimitry Andric ((gtid) >= 1 && (gtid) <= __kmp_hidden_helper_threads_num) 4090e8d8bef9SDimitry Andric 4091e8d8bef9SDimitry Andric #define KMP_HIDDEN_HELPER_WORKER_THREAD(gtid) \ 4092e8d8bef9SDimitry Andric ((gtid) > 1 && (gtid) <= __kmp_hidden_helper_threads_num) 4093e8d8bef9SDimitry Andric 4094*fe6060f1SDimitry Andric #define KMP_HIDDEN_HELPER_TEAM(team) \ 4095*fe6060f1SDimitry Andric (team->t.t_threads[0] == __kmp_hidden_helper_main_thread) 4096*fe6060f1SDimitry Andric 4097e8d8bef9SDimitry Andric // Map a gtid to a hidden helper thread. The first hidden helper thread, a.k.a 4098e8d8bef9SDimitry Andric // main thread, is skipped. 4099e8d8bef9SDimitry Andric #define KMP_GTID_TO_SHADOW_GTID(gtid) \ 4100e8d8bef9SDimitry Andric ((gtid) % (__kmp_hidden_helper_threads_num - 1) + 2) 4101e8d8bef9SDimitry Andric 4102*fe6060f1SDimitry Andric // Return the adjusted gtid value by subtracting from gtid the number 4103*fe6060f1SDimitry Andric // of hidden helper threads. This adjusted value is the gtid the thread would 4104*fe6060f1SDimitry Andric // have received if there were no hidden helper threads. 4105*fe6060f1SDimitry Andric static inline int __kmp_adjust_gtid_for_hidden_helpers(int gtid) { 4106*fe6060f1SDimitry Andric int adjusted_gtid = gtid; 4107*fe6060f1SDimitry Andric if (__kmp_hidden_helper_threads_num > 0 && gtid > 0 && 4108*fe6060f1SDimitry Andric gtid - __kmp_hidden_helper_threads_num >= 0) { 4109*fe6060f1SDimitry Andric adjusted_gtid -= __kmp_hidden_helper_threads_num; 4110*fe6060f1SDimitry Andric } 4111*fe6060f1SDimitry Andric return adjusted_gtid; 4112*fe6060f1SDimitry Andric } 4113*fe6060f1SDimitry Andric 4114*fe6060f1SDimitry Andric // Support for error directive 4115*fe6060f1SDimitry Andric typedef enum kmp_severity_t { 4116*fe6060f1SDimitry Andric severity_warning = 1, 4117*fe6060f1SDimitry Andric severity_fatal = 2 4118*fe6060f1SDimitry Andric } kmp_severity_t; 4119*fe6060f1SDimitry Andric extern void __kmpc_error(ident_t *loc, int severity, const char *message); 4120*fe6060f1SDimitry Andric 41210b57cec5SDimitry Andric #ifdef __cplusplus 41220b57cec5SDimitry Andric } 41230b57cec5SDimitry Andric #endif 41240b57cec5SDimitry Andric 4125e8d8bef9SDimitry Andric template <bool C, bool S> 4126e8d8bef9SDimitry Andric extern void __kmp_suspend_32(int th_gtid, kmp_flag_32<C, S> *flag); 4127e8d8bef9SDimitry Andric template <bool C, bool S> 4128e8d8bef9SDimitry Andric extern void __kmp_suspend_64(int th_gtid, kmp_flag_64<C, S> *flag); 4129e8d8bef9SDimitry Andric extern void __kmp_suspend_oncore(int th_gtid, kmp_flag_oncore *flag); 4130e8d8bef9SDimitry Andric #if KMP_HAVE_MWAIT || KMP_HAVE_UMWAIT 4131e8d8bef9SDimitry Andric template <bool C, bool S> 4132e8d8bef9SDimitry Andric extern void __kmp_mwait_32(int th_gtid, kmp_flag_32<C, S> *flag); 4133e8d8bef9SDimitry Andric template <bool C, bool S> 4134e8d8bef9SDimitry Andric extern void __kmp_mwait_64(int th_gtid, kmp_flag_64<C, S> *flag); 4135e8d8bef9SDimitry Andric extern void __kmp_mwait_oncore(int th_gtid, kmp_flag_oncore *flag); 4136e8d8bef9SDimitry Andric #endif 4137e8d8bef9SDimitry Andric template <bool C, bool S> 4138e8d8bef9SDimitry Andric extern void __kmp_resume_32(int target_gtid, kmp_flag_32<C, S> *flag); 4139e8d8bef9SDimitry Andric template <bool C, bool S> 4140e8d8bef9SDimitry Andric extern void __kmp_resume_64(int target_gtid, kmp_flag_64<C, S> *flag); 4141e8d8bef9SDimitry Andric extern void __kmp_resume_oncore(int target_gtid, kmp_flag_oncore *flag); 4142e8d8bef9SDimitry Andric 4143e8d8bef9SDimitry Andric template <bool C, bool S> 4144e8d8bef9SDimitry Andric int __kmp_execute_tasks_32(kmp_info_t *thread, kmp_int32 gtid, 4145e8d8bef9SDimitry Andric kmp_flag_32<C, S> *flag, int final_spin, 4146e8d8bef9SDimitry Andric int *thread_finished, 4147e8d8bef9SDimitry Andric #if USE_ITT_BUILD 4148e8d8bef9SDimitry Andric void *itt_sync_obj, 4149e8d8bef9SDimitry Andric #endif /* USE_ITT_BUILD */ 4150e8d8bef9SDimitry Andric kmp_int32 is_constrained); 4151e8d8bef9SDimitry Andric template <bool C, bool S> 4152e8d8bef9SDimitry Andric int __kmp_execute_tasks_64(kmp_info_t *thread, kmp_int32 gtid, 4153e8d8bef9SDimitry Andric kmp_flag_64<C, S> *flag, int final_spin, 4154e8d8bef9SDimitry Andric int *thread_finished, 4155e8d8bef9SDimitry Andric #if USE_ITT_BUILD 4156e8d8bef9SDimitry Andric void *itt_sync_obj, 4157e8d8bef9SDimitry Andric #endif /* USE_ITT_BUILD */ 4158e8d8bef9SDimitry Andric kmp_int32 is_constrained); 4159e8d8bef9SDimitry Andric int __kmp_execute_tasks_oncore(kmp_info_t *thread, kmp_int32 gtid, 4160e8d8bef9SDimitry Andric kmp_flag_oncore *flag, int final_spin, 4161e8d8bef9SDimitry Andric int *thread_finished, 4162e8d8bef9SDimitry Andric #if USE_ITT_BUILD 4163e8d8bef9SDimitry Andric void *itt_sync_obj, 4164e8d8bef9SDimitry Andric #endif /* USE_ITT_BUILD */ 4165e8d8bef9SDimitry Andric kmp_int32 is_constrained); 4166e8d8bef9SDimitry Andric 4167*fe6060f1SDimitry Andric extern int __kmp_nesting_mode; 4168*fe6060f1SDimitry Andric extern int __kmp_nesting_mode_nlevels; 4169*fe6060f1SDimitry Andric extern int *__kmp_nesting_nth_level; 4170*fe6060f1SDimitry Andric extern void __kmp_init_nesting_mode(); 4171*fe6060f1SDimitry Andric extern void __kmp_set_nesting_mode_threads(); 4172*fe6060f1SDimitry Andric 4173e8d8bef9SDimitry Andric /// This class safely opens and closes a C-style FILE* object using RAII 4174e8d8bef9SDimitry Andric /// semantics. There are also methods which allow using stdout or stderr as 4175e8d8bef9SDimitry Andric /// the underlying FILE* object. With the implicit conversion operator to 4176e8d8bef9SDimitry Andric /// FILE*, an object with this type can be used in any function which takes 4177e8d8bef9SDimitry Andric /// a FILE* object e.g., fprintf(). 4178e8d8bef9SDimitry Andric /// No close method is needed at use sites. 4179e8d8bef9SDimitry Andric class kmp_safe_raii_file_t { 4180e8d8bef9SDimitry Andric FILE *f; 4181e8d8bef9SDimitry Andric 4182e8d8bef9SDimitry Andric void close() { 4183e8d8bef9SDimitry Andric if (f && f != stdout && f != stderr) { 4184e8d8bef9SDimitry Andric fclose(f); 4185e8d8bef9SDimitry Andric f = nullptr; 4186e8d8bef9SDimitry Andric } 4187e8d8bef9SDimitry Andric } 4188e8d8bef9SDimitry Andric 4189e8d8bef9SDimitry Andric public: 4190e8d8bef9SDimitry Andric kmp_safe_raii_file_t() : f(nullptr) {} 4191e8d8bef9SDimitry Andric kmp_safe_raii_file_t(const char *filename, const char *mode, 4192e8d8bef9SDimitry Andric const char *env_var = nullptr) 4193e8d8bef9SDimitry Andric : f(nullptr) { 4194e8d8bef9SDimitry Andric open(filename, mode, env_var); 4195e8d8bef9SDimitry Andric } 4196e8d8bef9SDimitry Andric ~kmp_safe_raii_file_t() { close(); } 4197e8d8bef9SDimitry Andric 4198e8d8bef9SDimitry Andric /// Open filename using mode. This is automatically closed in the destructor. 4199e8d8bef9SDimitry Andric /// The env_var parameter indicates the environment variable the filename 4200e8d8bef9SDimitry Andric /// came from if != nullptr. 4201e8d8bef9SDimitry Andric void open(const char *filename, const char *mode, 4202e8d8bef9SDimitry Andric const char *env_var = nullptr) { 4203e8d8bef9SDimitry Andric KMP_ASSERT(!f); 4204e8d8bef9SDimitry Andric f = fopen(filename, mode); 4205e8d8bef9SDimitry Andric if (!f) { 4206e8d8bef9SDimitry Andric int code = errno; 4207e8d8bef9SDimitry Andric if (env_var) { 4208e8d8bef9SDimitry Andric __kmp_fatal(KMP_MSG(CantOpenFileForReading, filename), KMP_ERR(code), 4209e8d8bef9SDimitry Andric KMP_HNT(CheckEnvVar, env_var, filename), __kmp_msg_null); 4210e8d8bef9SDimitry Andric } else { 4211e8d8bef9SDimitry Andric __kmp_fatal(KMP_MSG(CantOpenFileForReading, filename), KMP_ERR(code), 4212e8d8bef9SDimitry Andric __kmp_msg_null); 4213e8d8bef9SDimitry Andric } 4214e8d8bef9SDimitry Andric } 4215e8d8bef9SDimitry Andric } 4216e8d8bef9SDimitry Andric /// Set the FILE* object to stdout and output there 4217e8d8bef9SDimitry Andric /// No open call should happen before this call. 4218e8d8bef9SDimitry Andric void set_stdout() { 4219e8d8bef9SDimitry Andric KMP_ASSERT(!f); 4220e8d8bef9SDimitry Andric f = stdout; 4221e8d8bef9SDimitry Andric } 4222e8d8bef9SDimitry Andric /// Set the FILE* object to stderr and output there 4223e8d8bef9SDimitry Andric /// No open call should happen before this call. 4224e8d8bef9SDimitry Andric void set_stderr() { 4225e8d8bef9SDimitry Andric KMP_ASSERT(!f); 4226e8d8bef9SDimitry Andric f = stderr; 4227e8d8bef9SDimitry Andric } 4228e8d8bef9SDimitry Andric operator bool() { return bool(f); } 4229e8d8bef9SDimitry Andric operator FILE *() { return f; } 4230e8d8bef9SDimitry Andric }; 4231e8d8bef9SDimitry Andric 4232e8d8bef9SDimitry Andric template <typename SourceType, typename TargetType, 4233e8d8bef9SDimitry Andric bool isSourceSmaller = (sizeof(SourceType) < sizeof(TargetType)), 4234e8d8bef9SDimitry Andric bool isSourceEqual = (sizeof(SourceType) == sizeof(TargetType)), 4235e8d8bef9SDimitry Andric bool isSourceSigned = std::is_signed<SourceType>::value, 4236e8d8bef9SDimitry Andric bool isTargetSigned = std::is_signed<TargetType>::value> 4237e8d8bef9SDimitry Andric struct kmp_convert {}; 4238e8d8bef9SDimitry Andric 4239e8d8bef9SDimitry Andric // Both types are signed; Source smaller 4240e8d8bef9SDimitry Andric template <typename SourceType, typename TargetType> 4241e8d8bef9SDimitry Andric struct kmp_convert<SourceType, TargetType, true, false, true, true> { 4242e8d8bef9SDimitry Andric static TargetType to(SourceType src) { return (TargetType)src; } 4243e8d8bef9SDimitry Andric }; 4244e8d8bef9SDimitry Andric // Source equal 4245e8d8bef9SDimitry Andric template <typename SourceType, typename TargetType> 4246e8d8bef9SDimitry Andric struct kmp_convert<SourceType, TargetType, false, true, true, true> { 4247e8d8bef9SDimitry Andric static TargetType to(SourceType src) { return src; } 4248e8d8bef9SDimitry Andric }; 4249e8d8bef9SDimitry Andric // Source bigger 4250e8d8bef9SDimitry Andric template <typename SourceType, typename TargetType> 4251e8d8bef9SDimitry Andric struct kmp_convert<SourceType, TargetType, false, false, true, true> { 4252e8d8bef9SDimitry Andric static TargetType to(SourceType src) { 4253e8d8bef9SDimitry Andric KMP_ASSERT(src <= static_cast<SourceType>( 4254e8d8bef9SDimitry Andric (std::numeric_limits<TargetType>::max)())); 4255e8d8bef9SDimitry Andric KMP_ASSERT(src >= static_cast<SourceType>( 4256e8d8bef9SDimitry Andric (std::numeric_limits<TargetType>::min)())); 4257e8d8bef9SDimitry Andric return (TargetType)src; 4258e8d8bef9SDimitry Andric } 4259e8d8bef9SDimitry Andric }; 4260e8d8bef9SDimitry Andric 4261e8d8bef9SDimitry Andric // Source signed, Target unsigned 4262e8d8bef9SDimitry Andric // Source smaller 4263e8d8bef9SDimitry Andric template <typename SourceType, typename TargetType> 4264e8d8bef9SDimitry Andric struct kmp_convert<SourceType, TargetType, true, false, true, false> { 4265e8d8bef9SDimitry Andric static TargetType to(SourceType src) { 4266e8d8bef9SDimitry Andric KMP_ASSERT(src >= 0); 4267e8d8bef9SDimitry Andric return (TargetType)src; 4268e8d8bef9SDimitry Andric } 4269e8d8bef9SDimitry Andric }; 4270e8d8bef9SDimitry Andric // Source equal 4271e8d8bef9SDimitry Andric template <typename SourceType, typename TargetType> 4272e8d8bef9SDimitry Andric struct kmp_convert<SourceType, TargetType, false, true, true, false> { 4273e8d8bef9SDimitry Andric static TargetType to(SourceType src) { 4274e8d8bef9SDimitry Andric KMP_ASSERT(src >= 0); 4275e8d8bef9SDimitry Andric return (TargetType)src; 4276e8d8bef9SDimitry Andric } 4277e8d8bef9SDimitry Andric }; 4278e8d8bef9SDimitry Andric // Source bigger 4279e8d8bef9SDimitry Andric template <typename SourceType, typename TargetType> 4280e8d8bef9SDimitry Andric struct kmp_convert<SourceType, TargetType, false, false, true, false> { 4281e8d8bef9SDimitry Andric static TargetType to(SourceType src) { 4282e8d8bef9SDimitry Andric KMP_ASSERT(src >= 0); 4283e8d8bef9SDimitry Andric KMP_ASSERT(src <= static_cast<SourceType>( 4284e8d8bef9SDimitry Andric (std::numeric_limits<TargetType>::max)())); 4285e8d8bef9SDimitry Andric return (TargetType)src; 4286e8d8bef9SDimitry Andric } 4287e8d8bef9SDimitry Andric }; 4288e8d8bef9SDimitry Andric 4289e8d8bef9SDimitry Andric // Source unsigned, Target signed 4290e8d8bef9SDimitry Andric // Source smaller 4291e8d8bef9SDimitry Andric template <typename SourceType, typename TargetType> 4292e8d8bef9SDimitry Andric struct kmp_convert<SourceType, TargetType, true, false, false, true> { 4293e8d8bef9SDimitry Andric static TargetType to(SourceType src) { return (TargetType)src; } 4294e8d8bef9SDimitry Andric }; 4295e8d8bef9SDimitry Andric // Source equal 4296e8d8bef9SDimitry Andric template <typename SourceType, typename TargetType> 4297e8d8bef9SDimitry Andric struct kmp_convert<SourceType, TargetType, false, true, false, true> { 4298e8d8bef9SDimitry Andric static TargetType to(SourceType src) { 4299e8d8bef9SDimitry Andric KMP_ASSERT(src <= static_cast<SourceType>( 4300e8d8bef9SDimitry Andric (std::numeric_limits<TargetType>::max)())); 4301e8d8bef9SDimitry Andric return (TargetType)src; 4302e8d8bef9SDimitry Andric } 4303e8d8bef9SDimitry Andric }; 4304e8d8bef9SDimitry Andric // Source bigger 4305e8d8bef9SDimitry Andric template <typename SourceType, typename TargetType> 4306e8d8bef9SDimitry Andric struct kmp_convert<SourceType, TargetType, false, false, false, true> { 4307e8d8bef9SDimitry Andric static TargetType to(SourceType src) { 4308e8d8bef9SDimitry Andric KMP_ASSERT(src <= static_cast<SourceType>( 4309e8d8bef9SDimitry Andric (std::numeric_limits<TargetType>::max)())); 4310e8d8bef9SDimitry Andric return (TargetType)src; 4311e8d8bef9SDimitry Andric } 4312e8d8bef9SDimitry Andric }; 4313e8d8bef9SDimitry Andric 4314e8d8bef9SDimitry Andric // Source unsigned, Target unsigned 4315e8d8bef9SDimitry Andric // Source smaller 4316e8d8bef9SDimitry Andric template <typename SourceType, typename TargetType> 4317e8d8bef9SDimitry Andric struct kmp_convert<SourceType, TargetType, true, false, false, false> { 4318e8d8bef9SDimitry Andric static TargetType to(SourceType src) { return (TargetType)src; } 4319e8d8bef9SDimitry Andric }; 4320e8d8bef9SDimitry Andric // Source equal 4321e8d8bef9SDimitry Andric template <typename SourceType, typename TargetType> 4322e8d8bef9SDimitry Andric struct kmp_convert<SourceType, TargetType, false, true, false, false> { 4323e8d8bef9SDimitry Andric static TargetType to(SourceType src) { return src; } 4324e8d8bef9SDimitry Andric }; 4325e8d8bef9SDimitry Andric // Source bigger 4326e8d8bef9SDimitry Andric template <typename SourceType, typename TargetType> 4327e8d8bef9SDimitry Andric struct kmp_convert<SourceType, TargetType, false, false, false, false> { 4328e8d8bef9SDimitry Andric static TargetType to(SourceType src) { 4329e8d8bef9SDimitry Andric KMP_ASSERT(src <= static_cast<SourceType>( 4330e8d8bef9SDimitry Andric (std::numeric_limits<TargetType>::max)())); 4331e8d8bef9SDimitry Andric return (TargetType)src; 4332e8d8bef9SDimitry Andric } 4333e8d8bef9SDimitry Andric }; 4334e8d8bef9SDimitry Andric 4335e8d8bef9SDimitry Andric template <typename T1, typename T2> 4336e8d8bef9SDimitry Andric static inline void __kmp_type_convert(T1 src, T2 *dest) { 4337e8d8bef9SDimitry Andric *dest = kmp_convert<T1, T2>::to(src); 4338e8d8bef9SDimitry Andric } 4339e8d8bef9SDimitry Andric 43400b57cec5SDimitry Andric #endif /* KMP_H */ 4341