1/*
2 * kmp_os.h -- KPTS runtime header file.
3 */
4
5//===----------------------------------------------------------------------===//
6//
7// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
8// See https://llvm.org/LICENSE.txt for license information.
9// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef KMP_OS_H
14#define KMP_OS_H
15
16#include "kmp_config.h"
17#include <atomic>
18#include <stdarg.h>
19#include <stdlib.h>
20
21#define KMP_FTN_PLAIN 1
22#define KMP_FTN_APPEND 2
23#define KMP_FTN_UPPER 3
24/*
25#define KMP_FTN_PREPEND 4
26#define KMP_FTN_UAPPEND 5
27*/
28
29#define KMP_PTR_SKIP (sizeof(void *))
30
31/* -------------------------- Compiler variations ------------------------ */
32
33#define KMP_OFF 0
34#define KMP_ON 1
35
36#define KMP_MEM_CONS_VOLATILE 0
37#define KMP_MEM_CONS_FENCE 1
38
39#ifndef KMP_MEM_CONS_MODEL
40#define KMP_MEM_CONS_MODEL KMP_MEM_CONS_VOLATILE
41#endif
42
43#ifndef __has_cpp_attribute
44#define __has_cpp_attribute(x) 0
45#endif
46
47#ifndef __has_attribute
48#define __has_attribute(x) 0
49#endif
50
51/* ------------------------- Compiler recognition ---------------------- */
52#define KMP_COMPILER_ICC 0
53#define KMP_COMPILER_GCC 0
54#define KMP_COMPILER_CLANG 0
55#define KMP_COMPILER_MSVC 0
56
57#if defined(__INTEL_COMPILER)
58#undef KMP_COMPILER_ICC
59#define KMP_COMPILER_ICC 1
60#elif defined(__clang__)
61#undef KMP_COMPILER_CLANG
62#define KMP_COMPILER_CLANG 1
63#elif defined(__GNUC__)
64#undef KMP_COMPILER_GCC
65#define KMP_COMPILER_GCC 1
66#elif defined(_MSC_VER)
67#undef KMP_COMPILER_MSVC
68#define KMP_COMPILER_MSVC 1
69#else
70#error Unknown compiler
71#endif
72
73#if (KMP_OS_LINUX || KMP_OS_WINDOWS || KMP_OS_FREEBSD) && !KMP_OS_CNK
74#define KMP_AFFINITY_SUPPORTED 1
75#if KMP_OS_WINDOWS && KMP_ARCH_X86_64
76#define KMP_GROUP_AFFINITY 1
77#else
78#define KMP_GROUP_AFFINITY 0
79#endif
80#else
81#define KMP_AFFINITY_SUPPORTED 0
82#define KMP_GROUP_AFFINITY 0
83#endif
84
85/* Check for quad-precision extension. */
86#define KMP_HAVE_QUAD 0
87#if KMP_ARCH_X86 || KMP_ARCH_X86_64
88#if KMP_COMPILER_ICC
89/* _Quad is already defined for icc */
90#undef KMP_HAVE_QUAD
91#define KMP_HAVE_QUAD 1
92#elif KMP_COMPILER_CLANG
93/* Clang doesn't support a software-implemented
94   128-bit extended precision type yet */
95typedef long double _Quad;
96#elif KMP_COMPILER_GCC
97/* GCC on NetBSD lacks __multc3/__divtc3 builtins needed for quad */
98#if !KMP_OS_NETBSD
99typedef __float128 _Quad;
100#undef KMP_HAVE_QUAD
101#define KMP_HAVE_QUAD 1
102#endif
103#elif KMP_COMPILER_MSVC
104typedef long double _Quad;
105#endif
106#else
107#if __LDBL_MAX_EXP__ >= 16384 && KMP_COMPILER_GCC
108typedef long double _Quad;
109#undef KMP_HAVE_QUAD
110#define KMP_HAVE_QUAD 1
111#endif
112#endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
113
114#define KMP_USE_X87CONTROL 0
115#if KMP_OS_WINDOWS
116#define KMP_END_OF_LINE "\r\n"
117typedef char kmp_int8;
118typedef unsigned char kmp_uint8;
119typedef short kmp_int16;
120typedef unsigned short kmp_uint16;
121typedef int kmp_int32;
122typedef unsigned int kmp_uint32;
123#define KMP_INT32_SPEC "d"
124#define KMP_UINT32_SPEC "u"
125#ifndef KMP_STRUCT64
126typedef __int64 kmp_int64;
127typedef unsigned __int64 kmp_uint64;
128#define KMP_INT64_SPEC "I64d"
129#define KMP_UINT64_SPEC "I64u"
130#else
131struct kmp_struct64 {
132  kmp_int32 a, b;
133};
134typedef struct kmp_struct64 kmp_int64;
135typedef struct kmp_struct64 kmp_uint64;
136/* Not sure what to use for KMP_[U]INT64_SPEC here */
137#endif
138#if KMP_ARCH_X86 && KMP_MSVC_COMPAT
139#undef KMP_USE_X87CONTROL
140#define KMP_USE_X87CONTROL 1
141#endif
142#if KMP_ARCH_X86_64
143#define KMP_INTPTR 1
144typedef __int64 kmp_intptr_t;
145typedef unsigned __int64 kmp_uintptr_t;
146#define KMP_INTPTR_SPEC "I64d"
147#define KMP_UINTPTR_SPEC "I64u"
148#endif
149#endif /* KMP_OS_WINDOWS */
150
151#if KMP_OS_UNIX
152#define KMP_END_OF_LINE "\n"
153typedef char kmp_int8;
154typedef unsigned char kmp_uint8;
155typedef short kmp_int16;
156typedef unsigned short kmp_uint16;
157typedef int kmp_int32;
158typedef unsigned int kmp_uint32;
159typedef long long kmp_int64;
160typedef unsigned long long kmp_uint64;
161#define KMP_INT32_SPEC "d"
162#define KMP_UINT32_SPEC "u"
163#define KMP_INT64_SPEC "lld"
164#define KMP_UINT64_SPEC "llu"
165#endif /* KMP_OS_UNIX */
166
167#if KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_MIPS
168#define KMP_SIZE_T_SPEC KMP_UINT32_SPEC
169#elif KMP_ARCH_X86_64 || KMP_ARCH_PPC64 || KMP_ARCH_AARCH64 ||                 \
170    KMP_ARCH_MIPS64 || KMP_ARCH_RISCV64
171#define KMP_SIZE_T_SPEC KMP_UINT64_SPEC
172#else
173#error "Can't determine size_t printf format specifier."
174#endif
175
176#if KMP_ARCH_X86
177#define KMP_SIZE_T_MAX (0xFFFFFFFF)
178#else
179#define KMP_SIZE_T_MAX (0xFFFFFFFFFFFFFFFF)
180#endif
181
182typedef size_t kmp_size_t;
183typedef float kmp_real32;
184typedef double kmp_real64;
185
186#ifndef KMP_INTPTR
187#define KMP_INTPTR 1
188typedef long kmp_intptr_t;
189typedef unsigned long kmp_uintptr_t;
190#define KMP_INTPTR_SPEC "ld"
191#define KMP_UINTPTR_SPEC "lu"
192#endif
193
194#ifdef BUILD_I8
195typedef kmp_int64 kmp_int;
196typedef kmp_uint64 kmp_uint;
197#else
198typedef kmp_int32 kmp_int;
199typedef kmp_uint32 kmp_uint;
200#endif /* BUILD_I8 */
201#define KMP_INT_MAX ((kmp_int32)0x7FFFFFFF)
202#define KMP_INT_MIN ((kmp_int32)0x80000000)
203
204// stdarg handling
205#if (KMP_ARCH_ARM || KMP_ARCH_X86_64 || KMP_ARCH_AARCH64) &&                   \
206    (KMP_OS_FREEBSD || KMP_OS_LINUX)
207typedef va_list *kmp_va_list;
208#define kmp_va_deref(ap) (*(ap))
209#define kmp_va_addr_of(ap) (&(ap))
210#else
211typedef va_list kmp_va_list;
212#define kmp_va_deref(ap) (ap)
213#define kmp_va_addr_of(ap) (ap)
214#endif
215
216#ifdef __cplusplus
217// macros to cast out qualifiers and to re-interpret types
218#define CCAST(type, var) const_cast<type>(var)
219#define RCAST(type, var) reinterpret_cast<type>(var)
220//-------------------------------------------------------------------------
221// template for debug prints specification ( d, u, lld, llu ), and to obtain
222// signed/unsigned flavors of a type
223template <typename T> struct traits_t {};
224// int
225template <> struct traits_t<signed int> {
226  typedef signed int signed_t;
227  typedef unsigned int unsigned_t;
228  typedef double floating_t;
229  static char const *spec;
230  static const signed_t max_value = 0x7fffffff;
231  static const signed_t min_value = 0x80000000;
232  static const int type_size = sizeof(signed_t);
233};
234// unsigned int
235template <> struct traits_t<unsigned int> {
236  typedef signed int signed_t;
237  typedef unsigned int unsigned_t;
238  typedef double floating_t;
239  static char const *spec;
240  static const unsigned_t max_value = 0xffffffff;
241  static const unsigned_t min_value = 0x00000000;
242  static const int type_size = sizeof(unsigned_t);
243};
244// long
245template <> struct traits_t<signed long> {
246  typedef signed long signed_t;
247  typedef unsigned long unsigned_t;
248  typedef long double floating_t;
249  static char const *spec;
250  static const int type_size = sizeof(signed_t);
251};
252// long long
253template <> struct traits_t<signed long long> {
254  typedef signed long long signed_t;
255  typedef unsigned long long unsigned_t;
256  typedef long double floating_t;
257  static char const *spec;
258  static const signed_t max_value = 0x7fffffffffffffffLL;
259  static const signed_t min_value = 0x8000000000000000LL;
260  static const int type_size = sizeof(signed_t);
261};
262// unsigned long long
263template <> struct traits_t<unsigned long long> {
264  typedef signed long long signed_t;
265  typedef unsigned long long unsigned_t;
266  typedef long double floating_t;
267  static char const *spec;
268  static const unsigned_t max_value = 0xffffffffffffffffLL;
269  static const unsigned_t min_value = 0x0000000000000000LL;
270  static const int type_size = sizeof(unsigned_t);
271};
272//-------------------------------------------------------------------------
273#else
274#define CCAST(type, var) (type)(var)
275#define RCAST(type, var) (type)(var)
276#endif // __cplusplus
277
278#define KMP_EXPORT extern /* export declaration in guide libraries */
279
280#if __GNUC__ >= 4 && !defined(__MINGW32__)
281#define __forceinline __inline
282#endif
283
284#if KMP_OS_WINDOWS
285#include <windows.h>
286
287static inline int KMP_GET_PAGE_SIZE(void) {
288  SYSTEM_INFO si;
289  GetSystemInfo(&si);
290  return si.dwPageSize;
291}
292#else
293#define KMP_GET_PAGE_SIZE() getpagesize()
294#endif
295
296#define PAGE_ALIGNED(_addr)                                                    \
297  (!((size_t)_addr & (size_t)(KMP_GET_PAGE_SIZE() - 1)))
298#define ALIGN_TO_PAGE(x)                                                       \
299  (void *)(((size_t)(x)) & ~((size_t)(KMP_GET_PAGE_SIZE() - 1)))
300
301/* ---------- Support for cache alignment, padding, etc. ----------------*/
302
303#ifdef __cplusplus
304extern "C" {
305#endif // __cplusplus
306
307#define INTERNODE_CACHE_LINE 4096 /* for multi-node systems */
308
309/* Define the default size of the cache line */
310#ifndef CACHE_LINE
311#define CACHE_LINE 128 /* cache line size in bytes */
312#else
313#if (CACHE_LINE < 64) && !defined(KMP_OS_DARWIN)
314// 2006-02-13: This produces too many warnings on OS X*. Disable for now
315#warning CACHE_LINE is too small.
316#endif
317#endif /* CACHE_LINE */
318
319#define KMP_CACHE_PREFETCH(ADDR) /* nothing */
320
321// Define attribute that indicates that the fall through from the previous
322// case label is intentional and should not be diagnosed by a compiler
323//   Code from libcxx/include/__config
324// Use a function like macro to imply that it must be followed by a semicolon
325#if __cplusplus > 201402L && __has_cpp_attribute(fallthrough)
326#  define KMP_FALLTHROUGH() [[fallthrough]]
327#elif __has_cpp_attribute(clang::fallthrough)
328#  define KMP_FALLTHROUGH() [[clang::fallthrough]]
329#elif __has_attribute(fallthrough) || __GNUC__ >= 7
330#  define KMP_FALLTHROUGH() __attribute__((__fallthrough__))
331#else
332#  define KMP_FALLTHROUGH() ((void)0)
333#endif
334
335// Define attribute that indicates a function does not return
336#if __cplusplus >= 201103L
337#define KMP_NORETURN [[noreturn]]
338#elif KMP_OS_WINDOWS
339#define KMP_NORETURN __declspec(noreturn)
340#else
341#define KMP_NORETURN __attribute__((noreturn))
342#endif
343
344#if KMP_OS_WINDOWS && KMP_MSVC_COMPAT
345#define KMP_ALIGN(bytes) __declspec(align(bytes))
346#define KMP_THREAD_LOCAL __declspec(thread)
347#define KMP_ALIAS /* Nothing */
348#else
349#define KMP_ALIGN(bytes) __attribute__((aligned(bytes)))
350#define KMP_THREAD_LOCAL __thread
351#define KMP_ALIAS(alias_of) __attribute__((alias(alias_of)))
352#endif
353
354#if KMP_HAVE_WEAK_ATTRIBUTE && !KMP_DYNAMIC_LIB
355#define KMP_WEAK_ATTRIBUTE_EXTERNAL __attribute__((weak))
356#else
357#define KMP_WEAK_ATTRIBUTE_EXTERNAL /* Nothing */
358#endif
359
360#if KMP_HAVE_WEAK_ATTRIBUTE
361#define KMP_WEAK_ATTRIBUTE_INTERNAL __attribute__((weak))
362#else
363#define KMP_WEAK_ATTRIBUTE_INTERNAL /* Nothing */
364#endif
365
366// Define KMP_VERSION_SYMBOL and KMP_EXPAND_NAME
367#ifndef KMP_STR
368#define KMP_STR(x) _KMP_STR(x)
369#define _KMP_STR(x) #x
370#endif
371
372#ifdef KMP_USE_VERSION_SYMBOLS
373// If using versioned symbols, KMP_EXPAND_NAME prepends
374// __kmp_api_ to the real API name
375#define KMP_EXPAND_NAME(api_name) _KMP_EXPAND_NAME(api_name)
376#define _KMP_EXPAND_NAME(api_name) __kmp_api_##api_name
377#define KMP_VERSION_SYMBOL(api_name, ver_num, ver_str)                         \
378  _KMP_VERSION_SYMBOL(api_name, ver_num, ver_str, "VERSION")
379#define _KMP_VERSION_SYMBOL(api_name, ver_num, ver_str, default_ver)            \
380  __typeof__(__kmp_api_##api_name) __kmp_api_##api_name##_##ver_num##_alias     \
381      __attribute__((alias(KMP_STR(__kmp_api_##api_name))));                    \
382  __asm__(                                                                      \
383      ".symver " KMP_STR(__kmp_api_##api_name##_##ver_num##_alias) "," KMP_STR( \
384          api_name) "@" ver_str "\n\t");                                        \
385  __asm__(".symver " KMP_STR(__kmp_api_##api_name) "," KMP_STR(                 \
386      api_name) "@@" default_ver "\n\t")
387#else // KMP_USE_VERSION_SYMBOLS
388#define KMP_EXPAND_NAME(api_name) api_name
389#define KMP_VERSION_SYMBOL(api_name, ver_num, ver_str) /* Nothing */
390#endif // KMP_USE_VERSION_SYMBOLS
391
392/* Temporary note: if performance testing of this passes, we can remove
393   all references to KMP_DO_ALIGN and replace with KMP_ALIGN.  */
394#define KMP_DO_ALIGN(bytes) KMP_ALIGN(bytes)
395#define KMP_ALIGN_CACHE KMP_ALIGN(CACHE_LINE)
396#define KMP_ALIGN_CACHE_INTERNODE KMP_ALIGN(INTERNODE_CACHE_LINE)
397
398/* General purpose fence types for memory operations */
399enum kmp_mem_fence_type {
400  kmp_no_fence, /* No memory fence */
401  kmp_acquire_fence, /* Acquire (read) memory fence */
402  kmp_release_fence, /* Release (write) memory fence */
403  kmp_full_fence /* Full (read+write) memory fence */
404};
405
406// Synchronization primitives
407
408#if KMP_ASM_INTRINS && KMP_OS_WINDOWS
409
410#if KMP_MSVC_COMPAT && !KMP_COMPILER_CLANG
411#pragma intrinsic(InterlockedExchangeAdd)
412#pragma intrinsic(InterlockedCompareExchange)
413#pragma intrinsic(InterlockedExchange)
414#pragma intrinsic(InterlockedExchange64)
415#endif
416
417// Using InterlockedIncrement / InterlockedDecrement causes a library loading
418// ordering problem, so we use InterlockedExchangeAdd instead.
419#define KMP_TEST_THEN_INC32(p) InterlockedExchangeAdd((volatile long *)(p), 1)
420#define KMP_TEST_THEN_INC_ACQ32(p)                                             \
421  InterlockedExchangeAdd((volatile long *)(p), 1)
422#define KMP_TEST_THEN_ADD4_32(p) InterlockedExchangeAdd((volatile long *)(p), 4)
423#define KMP_TEST_THEN_ADD4_ACQ32(p)                                            \
424  InterlockedExchangeAdd((volatile long *)(p), 4)
425#define KMP_TEST_THEN_DEC32(p) InterlockedExchangeAdd((volatile long *)(p), -1)
426#define KMP_TEST_THEN_DEC_ACQ32(p)                                             \
427  InterlockedExchangeAdd((volatile long *)(p), -1)
428#define KMP_TEST_THEN_ADD32(p, v)                                              \
429  InterlockedExchangeAdd((volatile long *)(p), (v))
430
431#define KMP_COMPARE_AND_STORE_RET32(p, cv, sv)                                 \
432  InterlockedCompareExchange((volatile long *)(p), (long)(sv), (long)(cv))
433
434#define KMP_XCHG_FIXED32(p, v)                                                 \
435  InterlockedExchange((volatile long *)(p), (long)(v))
436#define KMP_XCHG_FIXED64(p, v)                                                 \
437  InterlockedExchange64((volatile kmp_int64 *)(p), (kmp_int64)(v))
438
439inline kmp_real32 KMP_XCHG_REAL32(volatile kmp_real32 *p, kmp_real32 v) {
440  kmp_int32 tmp = InterlockedExchange((volatile long *)p, *(long *)&v);
441  return *(kmp_real32 *)&tmp;
442}
443
444// Routines that we still need to implement in assembly.
445extern kmp_int8 __kmp_test_then_add8(volatile kmp_int8 *p, kmp_int8 v);
446extern kmp_int8 __kmp_test_then_or8(volatile kmp_int8 *p, kmp_int8 v);
447extern kmp_int8 __kmp_test_then_and8(volatile kmp_int8 *p, kmp_int8 v);
448extern kmp_int32 __kmp_test_then_add32(volatile kmp_int32 *p, kmp_int32 v);
449extern kmp_uint32 __kmp_test_then_or32(volatile kmp_uint32 *p, kmp_uint32 v);
450extern kmp_uint32 __kmp_test_then_and32(volatile kmp_uint32 *p, kmp_uint32 v);
451extern kmp_int64 __kmp_test_then_add64(volatile kmp_int64 *p, kmp_int64 v);
452extern kmp_uint64 __kmp_test_then_or64(volatile kmp_uint64 *p, kmp_uint64 v);
453extern kmp_uint64 __kmp_test_then_and64(volatile kmp_uint64 *p, kmp_uint64 v);
454
455extern kmp_int8 __kmp_compare_and_store8(volatile kmp_int8 *p, kmp_int8 cv,
456                                         kmp_int8 sv);
457extern kmp_int16 __kmp_compare_and_store16(volatile kmp_int16 *p, kmp_int16 cv,
458                                           kmp_int16 sv);
459extern kmp_int32 __kmp_compare_and_store32(volatile kmp_int32 *p, kmp_int32 cv,
460                                           kmp_int32 sv);
461extern kmp_int32 __kmp_compare_and_store64(volatile kmp_int64 *p, kmp_int64 cv,
462                                           kmp_int64 sv);
463extern kmp_int8 __kmp_compare_and_store_ret8(volatile kmp_int8 *p, kmp_int8 cv,
464                                             kmp_int8 sv);
465extern kmp_int16 __kmp_compare_and_store_ret16(volatile kmp_int16 *p,
466                                               kmp_int16 cv, kmp_int16 sv);
467extern kmp_int32 __kmp_compare_and_store_ret32(volatile kmp_int32 *p,
468                                               kmp_int32 cv, kmp_int32 sv);
469extern kmp_int64 __kmp_compare_and_store_ret64(volatile kmp_int64 *p,
470                                               kmp_int64 cv, kmp_int64 sv);
471
472extern kmp_int8 __kmp_xchg_fixed8(volatile kmp_int8 *p, kmp_int8 v);
473extern kmp_int16 __kmp_xchg_fixed16(volatile kmp_int16 *p, kmp_int16 v);
474extern kmp_int32 __kmp_xchg_fixed32(volatile kmp_int32 *p, kmp_int32 v);
475extern kmp_int64 __kmp_xchg_fixed64(volatile kmp_int64 *p, kmp_int64 v);
476extern kmp_real32 __kmp_xchg_real32(volatile kmp_real32 *p, kmp_real32 v);
477extern kmp_real64 __kmp_xchg_real64(volatile kmp_real64 *p, kmp_real64 v);
478
479//#define KMP_TEST_THEN_INC32(p) __kmp_test_then_add32((p), 1)
480//#define KMP_TEST_THEN_INC_ACQ32(p) __kmp_test_then_add32((p), 1)
481#define KMP_TEST_THEN_INC64(p) __kmp_test_then_add64((p), 1LL)
482#define KMP_TEST_THEN_INC_ACQ64(p) __kmp_test_then_add64((p), 1LL)
483//#define KMP_TEST_THEN_ADD4_32(p) __kmp_test_then_add32((p), 4)
484//#define KMP_TEST_THEN_ADD4_ACQ32(p) __kmp_test_then_add32((p), 4)
485#define KMP_TEST_THEN_ADD4_64(p) __kmp_test_then_add64((p), 4LL)
486#define KMP_TEST_THEN_ADD4_ACQ64(p) __kmp_test_then_add64((p), 4LL)
487//#define KMP_TEST_THEN_DEC32(p) __kmp_test_then_add32((p), -1)
488//#define KMP_TEST_THEN_DEC_ACQ32(p) __kmp_test_then_add32((p), -1)
489#define KMP_TEST_THEN_DEC64(p) __kmp_test_then_add64((p), -1LL)
490#define KMP_TEST_THEN_DEC_ACQ64(p) __kmp_test_then_add64((p), -1LL)
491//#define KMP_TEST_THEN_ADD32(p, v) __kmp_test_then_add32((p), (v))
492#define KMP_TEST_THEN_ADD8(p, v) __kmp_test_then_add8((p), (v))
493#define KMP_TEST_THEN_ADD64(p, v) __kmp_test_then_add64((p), (v))
494
495#define KMP_TEST_THEN_OR8(p, v) __kmp_test_then_or8((p), (v))
496#define KMP_TEST_THEN_AND8(p, v) __kmp_test_then_and8((p), (v))
497#define KMP_TEST_THEN_OR32(p, v) __kmp_test_then_or32((p), (v))
498#define KMP_TEST_THEN_AND32(p, v) __kmp_test_then_and32((p), (v))
499#define KMP_TEST_THEN_OR64(p, v) __kmp_test_then_or64((p), (v))
500#define KMP_TEST_THEN_AND64(p, v) __kmp_test_then_and64((p), (v))
501
502#define KMP_COMPARE_AND_STORE_ACQ8(p, cv, sv)                                  \
503  __kmp_compare_and_store8((p), (cv), (sv))
504#define KMP_COMPARE_AND_STORE_REL8(p, cv, sv)                                  \
505  __kmp_compare_and_store8((p), (cv), (sv))
506#define KMP_COMPARE_AND_STORE_ACQ16(p, cv, sv)                                 \
507  __kmp_compare_and_store16((p), (cv), (sv))
508#define KMP_COMPARE_AND_STORE_REL16(p, cv, sv)                                 \
509  __kmp_compare_and_store16((p), (cv), (sv))
510#define KMP_COMPARE_AND_STORE_ACQ32(p, cv, sv)                                 \
511  __kmp_compare_and_store32((volatile kmp_int32 *)(p), (kmp_int32)(cv),        \
512                            (kmp_int32)(sv))
513#define KMP_COMPARE_AND_STORE_REL32(p, cv, sv)                                 \
514  __kmp_compare_and_store32((volatile kmp_int32 *)(p), (kmp_int32)(cv),        \
515                            (kmp_int32)(sv))
516#define KMP_COMPARE_AND_STORE_ACQ64(p, cv, sv)                                 \
517  __kmp_compare_and_store64((volatile kmp_int64 *)(p), (kmp_int64)(cv),        \
518                            (kmp_int64)(sv))
519#define KMP_COMPARE_AND_STORE_REL64(p, cv, sv)                                 \
520  __kmp_compare_and_store64((volatile kmp_int64 *)(p), (kmp_int64)(cv),        \
521                            (kmp_int64)(sv))
522
523#if KMP_ARCH_X86
524#define KMP_COMPARE_AND_STORE_PTR(p, cv, sv)                                   \
525  __kmp_compare_and_store32((volatile kmp_int32 *)(p), (kmp_int32)(cv),        \
526                            (kmp_int32)(sv))
527#else /* 64 bit pointers */
528#define KMP_COMPARE_AND_STORE_PTR(p, cv, sv)                                   \
529  __kmp_compare_and_store64((volatile kmp_int64 *)(p), (kmp_int64)(cv),        \
530                            (kmp_int64)(sv))
531#endif /* KMP_ARCH_X86 */
532
533#define KMP_COMPARE_AND_STORE_RET8(p, cv, sv)                                  \
534  __kmp_compare_and_store_ret8((p), (cv), (sv))
535#define KMP_COMPARE_AND_STORE_RET16(p, cv, sv)                                 \
536  __kmp_compare_and_store_ret16((p), (cv), (sv))
537#define KMP_COMPARE_AND_STORE_RET64(p, cv, sv)                                 \
538  __kmp_compare_and_store_ret64((volatile kmp_int64 *)(p), (kmp_int64)(cv),    \
539                                (kmp_int64)(sv))
540
541#define KMP_XCHG_FIXED8(p, v)                                                  \
542  __kmp_xchg_fixed8((volatile kmp_int8 *)(p), (kmp_int8)(v));
543#define KMP_XCHG_FIXED16(p, v) __kmp_xchg_fixed16((p), (v));
544//#define KMP_XCHG_FIXED32(p, v) __kmp_xchg_fixed32((p), (v));
545//#define KMP_XCHG_FIXED64(p, v) __kmp_xchg_fixed64((p), (v));
546//#define KMP_XCHG_REAL32(p, v) __kmp_xchg_real32((p), (v));
547#define KMP_XCHG_REAL64(p, v) __kmp_xchg_real64((p), (v));
548
549#elif (KMP_ASM_INTRINS && KMP_OS_UNIX) || !(KMP_ARCH_X86 || KMP_ARCH_X86_64)
550
551/* cast p to correct type so that proper intrinsic will be used */
552#define KMP_TEST_THEN_INC32(p)                                                 \
553  __sync_fetch_and_add((volatile kmp_int32 *)(p), 1)
554#define KMP_TEST_THEN_INC_ACQ32(p)                                             \
555  __sync_fetch_and_add((volatile kmp_int32 *)(p), 1)
556#if KMP_ARCH_MIPS
557#define KMP_TEST_THEN_INC64(p)                                                 \
558  __atomic_fetch_add((volatile kmp_int64 *)(p), 1LL, __ATOMIC_SEQ_CST)
559#define KMP_TEST_THEN_INC_ACQ64(p)                                             \
560  __atomic_fetch_add((volatile kmp_int64 *)(p), 1LL, __ATOMIC_SEQ_CST)
561#else
562#define KMP_TEST_THEN_INC64(p)                                                 \
563  __sync_fetch_and_add((volatile kmp_int64 *)(p), 1LL)
564#define KMP_TEST_THEN_INC_ACQ64(p)                                             \
565  __sync_fetch_and_add((volatile kmp_int64 *)(p), 1LL)
566#endif
567#define KMP_TEST_THEN_ADD4_32(p)                                               \
568  __sync_fetch_and_add((volatile kmp_int32 *)(p), 4)
569#define KMP_TEST_THEN_ADD4_ACQ32(p)                                            \
570  __sync_fetch_and_add((volatile kmp_int32 *)(p), 4)
571#if KMP_ARCH_MIPS
572#define KMP_TEST_THEN_ADD4_64(p)                                               \
573  __atomic_fetch_add((volatile kmp_int64 *)(p), 4LL, __ATOMIC_SEQ_CST)
574#define KMP_TEST_THEN_ADD4_ACQ64(p)                                            \
575  __atomic_fetch_add((volatile kmp_int64 *)(p), 4LL, __ATOMIC_SEQ_CST)
576#define KMP_TEST_THEN_DEC64(p)                                                 \
577  __atomic_fetch_sub((volatile kmp_int64 *)(p), 1LL, __ATOMIC_SEQ_CST)
578#define KMP_TEST_THEN_DEC_ACQ64(p)                                             \
579  __atomic_fetch_sub((volatile kmp_int64 *)(p), 1LL, __ATOMIC_SEQ_CST)
580#else
581#define KMP_TEST_THEN_ADD4_64(p)                                               \
582  __sync_fetch_and_add((volatile kmp_int64 *)(p), 4LL)
583#define KMP_TEST_THEN_ADD4_ACQ64(p)                                            \
584  __sync_fetch_and_add((volatile kmp_int64 *)(p), 4LL)
585#define KMP_TEST_THEN_DEC64(p)                                                 \
586  __sync_fetch_and_sub((volatile kmp_int64 *)(p), 1LL)
587#define KMP_TEST_THEN_DEC_ACQ64(p)                                             \
588  __sync_fetch_and_sub((volatile kmp_int64 *)(p), 1LL)
589#endif
590#define KMP_TEST_THEN_DEC32(p)                                                 \
591  __sync_fetch_and_sub((volatile kmp_int32 *)(p), 1)
592#define KMP_TEST_THEN_DEC_ACQ32(p)                                             \
593  __sync_fetch_and_sub((volatile kmp_int32 *)(p), 1)
594#define KMP_TEST_THEN_ADD8(p, v)                                               \
595  __sync_fetch_and_add((volatile kmp_int8 *)(p), (kmp_int8)(v))
596#define KMP_TEST_THEN_ADD32(p, v)                                              \
597  __sync_fetch_and_add((volatile kmp_int32 *)(p), (kmp_int32)(v))
598#if KMP_ARCH_MIPS
599#define KMP_TEST_THEN_ADD64(p, v)                                              \
600  __atomic_fetch_add((volatile kmp_uint64 *)(p), (kmp_uint64)(v),              \
601                     __ATOMIC_SEQ_CST)
602#else
603#define KMP_TEST_THEN_ADD64(p, v)                                              \
604  __sync_fetch_and_add((volatile kmp_int64 *)(p), (kmp_int64)(v))
605#endif
606
607#define KMP_TEST_THEN_OR8(p, v)                                                \
608  __sync_fetch_and_or((volatile kmp_int8 *)(p), (kmp_int8)(v))
609#define KMP_TEST_THEN_AND8(p, v)                                               \
610  __sync_fetch_and_and((volatile kmp_int8 *)(p), (kmp_int8)(v))
611#define KMP_TEST_THEN_OR32(p, v)                                               \
612  __sync_fetch_and_or((volatile kmp_uint32 *)(p), (kmp_uint32)(v))
613#define KMP_TEST_THEN_AND32(p, v)                                              \
614  __sync_fetch_and_and((volatile kmp_uint32 *)(p), (kmp_uint32)(v))
615#if KMP_ARCH_MIPS
616#define KMP_TEST_THEN_OR64(p, v)                                               \
617  __atomic_fetch_or((volatile kmp_uint64 *)(p), (kmp_uint64)(v),               \
618                    __ATOMIC_SEQ_CST)
619#define KMP_TEST_THEN_AND64(p, v)                                              \
620  __atomic_fetch_and((volatile kmp_uint64 *)(p), (kmp_uint64)(v),              \
621                     __ATOMIC_SEQ_CST)
622#else
623#define KMP_TEST_THEN_OR64(p, v)                                               \
624  __sync_fetch_and_or((volatile kmp_uint64 *)(p), (kmp_uint64)(v))
625#define KMP_TEST_THEN_AND64(p, v)                                              \
626  __sync_fetch_and_and((volatile kmp_uint64 *)(p), (kmp_uint64)(v))
627#endif
628
629#define KMP_COMPARE_AND_STORE_ACQ8(p, cv, sv)                                  \
630  __sync_bool_compare_and_swap((volatile kmp_uint8 *)(p), (kmp_uint8)(cv),     \
631                               (kmp_uint8)(sv))
632#define KMP_COMPARE_AND_STORE_REL8(p, cv, sv)                                  \
633  __sync_bool_compare_and_swap((volatile kmp_uint8 *)(p), (kmp_uint8)(cv),     \
634                               (kmp_uint8)(sv))
635#define KMP_COMPARE_AND_STORE_ACQ16(p, cv, sv)                                 \
636  __sync_bool_compare_and_swap((volatile kmp_uint16 *)(p), (kmp_uint16)(cv),   \
637                               (kmp_uint16)(sv))
638#define KMP_COMPARE_AND_STORE_REL16(p, cv, sv)                                 \
639  __sync_bool_compare_and_swap((volatile kmp_uint16 *)(p), (kmp_uint16)(cv),   \
640                               (kmp_uint16)(sv))
641#define KMP_COMPARE_AND_STORE_ACQ32(p, cv, sv)                                 \
642  __sync_bool_compare_and_swap((volatile kmp_uint32 *)(p), (kmp_uint32)(cv),   \
643                               (kmp_uint32)(sv))
644#define KMP_COMPARE_AND_STORE_REL32(p, cv, sv)                                 \
645  __sync_bool_compare_and_swap((volatile kmp_uint32 *)(p), (kmp_uint32)(cv),   \
646                               (kmp_uint32)(sv))
647#define KMP_COMPARE_AND_STORE_PTR(p, cv, sv)                                   \
648  __sync_bool_compare_and_swap((void *volatile *)(p), (void *)(cv),            \
649                               (void *)(sv))
650
651#define KMP_COMPARE_AND_STORE_RET8(p, cv, sv)                                  \
652  __sync_val_compare_and_swap((volatile kmp_uint8 *)(p), (kmp_uint8)(cv),      \
653                              (kmp_uint8)(sv))
654#define KMP_COMPARE_AND_STORE_RET16(p, cv, sv)                                 \
655  __sync_val_compare_and_swap((volatile kmp_uint16 *)(p), (kmp_uint16)(cv),    \
656                              (kmp_uint16)(sv))
657#define KMP_COMPARE_AND_STORE_RET32(p, cv, sv)                                 \
658  __sync_val_compare_and_swap((volatile kmp_uint32 *)(p), (kmp_uint32)(cv),    \
659                              (kmp_uint32)(sv))
660#if KMP_ARCH_MIPS
661static inline bool mips_sync_bool_compare_and_swap(
662  volatile kmp_uint64 *p, kmp_uint64 cv, kmp_uint64 sv) {
663  return __atomic_compare_exchange(p, &cv, &sv, false, __ATOMIC_SEQ_CST,
664                                                       __ATOMIC_SEQ_CST);
665}
666static inline bool mips_sync_val_compare_and_swap(
667  volatile kmp_uint64 *p, kmp_uint64 cv, kmp_uint64 sv) {
668  __atomic_compare_exchange(p, &cv, &sv, false, __ATOMIC_SEQ_CST,
669                                                __ATOMIC_SEQ_CST);
670  return cv;
671}
672#define KMP_COMPARE_AND_STORE_ACQ64(p, cv, sv)                                 \
673  mips_sync_bool_compare_and_swap((volatile kmp_uint64 *)(p), (kmp_uint64)(cv),\
674                               (kmp_uint64)(sv))
675#define KMP_COMPARE_AND_STORE_REL64(p, cv, sv)                                 \
676  mips_sync_bool_compare_and_swap((volatile kmp_uint64 *)(p), (kmp_uint64)(cv),\
677                               (kmp_uint64)(sv))
678#define KMP_COMPARE_AND_STORE_RET64(p, cv, sv)                                 \
679  mips_sync_val_compare_and_swap((volatile kmp_uint64 *)(p), (kmp_uint64)(cv), \
680                              (kmp_uint64)(sv))
681#else
682#define KMP_COMPARE_AND_STORE_ACQ64(p, cv, sv)                                 \
683  __sync_bool_compare_and_swap((volatile kmp_uint64 *)(p), (kmp_uint64)(cv),   \
684                               (kmp_uint64)(sv))
685#define KMP_COMPARE_AND_STORE_REL64(p, cv, sv)                                 \
686  __sync_bool_compare_and_swap((volatile kmp_uint64 *)(p), (kmp_uint64)(cv),   \
687                               (kmp_uint64)(sv))
688#define KMP_COMPARE_AND_STORE_RET64(p, cv, sv)                                 \
689  __sync_val_compare_and_swap((volatile kmp_uint64 *)(p), (kmp_uint64)(cv),    \
690                              (kmp_uint64)(sv))
691#endif
692
693#define KMP_XCHG_FIXED8(p, v)                                                  \
694  __sync_lock_test_and_set((volatile kmp_uint8 *)(p), (kmp_uint8)(v))
695#define KMP_XCHG_FIXED16(p, v)                                                 \
696  __sync_lock_test_and_set((volatile kmp_uint16 *)(p), (kmp_uint16)(v))
697#define KMP_XCHG_FIXED32(p, v)                                                 \
698  __sync_lock_test_and_set((volatile kmp_uint32 *)(p), (kmp_uint32)(v))
699#define KMP_XCHG_FIXED64(p, v)                                                 \
700  __sync_lock_test_and_set((volatile kmp_uint64 *)(p), (kmp_uint64)(v))
701
702inline kmp_real32 KMP_XCHG_REAL32(volatile kmp_real32 *p, kmp_real32 v) {
703  kmp_int32 tmp =
704      __sync_lock_test_and_set((volatile kmp_uint32 *)(p), *(kmp_uint32 *)&v);
705  return *(kmp_real32 *)&tmp;
706}
707
708inline kmp_real64 KMP_XCHG_REAL64(volatile kmp_real64 *p, kmp_real64 v) {
709  kmp_int64 tmp =
710      __sync_lock_test_and_set((volatile kmp_uint64 *)(p), *(kmp_uint64 *)&v);
711  return *(kmp_real64 *)&tmp;
712}
713
714#else
715
716extern kmp_int8 __kmp_test_then_add8(volatile kmp_int8 *p, kmp_int8 v);
717extern kmp_int8 __kmp_test_then_or8(volatile kmp_int8 *p, kmp_int8 v);
718extern kmp_int8 __kmp_test_then_and8(volatile kmp_int8 *p, kmp_int8 v);
719extern kmp_int32 __kmp_test_then_add32(volatile kmp_int32 *p, kmp_int32 v);
720extern kmp_uint32 __kmp_test_then_or32(volatile kmp_uint32 *p, kmp_uint32 v);
721extern kmp_uint32 __kmp_test_then_and32(volatile kmp_uint32 *p, kmp_uint32 v);
722extern kmp_int64 __kmp_test_then_add64(volatile kmp_int64 *p, kmp_int64 v);
723extern kmp_uint64 __kmp_test_then_or64(volatile kmp_uint64 *p, kmp_uint64 v);
724extern kmp_uint64 __kmp_test_then_and64(volatile kmp_uint64 *p, kmp_uint64 v);
725
726extern kmp_int8 __kmp_compare_and_store8(volatile kmp_int8 *p, kmp_int8 cv,
727                                         kmp_int8 sv);
728extern kmp_int16 __kmp_compare_and_store16(volatile kmp_int16 *p, kmp_int16 cv,
729                                           kmp_int16 sv);
730extern kmp_int32 __kmp_compare_and_store32(volatile kmp_int32 *p, kmp_int32 cv,
731                                           kmp_int32 sv);
732extern kmp_int32 __kmp_compare_and_store64(volatile kmp_int64 *p, kmp_int64 cv,
733                                           kmp_int64 sv);
734extern kmp_int8 __kmp_compare_and_store_ret8(volatile kmp_int8 *p, kmp_int8 cv,
735                                             kmp_int8 sv);
736extern kmp_int16 __kmp_compare_and_store_ret16(volatile kmp_int16 *p,
737                                               kmp_int16 cv, kmp_int16 sv);
738extern kmp_int32 __kmp_compare_and_store_ret32(volatile kmp_int32 *p,
739                                               kmp_int32 cv, kmp_int32 sv);
740extern kmp_int64 __kmp_compare_and_store_ret64(volatile kmp_int64 *p,
741                                               kmp_int64 cv, kmp_int64 sv);
742
743extern kmp_int8 __kmp_xchg_fixed8(volatile kmp_int8 *p, kmp_int8 v);
744extern kmp_int16 __kmp_xchg_fixed16(volatile kmp_int16 *p, kmp_int16 v);
745extern kmp_int32 __kmp_xchg_fixed32(volatile kmp_int32 *p, kmp_int32 v);
746extern kmp_int64 __kmp_xchg_fixed64(volatile kmp_int64 *p, kmp_int64 v);
747extern kmp_real32 __kmp_xchg_real32(volatile kmp_real32 *p, kmp_real32 v);
748extern kmp_real64 __kmp_xchg_real64(volatile kmp_real64 *p, kmp_real64 v);
749
750#define KMP_TEST_THEN_INC32(p)                                                 \
751  __kmp_test_then_add32((volatile kmp_int32 *)(p), 1)
752#define KMP_TEST_THEN_INC_ACQ32(p)                                             \
753  __kmp_test_then_add32((volatile kmp_int32 *)(p), 1)
754#define KMP_TEST_THEN_INC64(p)                                                 \
755  __kmp_test_then_add64((volatile kmp_int64 *)(p), 1LL)
756#define KMP_TEST_THEN_INC_ACQ64(p)                                             \
757  __kmp_test_then_add64((volatile kmp_int64 *)(p), 1LL)
758#define KMP_TEST_THEN_ADD4_32(p)                                               \
759  __kmp_test_then_add32((volatile kmp_int32 *)(p), 4)
760#define KMP_TEST_THEN_ADD4_ACQ32(p)                                            \
761  __kmp_test_then_add32((volatile kmp_int32 *)(p), 4)
762#define KMP_TEST_THEN_ADD4_64(p)                                               \
763  __kmp_test_then_add64((volatile kmp_int64 *)(p), 4LL)
764#define KMP_TEST_THEN_ADD4_ACQ64(p)                                            \
765  __kmp_test_then_add64((volatile kmp_int64 *)(p), 4LL)
766#define KMP_TEST_THEN_DEC32(p)                                                 \
767  __kmp_test_then_add32((volatile kmp_int32 *)(p), -1)
768#define KMP_TEST_THEN_DEC_ACQ32(p)                                             \
769  __kmp_test_then_add32((volatile kmp_int32 *)(p), -1)
770#define KMP_TEST_THEN_DEC64(p)                                                 \
771  __kmp_test_then_add64((volatile kmp_int64 *)(p), -1LL)
772#define KMP_TEST_THEN_DEC_ACQ64(p)                                             \
773  __kmp_test_then_add64((volatile kmp_int64 *)(p), -1LL)
774#define KMP_TEST_THEN_ADD8(p, v)                                               \
775  __kmp_test_then_add8((volatile kmp_int8 *)(p), (kmp_int8)(v))
776#define KMP_TEST_THEN_ADD32(p, v)                                              \
777  __kmp_test_then_add32((volatile kmp_int32 *)(p), (kmp_int32)(v))
778#define KMP_TEST_THEN_ADD64(p, v)                                              \
779  __kmp_test_then_add64((volatile kmp_int64 *)(p), (kmp_int64)(v))
780
781#define KMP_TEST_THEN_OR8(p, v)                                                \
782  __kmp_test_then_or8((volatile kmp_int8 *)(p), (kmp_int8)(v))
783#define KMP_TEST_THEN_AND8(p, v)                                               \
784  __kmp_test_then_and8((volatile kmp_int8 *)(p), (kmp_int8)(v))
785#define KMP_TEST_THEN_OR32(p, v)                                               \
786  __kmp_test_then_or32((volatile kmp_uint32 *)(p), (kmp_uint32)(v))
787#define KMP_TEST_THEN_AND32(p, v)                                              \
788  __kmp_test_then_and32((volatile kmp_uint32 *)(p), (kmp_uint32)(v))
789#define KMP_TEST_THEN_OR64(p, v)                                               \
790  __kmp_test_then_or64((volatile kmp_uint64 *)(p), (kmp_uint64)(v))
791#define KMP_TEST_THEN_AND64(p, v)                                              \
792  __kmp_test_then_and64((volatile kmp_uint64 *)(p), (kmp_uint64)(v))
793
794#define KMP_COMPARE_AND_STORE_ACQ8(p, cv, sv)                                  \
795  __kmp_compare_and_store8((volatile kmp_int8 *)(p), (kmp_int8)(cv),           \
796                           (kmp_int8)(sv))
797#define KMP_COMPARE_AND_STORE_REL8(p, cv, sv)                                  \
798  __kmp_compare_and_store8((volatile kmp_int8 *)(p), (kmp_int8)(cv),           \
799                           (kmp_int8)(sv))
800#define KMP_COMPARE_AND_STORE_ACQ16(p, cv, sv)                                 \
801  __kmp_compare_and_store16((volatile kmp_int16 *)(p), (kmp_int16)(cv),        \
802                            (kmp_int16)(sv))
803#define KMP_COMPARE_AND_STORE_REL16(p, cv, sv)                                 \
804  __kmp_compare_and_store16((volatile kmp_int16 *)(p), (kmp_int16)(cv),        \
805                            (kmp_int16)(sv))
806#define KMP_COMPARE_AND_STORE_ACQ32(p, cv, sv)                                 \
807  __kmp_compare_and_store32((volatile kmp_int32 *)(p), (kmp_int32)(cv),        \
808                            (kmp_int32)(sv))
809#define KMP_COMPARE_AND_STORE_REL32(p, cv, sv)                                 \
810  __kmp_compare_and_store32((volatile kmp_int32 *)(p), (kmp_int32)(cv),        \
811                            (kmp_int32)(sv))
812#define KMP_COMPARE_AND_STORE_ACQ64(p, cv, sv)                                 \
813  __kmp_compare_and_store64((volatile kmp_int64 *)(p), (kmp_int64)(cv),        \
814                            (kmp_int64)(sv))
815#define KMP_COMPARE_AND_STORE_REL64(p, cv, sv)                                 \
816  __kmp_compare_and_store64((volatile kmp_int64 *)(p), (kmp_int64)(cv),        \
817                            (kmp_int64)(sv))
818
819#if KMP_ARCH_X86
820#define KMP_COMPARE_AND_STORE_PTR(p, cv, sv)                                   \
821  __kmp_compare_and_store32((volatile kmp_int32 *)(p), (kmp_int32)(cv),        \
822                            (kmp_int32)(sv))
823#else /* 64 bit pointers */
824#define KMP_COMPARE_AND_STORE_PTR(p, cv, sv)                                   \
825  __kmp_compare_and_store64((volatile kmp_int64 *)(p), (kmp_int64)(cv),        \
826                            (kmp_int64)(sv))
827#endif /* KMP_ARCH_X86 */
828
829#define KMP_COMPARE_AND_STORE_RET8(p, cv, sv)                                  \
830  __kmp_compare_and_store_ret8((p), (cv), (sv))
831#define KMP_COMPARE_AND_STORE_RET16(p, cv, sv)                                 \
832  __kmp_compare_and_store_ret16((p), (cv), (sv))
833#define KMP_COMPARE_AND_STORE_RET32(p, cv, sv)                                 \
834  __kmp_compare_and_store_ret32((volatile kmp_int32 *)(p), (kmp_int32)(cv),    \
835                                (kmp_int32)(sv))
836#define KMP_COMPARE_AND_STORE_RET64(p, cv, sv)                                 \
837  __kmp_compare_and_store_ret64((volatile kmp_int64 *)(p), (kmp_int64)(cv),    \
838                                (kmp_int64)(sv))
839
840#define KMP_XCHG_FIXED8(p, v)                                                  \
841  __kmp_xchg_fixed8((volatile kmp_int8 *)(p), (kmp_int8)(v));
842#define KMP_XCHG_FIXED16(p, v) __kmp_xchg_fixed16((p), (v));
843#define KMP_XCHG_FIXED32(p, v) __kmp_xchg_fixed32((p), (v));
844#define KMP_XCHG_FIXED64(p, v) __kmp_xchg_fixed64((p), (v));
845#define KMP_XCHG_REAL32(p, v) __kmp_xchg_real32((p), (v));
846#define KMP_XCHG_REAL64(p, v) __kmp_xchg_real64((p), (v));
847
848#endif /* KMP_ASM_INTRINS */
849
850/* ------------- relaxed consistency memory model stuff ------------------ */
851
852#if KMP_OS_WINDOWS
853#ifdef __ABSOFT_WIN
854#define KMP_MB() asm("nop")
855#define KMP_IMB() asm("nop")
856#else
857#define KMP_MB() /* _asm{ nop } */
858#define KMP_IMB() /* _asm{ nop } */
859#endif
860#endif /* KMP_OS_WINDOWS */
861
862#if KMP_ARCH_PPC64 || KMP_ARCH_ARM || KMP_ARCH_AARCH64 || KMP_ARCH_MIPS ||     \
863    KMP_ARCH_MIPS64 || KMP_ARCH_RISCV64
864#define KMP_MB() __sync_synchronize()
865#endif
866
867#ifndef KMP_MB
868#define KMP_MB() /* nothing to do */
869#endif
870
871#ifndef KMP_IMB
872#define KMP_IMB() /* nothing to do */
873#endif
874
875#ifndef KMP_ST_REL32
876#define KMP_ST_REL32(A, D) (*(A) = (D))
877#endif
878
879#ifndef KMP_ST_REL64
880#define KMP_ST_REL64(A, D) (*(A) = (D))
881#endif
882
883#ifndef KMP_LD_ACQ32
884#define KMP_LD_ACQ32(A) (*(A))
885#endif
886
887#ifndef KMP_LD_ACQ64
888#define KMP_LD_ACQ64(A) (*(A))
889#endif
890
891/* ------------------------------------------------------------------------ */
892// FIXME - maybe this should this be
893//
894// #define TCR_4(a)    (*(volatile kmp_int32 *)(&a))
895// #define TCW_4(a,b)  (a) = (*(volatile kmp_int32 *)&(b))
896//
897// #define TCR_8(a)    (*(volatile kmp_int64 *)(a))
898// #define TCW_8(a,b)  (a) = (*(volatile kmp_int64 *)(&b))
899//
900// I'm fairly certain this is the correct thing to do, but I'm afraid
901// of performance regressions.
902
903#define TCR_1(a) (a)
904#define TCW_1(a, b) (a) = (b)
905#define TCR_4(a) (a)
906#define TCW_4(a, b) (a) = (b)
907#define TCI_4(a) (++(a))
908#define TCD_4(a) (--(a))
909#define TCR_8(a) (a)
910#define TCW_8(a, b) (a) = (b)
911#define TCI_8(a) (++(a))
912#define TCD_8(a) (--(a))
913#define TCR_SYNC_4(a) (a)
914#define TCW_SYNC_4(a, b) (a) = (b)
915#define TCX_SYNC_4(a, b, c)                                                    \
916  KMP_COMPARE_AND_STORE_REL32((volatile kmp_int32 *)(volatile void *)&(a),     \
917                              (kmp_int32)(b), (kmp_int32)(c))
918#define TCR_SYNC_8(a) (a)
919#define TCW_SYNC_8(a, b) (a) = (b)
920#define TCX_SYNC_8(a, b, c)                                                    \
921  KMP_COMPARE_AND_STORE_REL64((volatile kmp_int64 *)(volatile void *)&(a),     \
922                              (kmp_int64)(b), (kmp_int64)(c))
923
924#if KMP_ARCH_X86 || KMP_ARCH_MIPS
925// What about ARM?
926#define TCR_PTR(a) ((void *)TCR_4(a))
927#define TCW_PTR(a, b) TCW_4((a), (b))
928#define TCR_SYNC_PTR(a) ((void *)TCR_SYNC_4(a))
929#define TCW_SYNC_PTR(a, b) TCW_SYNC_4((a), (b))
930#define TCX_SYNC_PTR(a, b, c) ((void *)TCX_SYNC_4((a), (b), (c)))
931
932#else /* 64 bit pointers */
933
934#define TCR_PTR(a) ((void *)TCR_8(a))
935#define TCW_PTR(a, b) TCW_8((a), (b))
936#define TCR_SYNC_PTR(a) ((void *)TCR_SYNC_8(a))
937#define TCW_SYNC_PTR(a, b) TCW_SYNC_8((a), (b))
938#define TCX_SYNC_PTR(a, b, c) ((void *)TCX_SYNC_8((a), (b), (c)))
939
940#endif /* KMP_ARCH_X86 */
941
942/* If these FTN_{TRUE,FALSE} values change, may need to change several places
943   where they are used to check that language is Fortran, not C. */
944
945#ifndef FTN_TRUE
946#define FTN_TRUE TRUE
947#endif
948
949#ifndef FTN_FALSE
950#define FTN_FALSE FALSE
951#endif
952
953typedef void (*microtask_t)(int *gtid, int *npr, ...);
954
955#ifdef USE_VOLATILE_CAST
956#define VOLATILE_CAST(x) (volatile x)
957#else
958#define VOLATILE_CAST(x) (x)
959#endif
960
961#define KMP_WAIT __kmp_wait_4
962#define KMP_WAIT_PTR __kmp_wait_4_ptr
963#define KMP_EQ __kmp_eq_4
964#define KMP_NEQ __kmp_neq_4
965#define KMP_LT __kmp_lt_4
966#define KMP_GE __kmp_ge_4
967#define KMP_LE __kmp_le_4
968
969/* Workaround for Intel(R) 64 code gen bug when taking address of static array
970 * (Intel(R) 64 Tracker #138) */
971#if (KMP_ARCH_X86_64 || KMP_ARCH_PPC64) && KMP_OS_LINUX
972#define STATIC_EFI2_WORKAROUND
973#else
974#define STATIC_EFI2_WORKAROUND static
975#endif
976
977// Support of BGET usage
978#ifndef KMP_USE_BGET
979#define KMP_USE_BGET 1
980#endif
981
982// Switches for OSS builds
983#ifndef USE_CMPXCHG_FIX
984#define USE_CMPXCHG_FIX 1
985#endif
986
987// Enable dynamic user lock
988#define KMP_USE_DYNAMIC_LOCK 1
989
990// Enable Intel(R) Transactional Synchronization Extensions (Intel(R) TSX) if
991// dynamic user lock is turned on
992#if KMP_USE_DYNAMIC_LOCK
993// Visual studio can't handle the asm sections in this code
994#define KMP_USE_TSX (KMP_ARCH_X86 || KMP_ARCH_X86_64) && !KMP_COMPILER_MSVC
995#ifdef KMP_USE_ADAPTIVE_LOCKS
996#undef KMP_USE_ADAPTIVE_LOCKS
997#endif
998#define KMP_USE_ADAPTIVE_LOCKS KMP_USE_TSX
999#endif
1000
1001// Enable tick time conversion of ticks to seconds
1002#if KMP_STATS_ENABLED
1003#define KMP_HAVE_TICK_TIME                                                     \
1004  (KMP_OS_LINUX && (KMP_MIC || KMP_ARCH_X86 || KMP_ARCH_X86_64))
1005#endif
1006
1007// Warning levels
1008enum kmp_warnings_level {
1009  kmp_warnings_off = 0, /* No warnings */
1010  kmp_warnings_low, /* Minimal warnings (default) */
1011  kmp_warnings_explicit = 6, /* Explicitly set to ON - more warnings */
1012  kmp_warnings_verbose /* reserved */
1013};
1014
1015#ifdef __cplusplus
1016} // extern "C"
1017#endif // __cplusplus
1018
1019// Macros for C++11 atomic functions
1020#define KMP_ATOMIC_LD(p, order) (p)->load(std::memory_order_##order)
1021#define KMP_ATOMIC_OP(op, p, v, order) (p)->op(v, std::memory_order_##order)
1022
1023// For non-default load/store
1024#define KMP_ATOMIC_LD_ACQ(p) KMP_ATOMIC_LD(p, acquire)
1025#define KMP_ATOMIC_LD_RLX(p) KMP_ATOMIC_LD(p, relaxed)
1026#define KMP_ATOMIC_ST_REL(p, v) KMP_ATOMIC_OP(store, p, v, release)
1027#define KMP_ATOMIC_ST_RLX(p, v) KMP_ATOMIC_OP(store, p, v, relaxed)
1028
1029// For non-default fetch_<op>
1030#define KMP_ATOMIC_ADD(p, v) KMP_ATOMIC_OP(fetch_add, p, v, acq_rel)
1031#define KMP_ATOMIC_SUB(p, v) KMP_ATOMIC_OP(fetch_sub, p, v, acq_rel)
1032#define KMP_ATOMIC_AND(p, v) KMP_ATOMIC_OP(fetch_and, p, v, acq_rel)
1033#define KMP_ATOMIC_OR(p, v) KMP_ATOMIC_OP(fetch_or, p, v, acq_rel)
1034#define KMP_ATOMIC_INC(p) KMP_ATOMIC_OP(fetch_add, p, 1, acq_rel)
1035#define KMP_ATOMIC_DEC(p) KMP_ATOMIC_OP(fetch_sub, p, 1, acq_rel)
1036#define KMP_ATOMIC_ADD_RLX(p, v) KMP_ATOMIC_OP(fetch_add, p, v, relaxed)
1037#define KMP_ATOMIC_INC_RLX(p) KMP_ATOMIC_OP(fetch_add, p, 1, relaxed)
1038
1039// Callers of the following functions cannot see the side effect on "expected".
1040template <typename T>
1041bool __kmp_atomic_compare_store(std::atomic<T> *p, T expected, T desired) {
1042  return p->compare_exchange_strong(
1043      expected, desired, std::memory_order_acq_rel, std::memory_order_relaxed);
1044}
1045
1046template <typename T>
1047bool __kmp_atomic_compare_store_acq(std::atomic<T> *p, T expected, T desired) {
1048  return p->compare_exchange_strong(
1049      expected, desired, std::memory_order_acquire, std::memory_order_relaxed);
1050}
1051
1052template <typename T>
1053bool __kmp_atomic_compare_store_rel(std::atomic<T> *p, T expected, T desired) {
1054  return p->compare_exchange_strong(
1055      expected, desired, std::memory_order_release, std::memory_order_relaxed);
1056}
1057
1058#endif /* KMP_OS_H */
1059// Safe C API
1060#include "kmp_safe_c_api.h"
1061