Add OpenMP support

This commit is contained in:
Justine Tunney 2024-01-28 21:57:40 -08:00
parent c1e18e7903
commit 5f8e9f14c1
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
742 changed files with 94643 additions and 1279 deletions

View file

@ -286,6 +286,7 @@ include third_party/readline/BUILD.mk # │
include third_party/libunwind/BUILD.mk # |
include third_party/libcxxabi/BUILD.mk # |
include third_party/libcxx/BUILD.mk # │
include third_party/openmp/BUILD.mk # │
include third_party/double-conversion/BUILD.mk # │
include third_party/pcre/BUILD.mk # │
include third_party/less/BUILD.mk # │
@ -441,6 +442,7 @@ COSMOPOLITAN_OBJECTS = \
THIRD_PARTY_GETOPT \
LIBC_LOG \
LIBC_TIME \
THIRD_PARTY_OPENMP \
THIRD_PARTY_MUSL \
THIRD_PARTY_ZLIB_GZ \
THIRD_PARTY_LIBCXXABI \
@ -522,6 +524,7 @@ COSMOCC_PKGS = \
THIRD_PARTY_AARCH64 \
THIRD_PARTY_LIBCXX \
THIRD_PARTY_LIBCXXABI \
THIRD_PARTY_OPENMP \
THIRD_PARTY_INTEL
o/$(MODE)/cosmopolitan.a: \

View file

@ -40,6 +40,9 @@ o/$(MODE)/%.h: %.c
o/$(MODE)/%.o: %.cc
@$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
o/$(MODE)/%.o: %.cpp
@$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
o/$(MODE)/%.lds: %.lds
@$(COMPILE) -APREPROCESS $(PREPROCESS.lds) $(OUTPUT_OPTION) $<

47
libc/calls/sched_getcpu.c Normal file
View file

@ -0,0 +1,47 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2024 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/struct/cpuset.h"
#include "libc/dce.h"
#include "libc/nexgen32e/rdtscp.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/nt/struct/processornumber.h"
#include "libc/nt/synchronization.h"
int sys_getcpu(unsigned *opt_cpu, unsigned *opt_node, void *tcache);
/**
* Returns ID of CPU on which thread is currently scheduled.
*/
int sched_getcpu(void) {
if (X86_HAVE(RDTSCP)) {
unsigned tsc_aux;
rdtscp(&tsc_aux);
return TSC_AUX_CORE(tsc_aux);
} else if (IsWindows()) {
struct NtProcessorNumber pn;
GetCurrentProcessorNumberEx(&pn);
return 64 * pn.Group + pn.Number;
} else {
unsigned cpu = 0;
int rc = sys_getcpu(&cpu, 0, 0);
if (rc == -1) return -1;
return cpu;
}
}

View file

@ -53,5 +53,7 @@ int CPU_COUNT_S(size_t, const cpu_set_t *) libcesque;
#define CPU_CLR_S(i, size, set) _CPU_S(i, size, set, &= ~)
#define CPU_ISSET_S(i, size, set) _CPU_S(i, size, set, &)
typedef cpu_set_t cpuset_t; /* for freebsd compatibility */
COSMOPOLITAN_C_END_
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_CPUSET_H_ */

View file

@ -45,7 +45,7 @@ int gettid(void) {
}
}
if (IsXnuSilicon()) {
return enosys();
return enosys(); // can only happen if we can't access thread local storage
} else {
return sys_gettid();
}

View file

@ -18,8 +18,8 @@ COSMOPOLITAN_C_START_
*/
#define rdtscp(OPT_OUT_IA32_TSC_AUX) \
({ \
uint64_t Rax, Rdx; \
uint32_t Ecx, *EcxOut; \
uint64_t Rax, Rcx, Rdx; \
asm volatile("rdtscp" \
: "=a"(Rax), "=c"(Ecx), "=d"(Rdx) \
: /* no inputs */ \

View file

@ -0,0 +1,20 @@
#include "libc/nt/codegen.h"
.imp kernel32,__imp_GetCurrentProcessorNumberEx,GetCurrentProcessorNumberEx
.text.windows
.ftrace1
GetCurrentProcessorNumberEx:
.ftrace2
#ifdef __x86_64__
push %rbp
mov %rsp,%rbp
mov %rdi,%rcx
sub $32,%rsp
call *__imp_GetCurrentProcessorNumberEx(%rip)
leave
#elif defined(__aarch64__)
mov x0,#0
#endif
ret
.endfn GetCurrentProcessorNumberEx,globl
.previous

View file

@ -109,6 +109,7 @@ imp 'GetConsoleTitle' GetConsoleTitleW kernel32 2
imp 'GetConsoleWindow' GetConsoleWindow kernel32 0
imp 'GetCurrentDirectory' GetCurrentDirectoryW kernel32 2
imp 'GetCurrentProcessId' GetCurrentProcessId kernel32 0
imp 'GetCurrentProcessorNumberEx' GetCurrentProcessorNumberEx kernel32 1
imp 'GetCurrentThread' GetCurrentThread kernel32 0
imp 'GetCurrentThreadId' GetCurrentThreadId kernel32 0
imp 'GetEnvironmentStrings' GetEnvironmentStringsW kernel32 1

View file

@ -0,0 +1,12 @@
#ifndef COSMOPOLITAN_LIBC_NT_STRUCT_PROCESSORNUMBER_H_
#define COSMOPOLITAN_LIBC_NT_STRUCT_PROCESSORNUMBER_H_
COSMOPOLITAN_C_START_
struct NtProcessorNumber {
uint16_t Group;
uint8_t Number;
uint8_t Reserved;
};
COSMOPOLITAN_C_END_
#endif /* COSMOPOLITAN_LIBC_NT_STRUCT_PROCESSORNUMBER_H_ */

View file

@ -4,6 +4,7 @@
#include "libc/nt/struct/criticalsection.h"
#include "libc/nt/struct/filetime.h"
#include "libc/nt/struct/linkedlist.h"
#include "libc/nt/struct/processornumber.h"
#include "libc/nt/struct/securityattributes.h"
#include "libc/nt/struct/systemtime.h"
#include "libc/nt/thunk/msabi.h"
@ -115,6 +116,8 @@ bool32 GetSystemTimeAdjustment(uint32_t *lpTimeAdjustment,
uint32_t *lpTimeIncrement,
bool32 *lpTimeAdjustmentDisabled);
void GetCurrentProcessorNumberEx(struct NtProcessorNumber *out_ProcNumber);
#if ShouldUseMsabiAttribute()
#include "libc/nt/thunk/synchronization.inc"
#endif /* ShouldUseMsabiAttribute() */

View file

@ -9,9 +9,9 @@ COSMOPOLITAN_C_START_
typedef int nl_item;
typedef void *nl_catd;
nl_catd catopen(const char *, int) libcesque;
char *catgets(nl_catd, int, int, const char *) libcesque;
int catclose(nl_catd) libcesque;
nl_catd catopen(const char *, int);
char *catgets(nl_catd, int, int, const char *);
int catclose(nl_catd);
COSMOPOLITAN_C_END_
#endif /* COSMOPOLITAN_LIBC_STR_NLTYPES_H_ */

View file

@ -38,6 +38,7 @@ static const char *DescribeReturnValue(char buf[30], int err, void **value) {
*p++ = '[';
p = FormatHex64(p, (uintptr_t)*value, 1);
*p++ = ']';
*p = 0;
return buf;
}

View file

@ -12,10 +12,14 @@ TEST_LIBCXX_CHECKS = $(TEST_LIBCXX_COMS:%=%.runs)
TEST_LIBCXX_TESTS = $(TEST_LIBCXX_COMS:%=%.ok)
TEST_LIBCXX_DIRECTDEPS = \
LIBC_CALLS \
LIBC_INTRIN \
LIBC_NEXGEN32E \
LIBC_RUNTIME \
THIRD_PARTY_LIBCXX
LIBC_STDIO \
THIRD_PARTY_LIBCXX \
THIRD_PARTY_DOUBLECONVERSION \
THIRD_PARTY_OPENMP
TEST_LIBCXX_DEPS := \
$(call uniq,$(foreach x,$(TEST_LIBCXX_DIRECTDEPS),$($(x))))
@ -34,6 +38,8 @@ o/$(MODE)/test/libcxx/%.com.dbg: \
$(TEST_LIBCXX_OBJS): private CCFLAGS += -fexceptions -frtti
o/$(MODE)/test/libcxx/openmp_test.o: private CXXFLAGS += -fopenmp -O3
.PHONY: o/$(MODE)/test/libcxx
o/$(MODE)/test/libcxx: \
$(TEST_LIBCXX_BINS) \

236
test/libcxx/openmp_test.cc Normal file
View file

@ -0,0 +1,236 @@
/*-*-mode:c++;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8-*-│
vi: set et ft=c++ ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2024 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/struct/timespec.h"
#include "libc/fmt/itoa.h"
#include "libc/inttypes.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/clock.h"
#include "third_party/double-conversion/double-to-string.h"
#include "third_party/double-conversion/utils.h"
#include "third_party/openmp/omp.h"
#ifndef __FAST_MATH__
#define FLAWLESS 0
#else
#define FLAWLESS 1e-05
#endif
#if defined(__OPTIMIZE__) && !defined(__SANITIZE_ADDRESS__)
#define ITERATIONS 10
#else
#define ITERATIONS 1
#endif
// m×n → (m×n)ᵀ
template <typename T>
void transpose(long m, long n, const T *A, long sa, T *B, long sb) {
#pragma omp parallel for collapse(2)
for (long i = 0; i < m; ++i) {
for (long j = 0; j < n; ++j) {
B[sb * j + i] = A[sa * i + j];
}
}
}
// m×k * k×n → m×n
template <typename T>
void matmul(long m, long n, long k, const T *A, long sa, const T *B, long sb,
T *C, long sc) {
#pragma omp parallel for collapse(2)
for (long i = 0; i < m; ++i) {
for (long j = 0; j < n; ++j) {
T sum = 0;
for (long l = 0; l < k; ++l) {
sum += A[sa * i + l] * B[sb * l + j];
}
C[sc * i + j] = sum;
}
}
}
template <long BM, long BN, typename T>
void sgemmk(long k, const T *A, long sa, const T *B, long sb, T *C, long sc) {
T S[BM][BN] = {0};
for (long l = 0; l < k; ++l) {
for (long i = 0; i < BM; ++i) {
for (long j = 0; j < BN; ++j) {
S[i][j] += A[sa * l + i] * B[sb * l + j];
}
}
}
for (long i = 0; i < BM; ++i) {
for (long j = 0; j < BN; ++j) {
C[sc * i + j] = S[i][j];
}
}
}
// (m×k)ᵀ * k×n → m×n
template <long BM, long BN, typename T>
void sgemm(long m, long n, long k, const T *A, long sa, const T *B, long sb,
T *C, long sc) {
#pragma omp parallel for collapse(2)
for (long i = 0; i < m; i += BM) {
for (long j = 0; j < n; j += BN) {
sgemmk<BM, BN>(k, A + i, sa, B + j, sb, C + sc * i + j, sc);
}
}
}
template <typename T>
void show(long m, long n, const T *A, long sa) {
long max = 4;
printf("{");
for (long i = 0; i < m; ++i) {
if (i) {
if (i == max) {
printf(", ...");
break;
} else {
printf(", ");
}
}
printf("{");
for (long j = 0; j < n; ++j) {
if (j) {
if (j == max) {
printf(", ...");
break;
} else {
printf(", ");
}
}
printf("%g", static_cast<double>(A[j + i * sa]));
}
printf("}");
}
printf("}");
}
template <typename T>
double diff(long m, long n, const T *A, long sa, const T *B, long sb) {
double s = 0;
for (long i = 0; i < m; ++i) {
for (long j = 0; j < n; ++j) {
s += fabs(A[sa * i + j] - B[sb * i + j]);
}
}
return s / m / n;
}
template <typename T>
void check(double tol, long m, long n, const T *A, long sa, const T *B, long sb,
const char *file, long line) {
double sad = diff(m, n, A, sa, B, sb);
if (sad > tol) {
printf("%s:%d: sad %g exceeds %g\n\twant ", file, line, sad, tol);
show(m, n, A, sa);
printf("\n\t got ");
show(m, n, B, sb);
printf("\n");
exit(1);
}
}
#define check(tol, m, n, A, sa, B, sb) \
check(tol, m, n, A, sa, B, sb, __FILE__, __LINE__)
long micros(void) {
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
return ts.tv_sec * 1000000 + (ts.tv_nsec + 999) / 1000;
}
#define bench(x) \
do { \
long t1 = micros(); \
for (long i = 0; i < ITERATIONS; ++i) { \
asm volatile("" ::: "memory"); \
x; \
asm volatile("" ::: "memory"); \
} \
long t2 = micros(); \
printf("%8" PRId64 " µs %s\n", (t2 - t1 + ITERATIONS - 1) / ITERATIONS, \
#x); \
} while (0)
unsigned long rando(void) {
static unsigned long s;
unsigned long z = (s += 0x9e3779b97f4a7c15);
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
return z ^ (z >> 31);
}
double real01(unsigned long x) { // (0,1)
return 1. / 4503599627370496. * ((x >> 12) + .5);
}
double numba(void) { // (-1,1)
return real01(rando()) * 2 - 1;
}
template <typename T>
void fill(T *A, long n) {
for (long i = 0; i < n; ++i) {
A[i] = numba();
}
}
void check_reference_gemm_is_ok(void) {
constexpr long m = 2;
constexpr long n = 2;
constexpr long k = 2;
float A[m][k] = {{1, 2}, {3, 4}};
float B[k][n] = {{5, 6}, {7, 8}};
float C[m][n] = {{666, 666}, {666, 666}};
float G[m][n] = {{19, 22}, {43, 50}};
bench(matmul(m, n, k, (float *)A, k, (float *)B, n, (float *)C, n));
check(FLAWLESS, m, n, (float *)G, n, (float *)C, n);
}
void check_transposed_blocking_gemm_is_ok(void) {
long m = 1024;
long k = 512;
long n = 80;
float *A = new float[m * k];
float *B = new float[k * n];
float *C = new float[m * n];
float *D = new float[m * n];
fill(A, m * k);
fill(B, k * n);
bench(matmul(m, n, k, A, k, B, n, C, n));
float *At = new float[k * m];
bench(transpose(m, k, A, k, At, m));
bench((sgemm<8, 4>(m, n, k, At, m, B, n, D, n)));
check(FLAWLESS, m, n, C, n, D, n);
delete[] At;
delete[] D;
delete[] C;
delete[] B;
delete[] A;
}
int main(int argc, char *argv[]) {
check_reference_gemm_is_ok();
check_transposed_blocking_gemm_is_ok();
}

View file

@ -28,6 +28,7 @@ o/$(MODE)/third_party: \
o/$(MODE)/third_party/musl \
o/$(MODE)/third_party/ncurses \
o/$(MODE)/third_party/nsync \
o/$(MODE)/third_party/openmp \
o/$(MODE)/third_party/pcre \
o/$(MODE)/third_party/puff \
o/$(MODE)/third_party/python \

View file

@ -0,0 +1,119 @@
//===-- lib/fp_compare_impl.inc - Floating-point comparison -------*- C -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "fp_lib.inc"
// GCC uses long (at least for x86_64) as the return type of the comparison
// functions. We need to ensure that the return value is sign-extended in the
// same way as GCC expects (since otherwise GCC-generated __builtin_isinf
// returns true for finite 128-bit floating-point numbers).
#ifdef __aarch64__
// AArch64 GCC overrides libgcc_cmp_return to use int instead of long.
typedef int CMP_RESULT;
#elif __SIZEOF_POINTER__ == 8 && __SIZEOF_LONG__ == 4
// LLP64 ABIs use long long instead of long.
typedef long long CMP_RESULT;
#elif __AVR__
// AVR uses a single byte for the return value.
typedef char CMP_RESULT;
#else
// Otherwise the comparison functions return long.
typedef long CMP_RESULT;
#endif
#if !defined(__clang__) && defined(__GNUC__)
// GCC uses a special __libgcc_cmp_return__ mode to define the return type, so
// check that we are ABI-compatible when compiling the builtins with GCC.
typedef int GCC_CMP_RESULT __attribute__((__mode__(__libgcc_cmp_return__)));
_Static_assert(sizeof(GCC_CMP_RESULT) == sizeof(CMP_RESULT),
"SOFTFP ABI not compatible with GCC");
#endif
enum {
LE_LESS = -1,
LE_EQUAL = 0,
LE_GREATER = 1,
LE_UNORDERED = 1,
};
static inline CMP_RESULT __leXf2__(fp_t a, fp_t b) {
const srep_t aInt = toRep(a);
const srep_t bInt = toRep(b);
const rep_t aAbs = aInt & absMask;
const rep_t bAbs = bInt & absMask;
// If either a or b is NaN, they are unordered.
if (aAbs > infRep || bAbs > infRep)
return LE_UNORDERED;
// If a and b are both zeros, they are equal.
if ((aAbs | bAbs) == 0)
return LE_EQUAL;
// If at least one of a and b is positive, we get the same result comparing
// a and b as signed integers as we would with a floating-point compare.
if ((aInt & bInt) >= 0) {
if (aInt < bInt)
return LE_LESS;
else if (aInt == bInt)
return LE_EQUAL;
else
return LE_GREATER;
} else {
// Otherwise, both are negative, so we need to flip the sense of the
// comparison to get the correct result. (This assumes a twos- or ones-
// complement integer representation; if integers are represented in a
// sign-magnitude representation, then this flip is incorrect).
if (aInt > bInt)
return LE_LESS;
else if (aInt == bInt)
return LE_EQUAL;
else
return LE_GREATER;
}
}
enum {
GE_LESS = -1,
GE_EQUAL = 0,
GE_GREATER = 1,
GE_UNORDERED = -1 // Note: different from LE_UNORDERED
};
static inline CMP_RESULT __geXf2__(fp_t a, fp_t b) {
const srep_t aInt = toRep(a);
const srep_t bInt = toRep(b);
const rep_t aAbs = aInt & absMask;
const rep_t bAbs = bInt & absMask;
if (aAbs > infRep || bAbs > infRep)
return GE_UNORDERED;
if ((aAbs | bAbs) == 0)
return GE_EQUAL;
if ((aInt & bInt) >= 0) {
if (aInt < bInt)
return GE_LESS;
else if (aInt == bInt)
return GE_EQUAL;
else
return GE_GREATER;
} else {
if (aInt > bInt)
return GE_LESS;
else if (aInt == bInt)
return GE_EQUAL;
else
return GE_GREATER;
}
}
static inline CMP_RESULT __unordXf2__(fp_t a, fp_t b) {
const rep_t aAbs = toRep(a) & absMask;
const rep_t bAbs = toRep(b) & absMask;
return aAbs > infRep || bAbs > infRep;
}

View file

@ -11,10 +11,14 @@
#define _LIBCPP_CTIME
#include "third_party/libcxx/__config"
#include "libc/calls/calls.h"
#include "libc/calls/struct/timespec.h"
#include "libc/calls/struct/timeval.h"
#include "libc/sysv/consts/clock.h"
#include "libc/sysv/consts/sched.h"
#include "libc/sysv/consts/timer.h"
#include "libc/calls/weirdtypes.h"
#include "libc/time/struct/tm.h"
#include "libc/calls/calls.h"
#include "libc/time/time.h"
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)

View file

@ -83,6 +83,7 @@ $(THIRD_PARTY_LIBCXXABI_A).pkg: \
# TODO: Remove constinit hacks when we have C++20
$(THIRD_PARTY_LIBCXXABI_A_OBJS): private \
CXXFLAGS += \
-fno-sanitize=all \
-ffunction-sections \
-fdata-sections \
-fexceptions \

View file

@ -202,7 +202,7 @@ enum
/// @link http://dwarfstd.org/Dwarf4.pdf @unlink
/// @param data reference variable holding memory pointer to decode from
/// @returns decoded value
static dontasan
static
uintptr_t
readULEB128(const uint8_t** data)
{
@ -225,7 +225,7 @@ readULEB128(const uint8_t** data)
/// @link http://dwarfstd.org/Dwarf4.pdf @unlink
/// @param data reference variable holding memory pointer to decode from
/// @returns decoded value
static dontasan
static
intptr_t
readSLEB128(const uint8_t** data)
{
@ -542,7 +542,7 @@ struct scan_results
} // unnamed namespace
static dontasan
static
void
set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context,
const scan_results& results)
@ -581,7 +581,6 @@ set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context,
_UA_CLEANUP_PHASE && !_UA_HANDLER_FRAME
*/
dontasan
static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
bool native_exception,
_Unwind_Exception *unwind_exception,
@ -912,7 +911,6 @@ static _Unwind_Reason_Code __gxx_personality_imp
#else
_LIBCXXABI_FUNC_VIS _Unwind_Reason_Code
#ifdef __USING_SJLJ_EXCEPTIONS__
dontasan
__gxx_personality_sj0
#elif defined(__MVS__)
__zos_cxx_personality_v2

View file

@ -68,8 +68,16 @@ $(THIRD_PARTY_LIBUNWIND_A).pkg: \
$(THIRD_PARTY_LIBUNWIND_A_OBJS) \
$(foreach x,$(THIRD_PARTY_LIBUNWIND_A_DIRECTDEPS),$($(x)_A).pkg)
$(THIRD_PARTY_LIBUNWIND_A_OBJS): private \
CFLAGS += \
-fno-sanitize=all \
-ffunction-sections \
-fdata-sections \
-D_LIBUNWIND_USE_DLADDR=0
$(THIRD_PARTY_LIBUNWIND_A_OBJS): private \
CXXFLAGS += \
-fno-sanitize=all \
-ffunction-sections \
-fdata-sections \
-D_LIBUNWIND_USE_DLADDR=0

View file

@ -15,5 +15,3 @@ LOCAL CHANGES
- Fixed `_Unwind_FunctionContext` struct to be ABI-compatible with
code generated by GCC.
- Added `dontasan` annotations to functions that raised ASAN errors.

View file

@ -105,7 +105,7 @@ __Unwind_SjLj_SetTopOfFunctionStack(struct _Unwind_FunctionContext *fc) {
/// Called at start of each function that catches exceptions
_LIBUNWIND_EXPORT void dontasan
_LIBUNWIND_EXPORT void
_Unwind_SjLj_Register(struct _Unwind_FunctionContext *fc) {
fc->prev = __Unwind_SjLj_GetTopOfFunctionStack();
__Unwind_SjLj_SetTopOfFunctionStack(fc);
@ -113,7 +113,7 @@ _Unwind_SjLj_Register(struct _Unwind_FunctionContext *fc) {
/// Called at end of each function that catches exceptions
_LIBUNWIND_EXPORT void dontasan
_LIBUNWIND_EXPORT void
_Unwind_SjLj_Unregister(struct _Unwind_FunctionContext *fc) {
__Unwind_SjLj_SetTopOfFunctionStack(fc->prev);
}
@ -426,7 +426,6 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context *context,
/// Called by personality handler during phase 2 to alter register values.
dontasan
_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
uintptr_t new_value) {
_LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%" PRIuPTR

14
third_party/musl/catclose.c vendored Normal file
View file

@ -0,0 +1,14 @@
#define _BSD_SOURCE
#include <nl_types.h>
#include <stdint.h>
#include <endian.h>
#include <sys/mman.h>
#define V(p) be32toh(*(uint32_t *)(p))
int catclose (nl_catd catd)
{
char *map = (char *)catd;
munmap(map, V(map+8)+20);
return 0;
}

38
third_party/musl/catgets.c vendored Normal file
View file

@ -0,0 +1,38 @@
#define _BSD_SOURCE
#include <nl_types.h>
#include <endian.h>
#include <stdlib.h>
#include <stdint.h>
#include <errno.h>
#define V(p) be32toh(*(uint32_t *)(p))
static int cmp(const void *a, const void *b)
{
uint32_t x = V(a), y = V(b);
return x<y ? -1 : x>y ? 1 : 0;
}
char *catgets (nl_catd catd, int set_id, int msg_id, const char *s)
{
const char *map = (const char *)catd;
uint32_t nsets = V(map+4);
const char *sets = map+20;
const char *msgs = map+20+V(map+12);
const char *strings = map+20+V(map+16);
uint32_t set_id_be = htobe32(set_id);
uint32_t msg_id_be = htobe32(msg_id);
const char *set = bsearch(&set_id_be, sets, nsets, 12, cmp);
if (!set) {
errno = ENOMSG;
return (char *)s;
}
uint32_t nmsgs = V(set+4);
msgs += 12*V(set+8);
const char *msg = bsearch(&msg_id_be, msgs, nmsgs, 12, cmp);
if (!msg) {
errno = ENOMSG;
return (char *)s;
}
return (char *)(strings + V(msg+8));
}

79
third_party/musl/catopen.c vendored Normal file
View file

@ -0,0 +1,79 @@
#define _BSD_SOURCE
#include <nl_types.h>
#include <string.h>
#include <stdint.h>
#include <endian.h>
#include <errno.h>
#include <langinfo.h>
#include <locale.h>
#include "third_party/musl/mapfile.internal.h"
#include <sys/mman.h>
#define V(p) be32toh(*(uint32_t *)(p))
static nl_catd do_catopen(const char *name)
{
size_t size;
const unsigned char *map = __map_file(name, &size);
/* Size recorded in the file must match file size; otherwise
* the information needed to unmap the file will be lost. */
if (!map || V(map) != 0xff88ff89 || 20+V(map+8) != size) {
if(map) munmap((void *)map, size);
errno = ENOENT;
return (nl_catd)-1;
}
return (nl_catd)map;
}
nl_catd catopen(const char *name, int oflag)
{
nl_catd catd;
if (strchr(name, '/')) return do_catopen(name);
char buf[PATH_MAX];
size_t i;
const char *path, *lang, *p, *z;
if (issetugid() || !(path = getenv("NLSPATH"))) {
errno = ENOENT;
return (nl_catd)-1;
}
lang = oflag ? nl_langinfo(_NL_LOCALE_NAME(LC_MESSAGES)) : getenv("LANG");
if (!lang) lang = "";
for (p=path; *p; p=z) {
i = 0;
z = strchrnul(p, ':');
for (; p<z; p++) {
const char *v;
size_t l;
if (*p!='%') v=p, l=1;
else switch (*++p) {
case 'N': v=name; l=strlen(v); break;
case 'L': v=lang; l=strlen(v); break;
case 'l': v=lang; l=strcspn(v,"_.@"); break;
case 't':
v=strchrnul(lang,'_');
if (*v) v++;
l=strcspn(v,".@");
break;
case 'c': v="UTF-8"; l=5; break;
case '%': v="%"; l=1; break;
default: v=0;
}
if (!v || l >= sizeof buf - i) {
break;
}
memcpy(buf+i, v, l);
i += l;
}
if (!*z && (p<z || !i)) break;
if (p<z) continue;
if (*z) z++;
buf[i] = 0;
/* Leading : or :: in NLSPATH is same as %N */
catd = do_catopen(i ? buf : name);
if (catd != (nl_catd)-1) return catd;
}
errno = ENOENT;
return (nl_catd)-1;
}

17
third_party/musl/mapfile.c vendored Normal file
View file

@ -0,0 +1,17 @@
#include <sys/mman.h>
#include <fcntl.h>
#include <sys/stat.h>
const char unsigned *__map_file(const char *pathname, size_t *size)
{
struct stat st;
const unsigned char *map = MAP_FAILED;
int fd = open(pathname, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
if (fd < 0) return 0;
if (!fstat(fd, &st)) {
map = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
*size = st.st_size;
}
close(fd);
return map == MAP_FAILED ? 0 : map;
}

8
third_party/musl/mapfile.internal.h vendored Normal file
View file

@ -0,0 +1,8 @@
#ifndef COSMOPOLITAN_THIRD_PARTY_MUSL_MAPFILE_INTERNAL_H_
#define COSMOPOLITAN_THIRD_PARTY_MUSL_MAPFILE_INTERNAL_H_
COSMOPOLITAN_C_START_
const char unsigned *__map_file(const char *, size_t *);
COSMOPOLITAN_C_END_
#endif /* COSMOPOLITAN_THIRD_PARTY_MUSL_MAPFILE_INTERNAL_H_ */

82
third_party/openmp/BUILD.mk vendored Normal file
View file

@ -0,0 +1,82 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘
PKGS += THIRD_PARTY_OPENMP
THIRD_PARTY_OPENMP_ARTIFACTS += THIRD_PARTY_OPENMP_A
THIRD_PARTY_OPENMP = $(THIRD_PARTY_OPENMP_A_DEPS) $(THIRD_PARTY_OPENMP_A)
THIRD_PARTY_OPENMP_A = o/$(MODE)/third_party/openmp/openmp.a
THIRD_PARTY_OPENMP_A_FILES := $(wildcard third_party/openmp/*)
THIRD_PARTY_OPENMP_A_HDRS = $(filter %.h,$(THIRD_PARTY_OPENMP_A_FILES))
THIRD_PARTY_OPENMP_A_INCS = $(filter %.inc,$(THIRD_PARTY_OPENMP_A_FILES))
THIRD_PARTY_OPENMP_A_SRCS_CPP = $(filter %.cpp,$(THIRD_PARTY_OPENMP_A_FILES))
THIRD_PARTY_OPENMP_A_SRCS_S = $(filter %.S,$(THIRD_PARTY_OPENMP_A_FILES))
THIRD_PARTY_OPENMP_A_SRCS = $(THIRD_PARTY_OPENMP_A_SRCS_CPP) $(THIRD_PARTY_OPENMP_A_SRCS_S)
THIRD_PARTY_OPENMP_A_OBJS_CPP = $(THIRD_PARTY_OPENMP_A_SRCS_CPP:%.cpp=o/$(MODE)/%.o)
THIRD_PARTY_OPENMP_A_OBJS_S = $(THIRD_PARTY_OPENMP_A_SRCS_S:%.S=o/$(MODE)/%.o)
THIRD_PARTY_OPENMP_A_OBJS = $(THIRD_PARTY_OPENMP_A_OBJS_CPP) $(THIRD_PARTY_OPENMP_A_OBJS_S)
THIRD_PARTY_OPENMP_A_DIRECTDEPS = \
LIBC_CALLS \
LIBC_DLOPEN \
LIBC_FMT \
LIBC_INTRIN \
LIBC_MEM \
LIBC_NEXGEN32E \
LIBC_PROC \
LIBC_RUNTIME \
LIBC_STDIO \
LIBC_STR \
LIBC_SYSV \
LIBC_SYSV_CALLS \
LIBC_THREAD \
THIRD_PARTY_COMPILER_RT \
THIRD_PARTY_GDTOA \
THIRD_PARTY_LIBCXX \
THIRD_PARTY_NSYNC \
THIRD_PARTY_MUSL
THIRD_PARTY_OPENMP_A_DEPS := \
$(call uniq,$(foreach x,$(THIRD_PARTY_OPENMP_A_DIRECTDEPS),$($(x))))
THIRD_PARTY_OPENMP_A_CHECKS = \
$(THIRD_PARTY_OPENMP_A).pkg
$(THIRD_PARTY_OPENMP_A): \
third_party/openmp/ \
$(THIRD_PARTY_OPENMP_A).pkg \
$(THIRD_PARTY_OPENMP_A_OBJS)
$(THIRD_PARTY_OPENMP_A).pkg: \
$(THIRD_PARTY_OPENMP_A_OBJS) \
$(foreach x,$(THIRD_PARTY_OPENMP_A_DIRECTDEPS),$($(x)_A).pkg)
$(THIRD_PARTY_OPENMP_A_OBJS): private \
COPTS += \
-fno-sanitize=all \
-fdata-sections \
-ffunction-sections \
-Wno-maybe-uninitialized \
-Wno-stringop-truncation \
-Wno-class-memaccess \
-Wno-unused-but-set-variable \
-Wno-frame-address \
-fno-strict-aliasing
o/$(MODE)/third_party/openmp/util1.o: private COPTS += -fportcosmo
# these assembly files are safe to build on aarch64
o/$(MODE)/third_party/openmp/util2.o: third_party/openmp/util2.S
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
THIRD_PARTY_OPENMP_LIBS = $(foreach x,$(THIRD_PARTY_OPENMP_ARTIFACTS),$($(x)))
THIRD_PARTY_OPENMP_SRCS = $(foreach x,$(THIRD_PARTY_OPENMP_ARTIFACTS),$($(x)_SRCS))
THIRD_PARTY_OPENMP_HDRS = $(foreach x,$(THIRD_PARTY_OPENMP_ARTIFACTS),$($(x)_HDRS))
THIRD_PARTY_OPENMP_INCS = $(foreach x,$(THIRD_PARTY_OPENMP_ARTIFACTS),$($(x)_INCS))
THIRD_PARTY_OPENMP_CHECKS = $(foreach x,$(THIRD_PARTY_OPENMP_ARTIFACTS),$($(x)_CHECKS))
THIRD_PARTY_OPENMP_OBJS = $(foreach x,$(THIRD_PARTY_OPENMP_ARTIFACTS),$($(x)_OBJS))
$(THIRD_PARTY_OPENMP_OBJS): third_party/openmp/BUILD.mk
.PHONY: o/$(MODE)/third_party/openmp
o/$(MODE)/third_party/openmp: \
$(THIRD_PARTY_OPENMP_CHECKS)

16
third_party/openmp/README.cosmo vendored Normal file
View file

@ -0,0 +1,16 @@
DESCRIPTION
libomp - LLVM's Compiler Runtime for Multiprocessing
ORIGIN
https://github.com/llvm/llvm-project/
commit 70c3e30e01bd123e87824e36b6e38a39451ac28d
date Mon Jan 29 09:54:34 2024 +0800
LOCAL CHANGES
- Use Cosmo's gettid() function
- Ran third_party/openmp/generate.sh
- Removed usage of syscall() function
- Turned off quad floating point support (why does openmp have it?)

9
third_party/openmp/generate.sh vendored Executable file
View file

@ -0,0 +1,9 @@
#!/bin/sh
perl ~/vendor/llvm-project/openmp/runtime/tools/message-converter.pl \
--os=lin --prefix=kmp_i18n --enum=third_party/openmp/kmp_i18n_id.inc \
~/vendor/llvm-project/openmp/runtime/src/i18n/en_US.txt || exit
perl ~/vendor/llvm-project/openmp/runtime/tools/message-converter.pl \
--os=lin --prefix=kmp_i18n --default=third_party/openmp/kmp_i18n_default.inc \
~/vendor/llvm-project/openmp/runtime/src/i18n/en_US.txt

4835
third_party/openmp/kmp.h vendored Normal file

File diff suppressed because it is too large Load diff

5599
third_party/openmp/kmp_affinity.cpp vendored Normal file

File diff suppressed because it is too large Load diff

1321
third_party/openmp/kmp_affinity.h vendored Normal file

File diff suppressed because it is too large Load diff

2324
third_party/openmp/kmp_alloc.cpp vendored Normal file

File diff suppressed because it is too large Load diff

3877
third_party/openmp/kmp_atomic.cpp vendored Normal file

File diff suppressed because it is too large Load diff

1855
third_party/openmp/kmp_atomic.h vendored Normal file

File diff suppressed because it is too large Load diff

2670
third_party/openmp/kmp_barrier.cpp vendored Normal file

File diff suppressed because it is too large Load diff

144
third_party/openmp/kmp_barrier.h vendored Normal file
View file

@ -0,0 +1,144 @@
/*
* kmp_barrier.h
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef KMP_BARRIER_H
#define KMP_BARRIER_H
#include "kmp.h"
#include "kmp_i18n.h"
#if KMP_HAVE_XMMINTRIN_H && KMP_HAVE__MM_MALLOC
#include <xmmintrin.h>
#define KMP_ALIGNED_ALLOCATE(size, alignment) _mm_malloc(size, alignment)
#define KMP_ALIGNED_FREE(ptr) _mm_free(ptr)
#elif KMP_HAVE_ALIGNED_ALLOC
#define KMP_ALGIN_UP(val, alignment) \
(((val) + (alignment)-1) / (alignment) * (alignment))
#define KMP_ALIGNED_ALLOCATE(size, alignment) \
aligned_alloc(alignment, KMP_ALGIN_UP(size, alignment))
#define KMP_ALIGNED_FREE(ptr) free(ptr)
#elif KMP_HAVE_POSIX_MEMALIGN
static inline void *KMP_ALIGNED_ALLOCATE(size_t size, size_t alignment) {
void *ptr;
int n = posix_memalign(&ptr, alignment, size);
if (n != 0) {
if (ptr)
free(ptr);
return nullptr;
}
return ptr;
}
#define KMP_ALIGNED_FREE(ptr) free(ptr)
#elif KMP_HAVE__ALIGNED_MALLOC
#include <malloc.h>
#define KMP_ALIGNED_ALLOCATE(size, alignment) _aligned_malloc(size, alignment)
#define KMP_ALIGNED_FREE(ptr) _aligned_free(ptr)
#else
#define KMP_ALIGNED_ALLOCATE(size, alignment) KMP_INTERNAL_MALLOC(size)
#define KMP_ALIGNED_FREE(ptr) KMP_INTERNAL_FREE(ptr)
#endif
// Use four cache lines: MLC tends to prefetch the next or previous cache line
// creating a possible fake conflict between cores, so this is the only way to
// guarantee that no such prefetch can happen.
#ifndef KMP_FOURLINE_ALIGN_CACHE
#define KMP_FOURLINE_ALIGN_CACHE KMP_ALIGN(4 * CACHE_LINE)
#endif
#define KMP_OPTIMIZE_FOR_REDUCTIONS 0
class distributedBarrier {
struct flags_s {
kmp_uint32 volatile KMP_FOURLINE_ALIGN_CACHE stillNeed;
};
struct go_s {
std::atomic<kmp_uint64> KMP_FOURLINE_ALIGN_CACHE go;
};
struct iter_s {
kmp_uint64 volatile KMP_FOURLINE_ALIGN_CACHE iter;
};
struct sleep_s {
std::atomic<bool> KMP_FOURLINE_ALIGN_CACHE sleep;
};
void init(size_t nthr);
void resize(size_t nthr);
void computeGo(size_t n);
void computeVarsForN(size_t n);
public:
enum {
MAX_ITERS = 3,
MAX_GOS = 8,
IDEAL_GOS = 4,
IDEAL_CONTENTION = 16,
};
flags_s *flags[MAX_ITERS];
go_s *go;
iter_s *iter;
sleep_s *sleep;
size_t KMP_ALIGN_CACHE num_threads; // number of threads in barrier
size_t KMP_ALIGN_CACHE max_threads; // size of arrays in data structure
// number of go signals each requiring one write per iteration
size_t KMP_ALIGN_CACHE num_gos;
// number of groups of gos
size_t KMP_ALIGN_CACHE num_groups;
// threads per go signal
size_t KMP_ALIGN_CACHE threads_per_go;
bool KMP_ALIGN_CACHE fix_threads_per_go;
// threads per group
size_t KMP_ALIGN_CACHE threads_per_group;
// number of go signals in a group
size_t KMP_ALIGN_CACHE gos_per_group;
void *team_icvs;
distributedBarrier() = delete;
~distributedBarrier() = delete;
// Used instead of constructor to create aligned data
static distributedBarrier *allocate(int nThreads) {
distributedBarrier *d = (distributedBarrier *)KMP_ALIGNED_ALLOCATE(
sizeof(distributedBarrier), 4 * CACHE_LINE);
if (!d) {
KMP_FATAL(MemoryAllocFailed);
}
d->num_threads = 0;
d->max_threads = 0;
for (int i = 0; i < MAX_ITERS; ++i)
d->flags[i] = NULL;
d->go = NULL;
d->iter = NULL;
d->sleep = NULL;
d->team_icvs = NULL;
d->fix_threads_per_go = false;
// calculate gos and groups ONCE on base size
d->computeGo(nThreads);
d->init(nThreads);
return d;
}
static void deallocate(distributedBarrier *db) { KMP_ALIGNED_FREE(db); }
void update_num_threads(size_t nthr) { init(nthr); }
bool need_resize(size_t new_nthr) { return (new_nthr > max_threads); }
size_t get_num_threads() { return num_threads; }
kmp_uint64 go_release();
void go_reset();
};
#endif // KMP_BARRIER_H

331
third_party/openmp/kmp_cancel.cpp vendored Normal file
View file

@ -0,0 +1,331 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "kmp.h"
#include "kmp_i18n.h"
#include "kmp_io.h"
#include "kmp_str.h"
#if OMPT_SUPPORT
#include "ompt-specific.h"
#endif
/*!
@ingroup CANCELLATION
@param loc_ref location of the original task directive
@param gtid Global thread ID of encountering thread
@param cncl_kind Cancellation kind (parallel, for, sections, taskgroup)
@return returns true if the cancellation request has been activated and the
execution thread needs to proceed to the end of the canceled region.
Request cancellation of the binding OpenMP region.
*/
kmp_int32 __kmpc_cancel(ident_t *loc_ref, kmp_int32 gtid, kmp_int32 cncl_kind) {
kmp_info_t *this_thr = __kmp_threads[gtid];
KC_TRACE(10, ("__kmpc_cancel: T#%d request %d OMP_CANCELLATION=%d\n", gtid,
cncl_kind, __kmp_omp_cancellation));
KMP_DEBUG_ASSERT(cncl_kind != cancel_noreq);
KMP_DEBUG_ASSERT(cncl_kind == cancel_parallel || cncl_kind == cancel_loop ||
cncl_kind == cancel_sections ||
cncl_kind == cancel_taskgroup);
KMP_DEBUG_ASSERT(__kmp_get_gtid() == gtid);
if (__kmp_omp_cancellation) {
switch (cncl_kind) {
case cancel_parallel:
case cancel_loop:
case cancel_sections:
// cancellation requests for parallel and worksharing constructs
// are handled through the team structure
{
kmp_team_t *this_team = this_thr->th.th_team;
KMP_DEBUG_ASSERT(this_team);
kmp_int32 old = cancel_noreq;
this_team->t.t_cancel_request.compare_exchange_strong(old, cncl_kind);
if (old == cancel_noreq || old == cncl_kind) {
// we do not have a cancellation request in this team or we do have
// one that matches the current request -> cancel
#if OMPT_SUPPORT && OMPT_OPTIONAL
if (ompt_enabled.ompt_callback_cancel) {
ompt_data_t *task_data;
__ompt_get_task_info_internal(0, NULL, &task_data, NULL, NULL,
NULL);
ompt_cancel_flag_t type = ompt_cancel_parallel;
if (cncl_kind == cancel_parallel)
type = ompt_cancel_parallel;
else if (cncl_kind == cancel_loop)
type = ompt_cancel_loop;
else if (cncl_kind == cancel_sections)
type = ompt_cancel_sections;
ompt_callbacks.ompt_callback(ompt_callback_cancel)(
task_data, type | ompt_cancel_activated,
OMPT_GET_RETURN_ADDRESS(0));
}
#endif // OMPT_SUPPORT && OMPT_OPTIONAL
return 1 /* true */;
}
break;
}
case cancel_taskgroup:
// cancellation requests for a task group
// are handled through the taskgroup structure
{
kmp_taskdata_t *task;
kmp_taskgroup_t *taskgroup;
task = this_thr->th.th_current_task;
KMP_DEBUG_ASSERT(task);
taskgroup = task->td_taskgroup;
if (taskgroup) {
kmp_int32 old = cancel_noreq;
taskgroup->cancel_request.compare_exchange_strong(old, cncl_kind);
if (old == cancel_noreq || old == cncl_kind) {
// we do not have a cancellation request in this taskgroup or we do
// have one that matches the current request -> cancel
#if OMPT_SUPPORT && OMPT_OPTIONAL
if (ompt_enabled.ompt_callback_cancel) {
ompt_data_t *task_data;
__ompt_get_task_info_internal(0, NULL, &task_data, NULL, NULL,
NULL);
ompt_callbacks.ompt_callback(ompt_callback_cancel)(
task_data, ompt_cancel_taskgroup | ompt_cancel_activated,
OMPT_GET_RETURN_ADDRESS(0));
}
#endif
return 1 /* true */;
}
} else {
// TODO: what needs to happen here?
// the specification disallows cancellation w/o taskgroups
// so we might do anything here, let's abort for now
KMP_ASSERT(0 /* false */);
}
}
break;
default:
KMP_ASSERT(0 /* false */);
}
}
// ICV OMP_CANCELLATION=false, so we ignored this cancel request
KMP_DEBUG_ASSERT(!__kmp_omp_cancellation);
return 0 /* false */;
}
/*!
@ingroup CANCELLATION
@param loc_ref location of the original task directive
@param gtid Global thread ID of encountering thread
@param cncl_kind Cancellation kind (parallel, for, sections, taskgroup)
@return returns true if a matching cancellation request has been flagged in the
RTL and the encountering thread has to cancel..
Cancellation point for the encountering thread.
*/
kmp_int32 __kmpc_cancellationpoint(ident_t *loc_ref, kmp_int32 gtid,
kmp_int32 cncl_kind) {
kmp_info_t *this_thr = __kmp_threads[gtid];
KC_TRACE(10,
("__kmpc_cancellationpoint: T#%d request %d OMP_CANCELLATION=%d\n",
gtid, cncl_kind, __kmp_omp_cancellation));
KMP_DEBUG_ASSERT(cncl_kind != cancel_noreq);
KMP_DEBUG_ASSERT(cncl_kind == cancel_parallel || cncl_kind == cancel_loop ||
cncl_kind == cancel_sections ||
cncl_kind == cancel_taskgroup);
KMP_DEBUG_ASSERT(__kmp_get_gtid() == gtid);
if (__kmp_omp_cancellation) {
switch (cncl_kind) {
case cancel_parallel:
case cancel_loop:
case cancel_sections:
// cancellation requests for parallel and worksharing constructs
// are handled through the team structure
{
kmp_team_t *this_team = this_thr->th.th_team;
KMP_DEBUG_ASSERT(this_team);
if (this_team->t.t_cancel_request) {
if (cncl_kind == this_team->t.t_cancel_request) {
// the request in the team structure matches the type of
// cancellation point so we can cancel
#if OMPT_SUPPORT && OMPT_OPTIONAL
if (ompt_enabled.ompt_callback_cancel) {
ompt_data_t *task_data;
__ompt_get_task_info_internal(0, NULL, &task_data, NULL, NULL,
NULL);
ompt_cancel_flag_t type = ompt_cancel_parallel;
if (cncl_kind == cancel_parallel)
type = ompt_cancel_parallel;
else if (cncl_kind == cancel_loop)
type = ompt_cancel_loop;
else if (cncl_kind == cancel_sections)
type = ompt_cancel_sections;
ompt_callbacks.ompt_callback(ompt_callback_cancel)(
task_data, type | ompt_cancel_detected,
OMPT_GET_RETURN_ADDRESS(0));
}
#endif
return 1 /* true */;
}
KMP_ASSERT(0 /* false */);
} else {
// we do not have a cancellation request pending, so we just
// ignore this cancellation point
return 0;
}
break;
}
case cancel_taskgroup:
// cancellation requests for a task group
// are handled through the taskgroup structure
{
kmp_taskdata_t *task;
kmp_taskgroup_t *taskgroup;
task = this_thr->th.th_current_task;
KMP_DEBUG_ASSERT(task);
taskgroup = task->td_taskgroup;
if (taskgroup) {
// return the current status of cancellation for the taskgroup
#if OMPT_SUPPORT && OMPT_OPTIONAL
if (ompt_enabled.ompt_callback_cancel &&
!!taskgroup->cancel_request) {
ompt_data_t *task_data;
__ompt_get_task_info_internal(0, NULL, &task_data, NULL, NULL,
NULL);
ompt_callbacks.ompt_callback(ompt_callback_cancel)(
task_data, ompt_cancel_taskgroup | ompt_cancel_detected,
OMPT_GET_RETURN_ADDRESS(0));
}
#endif
return !!taskgroup->cancel_request;
} else {
// if a cancellation point is encountered by a task that does not
// belong to a taskgroup, it is OK to ignore it
return 0 /* false */;
}
}
default:
KMP_ASSERT(0 /* false */);
}
}
// ICV OMP_CANCELLATION=false, so we ignore the cancellation point
KMP_DEBUG_ASSERT(!__kmp_omp_cancellation);
return 0 /* false */;
}
/*!
@ingroup CANCELLATION
@param loc_ref location of the original task directive
@param gtid Global thread ID of encountering thread
@return returns true if a matching cancellation request has been flagged in the
RTL and the encountering thread has to cancel..
Barrier with cancellation point to send threads from the barrier to the
end of the parallel region. Needs a special code pattern as documented
in the design document for the cancellation feature.
*/
kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 gtid) {
int ret = 0 /* false */;
kmp_info_t *this_thr = __kmp_threads[gtid];
kmp_team_t *this_team = this_thr->th.th_team;
KMP_DEBUG_ASSERT(__kmp_get_gtid() == gtid);
// call into the standard barrier
__kmpc_barrier(loc, gtid);
// if cancellation is active, check cancellation flag
if (__kmp_omp_cancellation) {
// depending on which construct to cancel, check the flag and
// reset the flag
switch (KMP_ATOMIC_LD_RLX(&(this_team->t.t_cancel_request))) {
case cancel_parallel:
ret = 1;
// ensure that threads have checked the flag, when
// leaving the above barrier
__kmpc_barrier(loc, gtid);
this_team->t.t_cancel_request = cancel_noreq;
// the next barrier is the fork/join barrier, which
// synchronizes the threads leaving here
break;
case cancel_loop:
case cancel_sections:
ret = 1;
// ensure that threads have checked the flag, when
// leaving the above barrier
__kmpc_barrier(loc, gtid);
this_team->t.t_cancel_request = cancel_noreq;
// synchronize the threads again to make sure we do not have any run-away
// threads that cause a race on the cancellation flag
__kmpc_barrier(loc, gtid);
break;
case cancel_taskgroup:
// this case should not occur
KMP_ASSERT(0 /* false */);
break;
case cancel_noreq:
// do nothing
break;
default:
KMP_ASSERT(0 /* false */);
}
}
return ret;
}
/*!
@ingroup CANCELLATION
@param loc_ref location of the original task directive
@param gtid Global thread ID of encountering thread
@return returns true if a matching cancellation request has been flagged in the
RTL and the encountering thread has to cancel..
Query function to query the current status of cancellation requests.
Can be used to implement the following pattern:
if (kmp_get_cancellation_status(kmp_cancel_parallel)) {
perform_cleanup();
#pragma omp cancellation point parallel
}
*/
int __kmp_get_cancellation_status(int cancel_kind) {
if (__kmp_omp_cancellation) {
kmp_info_t *this_thr = __kmp_entry_thread();
switch (cancel_kind) {
case cancel_parallel:
case cancel_loop:
case cancel_sections: {
kmp_team_t *this_team = this_thr->th.th_team;
return this_team->t.t_cancel_request == cancel_kind;
}
case cancel_taskgroup: {
kmp_taskdata_t *task;
kmp_taskgroup_t *taskgroup;
task = this_thr->th.th_current_task;
taskgroup = task->td_taskgroup;
return taskgroup && taskgroup->cancel_request;
}
}
}
return 0 /* false */;
}

1475
third_party/openmp/kmp_collapse.cpp vendored Normal file

File diff suppressed because it is too large Load diff

240
third_party/openmp/kmp_collapse.h vendored Normal file
View file

@ -0,0 +1,240 @@
/*
* kmp_collapse.h -- header for loop collapse feature
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef KMP_COLLAPSE_H
#define KMP_COLLAPSE_H
#include <type_traits>
// Type of the index into the loop nest structures
// (with values from 0 to less than n from collapse(n))
typedef kmp_int32 kmp_index_t;
// Type for combined loop nest space IV:
typedef kmp_uint64 kmp_loop_nest_iv_t;
// Loop has <, <=, etc. as a comparison:
enum comparison_t : kmp_int32 {
comp_less_or_eq = 0,
comp_greater_or_eq = 1,
comp_not_eq = 2,
comp_less = 3,
comp_greater = 4
};
// Type of loop IV.
// Type of bounds and step, after usual promotions
// are a subset of these types (32 & 64 only):
enum loop_type_t : kmp_int32 {
loop_type_uint8 = 0,
loop_type_int8 = 1,
loop_type_uint16 = 2,
loop_type_int16 = 3,
loop_type_uint32 = 4,
loop_type_int32 = 5,
loop_type_uint64 = 6,
loop_type_int64 = 7
};
/*!
@ingroup WORK_SHARING
* Describes the structure for rectangular nested loops.
*/
template <typename T> struct bounds_infoXX_template {
// typedef typename traits_t<T>::unsigned_t UT;
typedef typename traits_t<T>::signed_t ST;
loop_type_t loop_type; // The differentiator
loop_type_t loop_iv_type;
comparison_t comparison;
// outer_iv should be 0 (or any other less then number of dimentions)
// if loop doesn't depend on it (lb1 and ub1 will be 0).
// This way we can do multiplication without a check.
kmp_index_t outer_iv;
// unions to keep the size constant:
union {
T lb0;
kmp_uint64 lb0_u64; // real type can be signed
};
union {
T lb1;
kmp_uint64 lb1_u64; // real type can be signed
};
union {
T ub0;
kmp_uint64 ub0_u64; // real type can be signed
};
union {
T ub1;
kmp_uint64 ub1_u64; // real type can be signed
};
union {
ST step; // signed even if bounds type is unsigned
kmp_int64 step_64; // signed
};
kmp_loop_nest_iv_t trip_count;
};
/*!
@ingroup WORK_SHARING
* Interface struct for rectangular nested loops.
* Same size as bounds_infoXX_template.
*/
struct bounds_info_t {
loop_type_t loop_type; // The differentiator
loop_type_t loop_iv_type;
comparison_t comparison;
// outer_iv should be 0 (or any other less then number of dimentions)
// if loop doesn't depend on it (lb1 and ub1 will be 0).
// This way we can do multiplication without a check.
kmp_index_t outer_iv;
kmp_uint64 lb0_u64; // real type can be signed
kmp_uint64 lb1_u64; // real type can be signed
kmp_uint64 ub0_u64; // real type can be signed
kmp_uint64 ub1_u64; // real type can be signed
kmp_int64 step_64; // signed
// This is internal, but it's the only internal thing we need
// in rectangular case, so let's expose it here:
kmp_loop_nest_iv_t trip_count;
};
//-------------------------------------------------------------------------
// Additional types for internal representation:
// Array for a point in the loop space, in the original space.
// It's represented in kmp_uint64, but each dimention is calculated in
// that loop IV type. Also dimentions have to be converted to those types
// when used in generated code.
typedef kmp_uint64* kmp_point_t;
// Array: Number of loop iterations on each nesting level to achieve some point,
// in expanded space or in original space.
// OMPTODO: move from using iterations to using offsets (iterations multiplied
// by steps). For those we need to be careful with the types, as step can be
// negative, but it'll remove multiplications and divisions in several places.
typedef kmp_loop_nest_iv_t* kmp_iterations_t;
// Internal struct with additional info:
template <typename T> struct bounds_info_internalXX_template {
// OMPTODO: should span have type T or should it better be
// kmp_uint64/kmp_int64 depending on T sign? (if kmp_uint64/kmp_int64 than
// updated bounds should probably also be kmp_uint64/kmp_int64). I'd like to
// use big_span_t, if it can be resolved at compile time.
typedef
typename std::conditional<std::is_signed<T>::value, kmp_int64, kmp_uint64>
big_span_t;
// typedef typename big_span_t span_t;
typedef T span_t;
bounds_infoXX_template<T> b; // possibly adjusted bounds
// Leaving this as a union in case we'll switch to span_t with different sizes
// (depending on T)
union {
// Smallest possible value of iv (may be smaller than actually possible)
span_t span_smallest;
kmp_uint64 span_smallest_u64;
};
// Leaving this as a union in case we'll switch to span_t with different sizes
// (depending on T)
union {
// Biggest possible value of iv (may be bigger than actually possible)
span_t span_biggest;
kmp_uint64 span_biggest_u64;
};
// Did we adjust loop bounds (not counting canonicalization)?
bool loop_bounds_adjusted;
};
// Internal struct with additional info:
struct bounds_info_internal_t {
bounds_info_t b; // possibly adjusted bounds
// Smallest possible value of iv (may be smaller than actually possible)
kmp_uint64 span_smallest_u64;
// Biggest possible value of iv (may be bigger than actually possible)
kmp_uint64 span_biggest_u64;
// Did we adjust loop bounds (not counting canonicalization)?
bool loop_bounds_adjusted;
};
//----------APIs for rectangular loop nests--------------------------------
// Canonicalize loop nest and calculate overall trip count.
// "bounds_nest" has to be allocated per thread.
// API will modify original bounds_nest array to bring it to a canonical form
// (only <= and >=, no !=, <, >). If the original loop nest was already in a
// canonical form there will be no changes to bounds in bounds_nest array
// (only trip counts will be calculated).
// Returns trip count of overall space.
extern "C" kmp_loop_nest_iv_t
__kmpc_process_loop_nest_rectang(ident_t *loc, kmp_int32 gtid,
/*in/out*/ bounds_info_t *original_bounds_nest,
kmp_index_t n);
// Calculate old induction variables corresponding to overall new_iv.
// Note: original IV will be returned as if it had kmp_uint64 type,
// will have to be converted to original type in user code.
// Note: trip counts should be already calculated by
// __kmpc_process_loop_nest_rectang.
// OMPTODO: special case 2, 3 nested loops - if it'll be possible to inline
// that into user code.
extern "C" void
__kmpc_calc_original_ivs_rectang(ident_t *loc, kmp_loop_nest_iv_t new_iv,
const bounds_info_t *original_bounds_nest,
/*out*/ kmp_uint64 *original_ivs,
kmp_index_t n);
//----------Init API for non-rectangular loops--------------------------------
// Init API for collapsed loops (static, no chunks defined).
// "bounds_nest" has to be allocated per thread.
// API will modify original bounds_nest array to bring it to a canonical form
// (only <= and >=, no !=, <, >). If the original loop nest was already in a
// canonical form there will be no changes to bounds in bounds_nest array
// (only trip counts will be calculated). Internally API will expand the space
// to parallelogram/parallelepiped, calculate total, calculate bounds for the
// chunks in terms of the new IV, re-calc them in terms of old IVs (especially
// important on the left side, to hit the lower bounds and not step over), and
// pick the correct chunk for this thread (so it will calculate chunks up to the
// needed one). It could be optimized to calculate just this chunk, potentially
// a bit less well distributed among threads. It is designed to make sure that
// threads will receive predictable chunks, deterministically (so that next nest
// of loops with similar characteristics will get exactly same chunks on same
// threads).
// Current contract: chunk_bounds_nest has only lb0 and ub0,
// lb1 and ub1 are set to 0 and can be ignored. (This may change in the future).
extern "C" kmp_int32
__kmpc_for_collapsed_init(ident_t *loc, kmp_int32 gtid,
/*in/out*/ bounds_info_t *original_bounds_nest,
/*out*/ bounds_info_t *chunk_bounds_nest,
kmp_index_t n,
/*out*/ kmp_int32 *plastiter);
#endif // KMP_COLLAPSE_H

176
third_party/openmp/kmp_config.h vendored Normal file
View file

@ -0,0 +1,176 @@
/*
* kmp_config.h -- Feature macros
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef KMP_CONFIG_H
#define KMP_CONFIG_H
#include "libc/dce.h"
#include "kmp_platform.h"
#ifndef __ASSEMBLER__
#include "libc/stdio/syscall.h"
#endif
#define KMP_USE_FUTEX 0
#define KMP_FTN_ENTRIES KMP_FTN_PLAIN
#define syscall {{openmp_shall_not_use_syscall}}
#define DEBUG_BUILD IsModeDbg()
#define RELWITHDEBINFO_BUILD (IsOptimized() && !IsTiny())
#define LIBOMP_USE_ITT_NOTIFY 0
#define USE_ITT_NOTIFY LIBOMP_USE_ITT_NOTIFY
#if ! LIBOMP_USE_ITT_NOTIFY
# define INTEL_NO_ITTNOTIFY_API
#endif
#define LIBOMP_USE_VERSION_SYMBOLS 0
#if LIBOMP_USE_VERSION_SYMBOLS
# define KMP_USE_VERSION_SYMBOLS
#endif
#define LIBOMP_HAVE_WEAK_ATTRIBUTE 1
#define KMP_HAVE_WEAK_ATTRIBUTE LIBOMP_HAVE_WEAK_ATTRIBUTE
#define LIBOMP_HAVE_PSAPI 0
#define KMP_HAVE_PSAPI LIBOMP_HAVE_PSAPI
#define LIBOMP_STATS 0
#define KMP_STATS_ENABLED LIBOMP_STATS
#ifdef __x86_64__
#define LIBOMP_HAVE_X86INTRIN_H 1
#else
#define LIBOMP_HAVE_X86INTRIN_H 0
#endif
#define KMP_HAVE_X86INTRIN_H LIBOMP_HAVE_X86INTRIN_H
#define LIBOMP_HAVE___BUILTIN_READCYCLECOUNTER 0
#define KMP_HAVE___BUILTIN_READCYCLECOUNTER LIBOMP_HAVE___BUILTIN_READCYCLECOUNTER
#define LIBOMP_HAVE___RDTSC 1
#define KMP_HAVE___RDTSC LIBOMP_HAVE___RDTSC
#define LIBOMP_USE_DEBUGGER 0
#define USE_DEBUGGER LIBOMP_USE_DEBUGGER
#define LIBOMP_OMPT_DEBUG 0
#define OMPT_DEBUG LIBOMP_OMPT_DEBUG
#define LIBOMP_OMPT_SUPPORT 1
#define OMPT_SUPPORT LIBOMP_OMPT_SUPPORT
#define LIBOMP_OMPD_SUPPORT 0
#define OMPD_SUPPORT LIBOMP_OMPD_SUPPORT
#define LIBOMP_OMPX_TASKGRAPH 0
#define OMPX_TASKGRAPH LIBOMP_OMPX_TASKGRAPH
#define LIBOMP_PROFILING_SUPPORT 0
#define OMP_PROFILING_SUPPORT LIBOMP_PROFILING_SUPPORT
#define LIBOMP_OMPT_OPTIONAL 0
#define OMPT_OPTIONAL LIBOMP_OMPT_OPTIONAL
#define LIBOMP_USE_ADAPTIVE_LOCKS 0
#define KMP_USE_ADAPTIVE_LOCKS LIBOMP_USE_ADAPTIVE_LOCKS
#define KMP_DEBUG_ADAPTIVE_LOCKS 0
#define LIBOMP_USE_INTERNODE_ALIGNMENT 0
#define KMP_USE_INTERNODE_ALIGNMENT LIBOMP_USE_INTERNODE_ALIGNMENT
#define LIBOMP_ENABLE_ASSERTIONS 0
#define KMP_USE_ASSERT LIBOMP_ENABLE_ASSERTIONS
#define LIBOMP_USE_HIER_SCHED 0
#define KMP_USE_HIER_SCHED LIBOMP_USE_HIER_SCHED
#define STUBS_LIBRARY 0
#define LIBOMP_USE_HWLOC 0
#define KMP_USE_HWLOC LIBOMP_USE_HWLOC
#define LIBOMP_ENABLE_SHARED 0
#define KMP_DYNAMIC_LIB LIBOMP_ENABLE_SHARED
#define KMP_ARCH_STR "@LIBOMP_LEGAL_ARCH@"
#define KMP_LIBRARY_FILE "@LIBOMP_LIB_FILE@"
#define KMP_VERSION_MAJOR 5
#define KMP_VERSION_MINOR 0
#define MSVC 0
#define KMP_MSVC_COMPAT MSVC
// #define LIBOMP_HAVE_WAITPKG_INTRINSICS
#define KMP_HAVE_WAITPKG_INTRINSICS LIBOMP_HAVE_WAITPKG_INTRINSICS
// #define LIBOMP_HAVE_RTM_INTRINSICS
#define KMP_HAVE_RTM_INTRINSICS LIBOMP_HAVE_RTM_INTRINSICS
#ifdef __x86_64__
#define LIBOMP_HAVE_IMMINTRIN_H 1
#else
#define LIBOMP_HAVE_IMMINTRIN_H 0
#endif
#define KMP_HAVE_IMMINTRIN_H LIBOMP_HAVE_IMMINTRIN_H
#define LIBOMP_HAVE_INTRIN_H 0
#define KMP_HAVE_INTRIN_H LIBOMP_HAVE_INTRIN_H
#define LIBOMP_HAVE_ATTRIBUTE_WAITPKG 0
#define KMP_HAVE_ATTRIBUTE_WAITPKG LIBOMP_HAVE_ATTRIBUTE_WAITPKG
#define LIBOMP_HAVE_ATTRIBUTE_RTM 0
#define KMP_HAVE_ATTRIBUTE_RTM LIBOMP_HAVE_ATTRIBUTE_RTM
#define LIBOMP_ARCH_AARCH64_A64FX 0
#define KMP_ARCH_AARCH64_A64FX LIBOMP_ARCH_AARCH64_A64FX
#ifdef __x86_64__
#define LIBOMP_HAVE_XMMINTRIN_H 1
#else
#define LIBOMP_HAVE_XMMINTRIN_H 0
#endif
#define KMP_HAVE_XMMINTRIN_H LIBOMP_HAVE_XMMINTRIN_H
#ifdef __x86_64__
#define LIBOMP_HAVE__MM_MALLOC 1
#else
#define LIBOMP_HAVE__MM_MALLOC 0
#endif
#define KMP_HAVE__MM_MALLOC LIBOMP_HAVE__MM_MALLOC
#define LIBOMP_HAVE_ALIGNED_ALLOC 1
#define KMP_HAVE_ALIGNED_ALLOC LIBOMP_HAVE_ALIGNED_ALLOC
#define LIBOMP_HAVE_POSIX_MEMALIGN 1
#define KMP_HAVE_POSIX_MEMALIGN LIBOMP_HAVE_POSIX_MEMALIGN
#define LIBOMP_HAVE__ALIGNED_MALLOC 0
#define KMP_HAVE__ALIGNED_MALLOC LIBOMP_HAVE__ALIGNED_MALLOC
#define OPENMP_ENABLE_LIBOMPTARGET 0
#define ENABLE_LIBOMPTARGET OPENMP_ENABLE_LIBOMPTARGET
// Configured cache line based on architecture
#if KMP_ARCH_PPC64 || KMP_ARCH_PPC
# define CACHE_LINE 128
#elif KMP_ARCH_AARCH64_A64FX
# define CACHE_LINE 256
#elif KMP_ARCH_S390X
# define CACHE_LINE 256
#else
# define CACHE_LINE 64
#endif
#if ! KMP_32_BIT_ARCH
# define BUILD_I8 1
#endif
#define KMP_NESTED_HOT_TEAMS 1
#define KMP_ADJUST_BLOCKTIME 1
#define BUILD_PARALLEL_ORDERED 1
#define KMP_ASM_INTRINS 1
#define USE_ITT_BUILD LIBOMP_USE_ITT_NOTIFY
#define INTEL_ITTNOTIFY_PREFIX __kmp_itt_
#if ! KMP_MIC
# define USE_LOAD_BALANCE 1
#endif
#if ! (KMP_OS_WINDOWS || KMP_OS_DARWIN)
# define KMP_TDATA_GTID 1
#endif
#if STUBS_LIBRARY
# define KMP_STUB 1
#endif
#if DEBUG_BUILD || RELWITHDEBINFO_BUILD
# define KMP_DEBUG 1
#endif
#if KMP_OS_WINDOWS
# define KMP_WIN_CDECL
#else
# define BUILD_TV
# define KMP_GOMP_COMPAT
#endif
// use shared memory with dynamic library (except Android, where shm_*
// functions don't exist).
#if KMP_OS_UNIX && KMP_DYNAMIC_LIB && !__ANDROID__
#define KMP_USE_SHM
#endif
#ifdef __COSMOPOLITAN__
#define KMP_USE_SHM
#endif
#endif // KMP_CONFIG_H

4569
third_party/openmp/kmp_csupport.cpp vendored Normal file

File diff suppressed because it is too large Load diff

131
third_party/openmp/kmp_debug.cpp vendored Normal file
View file

@ -0,0 +1,131 @@
/*
* kmp_debug.cpp -- debug utilities for the Guide library
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "kmp.h"
#include "kmp_debug.h" /* really necessary? */
#include "kmp_i18n.h"
#include "kmp_io.h"
#ifdef KMP_DEBUG
void __kmp_debug_printf_stdout(char const *format, ...) {
va_list ap;
va_start(ap, format);
__kmp_vprintf(kmp_out, format, ap);
va_end(ap);
}
#endif
void __kmp_debug_printf(char const *format, ...) {
va_list ap;
va_start(ap, format);
__kmp_vprintf(kmp_err, format, ap);
va_end(ap);
}
#ifdef KMP_USE_ASSERT
int __kmp_debug_assert(char const *msg, char const *file, int line) {
if (file == NULL) {
file = KMP_I18N_STR(UnknownFile);
} else {
// Remove directories from path, leave only file name. File name is enough,
// there is no need in bothering developers and customers with full paths.
char const *slash = strrchr(file, '/');
if (slash != NULL) {
file = slash + 1;
}
}
#ifdef KMP_DEBUG
__kmp_acquire_bootstrap_lock(&__kmp_stdio_lock);
__kmp_debug_printf("Assertion failure at %s(%d): %s.\n", file, line, msg);
__kmp_release_bootstrap_lock(&__kmp_stdio_lock);
#ifdef USE_ASSERT_BREAK
#if KMP_OS_WINDOWS
DebugBreak();
#endif
#endif // USE_ASSERT_BREAK
#ifdef USE_ASSERT_STALL
/* __kmp_infinite_loop(); */
for (;;)
;
#endif // USE_ASSERT_STALL
#ifdef USE_ASSERT_SEG
{
int volatile *ZERO = (int *)0;
++(*ZERO);
}
#endif // USE_ASSERT_SEG
#endif
__kmp_fatal(KMP_MSG(AssertionFailure, file, line), KMP_HNT(SubmitBugReport),
__kmp_msg_null);
return 0;
} // __kmp_debug_assert
#endif // KMP_USE_ASSERT
/* Dump debugging buffer to stderr */
void __kmp_dump_debug_buffer(void) {
if (__kmp_debug_buffer != NULL) {
int i;
int dc = __kmp_debug_count;
char *db = &__kmp_debug_buffer[(dc % __kmp_debug_buf_lines) *
__kmp_debug_buf_chars];
char *db_end =
&__kmp_debug_buffer[__kmp_debug_buf_lines * __kmp_debug_buf_chars];
char *db2;
__kmp_acquire_bootstrap_lock(&__kmp_stdio_lock);
__kmp_printf_no_lock("\nStart dump of debugging buffer (entry=%d):\n",
dc % __kmp_debug_buf_lines);
for (i = 0; i < __kmp_debug_buf_lines; i++) {
if (*db != '\0') {
/* Fix up where no carriage return before string termination char */
for (db2 = db + 1; db2 < db + __kmp_debug_buf_chars - 1; db2++) {
if (*db2 == '\0') {
if (*(db2 - 1) != '\n') {
*db2 = '\n';
*(db2 + 1) = '\0';
}
break;
}
}
/* Handle case at end by shortening the printed message by one char if
* necessary */
if (db2 == db + __kmp_debug_buf_chars - 1 && *db2 == '\0' &&
*(db2 - 1) != '\n') {
*(db2 - 1) = '\n';
}
__kmp_printf_no_lock("%4d: %.*s", i, __kmp_debug_buf_chars, db);
*db = '\0'; /* only let it print once! */
}
db += __kmp_debug_buf_chars;
if (db >= db_end)
db = __kmp_debug_buffer;
}
__kmp_printf_no_lock("End dump of debugging buffer (entry=%d).\n\n",
(dc + i - 1) % __kmp_debug_buf_lines);
__kmp_release_bootstrap_lock(&__kmp_stdio_lock);
}
}

179
third_party/openmp/kmp_debug.h vendored Normal file
View file

@ -0,0 +1,179 @@
/*
* kmp_debug.h -- debug / assertion code for Assure library
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef KMP_DEBUG_H
#define KMP_DEBUG_H
#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
// -----------------------------------------------------------------------------
// Build-time assertion.
// New C++11 style build assert
#define KMP_BUILD_ASSERT(expr) static_assert(expr, "Build condition error")
// -----------------------------------------------------------------------------
// Run-time assertions.
extern void __kmp_dump_debug_buffer(void);
#ifdef KMP_USE_ASSERT
extern int __kmp_debug_assert(char const *expr, char const *file, int line);
#ifdef KMP_DEBUG
#define KMP_ASSERT(cond) \
if (!(cond)) { \
__kmp_debug_assert(#cond, __FILE__, __LINE__); \
}
#define KMP_ASSERT2(cond, msg) \
if (!(cond)) { \
__kmp_debug_assert((msg), __FILE__, __LINE__); \
}
#define KMP_DEBUG_ASSERT(cond) KMP_ASSERT(cond)
#define KMP_DEBUG_ASSERT2(cond, msg) KMP_ASSERT2(cond, msg)
#define KMP_DEBUG_USE_VAR(x) /* Nothing (it is used!) */
#else
// Do not expose condition in release build. Use "assertion failure".
#define KMP_ASSERT(cond) \
if (!(cond)) { \
__kmp_debug_assert("assertion failure", __FILE__, __LINE__); \
}
#define KMP_ASSERT2(cond, msg) KMP_ASSERT(cond)
#define KMP_DEBUG_ASSERT(cond) /* Nothing */
#define KMP_DEBUG_ASSERT2(cond, msg) /* Nothing */
#define KMP_DEBUG_USE_VAR(x) ((void)(x))
#endif // KMP_DEBUG
#else
#define KMP_ASSERT(cond) /* Nothing */
#define KMP_ASSERT2(cond, msg) /* Nothing */
#define KMP_DEBUG_ASSERT(cond) /* Nothing */
#define KMP_DEBUG_ASSERT2(cond, msg) /* Nothing */
#define KMP_DEBUG_USE_VAR(x) ((void)(x))
#endif // KMP_USE_ASSERT
#ifdef KMP_DEBUG
extern void __kmp_debug_printf_stdout(char const *format, ...);
#endif
extern void __kmp_debug_printf(char const *format, ...);
#ifdef KMP_DEBUG
extern int kmp_a_debug;
extern int kmp_b_debug;
extern int kmp_c_debug;
extern int kmp_d_debug;
extern int kmp_e_debug;
extern int kmp_f_debug;
extern int kmp_diag;
#define KA_TRACE(d, x) \
if (kmp_a_debug >= d) { \
__kmp_debug_printf x; \
}
#define KB_TRACE(d, x) \
if (kmp_b_debug >= d) { \
__kmp_debug_printf x; \
}
#define KC_TRACE(d, x) \
if (kmp_c_debug >= d) { \
__kmp_debug_printf x; \
}
#define KD_TRACE(d, x) \
if (kmp_d_debug >= d) { \
__kmp_debug_printf x; \
}
#define KE_TRACE(d, x) \
if (kmp_e_debug >= d) { \
__kmp_debug_printf x; \
}
#define KF_TRACE(d, x) \
if (kmp_f_debug >= d) { \
__kmp_debug_printf x; \
}
#define K_DIAG(d, x) \
{ \
if (kmp_diag == d) { \
__kmp_debug_printf_stdout x; \
} \
}
#define KA_DUMP(d, x) \
if (kmp_a_debug >= d) { \
int ks; \
__kmp_disable(&ks); \
(x); \
__kmp_enable(ks); \
}
#define KB_DUMP(d, x) \
if (kmp_b_debug >= d) { \
int ks; \
__kmp_disable(&ks); \
(x); \
__kmp_enable(ks); \
}
#define KC_DUMP(d, x) \
if (kmp_c_debug >= d) { \
int ks; \
__kmp_disable(&ks); \
(x); \
__kmp_enable(ks); \
}
#define KD_DUMP(d, x) \
if (kmp_d_debug >= d) { \
int ks; \
__kmp_disable(&ks); \
(x); \
__kmp_enable(ks); \
}
#define KE_DUMP(d, x) \
if (kmp_e_debug >= d) { \
int ks; \
__kmp_disable(&ks); \
(x); \
__kmp_enable(ks); \
}
#define KF_DUMP(d, x) \
if (kmp_f_debug >= d) { \
int ks; \
__kmp_disable(&ks); \
(x); \
__kmp_enable(ks); \
}
#else
#define KA_TRACE(d, x) /* nothing to do */
#define KB_TRACE(d, x) /* nothing to do */
#define KC_TRACE(d, x) /* nothing to do */
#define KD_TRACE(d, x) /* nothing to do */
#define KE_TRACE(d, x) /* nothing to do */
#define KF_TRACE(d, x) /* nothing to do */
#define K_DIAG(d, x) \
{} /* nothing to do */
#define KA_DUMP(d, x) /* nothing to do */
#define KB_DUMP(d, x) /* nothing to do */
#define KC_DUMP(d, x) /* nothing to do */
#define KD_DUMP(d, x) /* nothing to do */
#define KE_DUMP(d, x) /* nothing to do */
#define KF_DUMP(d, x) /* nothing to do */
#endif // KMP_DEBUG
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif /* KMP_DEBUG_H */

286
third_party/openmp/kmp_debugger.cpp vendored Normal file
View file

@ -0,0 +1,286 @@
#include "kmp_config.h"
#if USE_DEBUGGER
/*
* kmp_debugger.cpp -- debugger support.
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "kmp.h"
#include "kmp_lock.h"
#include "kmp_omp.h"
#include "kmp_str.h"
// NOTE: All variable names are known to the debugger, do not change!
#ifdef __cplusplus
extern "C" {
extern kmp_omp_struct_info_t __kmp_omp_debug_struct_info;
} // extern "C"
#endif // __cplusplus
int __kmp_debugging = FALSE; // Boolean whether currently debugging OpenMP RTL.
#define offset_and_size_of(structure, field) \
{ offsetof(structure, field), sizeof(((structure *)NULL)->field) }
#define offset_and_size_not_available \
{ -1, -1 }
#define addr_and_size_of(var) \
{ (kmp_uint64)(&var), sizeof(var) }
#define nthr_buffer_size 1024
static kmp_int32 kmp_omp_nthr_info_buffer[nthr_buffer_size] = {
nthr_buffer_size * sizeof(kmp_int32)};
/* TODO: Check punctuation for various platforms here */
static char func_microtask[] = "__kmp_invoke_microtask";
static char func_fork[] = "__kmpc_fork_call";
static char func_fork_teams[] = "__kmpc_fork_teams";
// Various info about runtime structures: addresses, field offsets, sizes, etc.
kmp_omp_struct_info_t __kmp_omp_debug_struct_info = {
/* Change this only if you make a fundamental data structure change here */
KMP_OMP_VERSION,
/* sanity check. Only should be checked if versions are identical
* This is also used for backward compatibility to get the runtime
* structure size if it the runtime is older than the interface */
sizeof(kmp_omp_struct_info_t),
/* OpenMP RTL version info. */
addr_and_size_of(__kmp_version_major),
addr_and_size_of(__kmp_version_minor),
addr_and_size_of(__kmp_version_build),
addr_and_size_of(__kmp_openmp_version),
{(kmp_uint64)(__kmp_copyright) + KMP_VERSION_MAGIC_LEN,
0}, // Skip magic prefix.
/* Various globals. */
addr_and_size_of(__kmp_threads),
addr_and_size_of(__kmp_root),
addr_and_size_of(__kmp_threads_capacity),
#if KMP_USE_MONITOR
addr_and_size_of(__kmp_monitor),
#endif
#if !KMP_USE_DYNAMIC_LOCK
addr_and_size_of(__kmp_user_lock_table),
#endif
addr_and_size_of(func_microtask),
addr_and_size_of(func_fork),
addr_and_size_of(func_fork_teams),
addr_and_size_of(__kmp_team_counter),
addr_and_size_of(__kmp_task_counter),
addr_and_size_of(kmp_omp_nthr_info_buffer),
sizeof(void *),
OMP_LOCK_T_SIZE < sizeof(void *),
bs_last_barrier,
INITIAL_TASK_DEQUE_SIZE,
// thread structure information
sizeof(kmp_base_info_t),
offset_and_size_of(kmp_base_info_t, th_info),
offset_and_size_of(kmp_base_info_t, th_team),
offset_and_size_of(kmp_base_info_t, th_root),
offset_and_size_of(kmp_base_info_t, th_serial_team),
offset_and_size_of(kmp_base_info_t, th_ident),
offset_and_size_of(kmp_base_info_t, th_spin_here),
offset_and_size_of(kmp_base_info_t, th_next_waiting),
offset_and_size_of(kmp_base_info_t, th_task_team),
offset_and_size_of(kmp_base_info_t, th_current_task),
offset_and_size_of(kmp_base_info_t, th_task_state),
offset_and_size_of(kmp_base_info_t, th_bar),
offset_and_size_of(kmp_bstate_t, b_worker_arrived),
// teams information
offset_and_size_of(kmp_base_info_t, th_teams_microtask),
offset_and_size_of(kmp_base_info_t, th_teams_level),
offset_and_size_of(kmp_teams_size_t, nteams),
offset_and_size_of(kmp_teams_size_t, nth),
// kmp_desc structure (for info field above)
sizeof(kmp_desc_base_t),
offset_and_size_of(kmp_desc_base_t, ds_tid),
offset_and_size_of(kmp_desc_base_t, ds_gtid),
// On Windows* OS, ds_thread contains a thread /handle/, which is not usable,
// while thread /id/ is in ds_thread_id.
#if KMP_OS_WINDOWS
offset_and_size_of(kmp_desc_base_t, ds_thread_id),
#else
offset_and_size_of(kmp_desc_base_t, ds_thread),
#endif
// team structure information
sizeof(kmp_base_team_t),
offset_and_size_of(kmp_base_team_t, t_master_tid),
offset_and_size_of(kmp_base_team_t, t_ident),
offset_and_size_of(kmp_base_team_t, t_parent),
offset_and_size_of(kmp_base_team_t, t_nproc),
offset_and_size_of(kmp_base_team_t, t_threads),
offset_and_size_of(kmp_base_team_t, t_serialized),
offset_and_size_of(kmp_base_team_t, t_id),
offset_and_size_of(kmp_base_team_t, t_pkfn),
offset_and_size_of(kmp_base_team_t, t_task_team),
offset_and_size_of(kmp_base_team_t, t_implicit_task_taskdata),
offset_and_size_of(kmp_base_team_t, t_cancel_request),
offset_and_size_of(kmp_base_team_t, t_bar),
offset_and_size_of(kmp_balign_team_t, b_master_arrived),
offset_and_size_of(kmp_balign_team_t, b_team_arrived),
// root structure information
sizeof(kmp_base_root_t),
offset_and_size_of(kmp_base_root_t, r_root_team),
offset_and_size_of(kmp_base_root_t, r_hot_team),
offset_and_size_of(kmp_base_root_t, r_uber_thread),
offset_and_size_not_available,
// ident structure information
sizeof(ident_t),
offset_and_size_of(ident_t, psource),
offset_and_size_of(ident_t, flags),
// lock structure information
sizeof(kmp_base_queuing_lock_t),
offset_and_size_of(kmp_base_queuing_lock_t, initialized),
offset_and_size_of(kmp_base_queuing_lock_t, location),
offset_and_size_of(kmp_base_queuing_lock_t, tail_id),
offset_and_size_of(kmp_base_queuing_lock_t, head_id),
offset_and_size_of(kmp_base_queuing_lock_t, next_ticket),
offset_and_size_of(kmp_base_queuing_lock_t, now_serving),
offset_and_size_of(kmp_base_queuing_lock_t, owner_id),
offset_and_size_of(kmp_base_queuing_lock_t, depth_locked),
offset_and_size_of(kmp_base_queuing_lock_t, flags),
#if !KMP_USE_DYNAMIC_LOCK
/* Lock table. */
sizeof(kmp_lock_table_t),
offset_and_size_of(kmp_lock_table_t, used),
offset_and_size_of(kmp_lock_table_t, allocated),
offset_and_size_of(kmp_lock_table_t, table),
#endif
// Task team structure information.
sizeof(kmp_base_task_team_t),
offset_and_size_of(kmp_base_task_team_t, tt_threads_data),
offset_and_size_of(kmp_base_task_team_t, tt_found_tasks),
offset_and_size_of(kmp_base_task_team_t, tt_nproc),
offset_and_size_of(kmp_base_task_team_t, tt_unfinished_threads),
offset_and_size_of(kmp_base_task_team_t, tt_active),
// task_data_t.
sizeof(kmp_taskdata_t),
offset_and_size_of(kmp_taskdata_t, td_task_id),
offset_and_size_of(kmp_taskdata_t, td_flags),
offset_and_size_of(kmp_taskdata_t, td_team),
offset_and_size_of(kmp_taskdata_t, td_parent),
offset_and_size_of(kmp_taskdata_t, td_level),
offset_and_size_of(kmp_taskdata_t, td_ident),
offset_and_size_of(kmp_taskdata_t, td_allocated_child_tasks),
offset_and_size_of(kmp_taskdata_t, td_incomplete_child_tasks),
offset_and_size_of(kmp_taskdata_t, td_taskwait_ident),
offset_and_size_of(kmp_taskdata_t, td_taskwait_counter),
offset_and_size_of(kmp_taskdata_t, td_taskwait_thread),
offset_and_size_of(kmp_taskdata_t, td_taskgroup),
offset_and_size_of(kmp_taskgroup_t, count),
offset_and_size_of(kmp_taskgroup_t, cancel_request),
offset_and_size_of(kmp_taskdata_t, td_depnode),
offset_and_size_of(kmp_depnode_list_t, node),
offset_and_size_of(kmp_depnode_list_t, next),
offset_and_size_of(kmp_base_depnode_t, successors),
offset_and_size_of(kmp_base_depnode_t, task),
offset_and_size_of(kmp_base_depnode_t, npredecessors),
offset_and_size_of(kmp_base_depnode_t, nrefs),
offset_and_size_of(kmp_task_t, routine),
// thread_data_t.
sizeof(kmp_thread_data_t),
offset_and_size_of(kmp_base_thread_data_t, td_deque),
offset_and_size_of(kmp_base_thread_data_t, td_deque_size),
offset_and_size_of(kmp_base_thread_data_t, td_deque_head),
offset_and_size_of(kmp_base_thread_data_t, td_deque_tail),
offset_and_size_of(kmp_base_thread_data_t, td_deque_ntasks),
offset_and_size_of(kmp_base_thread_data_t, td_deque_last_stolen),
// The last field.
KMP_OMP_VERSION,
}; // __kmp_omp_debug_struct_info
#undef offset_and_size_of
#undef addr_and_size_of
/* Intel compiler on IA-32 architecture issues a warning "conversion
from "unsigned long long" to "char *" may lose significant bits"
when 64-bit value is assigned to 32-bit pointer. Use this function
to suppress the warning. */
static inline void *__kmp_convert_to_ptr(kmp_uint64 addr) {
#if KMP_COMPILER_ICC || KMP_COMPILER_ICX
#pragma warning(push)
#pragma warning(disable : 810) // conversion from "unsigned long long" to "char
// *" may lose significant bits
#pragma warning(disable : 1195) // conversion from integer to smaller pointer
#endif // KMP_COMPILER_ICC || KMP_COMPILER_ICX
return (void *)addr;
#if KMP_COMPILER_ICC || KMP_COMPILER_ICX
#pragma warning(pop)
#endif // KMP_COMPILER_ICC || KMP_COMPILER_ICX
} // __kmp_convert_to_ptr
static int kmp_location_match(kmp_str_loc_t *loc, kmp_omp_nthr_item_t *item) {
int file_match = 0;
int func_match = 0;
int line_match = 0;
char *file = (char *)__kmp_convert_to_ptr(item->file);
char *func = (char *)__kmp_convert_to_ptr(item->func);
file_match = __kmp_str_fname_match(&loc->fname, file);
func_match =
item->func == 0 // If item->func is NULL, it allows any func name.
|| strcmp(func, "*") == 0 ||
(loc->func != NULL && strcmp(loc->func, func) == 0);
line_match =
item->begin <= loc->line &&
(item->end <= 0 ||
loc->line <= item->end); // if item->end <= 0, it means "end of file".
return (file_match && func_match && line_match);
} // kmp_location_match
int __kmp_omp_num_threads(ident_t const *ident) {
int num_threads = 0;
kmp_omp_nthr_info_t *info = (kmp_omp_nthr_info_t *)__kmp_convert_to_ptr(
__kmp_omp_debug_struct_info.nthr_info.addr);
if (info->num > 0 && info->array != 0) {
kmp_omp_nthr_item_t *items =
(kmp_omp_nthr_item_t *)__kmp_convert_to_ptr(info->array);
kmp_str_loc_t loc = __kmp_str_loc_init(ident->psource, true);
int i;
for (i = 0; i < info->num; ++i) {
if (kmp_location_match(&loc, &items[i])) {
num_threads = items[i].num_threads;
}
}
__kmp_str_loc_free(&loc);
}
return num_threads;
;
} // __kmp_omp_num_threads
#endif /* USE_DEBUGGER */

48
third_party/openmp/kmp_debugger.h vendored Normal file
View file

@ -0,0 +1,48 @@
#if USE_DEBUGGER
/*
* kmp_debugger.h -- debugger support.
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef KMP_DEBUGGER_H
#define KMP_DEBUGGER_H
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
/* This external variable can be set by any debugger to flag to the runtime
that we are currently executing inside a debugger. This will allow the
debugger to override the number of threads spawned in a parallel region by
using __kmp_omp_num_threads() (below).
* When __kmp_debugging is TRUE, each team and each task gets a unique integer
identifier that can be used by debugger to conveniently identify teams and
tasks.
* The debugger has access to __kmp_omp_debug_struct_info which contains
information about the OpenMP library's important internal structures. This
access will allow the debugger to read detailed information from the typical
OpenMP constructs (teams, threads, tasking, etc. ) during a debugging
session and offer detailed and useful information which the user can probe
about the OpenMP portion of their code. */
extern int __kmp_debugging; /* Boolean whether currently debugging OpenMP RTL */
// Return number of threads specified by the debugger for given parallel region.
/* The ident field, which represents a source file location, is used to check if
the debugger has changed the number of threads for the parallel region at
source file location ident. This way, specific parallel regions' number of
threads can be changed at the debugger's request. */
int __kmp_omp_num_threads(ident_t const *ident);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // KMP_DEBUGGER_H
#endif // USE_DEBUGGER

3142
third_party/openmp/kmp_dispatch.cpp vendored Normal file

File diff suppressed because it is too large Load diff

513
third_party/openmp/kmp_dispatch.h vendored Normal file
View file

@ -0,0 +1,513 @@
/*
* kmp_dispatch.h: dynamic scheduling - iteration initialization and dispatch.
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef KMP_DISPATCH_H
#define KMP_DISPATCH_H
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
#include "kmp.h"
#include "kmp_error.h"
#include "kmp_i18n.h"
#include "kmp_itt.h"
#include "kmp_stats.h"
#include "kmp_str.h"
#if KMP_OS_WINDOWS && KMP_ARCH_X86
#include <float.h>
#endif
#if OMPT_SUPPORT
#include "ompt-internal.h"
#include "ompt-specific.h"
#endif
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
#if KMP_USE_HIER_SCHED
// Forward declarations of some hierarchical scheduling data structures
template <typename T> struct kmp_hier_t;
template <typename T> struct kmp_hier_top_unit_t;
#endif // KMP_USE_HIER_SCHED
template <typename T> struct dispatch_shared_info_template;
template <typename T> struct dispatch_private_info_template;
template <typename T>
extern void __kmp_dispatch_init_algorithm(ident_t *loc, int gtid,
dispatch_private_info_template<T> *pr,
enum sched_type schedule, T lb, T ub,
typename traits_t<T>::signed_t st,
#if USE_ITT_BUILD
kmp_uint64 *cur_chunk,
#endif
typename traits_t<T>::signed_t chunk,
T nproc, T unit_id);
template <typename T>
extern int __kmp_dispatch_next_algorithm(
int gtid, dispatch_private_info_template<T> *pr,
dispatch_shared_info_template<T> volatile *sh, kmp_int32 *p_last, T *p_lb,
T *p_ub, typename traits_t<T>::signed_t *p_st, T nproc, T unit_id);
void __kmp_dispatch_dxo_error(int *gtid_ref, int *cid_ref, ident_t *loc_ref);
void __kmp_dispatch_deo_error(int *gtid_ref, int *cid_ref, ident_t *loc_ref);
#if KMP_STATIC_STEAL_ENABLED
// replaces dispatch_private_info{32,64} structures and
// dispatch_private_info{32,64}_t types
template <typename T> struct dispatch_private_infoXX_template {
typedef typename traits_t<T>::unsigned_t UT;
typedef typename traits_t<T>::signed_t ST;
UT count; // unsigned
T ub;
/* Adding KMP_ALIGN_CACHE here doesn't help / can hurt performance */
T lb;
ST st; // signed
UT tc; // unsigned
kmp_lock_t *steal_lock; // lock used for chunk stealing
UT ordered_lower; // unsigned
UT ordered_upper; // unsigned
/* parm[1-4] are used in different ways by different scheduling algorithms */
// KMP_ALIGN(32) ensures ( if the KMP_ALIGN macro is turned on )
// a) parm3 is properly aligned and
// b) all parm1-4 are in the same cache line.
// Because of parm1-4 are used together, performance seems to be better
// if they are in the same line (not measured though).
struct KMP_ALIGN(32) { // compiler does not accept sizeof(T)*4
T parm1;
T parm2;
T parm3;
T parm4;
};
#if KMP_WEIGHTED_ITERATIONS_SUPPORTED
UT pchunks; // total number of chunks for processes with p-core
UT num_procs_with_pcore; // number of threads with p-core
T first_thread_with_ecore;
#endif
#if KMP_OS_WINDOWS
T last_upper;
#endif /* KMP_OS_WINDOWS */
};
#else /* KMP_STATIC_STEAL_ENABLED */
// replaces dispatch_private_info{32,64} structures and
// dispatch_private_info{32,64}_t types
template <typename T> struct dispatch_private_infoXX_template {
typedef typename traits_t<T>::unsigned_t UT;
typedef typename traits_t<T>::signed_t ST;
T lb;
T ub;
ST st; // signed
UT tc; // unsigned
T parm1;
T parm2;
T parm3;
T parm4;
UT count; // unsigned
UT ordered_lower; // unsigned
UT ordered_upper; // unsigned
#if KMP_OS_WINDOWS
T last_upper;
#endif /* KMP_OS_WINDOWS */
};
#endif /* KMP_STATIC_STEAL_ENABLED */
template <typename T> struct KMP_ALIGN_CACHE dispatch_private_info_template {
// duplicate alignment here, otherwise size of structure is not correct in our
// compiler
union KMP_ALIGN_CACHE private_info_tmpl {
dispatch_private_infoXX_template<T> p;
dispatch_private_info64_t p64;
} u;
enum sched_type schedule; /* scheduling algorithm */
kmp_sched_flags_t flags; /* flags (e.g., ordered, nomerge, etc.) */
std::atomic<kmp_uint32> steal_flag; // static_steal only, state of a buffer
kmp_uint32 ordered_bumped;
dispatch_private_info *next; /* stack of buffers for nest of serial regions */
kmp_uint32 type_size;
#if KMP_USE_HIER_SCHED
kmp_int32 hier_id;
kmp_hier_top_unit_t<T> *hier_parent;
// member functions
kmp_int32 get_hier_id() const { return hier_id; }
kmp_hier_top_unit_t<T> *get_parent() { return hier_parent; }
#endif
enum cons_type pushed_ws;
};
// replaces dispatch_shared_info{32,64} structures and
// dispatch_shared_info{32,64}_t types
template <typename T> struct dispatch_shared_infoXX_template {
typedef typename traits_t<T>::unsigned_t UT;
typedef typename traits_t<T>::signed_t ST;
/* chunk index under dynamic, number of idle threads under static-steal;
iteration index otherwise */
volatile UT iteration;
volatile ST num_done;
volatile UT ordered_iteration;
// to retain the structure size making ordered_iteration scalar
UT ordered_dummy[KMP_MAX_ORDERED - 3];
};
// replaces dispatch_shared_info structure and dispatch_shared_info_t type
template <typename T> struct dispatch_shared_info_template {
typedef typename traits_t<T>::unsigned_t UT;
// we need union here to keep the structure size
union shared_info_tmpl {
dispatch_shared_infoXX_template<UT> s;
dispatch_shared_info64_t s64;
} u;
volatile kmp_uint32 buffer_index;
volatile kmp_int32 doacross_buf_idx; // teamwise index
kmp_uint32 *doacross_flags; // array of iteration flags (0/1)
kmp_int32 doacross_num_done; // count finished threads
#if KMP_USE_HIER_SCHED
kmp_hier_t<T> *hier;
#endif
#if KMP_USE_HWLOC
// When linking with libhwloc, the ORDERED EPCC test slowsdown on big
// machines (> 48 cores). Performance analysis showed that a cache thrash
// was occurring and this padding helps alleviate the problem.
char padding[64];
#endif
};
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
#undef USE_TEST_LOCKS
// test_then_add template (general template should NOT be used)
template <typename T> static __forceinline T test_then_add(volatile T *p, T d);
template <>
__forceinline kmp_int32 test_then_add<kmp_int32>(volatile kmp_int32 *p,
kmp_int32 d) {
kmp_int32 r;
r = KMP_TEST_THEN_ADD32(p, d);
return r;
}
template <>
__forceinline kmp_int64 test_then_add<kmp_int64>(volatile kmp_int64 *p,
kmp_int64 d) {
kmp_int64 r;
r = KMP_TEST_THEN_ADD64(p, d);
return r;
}
// test_then_inc_acq template (general template should NOT be used)
template <typename T> static __forceinline T test_then_inc_acq(volatile T *p);
template <>
__forceinline kmp_int32 test_then_inc_acq<kmp_int32>(volatile kmp_int32 *p) {
kmp_int32 r;
r = KMP_TEST_THEN_INC_ACQ32(p);
return r;
}
template <>
__forceinline kmp_int64 test_then_inc_acq<kmp_int64>(volatile kmp_int64 *p) {
kmp_int64 r;
r = KMP_TEST_THEN_INC_ACQ64(p);
return r;
}
// test_then_inc template (general template should NOT be used)
template <typename T> static __forceinline T test_then_inc(volatile T *p);
template <>
__forceinline kmp_int32 test_then_inc<kmp_int32>(volatile kmp_int32 *p) {
kmp_int32 r;
r = KMP_TEST_THEN_INC32(p);
return r;
}
template <>
__forceinline kmp_int64 test_then_inc<kmp_int64>(volatile kmp_int64 *p) {
kmp_int64 r;
r = KMP_TEST_THEN_INC64(p);
return r;
}
// compare_and_swap template (general template should NOT be used)
template <typename T>
static __forceinline kmp_int32 compare_and_swap(volatile T *p, T c, T s);
template <>
__forceinline kmp_int32 compare_and_swap<kmp_int32>(volatile kmp_int32 *p,
kmp_int32 c, kmp_int32 s) {
return KMP_COMPARE_AND_STORE_REL32(p, c, s);
}
template <>
__forceinline kmp_int32 compare_and_swap<kmp_int64>(volatile kmp_int64 *p,
kmp_int64 c, kmp_int64 s) {
return KMP_COMPARE_AND_STORE_REL64(p, c, s);
}
template <typename T> kmp_uint32 __kmp_ge(T value, T checker) {
return value >= checker;
}
template <typename T> kmp_uint32 __kmp_eq(T value, T checker) {
return value == checker;
}
/*
Spin wait loop that pauses between checks.
Waits until function returns non-zero when called with *spinner and check.
Does NOT put threads to sleep.
Arguments:
UT is unsigned 4- or 8-byte type
spinner - memory location to check value
checker - value which spinner is >, <, ==, etc.
pred - predicate function to perform binary comparison of some sort
#if USE_ITT_BUILD
obj -- is higher-level synchronization object to report to ittnotify. It
is used to report locks consistently. For example, if lock is acquired
immediately, its address is reported to ittnotify via
KMP_FSYNC_ACQUIRED(). However, it lock cannot be acquired immediately
and lock routine calls to KMP_WAIT(), the later should report the
same address, not an address of low-level spinner.
#endif // USE_ITT_BUILD
TODO: make inline function (move to header file for icl)
*/
template <typename UT>
static UT __kmp_wait(volatile UT *spinner, UT checker,
kmp_uint32 (*pred)(UT, UT) USE_ITT_BUILD_ARG(void *obj)) {
// note: we may not belong to a team at this point
volatile UT *spin = spinner;
UT check = checker;
kmp_uint32 spins;
kmp_uint32 (*f)(UT, UT) = pred;
kmp_uint64 time;
UT r;
KMP_FSYNC_SPIN_INIT(obj, CCAST(UT *, spin));
KMP_INIT_YIELD(spins);
KMP_INIT_BACKOFF(time);
// main wait spin loop
while (!f(r = *spin, check)) {
KMP_FSYNC_SPIN_PREPARE(obj);
/* GEH - remove this since it was accidentally introduced when kmp_wait was
split.
It causes problems with infinite recursion because of exit lock */
/* if ( TCR_4(__kmp_global.g.g_done) && __kmp_global.g.g_abort)
__kmp_abort_thread(); */
// If oversubscribed, or have waited a bit then yield.
KMP_YIELD_OVERSUB_ELSE_SPIN(spins, time);
}
KMP_FSYNC_SPIN_ACQUIRED(obj);
return r;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
template <typename UT>
void __kmp_dispatch_deo(int *gtid_ref, int *cid_ref, ident_t *loc_ref) {
dispatch_private_info_template<UT> *pr;
int gtid = *gtid_ref;
// int cid = *cid_ref;
kmp_info_t *th = __kmp_threads[gtid];
KMP_DEBUG_ASSERT(th->th.th_dispatch);
KD_TRACE(100, ("__kmp_dispatch_deo: T#%d called\n", gtid));
if (__kmp_env_consistency_check) {
pr = reinterpret_cast<dispatch_private_info_template<UT> *>(
th->th.th_dispatch->th_dispatch_pr_current);
if (pr->pushed_ws != ct_none) {
#if KMP_USE_DYNAMIC_LOCK
__kmp_push_sync(gtid, ct_ordered_in_pdo, loc_ref, NULL, 0);
#else
__kmp_push_sync(gtid, ct_ordered_in_pdo, loc_ref, NULL);
#endif
}
}
if (!th->th.th_team->t.t_serialized) {
dispatch_shared_info_template<UT> *sh =
reinterpret_cast<dispatch_shared_info_template<UT> *>(
th->th.th_dispatch->th_dispatch_sh_current);
UT lower;
if (!__kmp_env_consistency_check) {
pr = reinterpret_cast<dispatch_private_info_template<UT> *>(
th->th.th_dispatch->th_dispatch_pr_current);
}
lower = pr->u.p.ordered_lower;
#if !defined(KMP_GOMP_COMPAT)
if (__kmp_env_consistency_check) {
if (pr->ordered_bumped) {
struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
__kmp_error_construct2(kmp_i18n_msg_CnsMultipleNesting,
ct_ordered_in_pdo, loc_ref,
&p->stack_data[p->w_top]);
}
}
#endif /* !defined(KMP_GOMP_COMPAT) */
KMP_MB();
#ifdef KMP_DEBUG
{
char *buff;
// create format specifiers before the debug output
buff = __kmp_str_format("__kmp_dispatch_deo: T#%%d before wait: "
"ordered_iter:%%%s lower:%%%s\n",
traits_t<UT>::spec, traits_t<UT>::spec);
KD_TRACE(1000, (buff, gtid, sh->u.s.ordered_iteration, lower));
__kmp_str_free(&buff);
}
#endif
__kmp_wait<UT>(&sh->u.s.ordered_iteration, lower,
__kmp_ge<UT> USE_ITT_BUILD_ARG(NULL));
KMP_MB(); /* is this necessary? */
#ifdef KMP_DEBUG
{
char *buff;
// create format specifiers before the debug output
buff = __kmp_str_format("__kmp_dispatch_deo: T#%%d after wait: "
"ordered_iter:%%%s lower:%%%s\n",
traits_t<UT>::spec, traits_t<UT>::spec);
KD_TRACE(1000, (buff, gtid, sh->u.s.ordered_iteration, lower));
__kmp_str_free(&buff);
}
#endif
}
KD_TRACE(100, ("__kmp_dispatch_deo: T#%d returned\n", gtid));
}
template <typename UT>
void __kmp_dispatch_dxo(int *gtid_ref, int *cid_ref, ident_t *loc_ref) {
typedef typename traits_t<UT>::signed_t ST;
dispatch_private_info_template<UT> *pr;
int gtid = *gtid_ref;
// int cid = *cid_ref;
kmp_info_t *th = __kmp_threads[gtid];
KMP_DEBUG_ASSERT(th->th.th_dispatch);
KD_TRACE(100, ("__kmp_dispatch_dxo: T#%d called\n", gtid));
if (__kmp_env_consistency_check) {
pr = reinterpret_cast<dispatch_private_info_template<UT> *>(
th->th.th_dispatch->th_dispatch_pr_current);
if (pr->pushed_ws != ct_none) {
__kmp_pop_sync(gtid, ct_ordered_in_pdo, loc_ref);
}
}
if (!th->th.th_team->t.t_serialized) {
dispatch_shared_info_template<UT> *sh =
reinterpret_cast<dispatch_shared_info_template<UT> *>(
th->th.th_dispatch->th_dispatch_sh_current);
if (!__kmp_env_consistency_check) {
pr = reinterpret_cast<dispatch_private_info_template<UT> *>(
th->th.th_dispatch->th_dispatch_pr_current);
}
KMP_FSYNC_RELEASING(CCAST(UT *, &sh->u.s.ordered_iteration));
#if !defined(KMP_GOMP_COMPAT)
if (__kmp_env_consistency_check) {
if (pr->ordered_bumped != 0) {
struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
/* How to test it? - OM */
__kmp_error_construct2(kmp_i18n_msg_CnsMultipleNesting,
ct_ordered_in_pdo, loc_ref,
&p->stack_data[p->w_top]);
}
}
#endif /* !defined(KMP_GOMP_COMPAT) */
KMP_MB(); /* Flush all pending memory write invalidates. */
pr->ordered_bumped += 1;
KD_TRACE(1000,
("__kmp_dispatch_dxo: T#%d bumping ordered ordered_bumped=%d\n",
gtid, pr->ordered_bumped));
KMP_MB(); /* Flush all pending memory write invalidates. */
/* TODO use general release procedure? */
test_then_inc<ST>((volatile ST *)&sh->u.s.ordered_iteration);
KMP_MB(); /* Flush all pending memory write invalidates. */
}
KD_TRACE(100, ("__kmp_dispatch_dxo: T#%d returned\n", gtid));
}
/* Computes and returns x to the power of y, where y must a non-negative integer
*/
template <typename UT>
static __forceinline long double __kmp_pow(long double x, UT y) {
long double s = 1.0L;
KMP_DEBUG_ASSERT(x > 0.0 && x < 1.0);
// KMP_DEBUG_ASSERT(y >= 0); // y is unsigned
while (y) {
if (y & 1)
s *= x;
x *= x;
y >>= 1;
}
return s;
}
/* Computes and returns the number of unassigned iterations after idx chunks
have been assigned
(the total number of unassigned iterations in chunks with index greater than
or equal to idx).
__forceinline seems to be broken so that if we __forceinline this function,
the behavior is wrong
(one of the unit tests, sch_guided_analytical_basic.cpp, fails)
*/
template <typename T>
static __inline typename traits_t<T>::unsigned_t
__kmp_dispatch_guided_remaining(T tc, typename traits_t<T>::floating_t base,
typename traits_t<T>::unsigned_t idx) {
/* Note: On Windows* OS on IA-32 architecture and Intel(R) 64, at
least for ICL 8.1, long double arithmetic may not really have
long double precision, even with /Qlong_double. Currently, we
workaround that in the caller code, by manipulating the FPCW for
Windows* OS on IA-32 architecture. The lack of precision is not
expected to be a correctness issue, though.
*/
typedef typename traits_t<T>::unsigned_t UT;
long double x = tc * __kmp_pow<UT>(base, idx);
UT r = (UT)x;
if (x == r)
return r;
return r + 1;
}
// Parameters of the guided-iterative algorithm:
// p2 = n * nproc * ( chunk + 1 ) // point of switching to dynamic
// p3 = 1 / ( n * nproc ) // remaining iterations multiplier
// by default n = 2. For example with n = 3 the chunks distribution will be more
// flat.
// With n = 1 first chunk is the same as for static schedule, e.g. trip / nproc.
static const int guided_int_param = 2;
static const double guided_flt_param = 0.5; // = 1.0 / guided_int_param;
#endif // KMP_DISPATCH_H

1112
third_party/openmp/kmp_dispatch_hier.h vendored Normal file

File diff suppressed because it is too large Load diff

500
third_party/openmp/kmp_environment.cpp vendored Normal file
View file

@ -0,0 +1,500 @@
/*
* kmp_environment.cpp -- Handle environment variables OS-independently.
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
/* We use GetEnvironmentVariable for Windows* OS instead of getenv because the
act of loading a DLL on Windows* OS makes any user-set environment variables
(i.e. with putenv()) unavailable. getenv() apparently gets a clean copy of
the env variables as they existed at the start of the run. JH 12/23/2002
On Windows* OS, there are two environments (at least, see below):
1. Environment maintained by Windows* OS on IA-32 architecture. Accessible
through GetEnvironmentVariable(), SetEnvironmentVariable(), and
GetEnvironmentStrings().
2. Environment maintained by C RTL. Accessible through getenv(), putenv().
putenv() function updates both C and Windows* OS on IA-32 architecture.
getenv() function search for variables in C RTL environment only.
Windows* OS on IA-32 architecture functions work *only* with Windows* OS on
IA-32 architecture.
Windows* OS on IA-32 architecture maintained by OS, so there is always only
one Windows* OS on IA-32 architecture per process. Changes in Windows* OS on
IA-32 architecture are process-visible.
C environment maintained by C RTL. Multiple copies of C RTL may be present
in the process, and each C RTL maintains its own environment. :-(
Thus, proper way to work with environment on Windows* OS is:
1. Set variables with putenv() function -- both C and Windows* OS on IA-32
architecture are being updated. Windows* OS on IA-32 architecture may be
considered primary target, while updating C RTL environment is free bonus.
2. Get variables with GetEnvironmentVariable() -- getenv() does not
search Windows* OS on IA-32 architecture, and can not see variables
set with SetEnvironmentVariable().
2007-04-05 -- lev
*/
#include "kmp_environment.h"
#include "kmp.h" //
#include "kmp_i18n.h"
#include "kmp_os.h" // KMP_OS_*.
#include "kmp_str.h" // __kmp_str_*().
#if KMP_OS_UNIX
#include <stdlib.h> // getenv, setenv, unsetenv.
#include <string.h> // strlen, strcpy.
#if KMP_OS_DARWIN
#include <crt_externs.h>
#define environ (*_NSGetEnviron())
#else
extern char **environ;
#endif
#elif KMP_OS_WINDOWS
#include <windows.h> // GetEnvironmentVariable, SetEnvironmentVariable,
// GetLastError.
#else
#error Unknown or unsupported OS.
#endif
// TODO: Eliminate direct memory allocations, use string operations instead.
static inline void *allocate(size_t size) {
void *ptr = KMP_INTERNAL_MALLOC(size);
if (ptr == NULL) {
KMP_FATAL(MemoryAllocFailed);
}
return ptr;
} // allocate
char *__kmp_env_get(char const *name) {
char *result = NULL;
#if KMP_OS_UNIX
char const *value = getenv(name);
if (value != NULL) {
size_t len = KMP_STRLEN(value) + 1;
result = (char *)KMP_INTERNAL_MALLOC(len);
if (result == NULL) {
KMP_FATAL(MemoryAllocFailed);
}
KMP_STRNCPY_S(result, len, value, len);
}
#elif KMP_OS_WINDOWS
/* We use GetEnvironmentVariable for Windows* OS instead of getenv because the
act of loading a DLL on Windows* OS makes any user-set environment
variables (i.e. with putenv()) unavailable. getenv() apparently gets a
clean copy of the env variables as they existed at the start of the run.
JH 12/23/2002 */
DWORD rc;
rc = GetEnvironmentVariable(name, NULL, 0);
if (!rc) {
DWORD error = GetLastError();
if (error != ERROR_ENVVAR_NOT_FOUND) {
__kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
}
// Variable is not found, it's ok, just continue.
} else {
DWORD len = rc;
result = (char *)KMP_INTERNAL_MALLOC(len);
if (result == NULL) {
KMP_FATAL(MemoryAllocFailed);
}
rc = GetEnvironmentVariable(name, result, len);
if (!rc) {
// GetEnvironmentVariable() may return 0 if variable is empty.
// In such a case GetLastError() returns ERROR_SUCCESS.
DWORD error = GetLastError();
if (error != ERROR_SUCCESS) {
// Unexpected error. The variable should be in the environment,
// and buffer should be large enough.
__kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error),
__kmp_msg_null);
KMP_INTERNAL_FREE((void *)result);
result = NULL;
}
}
}
#else
#error Unknown or unsupported OS.
#endif
return result;
} // func __kmp_env_get
// TODO: Find and replace all regular free() with __kmp_env_free().
void __kmp_env_free(char const **value) {
KMP_DEBUG_ASSERT(value != NULL);
KMP_INTERNAL_FREE(CCAST(char *, *value));
*value = NULL;
} // func __kmp_env_free
int __kmp_env_exists(char const *name) {
#if KMP_OS_UNIX
char const *value = getenv(name);
return ((value == NULL) ? (0) : (1));
#elif KMP_OS_WINDOWS
DWORD rc;
rc = GetEnvironmentVariable(name, NULL, 0);
if (rc == 0) {
DWORD error = GetLastError();
if (error != ERROR_ENVVAR_NOT_FOUND) {
__kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
}
return 0;
}
return 1;
#else
#error Unknown or unsupported OS.
#endif
} // func __kmp_env_exists
void __kmp_env_set(char const *name, char const *value, int overwrite) {
#if KMP_OS_UNIX
int rc = setenv(name, value, overwrite);
if (rc != 0) {
// Dead code. I tried to put too many variables into Linux* OS
// environment on IA-32 architecture. When application consumes
// more than ~2.5 GB of memory, entire system feels bad. Sometimes
// application is killed (by OS?), sometimes system stops
// responding... But this error message never appears. --ln
__kmp_fatal(KMP_MSG(CantSetEnvVar, name), KMP_HNT(NotEnoughMemory),
__kmp_msg_null);
}
#elif KMP_OS_WINDOWS
BOOL rc;
if (!overwrite) {
rc = GetEnvironmentVariable(name, NULL, 0);
if (rc) {
// Variable exists, do not overwrite.
return;
}
DWORD error = GetLastError();
if (error != ERROR_ENVVAR_NOT_FOUND) {
__kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
}
}
rc = SetEnvironmentVariable(name, value);
if (!rc) {
DWORD error = GetLastError();
__kmp_fatal(KMP_MSG(CantSetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
}
#else
#error Unknown or unsupported OS.
#endif
} // func __kmp_env_set
void __kmp_env_unset(char const *name) {
#if KMP_OS_UNIX
unsetenv(name);
#elif KMP_OS_WINDOWS
BOOL rc = SetEnvironmentVariable(name, NULL);
if (!rc) {
DWORD error = GetLastError();
__kmp_fatal(KMP_MSG(CantSetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
}
#else
#error Unknown or unsupported OS.
#endif
} // func __kmp_env_unset
/* Intel OpenMP RTL string representation of environment: just a string of
characters, variables are separated with vertical bars, e. g.:
"KMP_WARNINGS=0|KMP_AFFINITY=compact|"
Empty variables are allowed and ignored:
"||KMP_WARNINGS=1||"
*/
static void
___kmp_env_blk_parse_string(kmp_env_blk_t *block, // M: Env block to fill.
char const *env // I: String to parse.
) {
char const chr_delimiter = '|';
char const str_delimiter[] = {chr_delimiter, 0};
char *bulk = NULL;
kmp_env_var_t *vars = NULL;
int count = 0; // Number of used elements in vars array.
int delimiters = 0; // Number of delimiters in input string.
// Copy original string, we will modify the copy.
bulk = __kmp_str_format("%s", env);
// Loop thru all the vars in environment block. Count delimiters (maximum
// number of variables is number of delimiters plus one).
{
char const *ptr = bulk;
for (;;) {
ptr = strchr(ptr, chr_delimiter);
if (ptr == NULL) {
break;
}
++delimiters;
ptr += 1;
}
}
// Allocate vars array.
vars = (kmp_env_var_t *)allocate((delimiters + 1) * sizeof(kmp_env_var_t));
// Loop thru all the variables.
{
char *var; // Pointer to variable (both name and value).
char *name; // Pointer to name of variable.
char *value; // Pointer to value.
char *buf; // Buffer for __kmp_str_token() function.
var = __kmp_str_token(bulk, str_delimiter, &buf); // Get the first var.
while (var != NULL) {
// Save found variable in vars array.
__kmp_str_split(var, '=', &name, &value);
KMP_DEBUG_ASSERT(count < delimiters + 1);
vars[count].name = name;
vars[count].value = value;
++count;
// Get the next var.
var = __kmp_str_token(NULL, str_delimiter, &buf);
}
}
// Fill out result.
block->bulk = bulk;
block->vars = vars;
block->count = count;
}
/* Windows* OS (actually, DOS) environment block is a piece of memory with
environment variables. Each variable is terminated with zero byte, entire
block is terminated with one extra zero byte, so we have two zero bytes at
the end of environment block, e. g.:
"HOME=C:\\users\\lev\x00OS=Windows_NT\x00\x00"
It is not clear how empty environment is represented. "\x00\x00"?
*/
#if KMP_OS_WINDOWS
static void ___kmp_env_blk_parse_windows(
kmp_env_blk_t *block, // M: Env block to fill.
char const *env // I: Pointer to Windows* OS (DOS) environment block.
) {
char *bulk = NULL;
kmp_env_var_t *vars = NULL;
int count = 0; // Number of used elements in vars array.
int size = 0; // Size of bulk.
char *name; // Pointer to name of variable.
char *value; // Pointer to value.
if (env != NULL) {
// Loop thru all the vars in environment block. Count variables, find size
// of block.
{
char const *var; // Pointer to beginning of var.
int len; // Length of variable.
count = 0;
var =
env; // The first variable starts and beginning of environment block.
len = KMP_STRLEN(var);
while (len != 0) {
++count;
size = size + len + 1;
var = var + len +
1; // Move pointer to the beginning of the next variable.
len = KMP_STRLEN(var);
}
size =
size + 1; // Total size of env block, including terminating zero byte.
}
// Copy original block to bulk, we will modify bulk, not original block.
bulk = (char *)allocate(size);
KMP_MEMCPY_S(bulk, size, env, size);
// Allocate vars array.
vars = (kmp_env_var_t *)allocate(count * sizeof(kmp_env_var_t));
// Loop thru all the vars, now in bulk.
{
char *var; // Pointer to beginning of var.
int len; // Length of variable.
count = 0;
var = bulk;
len = KMP_STRLEN(var);
while (len != 0) {
// Save variable in vars array.
__kmp_str_split(var, '=', &name, &value);
vars[count].name = name;
vars[count].value = value;
++count;
// Get the next var.
var = var + len + 1;
len = KMP_STRLEN(var);
}
}
}
// Fill out result.
block->bulk = bulk;
block->vars = vars;
block->count = count;
}
#endif
/* Unix environment block is a array of pointers to variables, last pointer in
array is NULL:
{ "HOME=/home/lev", "TERM=xterm", NULL }
*/
#if KMP_OS_UNIX
static void
___kmp_env_blk_parse_unix(kmp_env_blk_t *block, // M: Env block to fill.
char **env // I: Unix environment to parse.
) {
char *bulk = NULL;
kmp_env_var_t *vars = NULL;
int count = 0;
size_t size = 0; // Size of bulk.
// Count number of variables and length of required bulk.
{
while (env[count] != NULL) {
size += KMP_STRLEN(env[count]) + 1;
++count;
}
}
// Allocate memory.
bulk = (char *)allocate(size);
vars = (kmp_env_var_t *)allocate(count * sizeof(kmp_env_var_t));
// Loop thru all the vars.
{
char *var; // Pointer to beginning of var.
char *name; // Pointer to name of variable.
char *value; // Pointer to value.
size_t len; // Length of variable.
int i;
var = bulk;
for (i = 0; i < count; ++i) {
KMP_ASSERT(var < bulk + size);
[[maybe_unused]] size_t ssize = size - (var - bulk);
// Copy variable to bulk.
len = KMP_STRLEN(env[i]);
KMP_MEMCPY_S(var, ssize, env[i], len + 1);
// Save found variable in vars array.
__kmp_str_split(var, '=', &name, &value);
vars[i].name = name;
vars[i].value = value;
// Move pointer.
var += len + 1;
}
}
// Fill out result.
block->bulk = bulk;
block->vars = vars;
block->count = count;
}
#endif
void __kmp_env_blk_init(kmp_env_blk_t *block, // M: Block to initialize.
char const *bulk // I: Initialization string, or NULL.
) {
if (bulk != NULL) {
___kmp_env_blk_parse_string(block, bulk);
} else {
#if KMP_OS_UNIX
___kmp_env_blk_parse_unix(block, environ);
#elif KMP_OS_WINDOWS
{
char *mem = GetEnvironmentStrings();
if (mem == NULL) {
DWORD error = GetLastError();
__kmp_fatal(KMP_MSG(CantGetEnvironment), KMP_ERR(error),
__kmp_msg_null);
}
___kmp_env_blk_parse_windows(block, mem);
FreeEnvironmentStrings(mem);
}
#else
#error Unknown or unsupported OS.
#endif
}
} // __kmp_env_blk_init
static int ___kmp_env_var_cmp( // Comparison function for qsort().
kmp_env_var_t const *lhs, kmp_env_var_t const *rhs) {
return strcmp(lhs->name, rhs->name);
}
void __kmp_env_blk_sort(
kmp_env_blk_t *block // M: Block of environment variables to sort.
) {
qsort(CCAST(kmp_env_var_t *, block->vars), block->count,
sizeof(kmp_env_var_t),
(int (*)(void const *, void const *)) & ___kmp_env_var_cmp);
} // __kmp_env_block_sort
void __kmp_env_blk_free(
kmp_env_blk_t *block // M: Block of environment variables to free.
) {
KMP_INTERNAL_FREE(CCAST(kmp_env_var_t *, block->vars));
__kmp_str_free(&(block->bulk));
block->count = 0;
block->vars = NULL;
} // __kmp_env_blk_free
char const * // R: Value of variable or NULL if variable does not exist.
__kmp_env_blk_var(kmp_env_blk_t *block, // I: Block of environment variables.
char const *name // I: Name of variable to find.
) {
int i;
for (i = 0; i < block->count; ++i) {
if (strcmp(block->vars[i].name, name) == 0) {
return block->vars[i].value;
}
}
return NULL;
} // __kmp_env_block_var
// end of file //

77
third_party/openmp/kmp_environment.h vendored Normal file
View file

@ -0,0 +1,77 @@
/*
* kmp_environment.h -- Handle environment variables OS-independently.
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef KMP_ENVIRONMENT_H
#define KMP_ENVIRONMENT_H
#ifdef __cplusplus
extern "C" {
#endif
// Return a copy of the value of environment variable or NULL if the variable
// does not exist.
// *Note*: Returned pointed *must* be freed after use with __kmp_env_free().
char *__kmp_env_get(char const *name);
void __kmp_env_free(char const **value);
// Return 1 if the environment variable exists or 0 if does not exist.
int __kmp_env_exists(char const *name);
// Set the environment variable.
void __kmp_env_set(char const *name, char const *value, int overwrite);
// Unset (remove) environment variable.
void __kmp_env_unset(char const *name);
// -----------------------------------------------------------------------------
// Working with environment blocks.
/* kmp_env_blk_t is read-only collection of environment variables (or
environment-like). Usage:
kmp_env_blk_t block;
__kmp_env_blk_init( & block, NULL ); // Initialize block from process
// environment.
// or
__kmp_env_blk_init( & block, "KMP_WARNING=1|KMP_AFFINITY=none" ); // from string
__kmp_env_blk_sort( & block ); // Optionally, sort list.
for ( i = 0; i < block.count; ++ i ) {
// Process block.vars[ i ].name and block.vars[ i ].value...
}
__kmp_env_block_free( & block );
*/
struct __kmp_env_var {
char *name;
char *value;
};
typedef struct __kmp_env_var kmp_env_var_t;
struct __kmp_env_blk {
char *bulk;
kmp_env_var_t *vars;
int count;
};
typedef struct __kmp_env_blk kmp_env_blk_t;
void __kmp_env_blk_init(kmp_env_blk_t *block, char const *bulk);
void __kmp_env_blk_free(kmp_env_blk_t *block);
void __kmp_env_blk_sort(kmp_env_blk_t *block);
char const *__kmp_env_blk_var(kmp_env_blk_t *block, char const *name);
#ifdef __cplusplus
}
#endif
#endif // KMP_ENVIRONMENT_H
// end of file //

451
third_party/openmp/kmp_error.cpp vendored Normal file
View file

@ -0,0 +1,451 @@
/*
* kmp_error.cpp -- KPTS functions for error checking at runtime
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "kmp.h"
#include "kmp_error.h"
#include "kmp_i18n.h"
#include "kmp_str.h"
/* ------------------------------------------------------------------------ */
#define MIN_STACK 100
static char const *cons_text_c[] = {
"(none)",
"\"parallel\"",
"work-sharing", /* this is not called "for"
because of lowering of
"sections" pragmas */
"\"ordered\" work-sharing", /* this is not called "for ordered" because of
lowering of "sections" pragmas */
"\"sections\"",
"work-sharing", /* this is not called "single" because of lowering of
"sections" pragmas */
"\"critical\"",
"\"ordered\"", /* in PARALLEL */
"\"ordered\"", /* in PDO */
"\"master\"",
"\"reduce\"",
"\"barrier\"",
"\"masked\""};
#define get_src(ident) ((ident) == NULL ? NULL : (ident)->psource)
#define PUSH_MSG(ct, ident) \
"\tpushing on stack: %s (%s)\n", cons_text_c[(ct)], get_src((ident))
#define POP_MSG(p) \
"\tpopping off stack: %s (%s)\n", cons_text_c[(p)->stack_data[tos].type], \
get_src((p)->stack_data[tos].ident)
static int const cons_text_c_num = sizeof(cons_text_c) / sizeof(char const *);
/* --------------- START OF STATIC LOCAL ROUTINES ------------------------- */
static void __kmp_check_null_func(void) { /* nothing to do */
}
static void __kmp_expand_cons_stack(int gtid, struct cons_header *p) {
int i;
struct cons_data *d;
/* TODO for monitor perhaps? */
if (gtid < 0)
__kmp_check_null_func();
KE_TRACE(10, ("expand cons_stack (%d %d)\n", gtid, __kmp_get_gtid()));
d = p->stack_data;
p->stack_size = (p->stack_size * 2) + 100;
/* TODO free the old data */
p->stack_data = (struct cons_data *)__kmp_allocate(sizeof(struct cons_data) *
(p->stack_size + 1));
for (i = p->stack_top; i >= 0; --i)
p->stack_data[i] = d[i];
/* NOTE: we do not free the old stack_data */
}
// NOTE: Function returns allocated memory, caller must free it!
static char *__kmp_pragma(int ct, ident_t const *ident) {
char const *cons = NULL; // Construct name.
char *file = NULL; // File name.
char *func = NULL; // Function (routine) name.
char *line = NULL; // Line number.
kmp_str_buf_t buffer;
kmp_msg_t prgm;
__kmp_str_buf_init(&buffer);
if (0 < ct && ct < cons_text_c_num) {
cons = cons_text_c[ct];
} else {
KMP_DEBUG_ASSERT(0);
}
if (ident != NULL && ident->psource != NULL) {
char *tail = NULL;
__kmp_str_buf_print(&buffer, "%s",
ident->psource); // Copy source to buffer.
// Split string in buffer to file, func, and line.
tail = buffer.str;
__kmp_str_split(tail, ';', NULL, &tail);
__kmp_str_split(tail, ';', &file, &tail);
__kmp_str_split(tail, ';', &func, &tail);
__kmp_str_split(tail, ';', &line, &tail);
}
prgm = __kmp_msg_format(kmp_i18n_fmt_Pragma, cons, file, func, line);
__kmp_str_buf_free(&buffer);
return prgm.str;
} // __kmp_pragma
/* ----------------- END OF STATIC LOCAL ROUTINES ------------------------- */
void __kmp_error_construct(kmp_i18n_id_t id, // Message identifier.
enum cons_type ct, // Construct type.
ident_t const *ident // Construct ident.
) {
char *construct = __kmp_pragma(ct, ident);
__kmp_fatal(__kmp_msg_format(id, construct), __kmp_msg_null);
KMP_INTERNAL_FREE(construct);
}
void __kmp_error_construct2(kmp_i18n_id_t id, // Message identifier.
enum cons_type ct, // First construct type.
ident_t const *ident, // First construct ident.
struct cons_data const *cons // Second construct.
) {
char *construct1 = __kmp_pragma(ct, ident);
char *construct2 = __kmp_pragma(cons->type, cons->ident);
__kmp_fatal(__kmp_msg_format(id, construct1, construct2), __kmp_msg_null);
KMP_INTERNAL_FREE(construct1);
KMP_INTERNAL_FREE(construct2);
}
struct cons_header *__kmp_allocate_cons_stack(int gtid) {
struct cons_header *p;
/* TODO for monitor perhaps? */
if (gtid < 0) {
__kmp_check_null_func();
}
KE_TRACE(10, ("allocate cons_stack (%d)\n", gtid));
p = (struct cons_header *)__kmp_allocate(sizeof(struct cons_header));
p->p_top = p->w_top = p->s_top = 0;
p->stack_data = (struct cons_data *)__kmp_allocate(sizeof(struct cons_data) *
(MIN_STACK + 1));
p->stack_size = MIN_STACK;
p->stack_top = 0;
p->stack_data[0].type = ct_none;
p->stack_data[0].prev = 0;
p->stack_data[0].ident = NULL;
return p;
}
void __kmp_free_cons_stack(void *ptr) {
struct cons_header *p = (struct cons_header *)ptr;
if (p != NULL) {
if (p->stack_data != NULL) {
__kmp_free(p->stack_data);
p->stack_data = NULL;
}
__kmp_free(p);
}
}
#if KMP_DEBUG
static void dump_cons_stack(int gtid, struct cons_header *p) {
int i;
int tos = p->stack_top;
kmp_str_buf_t buffer;
__kmp_str_buf_init(&buffer);
__kmp_str_buf_print(
&buffer,
"+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-\n");
__kmp_str_buf_print(&buffer,
"Begin construct stack with %d items for thread %d\n",
tos, gtid);
__kmp_str_buf_print(&buffer, " stack_top=%d { P=%d, W=%d, S=%d }\n", tos,
p->p_top, p->w_top, p->s_top);
for (i = tos; i > 0; i--) {
struct cons_data *c = &(p->stack_data[i]);
__kmp_str_buf_print(
&buffer, " stack_data[%2d] = { %s (%s) %d %p }\n", i,
cons_text_c[c->type], get_src(c->ident), c->prev, c->name);
}
__kmp_str_buf_print(&buffer, "End construct stack for thread %d\n", gtid);
__kmp_str_buf_print(
&buffer,
"+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-\n");
__kmp_debug_printf("%s", buffer.str);
__kmp_str_buf_free(&buffer);
}
#endif
void __kmp_push_parallel(int gtid, ident_t const *ident) {
int tos;
struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
KMP_DEBUG_ASSERT(__kmp_threads[gtid]->th.th_cons);
KE_TRACE(10, ("__kmp_push_parallel (%d %d)\n", gtid, __kmp_get_gtid()));
KE_TRACE(100, (PUSH_MSG(ct_parallel, ident)));
if (p->stack_top >= p->stack_size) {
__kmp_expand_cons_stack(gtid, p);
}
tos = ++p->stack_top;
p->stack_data[tos].type = ct_parallel;
p->stack_data[tos].prev = p->p_top;
p->stack_data[tos].ident = ident;
p->stack_data[tos].name = NULL;
p->p_top = tos;
KE_DUMP(1000, dump_cons_stack(gtid, p));
}
void __kmp_check_workshare(int gtid, enum cons_type ct, ident_t const *ident) {
struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
KMP_DEBUG_ASSERT(__kmp_threads[gtid]->th.th_cons);
KE_TRACE(10, ("__kmp_check_workshare (%d %d)\n", gtid, __kmp_get_gtid()));
if (p->stack_top >= p->stack_size) {
__kmp_expand_cons_stack(gtid, p);
}
if (p->w_top > p->p_top) {
// We are already in a WORKSHARE construct for this PARALLEL region.
__kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,
&p->stack_data[p->w_top]);
}
if (p->s_top > p->p_top) {
// We are already in a SYNC construct for this PARALLEL region.
__kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,
&p->stack_data[p->s_top]);
}
}
void __kmp_push_workshare(int gtid, enum cons_type ct, ident_t const *ident) {
int tos;
struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
KE_TRACE(10, ("__kmp_push_workshare (%d %d)\n", gtid, __kmp_get_gtid()));
__kmp_check_workshare(gtid, ct, ident);
KE_TRACE(100, (PUSH_MSG(ct, ident)));
tos = ++p->stack_top;
p->stack_data[tos].type = ct;
p->stack_data[tos].prev = p->w_top;
p->stack_data[tos].ident = ident;
p->stack_data[tos].name = NULL;
p->w_top = tos;
KE_DUMP(1000, dump_cons_stack(gtid, p));
}
void
#if KMP_USE_DYNAMIC_LOCK
__kmp_check_sync( int gtid, enum cons_type ct, ident_t const * ident, kmp_user_lock_p lck, kmp_uint32 seq )
#else
__kmp_check_sync( int gtid, enum cons_type ct, ident_t const * ident, kmp_user_lock_p lck )
#endif
{
struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
KE_TRACE(10, ("__kmp_check_sync (gtid=%d)\n", __kmp_get_gtid()));
if (p->stack_top >= p->stack_size)
__kmp_expand_cons_stack(gtid, p);
if (ct == ct_ordered_in_parallel || ct == ct_ordered_in_pdo) {
if (p->w_top <= p->p_top) {
/* we are not in a worksharing construct */
#ifdef BUILD_PARALLEL_ORDERED
/* do not report error messages for PARALLEL ORDERED */
KMP_ASSERT(ct == ct_ordered_in_parallel);
#else
__kmp_error_construct(kmp_i18n_msg_CnsBoundToWorksharing, ct, ident);
#endif /* BUILD_PARALLEL_ORDERED */
} else {
/* inside a WORKSHARING construct for this PARALLEL region */
if (!IS_CONS_TYPE_ORDERED(p->stack_data[p->w_top].type)) {
__kmp_error_construct2(kmp_i18n_msg_CnsNoOrderedClause, ct, ident,
&p->stack_data[p->w_top]);
}
}
if (p->s_top > p->p_top && p->s_top > p->w_top) {
/* inside a sync construct which is inside a worksharing construct */
int index = p->s_top;
enum cons_type stack_type;
stack_type = p->stack_data[index].type;
if (stack_type == ct_critical ||
((stack_type == ct_ordered_in_parallel ||
stack_type == ct_ordered_in_pdo) &&
/* C doesn't allow named ordered; ordered in ordered gets error */
p->stack_data[index].ident != NULL &&
(p->stack_data[index].ident->flags & KMP_IDENT_KMPC))) {
/* we are in ORDERED which is inside an ORDERED or CRITICAL construct */
__kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,
&p->stack_data[index]);
}
}
} else if (ct == ct_critical) {
#if KMP_USE_DYNAMIC_LOCK
if (lck != NULL &&
__kmp_get_user_lock_owner(lck, seq) ==
gtid) { /* this thread already has lock for this critical section */
#else
if (lck != NULL &&
__kmp_get_user_lock_owner(lck) ==
gtid) { /* this thread already has lock for this critical section */
#endif
int index = p->s_top;
struct cons_data cons = {NULL, ct_critical, 0, NULL};
/* walk up construct stack and try to find critical with matching name */
while (index != 0 && p->stack_data[index].name != lck) {
index = p->stack_data[index].prev;
}
if (index != 0) {
/* found match on the stack (may not always because of interleaved
* critical for Fortran) */
cons = p->stack_data[index];
}
/* we are in CRITICAL which is inside a CRITICAL construct of same name */
__kmp_error_construct2(kmp_i18n_msg_CnsNestingSameName, ct, ident, &cons);
}
} else if (ct == ct_master || ct == ct_masked || ct == ct_reduce) {
if (p->w_top > p->p_top) {
/* inside a WORKSHARING construct for this PARALLEL region */
__kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,
&p->stack_data[p->w_top]);
}
if (ct == ct_reduce && p->s_top > p->p_top) {
/* inside a another SYNC construct for this PARALLEL region */
__kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,
&p->stack_data[p->s_top]);
}
}
}
void
#if KMP_USE_DYNAMIC_LOCK
__kmp_push_sync( int gtid, enum cons_type ct, ident_t const * ident, kmp_user_lock_p lck, kmp_uint32 seq )
#else
__kmp_push_sync( int gtid, enum cons_type ct, ident_t const * ident, kmp_user_lock_p lck )
#endif
{
int tos;
struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
KMP_ASSERT(gtid == __kmp_get_gtid());
KE_TRACE(10, ("__kmp_push_sync (gtid=%d)\n", gtid));
#if KMP_USE_DYNAMIC_LOCK
__kmp_check_sync(gtid, ct, ident, lck, seq);
#else
__kmp_check_sync(gtid, ct, ident, lck);
#endif
KE_TRACE(100, (PUSH_MSG(ct, ident)));
tos = ++p->stack_top;
p->stack_data[tos].type = ct;
p->stack_data[tos].prev = p->s_top;
p->stack_data[tos].ident = ident;
p->stack_data[tos].name = lck;
p->s_top = tos;
KE_DUMP(1000, dump_cons_stack(gtid, p));
}
/* ------------------------------------------------------------------------ */
void __kmp_pop_parallel(int gtid, ident_t const *ident) {
int tos;
struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
tos = p->stack_top;
KE_TRACE(10, ("__kmp_pop_parallel (%d %d)\n", gtid, __kmp_get_gtid()));
if (tos == 0 || p->p_top == 0) {
__kmp_error_construct(kmp_i18n_msg_CnsDetectedEnd, ct_parallel, ident);
}
if (tos != p->p_top || p->stack_data[tos].type != ct_parallel) {
__kmp_error_construct2(kmp_i18n_msg_CnsExpectedEnd, ct_parallel, ident,
&p->stack_data[tos]);
}
KE_TRACE(100, (POP_MSG(p)));
p->p_top = p->stack_data[tos].prev;
p->stack_data[tos].type = ct_none;
p->stack_data[tos].ident = NULL;
p->stack_top = tos - 1;
KE_DUMP(1000, dump_cons_stack(gtid, p));
}
enum cons_type __kmp_pop_workshare(int gtid, enum cons_type ct,
ident_t const *ident) {
int tos;
struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
tos = p->stack_top;
KE_TRACE(10, ("__kmp_pop_workshare (%d %d)\n", gtid, __kmp_get_gtid()));
if (tos == 0 || p->w_top == 0) {
__kmp_error_construct(kmp_i18n_msg_CnsDetectedEnd, ct, ident);
}
if (tos != p->w_top ||
(p->stack_data[tos].type != ct &&
// below is the exception to the rule that construct types must match
!(p->stack_data[tos].type == ct_pdo_ordered && ct == ct_pdo))) {
__kmp_check_null_func();
__kmp_error_construct2(kmp_i18n_msg_CnsExpectedEnd, ct, ident,
&p->stack_data[tos]);
}
KE_TRACE(100, (POP_MSG(p)));
p->w_top = p->stack_data[tos].prev;
p->stack_data[tos].type = ct_none;
p->stack_data[tos].ident = NULL;
p->stack_top = tos - 1;
KE_DUMP(1000, dump_cons_stack(gtid, p));
return p->stack_data[p->w_top].type;
}
void __kmp_pop_sync(int gtid, enum cons_type ct, ident_t const *ident) {
int tos;
struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
tos = p->stack_top;
KE_TRACE(10, ("__kmp_pop_sync (%d %d)\n", gtid, __kmp_get_gtid()));
if (tos == 0 || p->s_top == 0) {
__kmp_error_construct(kmp_i18n_msg_CnsDetectedEnd, ct, ident);
}
if (tos != p->s_top || p->stack_data[tos].type != ct) {
__kmp_check_null_func();
__kmp_error_construct2(kmp_i18n_msg_CnsExpectedEnd, ct, ident,
&p->stack_data[tos]);
}
KE_TRACE(100, (POP_MSG(p)));
p->s_top = p->stack_data[tos].prev;
p->stack_data[tos].type = ct_none;
p->stack_data[tos].ident = NULL;
p->stack_top = tos - 1;
KE_DUMP(1000, dump_cons_stack(gtid, p));
}
/* ------------------------------------------------------------------------ */
void __kmp_check_barrier(int gtid, enum cons_type ct, ident_t const *ident) {
struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
KE_TRACE(10, ("__kmp_check_barrier (loc: %p, gtid: %d %d)\n", ident, gtid,
__kmp_get_gtid()));
if (ident != 0) {
__kmp_check_null_func();
}
if (p->w_top > p->p_top) {
/* we are already in a WORKSHARING construct for this PARALLEL region */
__kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,
&p->stack_data[p->w_top]);
}
if (p->s_top > p->p_top) {
/* we are already in a SYNC construct for this PARALLEL region */
__kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,
&p->stack_data[p->s_top]);
}
}

60
third_party/openmp/kmp_error.h vendored Normal file
View file

@ -0,0 +1,60 @@
/*
* kmp_error.h -- PTS functions for error checking at runtime.
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef KMP_ERROR_H
#define KMP_ERROR_H
#include "kmp_i18n.h"
/* ------------------------------------------------------------------------ */
#ifdef __cplusplus
extern "C" {
#endif
void __kmp_error_construct(kmp_i18n_id_t id, enum cons_type ct,
ident_t const *ident);
void __kmp_error_construct2(kmp_i18n_id_t id, enum cons_type ct,
ident_t const *ident, struct cons_data const *cons);
struct cons_header *__kmp_allocate_cons_stack(int gtid);
void __kmp_free_cons_stack(void *ptr);
void __kmp_push_parallel(int gtid, ident_t const *ident);
void __kmp_push_workshare(int gtid, enum cons_type ct, ident_t const *ident);
#if KMP_USE_DYNAMIC_LOCK
void __kmp_push_sync(int gtid, enum cons_type ct, ident_t const *ident,
kmp_user_lock_p name, kmp_uint32);
#else
void __kmp_push_sync(int gtid, enum cons_type ct, ident_t const *ident,
kmp_user_lock_p name);
#endif
void __kmp_check_workshare(int gtid, enum cons_type ct, ident_t const *ident);
#if KMP_USE_DYNAMIC_LOCK
void __kmp_check_sync(int gtid, enum cons_type ct, ident_t const *ident,
kmp_user_lock_p name, kmp_uint32);
#else
void __kmp_check_sync(int gtid, enum cons_type ct, ident_t const *ident,
kmp_user_lock_p name);
#endif
void __kmp_pop_parallel(int gtid, ident_t const *ident);
enum cons_type __kmp_pop_workshare(int gtid, enum cons_type ct,
ident_t const *ident);
void __kmp_pop_sync(int gtid, enum cons_type ct, ident_t const *ident);
void __kmp_check_barrier(int gtid, enum cons_type ct, ident_t const *ident);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // KMP_ERROR_H

34
third_party/openmp/kmp_ftn_cdecl.cpp vendored Normal file
View file

@ -0,0 +1,34 @@
/*
* kmp_ftn_cdecl.cpp -- Fortran __cdecl linkage support for OpenMP.
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "kmp.h"
#include "kmp_affinity.h"
#if KMP_OS_WINDOWS
#if defined KMP_WIN_CDECL || !KMP_DYNAMIC_LIB
#define KMP_FTN_ENTRIES KMP_FTN_UPPER
#endif
#elif KMP_OS_UNIX
#define KMP_FTN_ENTRIES KMP_FTN_PLAIN
#endif
// Note: This string is not printed when KMP_VERSION=1.
char const __kmp_version_ftncdecl[] =
KMP_VERSION_PREFIX "Fortran __cdecl OMP support: "
#ifdef KMP_FTN_ENTRIES
"yes";
#define FTN_STDCALL /* no stdcall */
#include "kmp_ftn_os.h"
#include "kmp_ftn_entry.h"
#else
"no";
#endif /* KMP_FTN_ENTRIES */

1783
third_party/openmp/kmp_ftn_entry.h vendored Normal file

File diff suppressed because it is too large Load diff

755
third_party/openmp/kmp_ftn_os.h vendored Normal file
View file

@ -0,0 +1,755 @@
/*
* kmp_ftn_os.h -- KPTS Fortran defines header file.
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef KMP_FTN_OS_H
#define KMP_FTN_OS_H
// KMP_FNT_ENTRIES may be one of: KMP_FTN_PLAIN, KMP_FTN_UPPER, KMP_FTN_APPEND,
// KMP_FTN_UAPPEND.
/* -------------------------- External definitions ------------------------ */
#if KMP_FTN_ENTRIES == KMP_FTN_PLAIN
#define FTN_SET_STACKSIZE kmp_set_stacksize
#define FTN_SET_STACKSIZE_S kmp_set_stacksize_s
#define FTN_GET_STACKSIZE kmp_get_stacksize
#define FTN_GET_STACKSIZE_S kmp_get_stacksize_s
#define FTN_SET_BLOCKTIME kmp_set_blocktime
#define FTN_GET_BLOCKTIME kmp_get_blocktime
#define FTN_SET_LIBRARY_SERIAL kmp_set_library_serial
#define FTN_SET_LIBRARY_TURNAROUND kmp_set_library_turnaround
#define FTN_SET_LIBRARY_THROUGHPUT kmp_set_library_throughput
#define FTN_SET_LIBRARY kmp_set_library
#define FTN_GET_LIBRARY kmp_get_library
#define FTN_SET_DEFAULTS kmp_set_defaults
#define FTN_SET_DISP_NUM_BUFFERS kmp_set_disp_num_buffers
#define FTN_SET_AFFINITY kmp_set_affinity
#define FTN_GET_AFFINITY kmp_get_affinity
#define FTN_GET_AFFINITY_MAX_PROC kmp_get_affinity_max_proc
#define FTN_CREATE_AFFINITY_MASK kmp_create_affinity_mask
#define FTN_DESTROY_AFFINITY_MASK kmp_destroy_affinity_mask
#define FTN_SET_AFFINITY_MASK_PROC kmp_set_affinity_mask_proc
#define FTN_UNSET_AFFINITY_MASK_PROC kmp_unset_affinity_mask_proc
#define FTN_GET_AFFINITY_MASK_PROC kmp_get_affinity_mask_proc
#define FTN_MALLOC kmp_malloc
#define FTN_ALIGNED_MALLOC kmp_aligned_malloc
#define FTN_CALLOC kmp_calloc
#define FTN_REALLOC kmp_realloc
#define FTN_KFREE kmp_free
#define FTN_GET_NUM_KNOWN_THREADS kmp_get_num_known_threads
#define FTN_SET_NUM_THREADS omp_set_num_threads
#define FTN_GET_NUM_THREADS omp_get_num_threads
#define FTN_GET_MAX_THREADS omp_get_max_threads
#define FTN_GET_THREAD_NUM omp_get_thread_num
#define FTN_GET_NUM_PROCS omp_get_num_procs
#define FTN_SET_DYNAMIC omp_set_dynamic
#define FTN_GET_DYNAMIC omp_get_dynamic
#define FTN_SET_NESTED omp_set_nested
#define FTN_GET_NESTED omp_get_nested
#define FTN_IN_PARALLEL omp_in_parallel
#define FTN_GET_THREAD_LIMIT omp_get_thread_limit
#define FTN_SET_SCHEDULE omp_set_schedule
#define FTN_GET_SCHEDULE omp_get_schedule
#define FTN_SET_MAX_ACTIVE_LEVELS omp_set_max_active_levels
#define FTN_GET_MAX_ACTIVE_LEVELS omp_get_max_active_levels
#define FTN_GET_ACTIVE_LEVEL omp_get_active_level
#define FTN_GET_LEVEL omp_get_level
#define FTN_GET_ANCESTOR_THREAD_NUM omp_get_ancestor_thread_num
#define FTN_GET_TEAM_SIZE omp_get_team_size
#define FTN_IN_FINAL omp_in_final
#define FTN_GET_PROC_BIND omp_get_proc_bind
#define FTN_GET_NUM_TEAMS omp_get_num_teams
#define FTN_GET_TEAM_NUM omp_get_team_num
#define FTN_INIT_LOCK omp_init_lock
#if KMP_USE_DYNAMIC_LOCK
#define FTN_INIT_LOCK_WITH_HINT omp_init_lock_with_hint
#define FTN_INIT_NEST_LOCK_WITH_HINT omp_init_nest_lock_with_hint
#endif
#define FTN_DESTROY_LOCK omp_destroy_lock
#define FTN_SET_LOCK omp_set_lock
#define FTN_UNSET_LOCK omp_unset_lock
#define FTN_TEST_LOCK omp_test_lock
#define FTN_INIT_NEST_LOCK omp_init_nest_lock
#define FTN_DESTROY_NEST_LOCK omp_destroy_nest_lock
#define FTN_SET_NEST_LOCK omp_set_nest_lock
#define FTN_UNSET_NEST_LOCK omp_unset_nest_lock
#define FTN_TEST_NEST_LOCK omp_test_nest_lock
#define FTN_SET_WARNINGS_ON kmp_set_warnings_on
#define FTN_SET_WARNINGS_OFF kmp_set_warnings_off
#define FTN_GET_WTIME omp_get_wtime
#define FTN_GET_WTICK omp_get_wtick
#define FTN_GET_NUM_DEVICES omp_get_num_devices
#define FTN_GET_DEFAULT_DEVICE omp_get_default_device
#define FTN_SET_DEFAULT_DEVICE omp_set_default_device
#define FTN_IS_INITIAL_DEVICE omp_is_initial_device
#define FTN_GET_CANCELLATION omp_get_cancellation
#define FTN_GET_CANCELLATION_STATUS kmp_get_cancellation_status
#define FTN_GET_MAX_TASK_PRIORITY omp_get_max_task_priority
#define FTN_GET_NUM_PLACES omp_get_num_places
#define FTN_GET_PLACE_NUM_PROCS omp_get_place_num_procs
#define FTN_GET_PLACE_PROC_IDS omp_get_place_proc_ids
#define FTN_GET_PLACE_NUM omp_get_place_num
#define FTN_GET_PARTITION_NUM_PLACES omp_get_partition_num_places
#define FTN_GET_PARTITION_PLACE_NUMS omp_get_partition_place_nums
#define FTN_GET_INITIAL_DEVICE omp_get_initial_device
#ifdef KMP_STUB
#define FTN_TARGET_ALLOC omp_target_alloc
#define FTN_TARGET_FREE omp_target_free
#define FTN_TARGET_IS_PRESENT omp_target_is_present
#define FTN_TARGET_MEMCPY omp_target_memcpy
#define FTN_TARGET_MEMCPY_RECT omp_target_memcpy_rect
#define FTN_TARGET_MEMSET omp_target_memset
#define FTN_TARGET_MEMSET_ASYNC omp_target_memset_async
#define FTN_TARGET_ASSOCIATE_PTR omp_target_associate_ptr
#define FTN_TARGET_DISASSOCIATE_PTR omp_target_disassociate_ptr
#endif
#define FTN_CONTROL_TOOL omp_control_tool
#define FTN_INIT_ALLOCATOR omp_init_allocator
#define FTN_DESTROY_ALLOCATOR omp_destroy_allocator
#define FTN_SET_DEFAULT_ALLOCATOR omp_set_default_allocator
#define FTN_GET_DEFAULT_ALLOCATOR omp_get_default_allocator
#define FTN_GET_DEVICE_NUM omp_get_device_num
#define FTN_SET_AFFINITY_FORMAT omp_set_affinity_format
#define FTN_GET_AFFINITY_FORMAT omp_get_affinity_format
#define FTN_DISPLAY_AFFINITY omp_display_affinity
#define FTN_CAPTURE_AFFINITY omp_capture_affinity
#define FTN_PAUSE_RESOURCE omp_pause_resource
#define FTN_PAUSE_RESOURCE_ALL omp_pause_resource_all
#define FTN_GET_SUPPORTED_ACTIVE_LEVELS omp_get_supported_active_levels
#define FTN_DISPLAY_ENV omp_display_env
#define FTN_IN_EXPLICIT_TASK omp_in_explicit_task
#define FTN_FULFILL_EVENT omp_fulfill_event
#define FTN_SET_NUM_TEAMS omp_set_num_teams
#define FTN_GET_MAX_TEAMS omp_get_max_teams
#define FTN_SET_TEAMS_THREAD_LIMIT omp_set_teams_thread_limit
#define FTN_GET_TEAMS_THREAD_LIMIT omp_get_teams_thread_limit
#define FTN_GET_NUM_INTEROP_PROPERTIES omp_get_num_interop_properties
#define FTN_GET_INTEROP_INT omp_get_interop_int
#define FTN_GET_INTEROP_PTR omp_get_interop_ptr
#define FTN_GET_INTEROP_STR omp_get_interop_str
#define FTN_GET_INTEROP_NAME omp_get_interop_name
#define FTN_GET_INTEROP_TYPE_DESC omp_get_interop_type_desc
#define FTN_GET_INTEROP_RC_DESC omp_get_interop_rc_desc
#endif /* KMP_FTN_PLAIN */
/* ------------------------------------------------------------------------ */
#if KMP_FTN_ENTRIES == KMP_FTN_APPEND
#define FTN_SET_STACKSIZE kmp_set_stacksize_
#define FTN_SET_STACKSIZE_S kmp_set_stacksize_s_
#define FTN_GET_STACKSIZE kmp_get_stacksize_
#define FTN_GET_STACKSIZE_S kmp_get_stacksize_s_
#define FTN_SET_BLOCKTIME kmp_set_blocktime_
#define FTN_GET_BLOCKTIME kmp_get_blocktime_
#define FTN_SET_LIBRARY_SERIAL kmp_set_library_serial_
#define FTN_SET_LIBRARY_TURNAROUND kmp_set_library_turnaround_
#define FTN_SET_LIBRARY_THROUGHPUT kmp_set_library_throughput_
#define FTN_SET_LIBRARY kmp_set_library_
#define FTN_GET_LIBRARY kmp_get_library_
#define FTN_SET_DEFAULTS kmp_set_defaults_
#define FTN_SET_DISP_NUM_BUFFERS kmp_set_disp_num_buffers_
#define FTN_SET_AFFINITY kmp_set_affinity_
#define FTN_GET_AFFINITY kmp_get_affinity_
#define FTN_GET_AFFINITY_MAX_PROC kmp_get_affinity_max_proc_
#define FTN_CREATE_AFFINITY_MASK kmp_create_affinity_mask_
#define FTN_DESTROY_AFFINITY_MASK kmp_destroy_affinity_mask_
#define FTN_SET_AFFINITY_MASK_PROC kmp_set_affinity_mask_proc_
#define FTN_UNSET_AFFINITY_MASK_PROC kmp_unset_affinity_mask_proc_
#define FTN_GET_AFFINITY_MASK_PROC kmp_get_affinity_mask_proc_
#define FTN_MALLOC kmp_malloc_
#define FTN_ALIGNED_MALLOC kmp_aligned_malloc_
#define FTN_CALLOC kmp_calloc_
#define FTN_REALLOC kmp_realloc_
#define FTN_KFREE kmp_free_
#define FTN_GET_NUM_KNOWN_THREADS kmp_get_num_known_threads_
#define FTN_SET_NUM_THREADS omp_set_num_threads_
#define FTN_GET_NUM_THREADS omp_get_num_threads_
#define FTN_GET_MAX_THREADS omp_get_max_threads_
#define FTN_GET_THREAD_NUM omp_get_thread_num_
#define FTN_GET_NUM_PROCS omp_get_num_procs_
#define FTN_SET_DYNAMIC omp_set_dynamic_
#define FTN_GET_DYNAMIC omp_get_dynamic_
#define FTN_SET_NESTED omp_set_nested_
#define FTN_GET_NESTED omp_get_nested_
#define FTN_IN_PARALLEL omp_in_parallel_
#define FTN_GET_THREAD_LIMIT omp_get_thread_limit_
#define FTN_SET_SCHEDULE omp_set_schedule_
#define FTN_GET_SCHEDULE omp_get_schedule_
#define FTN_SET_MAX_ACTIVE_LEVELS omp_set_max_active_levels_
#define FTN_GET_MAX_ACTIVE_LEVELS omp_get_max_active_levels_
#define FTN_GET_ACTIVE_LEVEL omp_get_active_level_
#define FTN_GET_LEVEL omp_get_level_
#define FTN_GET_ANCESTOR_THREAD_NUM omp_get_ancestor_thread_num_
#define FTN_GET_TEAM_SIZE omp_get_team_size_
#define FTN_IN_FINAL omp_in_final_
#define FTN_GET_PROC_BIND omp_get_proc_bind_
#define FTN_GET_NUM_TEAMS omp_get_num_teams_
#define FTN_GET_TEAM_NUM omp_get_team_num_
#define FTN_INIT_LOCK omp_init_lock_
#if KMP_USE_DYNAMIC_LOCK
#define FTN_INIT_LOCK_WITH_HINT omp_init_lock_with_hint_
#define FTN_INIT_NEST_LOCK_WITH_HINT omp_init_nest_lock_with_hint_
#endif
#define FTN_DESTROY_LOCK omp_destroy_lock_
#define FTN_SET_LOCK omp_set_lock_
#define FTN_UNSET_LOCK omp_unset_lock_
#define FTN_TEST_LOCK omp_test_lock_
#define FTN_INIT_NEST_LOCK omp_init_nest_lock_
#define FTN_DESTROY_NEST_LOCK omp_destroy_nest_lock_
#define FTN_SET_NEST_LOCK omp_set_nest_lock_
#define FTN_UNSET_NEST_LOCK omp_unset_nest_lock_
#define FTN_TEST_NEST_LOCK omp_test_nest_lock_
#define FTN_SET_WARNINGS_ON kmp_set_warnings_on_
#define FTN_SET_WARNINGS_OFF kmp_set_warnings_off_
#define FTN_GET_WTIME omp_get_wtime_
#define FTN_GET_WTICK omp_get_wtick_
#define FTN_GET_NUM_DEVICES omp_get_num_devices_
#define FTN_GET_DEFAULT_DEVICE omp_get_default_device_
#define FTN_SET_DEFAULT_DEVICE omp_set_default_device_
#define FTN_IS_INITIAL_DEVICE omp_is_initial_device_
#define FTN_GET_CANCELLATION omp_get_cancellation_
#define FTN_GET_CANCELLATION_STATUS kmp_get_cancellation_status_
#define FTN_GET_MAX_TASK_PRIORITY omp_get_max_task_priority_
#define FTN_GET_NUM_PLACES omp_get_num_places_
#define FTN_GET_PLACE_NUM_PROCS omp_get_place_num_procs_
#define FTN_GET_PLACE_PROC_IDS omp_get_place_proc_ids_
#define FTN_GET_PLACE_NUM omp_get_place_num_
#define FTN_GET_PARTITION_NUM_PLACES omp_get_partition_num_places_
#define FTN_GET_PARTITION_PLACE_NUMS omp_get_partition_place_nums_
#define FTN_GET_INITIAL_DEVICE omp_get_initial_device_
#ifdef KMP_STUB
#define FTN_TARGET_ALLOC omp_target_alloc_
#define FTN_TARGET_FREE omp_target_free_
#define FTN_TARGET_IS_PRESENT omp_target_is_present_
#define FTN_TARGET_MEMCPY omp_target_memcpy_
#define FTN_TARGET_MEMCPY_RECT omp_target_memcpy_rect_
#define FTN_TARGET_ASSOCIATE_PTR omp_target_associate_ptr_
#define FTN_TARGET_DISASSOCIATE_PTR omp_target_disassociate_ptr_
#endif
#define FTN_CONTROL_TOOL omp_control_tool_
#define FTN_INIT_ALLOCATOR omp_init_allocator_
#define FTN_DESTROY_ALLOCATOR omp_destroy_allocator_
#define FTN_SET_DEFAULT_ALLOCATOR omp_set_default_allocator_
#define FTN_GET_DEFAULT_ALLOCATOR omp_get_default_allocator_
#define FTN_ALLOC omp_alloc_
#define FTN_FREE omp_free_
#define FTN_GET_DEVICE_NUM omp_get_device_num_
#define FTN_SET_AFFINITY_FORMAT omp_set_affinity_format_
#define FTN_GET_AFFINITY_FORMAT omp_get_affinity_format_
#define FTN_DISPLAY_AFFINITY omp_display_affinity_
#define FTN_CAPTURE_AFFINITY omp_capture_affinity_
#define FTN_PAUSE_RESOURCE omp_pause_resource_
#define FTN_PAUSE_RESOURCE_ALL omp_pause_resource_all_
#define FTN_GET_SUPPORTED_ACTIVE_LEVELS omp_get_supported_active_levels_
#define FTN_DISPLAY_ENV omp_display_env_
#define FTN_IN_EXPLICIT_TASK omp_in_explicit_task_
#define FTN_FULFILL_EVENT omp_fulfill_event_
#define FTN_SET_NUM_TEAMS omp_set_num_teams_
#define FTN_GET_MAX_TEAMS omp_get_max_teams_
#define FTN_SET_TEAMS_THREAD_LIMIT omp_set_teams_thread_limit_
#define FTN_GET_TEAMS_THREAD_LIMIT omp_get_teams_thread_limit_
#define FTN_GET_NUM_INTEROP_PROPERTIES omp_get_num_interop_properties_
#define FTN_GET_INTEROP_INT omp_get_interop_int_
#define FTN_GET_INTEROP_PTR omp_get_interop_ptr_
#define FTN_GET_INTEROP_STR omp_get_interop_str_
#define FTN_GET_INTEROP_NAME omp_get_interop_name_
#define FTN_GET_INTEROP_TYPE_DESC omp_get_interop_type_desc_
#define FTN_GET_INTEROP_RC_DESC omp_get_interop_rc_desc_
#endif /* KMP_FTN_APPEND */
/* ------------------------------------------------------------------------ */
#if KMP_FTN_ENTRIES == KMP_FTN_UPPER
#define FTN_SET_STACKSIZE KMP_SET_STACKSIZE
#define FTN_SET_STACKSIZE_S KMP_SET_STACKSIZE_S
#define FTN_GET_STACKSIZE KMP_GET_STACKSIZE
#define FTN_GET_STACKSIZE_S KMP_GET_STACKSIZE_S
#define FTN_SET_BLOCKTIME KMP_SET_BLOCKTIME
#define FTN_GET_BLOCKTIME KMP_GET_BLOCKTIME
#define FTN_SET_LIBRARY_SERIAL KMP_SET_LIBRARY_SERIAL
#define FTN_SET_LIBRARY_TURNAROUND KMP_SET_LIBRARY_TURNAROUND
#define FTN_SET_LIBRARY_THROUGHPUT KMP_SET_LIBRARY_THROUGHPUT
#define FTN_SET_LIBRARY KMP_SET_LIBRARY
#define FTN_GET_LIBRARY KMP_GET_LIBRARY
#define FTN_SET_DEFAULTS KMP_SET_DEFAULTS
#define FTN_SET_DISP_NUM_BUFFERS KMP_SET_DISP_NUM_BUFFERS
#define FTN_SET_AFFINITY KMP_SET_AFFINITY
#define FTN_GET_AFFINITY KMP_GET_AFFINITY
#define FTN_GET_AFFINITY_MAX_PROC KMP_GET_AFFINITY_MAX_PROC
#define FTN_CREATE_AFFINITY_MASK KMP_CREATE_AFFINITY_MASK
#define FTN_DESTROY_AFFINITY_MASK KMP_DESTROY_AFFINITY_MASK
#define FTN_SET_AFFINITY_MASK_PROC KMP_SET_AFFINITY_MASK_PROC
#define FTN_UNSET_AFFINITY_MASK_PROC KMP_UNSET_AFFINITY_MASK_PROC
#define FTN_GET_AFFINITY_MASK_PROC KMP_GET_AFFINITY_MASK_PROC
#define FTN_MALLOC KMP_MALLOC
#define FTN_ALIGNED_MALLOC KMP_ALIGNED_MALLOC
#define FTN_CALLOC KMP_CALLOC
#define FTN_REALLOC KMP_REALLOC
#define FTN_KFREE KMP_FREE
#define FTN_GET_NUM_KNOWN_THREADS KMP_GET_NUM_KNOWN_THREADS
#define FTN_SET_NUM_THREADS OMP_SET_NUM_THREADS
#define FTN_GET_NUM_THREADS OMP_GET_NUM_THREADS
#define FTN_GET_MAX_THREADS OMP_GET_MAX_THREADS
#define FTN_GET_THREAD_NUM OMP_GET_THREAD_NUM
#define FTN_GET_NUM_PROCS OMP_GET_NUM_PROCS
#define FTN_SET_DYNAMIC OMP_SET_DYNAMIC
#define FTN_GET_DYNAMIC OMP_GET_DYNAMIC
#define FTN_SET_NESTED OMP_SET_NESTED
#define FTN_GET_NESTED OMP_GET_NESTED
#define FTN_IN_PARALLEL OMP_IN_PARALLEL
#define FTN_GET_THREAD_LIMIT OMP_GET_THREAD_LIMIT
#define FTN_SET_SCHEDULE OMP_SET_SCHEDULE
#define FTN_GET_SCHEDULE OMP_GET_SCHEDULE
#define FTN_SET_MAX_ACTIVE_LEVELS OMP_SET_MAX_ACTIVE_LEVELS
#define FTN_GET_MAX_ACTIVE_LEVELS OMP_GET_MAX_ACTIVE_LEVELS
#define FTN_GET_ACTIVE_LEVEL OMP_GET_ACTIVE_LEVEL
#define FTN_GET_LEVEL OMP_GET_LEVEL
#define FTN_GET_ANCESTOR_THREAD_NUM OMP_GET_ANCESTOR_THREAD_NUM
#define FTN_GET_TEAM_SIZE OMP_GET_TEAM_SIZE
#define FTN_IN_FINAL OMP_IN_FINAL
#define FTN_GET_PROC_BIND OMP_GET_PROC_BIND
#define FTN_GET_NUM_TEAMS OMP_GET_NUM_TEAMS
#define FTN_GET_TEAM_NUM OMP_GET_TEAM_NUM
#define FTN_INIT_LOCK OMP_INIT_LOCK
#if KMP_USE_DYNAMIC_LOCK
#define FTN_INIT_LOCK_WITH_HINT OMP_INIT_LOCK_WITH_HINT
#define FTN_INIT_NEST_LOCK_WITH_HINT OMP_INIT_NEST_LOCK_WITH_HINT
#endif
#define FTN_DESTROY_LOCK OMP_DESTROY_LOCK
#define FTN_SET_LOCK OMP_SET_LOCK
#define FTN_UNSET_LOCK OMP_UNSET_LOCK
#define FTN_TEST_LOCK OMP_TEST_LOCK
#define FTN_INIT_NEST_LOCK OMP_INIT_NEST_LOCK
#define FTN_DESTROY_NEST_LOCK OMP_DESTROY_NEST_LOCK
#define FTN_SET_NEST_LOCK OMP_SET_NEST_LOCK
#define FTN_UNSET_NEST_LOCK OMP_UNSET_NEST_LOCK
#define FTN_TEST_NEST_LOCK OMP_TEST_NEST_LOCK
#define FTN_SET_WARNINGS_ON KMP_SET_WARNINGS_ON
#define FTN_SET_WARNINGS_OFF KMP_SET_WARNINGS_OFF
#define FTN_GET_WTIME OMP_GET_WTIME
#define FTN_GET_WTICK OMP_GET_WTICK
#define FTN_GET_NUM_DEVICES OMP_GET_NUM_DEVICES
#define FTN_GET_DEFAULT_DEVICE OMP_GET_DEFAULT_DEVICE
#define FTN_SET_DEFAULT_DEVICE OMP_SET_DEFAULT_DEVICE
#define FTN_IS_INITIAL_DEVICE OMP_IS_INITIAL_DEVICE
#define FTN_GET_CANCELLATION OMP_GET_CANCELLATION
#define FTN_GET_CANCELLATION_STATUS KMP_GET_CANCELLATION_STATUS
#define FTN_GET_MAX_TASK_PRIORITY OMP_GET_MAX_TASK_PRIORITY
#define FTN_GET_NUM_PLACES OMP_GET_NUM_PLACES
#define FTN_GET_PLACE_NUM_PROCS OMP_GET_PLACE_NUM_PROCS
#define FTN_GET_PLACE_PROC_IDS OMP_GET_PLACE_PROC_IDS
#define FTN_GET_PLACE_NUM OMP_GET_PLACE_NUM
#define FTN_GET_PARTITION_NUM_PLACES OMP_GET_PARTITION_NUM_PLACES
#define FTN_GET_PARTITION_PLACE_NUMS OMP_GET_PARTITION_PLACE_NUMS
#define FTN_GET_INITIAL_DEVICE OMP_GET_INITIAL_DEVICE
#ifdef KMP_STUB
#define FTN_TARGET_ALLOC OMP_TARGET_ALLOC
#define FTN_TARGET_FREE OMP_TARGET_FREE
#define FTN_TARGET_IS_PRESENT OMP_TARGET_IS_PRESENT
#define FTN_TARGET_MEMCPY OMP_TARGET_MEMCPY
#define FTN_TARGET_MEMCPY_RECT OMP_TARGET_MEMCPY_RECT
#define FTN_TARGET_ASSOCIATE_PTR OMP_TARGET_ASSOCIATE_PTR
#define FTN_TARGET_DISASSOCIATE_PTR OMP_TARGET_DISASSOCIATE_PTR
#endif
#define FTN_CONTROL_TOOL OMP_CONTROL_TOOL
#define FTN_INIT_ALLOCATOR OMP_INIT_ALLOCATOR
#define FTN_DESTROY_ALLOCATOR OMP_DESTROY_ALLOCATOR
#define FTN_SET_DEFAULT_ALLOCATOR OMP_SET_DEFAULT_ALLOCATOR
#define FTN_GET_DEFAULT_ALLOCATOR OMP_GET_DEFAULT_ALLOCATOR
#define FTN_GET_DEVICE_NUM OMP_GET_DEVICE_NUM
#define FTN_SET_AFFINITY_FORMAT OMP_SET_AFFINITY_FORMAT
#define FTN_GET_AFFINITY_FORMAT OMP_GET_AFFINITY_FORMAT
#define FTN_DISPLAY_AFFINITY OMP_DISPLAY_AFFINITY
#define FTN_CAPTURE_AFFINITY OMP_CAPTURE_AFFINITY
#define FTN_PAUSE_RESOURCE OMP_PAUSE_RESOURCE
#define FTN_PAUSE_RESOURCE_ALL OMP_PAUSE_RESOURCE_ALL
#define FTN_GET_SUPPORTED_ACTIVE_LEVELS OMP_GET_SUPPORTED_ACTIVE_LEVELS
#define FTN_DISPLAY_ENV OMP_DISPLAY_ENV
#define FTN_IN_EXPLICIT_TASK OMP_IN_EXPLICIT_TASK
#define FTN_FULFILL_EVENT OMP_FULFILL_EVENT
#define FTN_SET_NUM_TEAMS OMP_SET_NUM_TEAMS
#define FTN_GET_MAX_TEAMS OMP_GET_MAX_TEAMS
#define FTN_SET_TEAMS_THREAD_LIMIT OMP_SET_TEAMS_THREAD_LIMIT
#define FTN_GET_TEAMS_THREAD_LIMIT OMP_GET_TEAMS_THREAD_LIMIT
#define FTN_GET_NUM_INTEROP_PROPERTIES OMP_GET_NUM_INTEROP_PROPERTIES
#define FTN_GET_INTEROP_INT OMP_GET_INTEROP_INT
#define FTN_GET_INTEROP_PTR OMP_GET_INTEROP_PTR
#define FTN_GET_INTEROP_STR OMP_GET_INTEROP_STR
#define FTN_GET_INTEROP_NAME OMP_GET_INTEROP_NAME
#define FTN_GET_INTEROP_TYPE_DESC OMP_GET_INTEROP_TYPE_DESC
#define FTN_GET_INTEROP_RC_DESC OMP_GET_INTEROP_RC_DESC
#endif /* KMP_FTN_UPPER */
/* ------------------------------------------------------------------------ */
#if KMP_FTN_ENTRIES == KMP_FTN_UAPPEND
#define FTN_SET_STACKSIZE KMP_SET_STACKSIZE_
#define FTN_SET_STACKSIZE_S KMP_SET_STACKSIZE_S_
#define FTN_GET_STACKSIZE KMP_GET_STACKSIZE_
#define FTN_GET_STACKSIZE_S KMP_GET_STACKSIZE_S_
#define FTN_SET_BLOCKTIME KMP_SET_BLOCKTIME_
#define FTN_GET_BLOCKTIME KMP_GET_BLOCKTIME_
#define FTN_SET_LIBRARY_SERIAL KMP_SET_LIBRARY_SERIAL_
#define FTN_SET_LIBRARY_TURNAROUND KMP_SET_LIBRARY_TURNAROUND_
#define FTN_SET_LIBRARY_THROUGHPUT KMP_SET_LIBRARY_THROUGHPUT_
#define FTN_SET_LIBRARY KMP_SET_LIBRARY_
#define FTN_GET_LIBRARY KMP_GET_LIBRARY_
#define FTN_SET_DEFAULTS KMP_SET_DEFAULTS_
#define FTN_SET_DISP_NUM_BUFFERS KMP_SET_DISP_NUM_BUFFERS_
#define FTN_SET_AFFINITY KMP_SET_AFFINITY_
#define FTN_GET_AFFINITY KMP_GET_AFFINITY_
#define FTN_GET_AFFINITY_MAX_PROC KMP_GET_AFFINITY_MAX_PROC_
#define FTN_CREATE_AFFINITY_MASK KMP_CREATE_AFFINITY_MASK_
#define FTN_DESTROY_AFFINITY_MASK KMP_DESTROY_AFFINITY_MASK_
#define FTN_SET_AFFINITY_MASK_PROC KMP_SET_AFFINITY_MASK_PROC_
#define FTN_UNSET_AFFINITY_MASK_PROC KMP_UNSET_AFFINITY_MASK_PROC_
#define FTN_GET_AFFINITY_MASK_PROC KMP_GET_AFFINITY_MASK_PROC_
#define FTN_MALLOC KMP_MALLOC_
#define FTN_ALIGNED_MALLOC KMP_ALIGNED_MALLOC_
#define FTN_CALLOC KMP_CALLOC_
#define FTN_REALLOC KMP_REALLOC_
#define FTN_KFREE KMP_FREE_
#define FTN_GET_NUM_KNOWN_THREADS KMP_GET_NUM_KNOWN_THREADS_
#define FTN_SET_NUM_THREADS OMP_SET_NUM_THREADS_
#define FTN_GET_NUM_THREADS OMP_GET_NUM_THREADS_
#define FTN_GET_MAX_THREADS OMP_GET_MAX_THREADS_
#define FTN_GET_THREAD_NUM OMP_GET_THREAD_NUM_
#define FTN_GET_NUM_PROCS OMP_GET_NUM_PROCS_
#define FTN_SET_DYNAMIC OMP_SET_DYNAMIC_
#define FTN_GET_DYNAMIC OMP_GET_DYNAMIC_
#define FTN_SET_NESTED OMP_SET_NESTED_
#define FTN_GET_NESTED OMP_GET_NESTED_
#define FTN_IN_PARALLEL OMP_IN_PARALLEL_
#define FTN_GET_THREAD_LIMIT OMP_GET_THREAD_LIMIT_
#define FTN_SET_SCHEDULE OMP_SET_SCHEDULE_
#define FTN_GET_SCHEDULE OMP_GET_SCHEDULE_
#define FTN_SET_MAX_ACTIVE_LEVELS OMP_SET_MAX_ACTIVE_LEVELS_
#define FTN_GET_MAX_ACTIVE_LEVELS OMP_GET_MAX_ACTIVE_LEVELS_
#define FTN_GET_ACTIVE_LEVEL OMP_GET_ACTIVE_LEVEL_
#define FTN_GET_LEVEL OMP_GET_LEVEL_
#define FTN_GET_ANCESTOR_THREAD_NUM OMP_GET_ANCESTOR_THREAD_NUM_
#define FTN_GET_TEAM_SIZE OMP_GET_TEAM_SIZE_
#define FTN_IN_FINAL OMP_IN_FINAL_
#define FTN_GET_PROC_BIND OMP_GET_PROC_BIND_
#define FTN_GET_NUM_TEAMS OMP_GET_NUM_TEAMS_
#define FTN_GET_TEAM_NUM OMP_GET_TEAM_NUM_
#define FTN_INIT_LOCK OMP_INIT_LOCK_
#if KMP_USE_DYNAMIC_LOCK
#define FTN_INIT_LOCK_WITH_HINT OMP_INIT_LOCK_WITH_HINT_
#define FTN_INIT_NEST_LOCK_WITH_HINT OMP_INIT_NEST_LOCK_WITH_HINT_
#endif
#define FTN_DESTROY_LOCK OMP_DESTROY_LOCK_
#define FTN_SET_LOCK OMP_SET_LOCK_
#define FTN_UNSET_LOCK OMP_UNSET_LOCK_
#define FTN_TEST_LOCK OMP_TEST_LOCK_
#define FTN_INIT_NEST_LOCK OMP_INIT_NEST_LOCK_
#define FTN_DESTROY_NEST_LOCK OMP_DESTROY_NEST_LOCK_
#define FTN_SET_NEST_LOCK OMP_SET_NEST_LOCK_
#define FTN_UNSET_NEST_LOCK OMP_UNSET_NEST_LOCK_
#define FTN_TEST_NEST_LOCK OMP_TEST_NEST_LOCK_
#define FTN_SET_WARNINGS_ON KMP_SET_WARNINGS_ON_
#define FTN_SET_WARNINGS_OFF KMP_SET_WARNINGS_OFF_
#define FTN_GET_WTIME OMP_GET_WTIME_
#define FTN_GET_WTICK OMP_GET_WTICK_
#define FTN_GET_NUM_DEVICES OMP_GET_NUM_DEVICES_
#define FTN_GET_DEFAULT_DEVICE OMP_GET_DEFAULT_DEVICE_
#define FTN_SET_DEFAULT_DEVICE OMP_SET_DEFAULT_DEVICE_
#define FTN_IS_INITIAL_DEVICE OMP_IS_INITIAL_DEVICE_
#define FTN_GET_CANCELLATION OMP_GET_CANCELLATION_
#define FTN_GET_CANCELLATION_STATUS KMP_GET_CANCELLATION_STATUS_
#define FTN_GET_MAX_TASK_PRIORITY OMP_GET_MAX_TASK_PRIORITY_
#define FTN_GET_NUM_PLACES OMP_GET_NUM_PLACES_
#define FTN_GET_PLACE_NUM_PROCS OMP_GET_PLACE_NUM_PROCS_
#define FTN_GET_PLACE_PROC_IDS OMP_GET_PLACE_PROC_IDS_
#define FTN_GET_PLACE_NUM OMP_GET_PLACE_NUM_
#define FTN_GET_PARTITION_NUM_PLACES OMP_GET_PARTITION_NUM_PLACES_
#define FTN_GET_PARTITION_PLACE_NUMS OMP_GET_PARTITION_PLACE_NUMS_
#define FTN_GET_INITIAL_DEVICE OMP_GET_INITIAL_DEVICE_
#ifdef KMP_STUB
#define FTN_TARGET_ALLOC OMP_TARGET_ALLOC_
#define FTN_TARGET_FREE OMP_TARGET_FREE_
#define FTN_TARGET_IS_PRESENT OMP_TARGET_IS_PRESENT_
#define FTN_TARGET_MEMCPY OMP_TARGET_MEMCPY_
#define FTN_TARGET_MEMCPY_RECT OMP_TARGET_MEMCPY_RECT_
#define FTN_TARGET_ASSOCIATE_PTR OMP_TARGET_ASSOCIATE_PTR_
#define FTN_TARGET_DISASSOCIATE_PTR OMP_TARGET_DISASSOCIATE_PTR_
#endif
#define FTN_CONTROL_TOOL OMP_CONTROL_TOOL_
#define FTN_INIT_ALLOCATOR OMP_INIT_ALLOCATOR_
#define FTN_DESTROY_ALLOCATOR OMP_DESTROY_ALLOCATOR_
#define FTN_SET_DEFAULT_ALLOCATOR OMP_SET_DEFAULT_ALLOCATOR_
#define FTN_GET_DEFAULT_ALLOCATOR OMP_GET_DEFAULT_ALLOCATOR_
#define FTN_ALLOC OMP_ALLOC_
#define FTN_FREE OMP_FREE_
#define FTN_GET_DEVICE_NUM OMP_GET_DEVICE_NUM_
#define FTN_SET_AFFINITY_FORMAT OMP_SET_AFFINITY_FORMAT_
#define FTN_GET_AFFINITY_FORMAT OMP_GET_AFFINITY_FORMAT_
#define FTN_DISPLAY_AFFINITY OMP_DISPLAY_AFFINITY_
#define FTN_CAPTURE_AFFINITY OMP_CAPTURE_AFFINITY_
#define FTN_PAUSE_RESOURCE OMP_PAUSE_RESOURCE_
#define FTN_PAUSE_RESOURCE_ALL OMP_PAUSE_RESOURCE_ALL_
#define FTN_GET_SUPPORTED_ACTIVE_LEVELS OMP_GET_SUPPORTED_ACTIVE_LEVELS_
#define FTN_DISPLAY_ENV OMP_DISPLAY_ENV_
#define FTN_IN_EXPLICIT_TASK OMP_IN_EXPLICIT_TASK_
#define FTN_FULFILL_EVENT OMP_FULFILL_EVENT_
#define FTN_SET_NUM_TEAMS OMP_SET_NUM_TEAMS_
#define FTN_GET_MAX_TEAMS OMP_GET_MAX_TEAMS_
#define FTN_SET_TEAMS_THREAD_LIMIT OMP_SET_TEAMS_THREAD_LIMIT_
#define FTN_GET_TEAMS_THREAD_LIMIT OMP_GET_TEAMS_THREAD_LIMIT_
#define FTN_GET_NUM_INTEROP_PROPERTIES OMP_GET_NUM_INTEROP_PROPERTIES_
#define FTN_GET_INTEROP_INT OMP_GET_INTEROP_INT_
#define FTN_GET_INTEROP_PTR OMP_GET_INTEROP_PTR_
#define FTN_GET_INTEROP_STR OMP_GET_INTEROP_STR_
#define FTN_GET_INTEROP_NAME OMP_GET_INTEROP_NAME_
#define FTN_GET_INTEROP_TYPE_DESC OMP_GET_INTEROP_TYPE_DESC_
#define FTN_GET_INTEROP_RC_DESC OMP_GET_INTEROP_RC_DESC_
#endif /* KMP_FTN_UAPPEND */
/* -------------------------- GOMP API NAMES ------------------------ */
// All GOMP_1.0 symbols
#define KMP_API_NAME_GOMP_ATOMIC_END GOMP_atomic_end
#define KMP_API_NAME_GOMP_ATOMIC_START GOMP_atomic_start
#define KMP_API_NAME_GOMP_BARRIER GOMP_barrier
#define KMP_API_NAME_GOMP_CRITICAL_END GOMP_critical_end
#define KMP_API_NAME_GOMP_CRITICAL_NAME_END GOMP_critical_name_end
#define KMP_API_NAME_GOMP_CRITICAL_NAME_START GOMP_critical_name_start
#define KMP_API_NAME_GOMP_CRITICAL_START GOMP_critical_start
#define KMP_API_NAME_GOMP_LOOP_DYNAMIC_NEXT GOMP_loop_dynamic_next
#define KMP_API_NAME_GOMP_LOOP_DYNAMIC_START GOMP_loop_dynamic_start
#define KMP_API_NAME_GOMP_LOOP_END GOMP_loop_end
#define KMP_API_NAME_GOMP_LOOP_END_NOWAIT GOMP_loop_end_nowait
#define KMP_API_NAME_GOMP_LOOP_GUIDED_NEXT GOMP_loop_guided_next
#define KMP_API_NAME_GOMP_LOOP_GUIDED_START GOMP_loop_guided_start
#define KMP_API_NAME_GOMP_LOOP_ORDERED_DYNAMIC_NEXT \
GOMP_loop_ordered_dynamic_next
#define KMP_API_NAME_GOMP_LOOP_ORDERED_DYNAMIC_START \
GOMP_loop_ordered_dynamic_start
#define KMP_API_NAME_GOMP_LOOP_ORDERED_GUIDED_NEXT GOMP_loop_ordered_guided_next
#define KMP_API_NAME_GOMP_LOOP_ORDERED_GUIDED_START \
GOMP_loop_ordered_guided_start
#define KMP_API_NAME_GOMP_LOOP_ORDERED_RUNTIME_NEXT \
GOMP_loop_ordered_runtime_next
#define KMP_API_NAME_GOMP_LOOP_ORDERED_RUNTIME_START \
GOMP_loop_ordered_runtime_start
#define KMP_API_NAME_GOMP_LOOP_ORDERED_STATIC_NEXT GOMP_loop_ordered_static_next
#define KMP_API_NAME_GOMP_LOOP_ORDERED_STATIC_START \
GOMP_loop_ordered_static_start
#define KMP_API_NAME_GOMP_LOOP_RUNTIME_NEXT GOMP_loop_runtime_next
#define KMP_API_NAME_GOMP_LOOP_RUNTIME_START GOMP_loop_runtime_start
#define KMP_API_NAME_GOMP_LOOP_STATIC_NEXT GOMP_loop_static_next
#define KMP_API_NAME_GOMP_LOOP_STATIC_START GOMP_loop_static_start
#define KMP_API_NAME_GOMP_ORDERED_END GOMP_ordered_end
#define KMP_API_NAME_GOMP_ORDERED_START GOMP_ordered_start
#define KMP_API_NAME_GOMP_PARALLEL_END GOMP_parallel_end
#define KMP_API_NAME_GOMP_PARALLEL_LOOP_DYNAMIC_START \
GOMP_parallel_loop_dynamic_start
#define KMP_API_NAME_GOMP_PARALLEL_LOOP_GUIDED_START \
GOMP_parallel_loop_guided_start
#define KMP_API_NAME_GOMP_PARALLEL_LOOP_RUNTIME_START \
GOMP_parallel_loop_runtime_start
#define KMP_API_NAME_GOMP_PARALLEL_LOOP_STATIC_START \
GOMP_parallel_loop_static_start
#define KMP_API_NAME_GOMP_PARALLEL_SECTIONS_START GOMP_parallel_sections_start
#define KMP_API_NAME_GOMP_PARALLEL_START GOMP_parallel_start
#define KMP_API_NAME_GOMP_SECTIONS_END GOMP_sections_end
#define KMP_API_NAME_GOMP_SECTIONS_END_NOWAIT GOMP_sections_end_nowait
#define KMP_API_NAME_GOMP_SECTIONS_NEXT GOMP_sections_next
#define KMP_API_NAME_GOMP_SECTIONS_START GOMP_sections_start
#define KMP_API_NAME_GOMP_SINGLE_COPY_END GOMP_single_copy_end
#define KMP_API_NAME_GOMP_SINGLE_COPY_START GOMP_single_copy_start
#define KMP_API_NAME_GOMP_SINGLE_START GOMP_single_start
// All GOMP_2.0 symbols
#define KMP_API_NAME_GOMP_TASK GOMP_task
#define KMP_API_NAME_GOMP_TASKWAIT GOMP_taskwait
#define KMP_API_NAME_GOMP_LOOP_ULL_DYNAMIC_NEXT GOMP_loop_ull_dynamic_next
#define KMP_API_NAME_GOMP_LOOP_ULL_DYNAMIC_START GOMP_loop_ull_dynamic_start
#define KMP_API_NAME_GOMP_LOOP_ULL_GUIDED_NEXT GOMP_loop_ull_guided_next
#define KMP_API_NAME_GOMP_LOOP_ULL_GUIDED_START GOMP_loop_ull_guided_start
#define KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_DYNAMIC_NEXT \
GOMP_loop_ull_ordered_dynamic_next
#define KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_DYNAMIC_START \
GOMP_loop_ull_ordered_dynamic_start
#define KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_GUIDED_NEXT \
GOMP_loop_ull_ordered_guided_next
#define KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_GUIDED_START \
GOMP_loop_ull_ordered_guided_start
#define KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_RUNTIME_NEXT \
GOMP_loop_ull_ordered_runtime_next
#define KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_RUNTIME_START \
GOMP_loop_ull_ordered_runtime_start
#define KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_STATIC_NEXT \
GOMP_loop_ull_ordered_static_next
#define KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_STATIC_START \
GOMP_loop_ull_ordered_static_start
#define KMP_API_NAME_GOMP_LOOP_ULL_RUNTIME_NEXT GOMP_loop_ull_runtime_next
#define KMP_API_NAME_GOMP_LOOP_ULL_RUNTIME_START GOMP_loop_ull_runtime_start
#define KMP_API_NAME_GOMP_LOOP_ULL_STATIC_NEXT GOMP_loop_ull_static_next
#define KMP_API_NAME_GOMP_LOOP_ULL_STATIC_START GOMP_loop_ull_static_start
// All GOMP_3.0 symbols
#define KMP_API_NAME_GOMP_TASKYIELD GOMP_taskyield
// All GOMP_4.0 symbols
#define KMP_API_NAME_GOMP_BARRIER_CANCEL GOMP_barrier_cancel
#define KMP_API_NAME_GOMP_CANCEL GOMP_cancel
#define KMP_API_NAME_GOMP_CANCELLATION_POINT GOMP_cancellation_point
#define KMP_API_NAME_GOMP_LOOP_END_CANCEL GOMP_loop_end_cancel
#define KMP_API_NAME_GOMP_PARALLEL_LOOP_DYNAMIC GOMP_parallel_loop_dynamic
#define KMP_API_NAME_GOMP_PARALLEL_LOOP_GUIDED GOMP_parallel_loop_guided
#define KMP_API_NAME_GOMP_PARALLEL_LOOP_RUNTIME GOMP_parallel_loop_runtime
#define KMP_API_NAME_GOMP_PARALLEL_LOOP_STATIC GOMP_parallel_loop_static
#define KMP_API_NAME_GOMP_PARALLEL_SECTIONS GOMP_parallel_sections
#define KMP_API_NAME_GOMP_PARALLEL GOMP_parallel
#define KMP_API_NAME_GOMP_SECTIONS_END_CANCEL GOMP_sections_end_cancel
#define KMP_API_NAME_GOMP_TASKGROUP_START GOMP_taskgroup_start
#define KMP_API_NAME_GOMP_TASKGROUP_END GOMP_taskgroup_end
/* Target functions should be taken care of by liboffload */
#define KMP_API_NAME_GOMP_TARGET GOMP_target
#define KMP_API_NAME_GOMP_TARGET_DATA GOMP_target_data
#define KMP_API_NAME_GOMP_TARGET_END_DATA GOMP_target_end_data
#define KMP_API_NAME_GOMP_TARGET_UPDATE GOMP_target_update
#define KMP_API_NAME_GOMP_TEAMS GOMP_teams
// All GOMP_4.5 symbols
#define KMP_API_NAME_GOMP_TASKLOOP GOMP_taskloop
#define KMP_API_NAME_GOMP_TASKLOOP_ULL GOMP_taskloop_ull
#define KMP_API_NAME_GOMP_DOACROSS_POST GOMP_doacross_post
#define KMP_API_NAME_GOMP_DOACROSS_WAIT GOMP_doacross_wait
#define KMP_API_NAME_GOMP_LOOP_DOACROSS_STATIC_START \
GOMP_loop_doacross_static_start
#define KMP_API_NAME_GOMP_LOOP_DOACROSS_DYNAMIC_START \
GOMP_loop_doacross_dynamic_start
#define KMP_API_NAME_GOMP_LOOP_DOACROSS_GUIDED_START \
GOMP_loop_doacross_guided_start
#define KMP_API_NAME_GOMP_LOOP_DOACROSS_RUNTIME_START \
GOMP_loop_doacross_runtime_start
#define KMP_API_NAME_GOMP_DOACROSS_ULL_POST GOMP_doacross_ull_post
#define KMP_API_NAME_GOMP_DOACROSS_ULL_WAIT GOMP_doacross_ull_wait
#define KMP_API_NAME_GOMP_LOOP_ULL_DOACROSS_STATIC_START \
GOMP_loop_ull_doacross_static_start
#define KMP_API_NAME_GOMP_LOOP_ULL_DOACROSS_DYNAMIC_START \
GOMP_loop_ull_doacross_dynamic_start
#define KMP_API_NAME_GOMP_LOOP_ULL_DOACROSS_GUIDED_START \
GOMP_loop_ull_doacross_guided_start
#define KMP_API_NAME_GOMP_LOOP_ULL_DOACROSS_RUNTIME_START \
GOMP_loop_ull_doacross_runtime_start
#define KMP_API_NAME_GOMP_LOOP_NONMONOTONIC_DYNAMIC_NEXT \
GOMP_loop_nonmonotonic_dynamic_next
#define KMP_API_NAME_GOMP_LOOP_NONMONOTONIC_DYNAMIC_START \
GOMP_loop_nonmonotonic_dynamic_start
#define KMP_API_NAME_GOMP_LOOP_NONMONOTONIC_GUIDED_NEXT \
GOMP_loop_nonmonotonic_guided_next
#define KMP_API_NAME_GOMP_LOOP_NONMONOTONIC_GUIDED_START \
GOMP_loop_nonmonotonic_guided_start
#define KMP_API_NAME_GOMP_LOOP_ULL_NONMONOTONIC_DYNAMIC_NEXT \
GOMP_loop_ull_nonmonotonic_dynamic_next
#define KMP_API_NAME_GOMP_LOOP_ULL_NONMONOTONIC_DYNAMIC_START \
GOMP_loop_ull_nonmonotonic_dynamic_start
#define KMP_API_NAME_GOMP_LOOP_ULL_NONMONOTONIC_GUIDED_NEXT \
GOMP_loop_ull_nonmonotonic_guided_next
#define KMP_API_NAME_GOMP_LOOP_ULL_NONMONOTONIC_GUIDED_START \
GOMP_loop_ull_nonmonotonic_guided_start
#define KMP_API_NAME_GOMP_PARALLEL_LOOP_NONMONOTONIC_DYNAMIC \
GOMP_parallel_loop_nonmonotonic_dynamic
#define KMP_API_NAME_GOMP_PARALLEL_LOOP_NONMONOTONIC_GUIDED \
GOMP_parallel_loop_nonmonotonic_guided
// All GOMP_5.0 symbols
#define KMP_API_NAME_GOMP_LOOP_MAYBE_NONMONOTONIC_RUNTIME_NEXT \
GOMP_loop_maybe_nonmonotonic_runtime_next
#define KMP_API_NAME_GOMP_LOOP_MAYBE_NONMONOTONIC_RUNTIME_START \
GOMP_loop_maybe_nonmonotonic_runtime_start
#define KMP_API_NAME_GOMP_LOOP_NONMONOTONIC_RUNTIME_NEXT \
GOMP_loop_nonmonotonic_runtime_next
#define KMP_API_NAME_GOMP_LOOP_NONMONOTONIC_RUNTIME_START \
GOMP_loop_nonmonotonic_runtime_start
#define KMP_API_NAME_GOMP_LOOP_ULL_MAYBE_NONMONOTONIC_RUNTIME_NEXT \
GOMP_loop_ull_maybe_nonmonotonic_runtime_next
#define KMP_API_NAME_GOMP_LOOP_ULL_MAYBE_NONMONOTONIC_RUNTIME_START \
GOMP_loop_ull_maybe_nonmonotonic_runtime_start
#define KMP_API_NAME_GOMP_LOOP_ULL_NONMONOTONIC_RUNTIME_NEXT \
GOMP_loop_ull_nonmonotonic_runtime_next
#define KMP_API_NAME_GOMP_LOOP_ULL_NONMONOTONIC_RUNTIME_START \
GOMP_loop_ull_nonmonotonic_runtime_start
#define KMP_API_NAME_GOMP_PARALLEL_LOOP_NONMONOTONIC_RUNTIME \
GOMP_parallel_loop_nonmonotonic_runtime
#define KMP_API_NAME_GOMP_PARALLEL_LOOP_MAYBE_NONMONOTONIC_RUNTIME \
GOMP_parallel_loop_maybe_nonmonotonic_runtime
#define KMP_API_NAME_GOMP_TEAMS_REG GOMP_teams_reg
#define KMP_API_NAME_GOMP_TASKWAIT_DEPEND GOMP_taskwait_depend
#define KMP_API_NAME_GOMP_TASKGROUP_REDUCTION_REGISTER \
GOMP_taskgroup_reduction_register
#define KMP_API_NAME_GOMP_TASKGROUP_REDUCTION_UNREGISTER \
GOMP_taskgroup_reduction_unregister
#define KMP_API_NAME_GOMP_TASK_REDUCTION_REMAP GOMP_task_reduction_remap
#define KMP_API_NAME_GOMP_PARALLEL_REDUCTIONS GOMP_parallel_reductions
#define KMP_API_NAME_GOMP_LOOP_START GOMP_loop_start
#define KMP_API_NAME_GOMP_LOOP_ULL_START GOMP_loop_ull_start
#define KMP_API_NAME_GOMP_LOOP_DOACROSS_START GOMP_loop_doacross_start
#define KMP_API_NAME_GOMP_LOOP_ULL_DOACROSS_START GOMP_loop_ull_doacross_start
#define KMP_API_NAME_GOMP_LOOP_ORDERED_START GOMP_loop_ordered_start
#define KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_START GOMP_loop_ull_ordered_start
#define KMP_API_NAME_GOMP_SECTIONS2_START GOMP_sections2_start
#define KMP_API_NAME_GOMP_WORKSHARE_TASK_REDUCTION_UNREGISTER \
GOMP_workshare_task_reduction_unregister
#define KMP_API_NAME_GOMP_ALLOC GOMP_alloc
#define KMP_API_NAME_GOMP_FREE GOMP_free
#endif /* KMP_FTN_OS_H */

32
third_party/openmp/kmp_ftn_stdcall.cpp vendored Normal file
View file

@ -0,0 +1,32 @@
/*
* kmp_ftn_stdcall.cpp -- Fortran __stdcall linkage support for OpenMP.
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "kmp.h"
// Note: This string is not printed when KMP_VERSION=1.
char const __kmp_version_ftnstdcall[] =
KMP_VERSION_PREFIX "Fortran __stdcall OMP support: "
#ifdef USE_FTN_STDCALL
"yes";
#else
"no";
#endif
#ifdef USE_FTN_STDCALL
#define FTN_STDCALL KMP_STDCALL
#define KMP_FTN_ENTRIES USE_FTN_STDCALL
#include "kmp_ftn_entry.h"
#include "kmp_ftn_os.h"
#endif /* USE_FTN_STDCALL */

578
third_party/openmp/kmp_global.cpp vendored Normal file
View file

@ -0,0 +1,578 @@
/*
* kmp_global.cpp -- KPTS global variables for runtime support library
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "kmp.h"
#include "kmp_affinity.h"
#if KMP_USE_HIER_SCHED
#include "kmp_dispatch_hier.h"
#endif
kmp_key_t __kmp_gtid_threadprivate_key;
#if KMP_ARCH_X86 || KMP_ARCH_X86_64
kmp_cpuinfo_t __kmp_cpuinfo = {0}; // Not initialized
#endif
#if KMP_STATS_ENABLED
#include "kmp_stats.h"
// lock for modifying the global __kmp_stats_list
kmp_tas_lock_t __kmp_stats_lock;
// global list of per thread stats, the head is a sentinel node which
// accumulates all stats produced before __kmp_create_worker is called.
kmp_stats_list *__kmp_stats_list;
// thread local pointer to stats node within list
KMP_THREAD_LOCAL kmp_stats_list *__kmp_stats_thread_ptr = NULL;
// gives reference tick for all events (considered the 0 tick)
tsc_tick_count __kmp_stats_start_time;
#endif
/* ----------------------------------------------------- */
/* INITIALIZATION VARIABLES */
/* they are syncronized to write during init, but read anytime */
volatile int __kmp_init_serial = FALSE;
volatile int __kmp_init_gtid = FALSE;
volatile int __kmp_init_common = FALSE;
volatile int __kmp_need_register_serial = TRUE;
volatile int __kmp_init_middle = FALSE;
volatile int __kmp_init_parallel = FALSE;
volatile int __kmp_init_hidden_helper = FALSE;
volatile int __kmp_init_hidden_helper_threads = FALSE;
volatile int __kmp_hidden_helper_team_done = FALSE;
#if KMP_USE_MONITOR
volatile int __kmp_init_monitor =
0; /* 1 - launched, 2 - actually started (Windows* OS only) */
#endif
volatile int __kmp_init_user_locks = FALSE;
/* list of address of allocated caches for commons */
kmp_cached_addr_t *__kmp_threadpriv_cache_list = NULL;
int __kmp_init_counter = 0;
int __kmp_root_counter = 0;
int __kmp_version = 0;
std::atomic<kmp_int32> __kmp_team_counter = 0;
std::atomic<kmp_int32> __kmp_task_counter = 0;
size_t __kmp_stksize = KMP_DEFAULT_STKSIZE;
#if KMP_USE_MONITOR
size_t __kmp_monitor_stksize = 0; // auto adjust
#endif
size_t __kmp_stkoffset = KMP_DEFAULT_STKOFFSET;
int __kmp_stkpadding = KMP_MIN_STKPADDING;
size_t __kmp_malloc_pool_incr = KMP_DEFAULT_MALLOC_POOL_INCR;
// Barrier method defaults, settings, and strings.
// branch factor = 2^branch_bits (only relevant for tree & hyper barrier types)
kmp_uint32 __kmp_barrier_gather_bb_dflt = 2;
/* branch_factor = 4 */ /* hyper2: C78980 */
kmp_uint32 __kmp_barrier_release_bb_dflt = 2;
/* branch_factor = 4 */ /* hyper2: C78980 */
kmp_bar_pat_e __kmp_barrier_gather_pat_dflt = bp_hyper_bar;
/* hyper2: C78980 */
kmp_bar_pat_e __kmp_barrier_release_pat_dflt = bp_hyper_bar;
/* hyper2: C78980 */
kmp_uint32 __kmp_barrier_gather_branch_bits[bs_last_barrier] = {0};
kmp_uint32 __kmp_barrier_release_branch_bits[bs_last_barrier] = {0};
kmp_bar_pat_e __kmp_barrier_gather_pattern[bs_last_barrier] = {bp_linear_bar};
kmp_bar_pat_e __kmp_barrier_release_pattern[bs_last_barrier] = {bp_linear_bar};
char const *__kmp_barrier_branch_bit_env_name[bs_last_barrier] = {
"KMP_PLAIN_BARRIER", "KMP_FORKJOIN_BARRIER"
#if KMP_FAST_REDUCTION_BARRIER
,
"KMP_REDUCTION_BARRIER"
#endif // KMP_FAST_REDUCTION_BARRIER
};
char const *__kmp_barrier_pattern_env_name[bs_last_barrier] = {
"KMP_PLAIN_BARRIER_PATTERN", "KMP_FORKJOIN_BARRIER_PATTERN"
#if KMP_FAST_REDUCTION_BARRIER
,
"KMP_REDUCTION_BARRIER_PATTERN"
#endif // KMP_FAST_REDUCTION_BARRIER
};
char const *__kmp_barrier_type_name[bs_last_barrier] = {"plain", "forkjoin"
#if KMP_FAST_REDUCTION_BARRIER
,
"reduction"
#endif // KMP_FAST_REDUCTION_BARRIER
};
char const *__kmp_barrier_pattern_name[bp_last_bar] = {
"linear", "tree", "hyper", "hierarchical", "dist"};
int __kmp_allThreadsSpecified = 0;
size_t __kmp_align_alloc = CACHE_LINE;
int __kmp_generate_warnings = kmp_warnings_low;
int __kmp_reserve_warn = 0;
int __kmp_xproc = 0;
int __kmp_avail_proc = 0;
size_t __kmp_sys_min_stksize = KMP_MIN_STKSIZE;
int __kmp_sys_max_nth = KMP_MAX_NTH;
int __kmp_max_nth = 0;
int __kmp_cg_max_nth = 0;
int __kmp_task_max_nth = 0;
int __kmp_teams_max_nth = 0;
int __kmp_threads_capacity = 0;
int __kmp_dflt_team_nth = 0;
int __kmp_dflt_team_nth_ub = 0;
int __kmp_tp_capacity = 0;
int __kmp_tp_cached = 0;
int __kmp_dispatch_num_buffers = KMP_DFLT_DISP_NUM_BUFF;
int __kmp_dflt_max_active_levels = 1; // Nesting off by default
bool __kmp_dflt_max_active_levels_set = false; // Don't override set value
#if KMP_NESTED_HOT_TEAMS
int __kmp_hot_teams_mode = 0; /* 0 - free extra threads when reduced */
/* 1 - keep extra threads when reduced */
int __kmp_hot_teams_max_level = 1; /* nesting level of hot teams */
#endif
enum library_type __kmp_library = library_none;
enum sched_type __kmp_sched =
kmp_sch_default; /* scheduling method for runtime scheduling */
enum sched_type __kmp_static =
kmp_sch_static_greedy; /* default static scheduling method */
enum sched_type __kmp_guided =
kmp_sch_guided_iterative_chunked; /* default guided scheduling method */
enum sched_type __kmp_auto =
kmp_sch_guided_analytical_chunked; /* default auto scheduling method */
#if KMP_USE_HIER_SCHED
int __kmp_dispatch_hand_threading = 0;
int __kmp_hier_max_units[kmp_hier_layer_e::LAYER_LAST + 1];
int __kmp_hier_threads_per[kmp_hier_layer_e::LAYER_LAST + 1];
kmp_hier_sched_env_t __kmp_hier_scheds = {0, 0, NULL, NULL, NULL};
#endif
int __kmp_dflt_blocktime = KMP_DEFAULT_BLOCKTIME; // in microseconds
char __kmp_blocktime_units = 'm'; // Units specified in KMP_BLOCKTIME
bool __kmp_wpolicy_passive = false;
#if KMP_USE_MONITOR
int __kmp_monitor_wakeups = KMP_MIN_MONITOR_WAKEUPS;
int __kmp_bt_intervals = KMP_INTERVALS_FROM_BLOCKTIME(KMP_DEFAULT_BLOCKTIME,
KMP_MIN_MONITOR_WAKEUPS);
#endif
#ifdef KMP_ADJUST_BLOCKTIME
int __kmp_zero_bt = FALSE;
#endif /* KMP_ADJUST_BLOCKTIME */
#ifdef KMP_DFLT_NTH_CORES
int __kmp_ncores = 0;
#endif
int __kmp_chunk = 0;
int __kmp_force_monotonic = 0;
int __kmp_abort_delay = 0;
#if (KMP_OS_LINUX || KMP_OS_AIX) && defined(KMP_TDATA_GTID)
int __kmp_gtid_mode = 3; /* use __declspec(thread) TLS to store gtid */
int __kmp_adjust_gtid_mode = FALSE;
#elif KMP_OS_WINDOWS
int __kmp_gtid_mode = 2; /* use TLS functions to store gtid */
int __kmp_adjust_gtid_mode = FALSE;
#else
int __kmp_gtid_mode = 0; /* select method to get gtid based on #threads */
int __kmp_adjust_gtid_mode = TRUE;
#endif /* KMP_OS_LINUX && defined(KMP_TDATA_GTID) */
#ifdef KMP_TDATA_GTID
KMP_THREAD_LOCAL int __kmp_gtid = KMP_GTID_DNE;
#endif /* KMP_TDATA_GTID */
int __kmp_tls_gtid_min = INT_MAX;
int __kmp_foreign_tp = TRUE;
#if KMP_ARCH_X86 || KMP_ARCH_X86_64
int __kmp_inherit_fp_control = TRUE;
kmp_int16 __kmp_init_x87_fpu_control_word = 0;
kmp_uint32 __kmp_init_mxcsr = 0;
#endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
#ifdef USE_LOAD_BALANCE
double __kmp_load_balance_interval = 1.0;
#endif /* USE_LOAD_BALANCE */
kmp_nested_nthreads_t __kmp_nested_nth = {NULL, 0, 0};
#if KMP_USE_ADAPTIVE_LOCKS
kmp_adaptive_backoff_params_t __kmp_adaptive_backoff_params = {
1, 1024}; // TODO: tune it!
#if KMP_DEBUG_ADAPTIVE_LOCKS
const char *__kmp_speculative_statsfile = "-";
#endif
#endif // KMP_USE_ADAPTIVE_LOCKS
int __kmp_display_env = FALSE;
int __kmp_display_env_verbose = FALSE;
int __kmp_omp_cancellation = FALSE;
int __kmp_nteams = 0;
int __kmp_teams_thread_limit = 0;
#if KMP_HAVE_MWAIT || KMP_HAVE_UMWAIT
int __kmp_user_level_mwait = FALSE;
int __kmp_umwait_enabled = FALSE;
int __kmp_mwait_enabled = FALSE;
int __kmp_mwait_hints = 0;
#endif
#if KMP_HAVE_UMWAIT
int __kmp_waitpkg_enabled = 0;
int __kmp_tpause_state = 0;
int __kmp_tpause_hint = 1;
int __kmp_tpause_enabled = 0;
#endif
/* map OMP 3.0 schedule types with our internal schedule types */
enum sched_type __kmp_sch_map[kmp_sched_upper - kmp_sched_lower_ext +
kmp_sched_upper_std - kmp_sched_lower - 2] = {
kmp_sch_static_chunked, // ==> kmp_sched_static = 1
kmp_sch_dynamic_chunked, // ==> kmp_sched_dynamic = 2
kmp_sch_guided_chunked, // ==> kmp_sched_guided = 3
kmp_sch_auto, // ==> kmp_sched_auto = 4
kmp_sch_trapezoidal // ==> kmp_sched_trapezoidal = 101
// will likely not be used, introduced here just to debug the code
// of public intel extension schedules
};
#if KMP_OS_LINUX
enum clock_function_type __kmp_clock_function;
int __kmp_clock_function_param;
#endif /* KMP_OS_LINUX */
#if KMP_MIC_SUPPORTED
enum mic_type __kmp_mic_type = non_mic;
#endif
#if KMP_AFFINITY_SUPPORTED
KMPAffinity *__kmp_affinity_dispatch = NULL;
#if KMP_USE_HWLOC
int __kmp_hwloc_error = FALSE;
hwloc_topology_t __kmp_hwloc_topology = NULL;
#endif
#if KMP_OS_WINDOWS
#if KMP_GROUP_AFFINITY
int __kmp_num_proc_groups = 1;
#endif /* KMP_GROUP_AFFINITY */
kmp_GetActiveProcessorCount_t __kmp_GetActiveProcessorCount = NULL;
kmp_GetActiveProcessorGroupCount_t __kmp_GetActiveProcessorGroupCount = NULL;
kmp_GetThreadGroupAffinity_t __kmp_GetThreadGroupAffinity = NULL;
kmp_SetThreadGroupAffinity_t __kmp_SetThreadGroupAffinity = NULL;
#endif /* KMP_OS_WINDOWS */
size_t __kmp_affin_mask_size = 0;
enum affinity_top_method __kmp_affinity_top_method =
affinity_top_method_default;
// Regular thread affinity settings from KMP_AFFINITY
kmp_affinity_t __kmp_affinity = KMP_AFFINITY_INIT("KMP_AFFINITY");
// Hidden helper thread affinity settings from KMP_HIDDEN_HELPER_AFFINITY
kmp_affinity_t __kmp_hh_affinity =
KMP_AFFINITY_INIT("KMP_HIDDEN_HELPER_AFFINITY");
kmp_affinity_t *__kmp_affinities[] = {&__kmp_affinity, &__kmp_hh_affinity};
char *__kmp_cpuinfo_file = NULL;
#if KMP_WEIGHTED_ITERATIONS_SUPPORTED
int __kmp_first_osid_with_ecore = -1;
#endif
#endif /* KMP_AFFINITY_SUPPORTED */
kmp_nested_proc_bind_t __kmp_nested_proc_bind = {NULL, 0, 0};
kmp_proc_bind_t __kmp_teams_proc_bind = proc_bind_spread;
int __kmp_affinity_num_places = 0;
int __kmp_display_affinity = FALSE;
char *__kmp_affinity_format = NULL;
kmp_int32 __kmp_default_device = 0;
kmp_tasking_mode_t __kmp_tasking_mode = tskm_task_teams;
kmp_int32 __kmp_max_task_priority = 0;
kmp_uint64 __kmp_taskloop_min_tasks = 0;
int __kmp_memkind_available = 0;
omp_allocator_handle_t const omp_null_allocator = NULL;
omp_allocator_handle_t const omp_default_mem_alloc =
(omp_allocator_handle_t const)1;
omp_allocator_handle_t const omp_large_cap_mem_alloc =
(omp_allocator_handle_t const)2;
omp_allocator_handle_t const omp_const_mem_alloc =
(omp_allocator_handle_t const)3;
omp_allocator_handle_t const omp_high_bw_mem_alloc =
(omp_allocator_handle_t const)4;
omp_allocator_handle_t const omp_low_lat_mem_alloc =
(omp_allocator_handle_t const)5;
omp_allocator_handle_t const omp_cgroup_mem_alloc =
(omp_allocator_handle_t const)6;
omp_allocator_handle_t const omp_pteam_mem_alloc =
(omp_allocator_handle_t const)7;
omp_allocator_handle_t const omp_thread_mem_alloc =
(omp_allocator_handle_t const)8;
omp_allocator_handle_t const llvm_omp_target_host_mem_alloc =
(omp_allocator_handle_t const)100;
omp_allocator_handle_t const llvm_omp_target_shared_mem_alloc =
(omp_allocator_handle_t const)101;
omp_allocator_handle_t const llvm_omp_target_device_mem_alloc =
(omp_allocator_handle_t const)102;
omp_allocator_handle_t const kmp_max_mem_alloc =
(omp_allocator_handle_t const)1024;
omp_allocator_handle_t __kmp_def_allocator = omp_default_mem_alloc;
omp_memspace_handle_t const omp_default_mem_space =
(omp_memspace_handle_t const)0;
omp_memspace_handle_t const omp_large_cap_mem_space =
(omp_memspace_handle_t const)1;
omp_memspace_handle_t const omp_const_mem_space =
(omp_memspace_handle_t const)2;
omp_memspace_handle_t const omp_high_bw_mem_space =
(omp_memspace_handle_t const)3;
omp_memspace_handle_t const omp_low_lat_mem_space =
(omp_memspace_handle_t const)4;
omp_memspace_handle_t const llvm_omp_target_host_mem_space =
(omp_memspace_handle_t const)100;
omp_memspace_handle_t const llvm_omp_target_shared_mem_space =
(omp_memspace_handle_t const)101;
omp_memspace_handle_t const llvm_omp_target_device_mem_space =
(omp_memspace_handle_t const)102;
/* This check ensures that the compiler is passing the correct data type for the
flags formal parameter of the function kmpc_omp_task_alloc(). If the type is
not a 4-byte type, then give an error message about a non-positive length
array pointing here. If that happens, the kmp_tasking_flags_t structure must
be redefined to have exactly 32 bits. */
KMP_BUILD_ASSERT(sizeof(kmp_tasking_flags_t) == 4);
int __kmp_task_stealing_constraint = 1; /* Constrain task stealing by default */
int __kmp_enable_task_throttling = 1;
#ifdef DEBUG_SUSPEND
int __kmp_suspend_count = 0;
#endif
int __kmp_settings = FALSE;
int __kmp_duplicate_library_ok = 0;
#if USE_ITT_BUILD
int __kmp_forkjoin_frames = 1;
int __kmp_forkjoin_frames_mode = 3;
#endif
PACKED_REDUCTION_METHOD_T __kmp_force_reduction_method =
reduction_method_not_defined;
int __kmp_determ_red = FALSE;
#ifdef KMP_DEBUG
int kmp_a_debug = 0;
int kmp_b_debug = 0;
int kmp_c_debug = 0;
int kmp_d_debug = 0;
int kmp_e_debug = 0;
int kmp_f_debug = 0;
int kmp_diag = 0;
#endif
/* For debug information logging using rotating buffer */
int __kmp_debug_buf =
FALSE; /* TRUE means use buffer, FALSE means print to stderr */
int __kmp_debug_buf_lines =
KMP_DEBUG_BUF_LINES_INIT; /* Lines of debug stored in buffer */
int __kmp_debug_buf_chars =
KMP_DEBUG_BUF_CHARS_INIT; /* Characters allowed per line in buffer */
int __kmp_debug_buf_atomic =
FALSE; /* TRUE means use atomic update of buffer entry pointer */
char *__kmp_debug_buffer = NULL; /* Debug buffer itself */
std::atomic<int> __kmp_debug_count =
0; /* number of lines printed in buffer so far */
int __kmp_debug_buf_warn_chars =
0; /* Keep track of char increase recommended in warnings */
/* end rotating debug buffer */
#ifdef KMP_DEBUG
int __kmp_par_range; /* +1 => only go par for constructs in range */
/* -1 => only go par for constructs outside range */
char __kmp_par_range_routine[KMP_PAR_RANGE_ROUTINE_LEN] = {'\0'};
char __kmp_par_range_filename[KMP_PAR_RANGE_FILENAME_LEN] = {'\0'};
int __kmp_par_range_lb = 0;
int __kmp_par_range_ub = INT_MAX;
#endif /* KMP_DEBUG */
/* For printing out dynamic storage map for threads and teams */
int __kmp_storage_map =
FALSE; /* True means print storage map for threads and teams */
int __kmp_storage_map_verbose =
FALSE; /* True means storage map includes placement info */
int __kmp_storage_map_verbose_specified = FALSE;
/* Initialize the library data structures when we fork a child process, defaults
* to TRUE */
int __kmp_need_register_atfork =
TRUE; /* At initialization, call pthread_atfork to install fork handler */
int __kmp_need_register_atfork_specified = TRUE;
int __kmp_env_stksize = FALSE; /* KMP_STACKSIZE specified? */
int __kmp_env_blocktime = FALSE; /* KMP_BLOCKTIME specified? */
int __kmp_env_checks = FALSE; /* KMP_CHECKS specified? */
int __kmp_env_consistency_check = FALSE; /* KMP_CONSISTENCY_CHECK specified? */
// From KMP_USE_YIELD:
// 0 = never yield;
// 1 = always yield (default);
// 2 = yield only if oversubscribed
#if KMP_OS_DARWIN && KMP_ARCH_AARCH64
// Set to 0 for environments where yield is slower
kmp_int32 __kmp_use_yield = 0;
#else
kmp_int32 __kmp_use_yield = 1;
#endif
// This will be 1 if KMP_USE_YIELD environment variable was set explicitly
kmp_int32 __kmp_use_yield_exp_set = 0;
kmp_uint32 __kmp_yield_init = KMP_INIT_WAIT;
kmp_uint32 __kmp_yield_next = KMP_NEXT_WAIT;
kmp_uint64 __kmp_pause_init = 1; // for tpause
/* ------------------------------------------------------ */
/* STATE mostly syncronized with global lock */
/* data written to rarely by primary threads, read often by workers */
/* TODO: None of this global padding stuff works consistently because the order
of declaration is not necessarily correlated to storage order. To fix this,
all the important globals must be put in a big structure instead. */
KMP_ALIGN_CACHE
kmp_info_t **__kmp_threads = NULL;
kmp_root_t **__kmp_root = NULL;
kmp_old_threads_list_t *__kmp_old_threads_list = NULL;
/* data read/written to often by primary threads */
KMP_ALIGN_CACHE
volatile int __kmp_nth = 0;
volatile int __kmp_all_nth = 0;
volatile kmp_info_t *__kmp_thread_pool = NULL;
volatile kmp_team_t *__kmp_team_pool = NULL;
KMP_ALIGN_CACHE
std::atomic<int> __kmp_thread_pool_active_nth = 0;
/* -------------------------------------------------
* GLOBAL/ROOT STATE */
KMP_ALIGN_CACHE
kmp_global_t __kmp_global;
/* ----------------------------------------------- */
/* GLOBAL SYNCHRONIZATION LOCKS */
/* TODO verify the need for these locks and if they need to be global */
#if KMP_USE_INTERNODE_ALIGNMENT
/* Multinode systems have larger cache line granularity which can cause
* false sharing if the alignment is not large enough for these locks */
KMP_ALIGN_CACHE_INTERNODE
KMP_BOOTSTRAP_LOCK_INIT(__kmp_initz_lock); /* Control initializations */
KMP_ALIGN_CACHE_INTERNODE
KMP_BOOTSTRAP_LOCK_INIT(__kmp_forkjoin_lock); /* control fork/join access */
KMP_ALIGN_CACHE_INTERNODE
KMP_BOOTSTRAP_LOCK_INIT(__kmp_exit_lock); /* exit() is not always thread-safe */
#if KMP_USE_MONITOR
/* control monitor thread creation */
KMP_ALIGN_CACHE_INTERNODE
KMP_BOOTSTRAP_LOCK_INIT(__kmp_monitor_lock);
#endif
/* used for the hack to allow threadprivate cache and __kmp_threads expansion
to co-exist */
KMP_ALIGN_CACHE_INTERNODE
KMP_BOOTSTRAP_LOCK_INIT(__kmp_tp_cached_lock);
KMP_ALIGN_CACHE_INTERNODE
KMP_LOCK_INIT(__kmp_global_lock); /* Control OS/global access */
KMP_ALIGN_CACHE_INTERNODE
kmp_queuing_lock_t __kmp_dispatch_lock; /* Control dispatch access */
KMP_ALIGN_CACHE_INTERNODE
KMP_LOCK_INIT(__kmp_debug_lock); /* Control I/O access for KMP_DEBUG */
#else
KMP_ALIGN_CACHE
KMP_BOOTSTRAP_LOCK_INIT(__kmp_initz_lock); /* Control initializations */
KMP_BOOTSTRAP_LOCK_INIT(__kmp_forkjoin_lock); /* control fork/join access */
KMP_BOOTSTRAP_LOCK_INIT(__kmp_exit_lock); /* exit() is not always thread-safe */
#if KMP_USE_MONITOR
/* control monitor thread creation */
KMP_BOOTSTRAP_LOCK_INIT(__kmp_monitor_lock);
#endif
/* used for the hack to allow threadprivate cache and __kmp_threads expansion
to co-exist */
KMP_BOOTSTRAP_LOCK_INIT(__kmp_tp_cached_lock);
KMP_ALIGN(128)
KMP_LOCK_INIT(__kmp_global_lock); /* Control OS/global access */
KMP_ALIGN(128)
kmp_queuing_lock_t __kmp_dispatch_lock; /* Control dispatch access */
KMP_ALIGN(128)
KMP_LOCK_INIT(__kmp_debug_lock); /* Control I/O access for KMP_DEBUG */
#endif
/* ----------------------------------------------- */
#if KMP_HANDLE_SIGNALS
/* Signal handling is disabled by default, because it confuses users: In case of
sigsegv (or other trouble) in user code signal handler catches the signal,
which then "appears" in the monitor thread (when the monitor executes raise()
function). Users see signal in the monitor thread and blame OpenMP RTL.
Grant said signal handling required on some older OSes (Irix?) supported by
KAI, because bad applications hung but not aborted. Currently it is not a
problem for Linux* OS, OS X* and Windows* OS.
Grant: Found new hangs for EL4, EL5, and a Fedora Core machine. So I'm
putting the default back for now to see if that fixes hangs on those
machines.
2010-04013 Lev: It was a bug in Fortran RTL. Fortran RTL prints a kind of
stack backtrace when program is aborting, but the code is not signal-safe.
When multiple signals raised at the same time (which occurs in dynamic
negative tests because all the worker threads detects the same error),
Fortran RTL may hang. The bug finally fixed in Fortran RTL library provided
by Steve R., and will be available soon. */
int __kmp_handle_signals = FALSE;
#endif
#ifdef DEBUG_SUSPEND
int get_suspend_count_(void) {
int count = __kmp_suspend_count;
__kmp_suspend_count = 0;
return count;
}
void set_suspend_count_(int *value) { __kmp_suspend_count = *value; }
#endif
kmp_target_offload_kind_t __kmp_target_offload = tgt_default;
// OMP Pause Resources
kmp_pause_status_t __kmp_pause_status = kmp_not_paused;
// Nesting mode
int __kmp_nesting_mode = 0;
int __kmp_nesting_mode_nlevels = 1;
int *__kmp_nesting_nth_level;
#if OMPX_TASKGRAPH
// TDG record & replay
int __kmp_tdg_dot = 0;
kmp_int32 __kmp_max_tdgs = 100;
kmp_tdg_info_t **__kmp_global_tdgs = NULL;
kmp_int32 __kmp_curr_tdg_idx =
0; // Id of the current TDG being recorded or executed
kmp_int32 __kmp_num_tdg = 0;
kmp_int32 __kmp_successors_size = 10; // Initial succesor size list for
// recording
std::atomic<kmp_int32> __kmp_tdg_task_id = 0;
#endif
// end of file //

2706
third_party/openmp/kmp_gsupport.cpp vendored Normal file

File diff suppressed because it is too large Load diff

876
third_party/openmp/kmp_i18n.cpp vendored Normal file
View file

@ -0,0 +1,876 @@
/*
* kmp_i18n.cpp
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "kmp_i18n.h"
#include "kmp.h"
#include "kmp_debug.h"
#include "kmp_io.h" // __kmp_printf.
#include "kmp_lock.h"
#include "kmp_os.h"
#include <errno.h>
#include <locale.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include "kmp_environment.h"
#include "kmp_i18n_default.inc"
#include "kmp_str.h"
#undef KMP_I18N_OK
#define get_section(id) ((id) >> 16)
#define get_number(id) ((id)&0xFFFF)
kmp_msg_t __kmp_msg_null = {kmp_mt_dummy, 0, NULL, 0};
static char const *no_message_available = "(No message available)";
static void __kmp_msg(kmp_msg_severity_t severity, kmp_msg_t message,
va_list ap);
enum kmp_i18n_cat_status {
KMP_I18N_CLOSED, // Not yet opened or closed.
KMP_I18N_OPENED, // Opened successfully, ready to use.
KMP_I18N_ABSENT // Opening failed, message catalog should not be used.
}; // enum kmp_i18n_cat_status
typedef enum kmp_i18n_cat_status kmp_i18n_cat_status_t;
static volatile kmp_i18n_cat_status_t status = KMP_I18N_CLOSED;
/* Message catalog is opened at first usage, so we have to synchronize opening
to avoid race and multiple openings.
Closing does not require synchronization, because catalog is closed very late
at library shutting down, when no other threads are alive. */
static void __kmp_i18n_do_catopen();
static kmp_bootstrap_lock_t lock = KMP_BOOTSTRAP_LOCK_INITIALIZER(lock);
// `lock' variable may be placed into __kmp_i18n_catopen function because it is
// used only by that function. But we afraid a (buggy) compiler may treat it
// wrongly. So we put it outside of function just in case.
void __kmp_i18n_catopen() {
if (status == KMP_I18N_CLOSED) {
__kmp_acquire_bootstrap_lock(&lock);
if (status == KMP_I18N_CLOSED) {
__kmp_i18n_do_catopen();
}
__kmp_release_bootstrap_lock(&lock);
}
} // func __kmp_i18n_catopen
/* Linux* OS and OS X* part */
#if KMP_OS_UNIX
#define KMP_I18N_OK
#include <nl_types.h>
#define KMP_I18N_NULLCAT ((nl_catd)(-1))
static nl_catd cat = KMP_I18N_NULLCAT; // !!! Shall it be volatile?
static char const *name =
(KMP_VERSION_MAJOR == 4 ? "libguide.cat" : "libomp.cat");
/* Useful links:
http://www.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap08.html#tag_08_02
http://www.opengroup.org/onlinepubs/000095399/functions/catopen.html
http://www.opengroup.org/onlinepubs/000095399/functions/setlocale.html
*/
void __kmp_i18n_do_catopen() {
int english = 0;
char *lang = __kmp_env_get("LANG");
// TODO: What about LC_ALL or LC_MESSAGES?
KMP_DEBUG_ASSERT(status == KMP_I18N_CLOSED);
KMP_DEBUG_ASSERT(cat == KMP_I18N_NULLCAT);
english = lang == NULL || // In all these cases English language is used.
strcmp(lang, "") == 0 || strcmp(lang, " ") == 0 ||
// Workaround for Fortran RTL bug DPD200137873 "Fortran runtime
// resets LANG env var to space if it is not set".
strcmp(lang, "C") == 0 || strcmp(lang, "POSIX") == 0;
if (!english) { // English language is not yet detected, let us continue.
// Format of LANG is: [language[_territory][.codeset][@modifier]]
// Strip all parts except language.
char *tail = NULL;
__kmp_str_split(lang, '@', &lang, &tail);
__kmp_str_split(lang, '.', &lang, &tail);
__kmp_str_split(lang, '_', &lang, &tail);
english = (strcmp(lang, "en") == 0);
}
KMP_INTERNAL_FREE(lang);
// Do not try to open English catalog because internal messages are
// exact copy of messages in English catalog.
if (english) {
status = KMP_I18N_ABSENT; // mark catalog as absent so it will not
// be re-opened.
return;
}
cat = catopen(name, 0);
// TODO: Why do we pass 0 in flags?
status = (cat == KMP_I18N_NULLCAT ? KMP_I18N_ABSENT : KMP_I18N_OPENED);
if (status == KMP_I18N_ABSENT) {
if (__kmp_generate_warnings > kmp_warnings_low) {
// AC: only issue warning in case explicitly asked to
int error = errno; // Save errno immediately.
char *nlspath = __kmp_env_get("NLSPATH");
char *lang = __kmp_env_get("LANG");
// Infinite recursion will not occur -- status is KMP_I18N_ABSENT now, so
// __kmp_i18n_catgets() will not try to open catalog, but will return
// default message.
kmp_msg_t err_code = KMP_ERR(error);
__kmp_msg(kmp_ms_warning, KMP_MSG(CantOpenMessageCatalog, name), err_code,
KMP_HNT(CheckEnvVar, "NLSPATH", nlspath),
KMP_HNT(CheckEnvVar, "LANG", lang), __kmp_msg_null);
if (__kmp_generate_warnings == kmp_warnings_off) {
__kmp_str_free(&err_code.str);
}
KMP_INFORM(WillUseDefaultMessages);
KMP_INTERNAL_FREE(nlspath);
KMP_INTERNAL_FREE(lang);
}
} else { // status == KMP_I18N_OPENED
int section = get_section(kmp_i18n_prp_Version);
int number = get_number(kmp_i18n_prp_Version);
char const *expected = __kmp_i18n_default_table.sect[section].str[number];
// Expected version of the catalog.
kmp_str_buf_t version; // Actual version of the catalog.
__kmp_str_buf_init(&version);
__kmp_str_buf_print(&version, "%s", catgets(cat, section, number, NULL));
// String returned by catgets is invalid after closing catalog, so copy it.
if (strcmp(version.str, expected) != 0) {
__kmp_i18n_catclose(); // Close bad catalog.
status = KMP_I18N_ABSENT; // And mark it as absent.
if (__kmp_generate_warnings > kmp_warnings_low) {
// AC: only issue warning in case explicitly asked to
// And now print a warning using default messages.
char const *name = "NLSPATH";
char const *nlspath = __kmp_env_get(name);
__kmp_msg(kmp_ms_warning,
KMP_MSG(WrongMessageCatalog, name, version.str, expected),
KMP_HNT(CheckEnvVar, name, nlspath), __kmp_msg_null);
KMP_INFORM(WillUseDefaultMessages);
KMP_INTERNAL_FREE(CCAST(char *, nlspath));
} // __kmp_generate_warnings
}
__kmp_str_buf_free(&version);
}
} // func __kmp_i18n_do_catopen
void __kmp_i18n_catclose() {
if (status == KMP_I18N_OPENED) {
KMP_DEBUG_ASSERT(cat != KMP_I18N_NULLCAT);
catclose(cat);
cat = KMP_I18N_NULLCAT;
}
status = KMP_I18N_CLOSED;
} // func __kmp_i18n_catclose
char const *__kmp_i18n_catgets(kmp_i18n_id_t id) {
int section = get_section(id);
int number = get_number(id);
char const *message = NULL;
if (1 <= section && section <= __kmp_i18n_default_table.size) {
if (1 <= number && number <= __kmp_i18n_default_table.sect[section].size) {
if (status == KMP_I18N_CLOSED) {
__kmp_i18n_catopen();
}
if (status == KMP_I18N_OPENED) {
message = catgets(cat, section, number,
__kmp_i18n_default_table.sect[section].str[number]);
}
if (message == NULL) {
message = __kmp_i18n_default_table.sect[section].str[number];
}
}
}
if (message == NULL) {
message = no_message_available;
}
return message;
} // func __kmp_i18n_catgets
#endif // KMP_OS_UNIX
/* Windows* OS part. */
#if KMP_OS_WINDOWS
#define KMP_I18N_OK
#include "kmp_environment.h"
#include <windows.h>
#define KMP_I18N_NULLCAT NULL
static HMODULE cat = KMP_I18N_NULLCAT; // !!! Shall it be volatile?
static char const *name =
(KMP_VERSION_MAJOR == 4 ? "libguide40ui.dll" : "libompui.dll");
static kmp_i18n_table_t table = {0, NULL};
// Messages formatted by FormatMessage() should be freed, but catgets()
// interface assumes user will not free messages. So we cache all the retrieved
// messages in the table, which are freed at catclose().
static UINT const default_code_page = CP_OEMCP;
static UINT code_page = default_code_page;
static char const *___catgets(kmp_i18n_id_t id);
static UINT get_code_page();
static void kmp_i18n_table_free(kmp_i18n_table_t *table);
static UINT get_code_page() {
UINT cp = default_code_page;
char const *value = __kmp_env_get("KMP_CODEPAGE");
if (value != NULL) {
if (_stricmp(value, "ANSI") == 0) {
cp = CP_ACP;
} else if (_stricmp(value, "OEM") == 0) {
cp = CP_OEMCP;
} else if (_stricmp(value, "UTF-8") == 0 || _stricmp(value, "UTF8") == 0) {
cp = CP_UTF8;
} else if (_stricmp(value, "UTF-7") == 0 || _stricmp(value, "UTF7") == 0) {
cp = CP_UTF7;
} else {
// !!! TODO: Issue a warning?
}
}
KMP_INTERNAL_FREE((void *)value);
return cp;
} // func get_code_page
static void kmp_i18n_table_free(kmp_i18n_table_t *table) {
int s;
int m;
for (s = 0; s < table->size; ++s) {
for (m = 0; m < table->sect[s].size; ++m) {
// Free message.
KMP_INTERNAL_FREE((void *)table->sect[s].str[m]);
table->sect[s].str[m] = NULL;
}
table->sect[s].size = 0;
// Free section itself.
KMP_INTERNAL_FREE((void *)table->sect[s].str);
table->sect[s].str = NULL;
}
table->size = 0;
KMP_INTERNAL_FREE((void *)table->sect);
table->sect = NULL;
} // kmp_i18n_table_free
void __kmp_i18n_do_catopen() {
LCID locale_id = GetThreadLocale();
WORD lang_id = LANGIDFROMLCID(locale_id);
WORD primary_lang_id = PRIMARYLANGID(lang_id);
kmp_str_buf_t path;
KMP_DEBUG_ASSERT(status == KMP_I18N_CLOSED);
KMP_DEBUG_ASSERT(cat == KMP_I18N_NULLCAT);
__kmp_str_buf_init(&path);
// Do not try to open English catalog because internal messages are exact copy
// of messages in English catalog.
if (primary_lang_id == LANG_ENGLISH) {
status = KMP_I18N_ABSENT; // mark catalog as absent so it will not
// be re-opened.
goto end;
}
// Construct resource DLL name.
/* Simple LoadLibrary( name ) is not suitable due to security issue (see
http://www.microsoft.com/technet/security/advisory/2269637.mspx). We have
to specify full path to the message catalog. */
{
// Get handle of our DLL first.
HMODULE handle;
BOOL brc = GetModuleHandleEx(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
reinterpret_cast<LPCSTR>(&__kmp_i18n_do_catopen), &handle);
if (!brc) { // Error occurred.
status = KMP_I18N_ABSENT; // mark catalog as absent so it will not be
// re-opened.
goto end;
// TODO: Enable multiple messages (KMP_MSG) to be passed to __kmp_msg; and
// print a proper warning.
}
// Now get path to the our DLL.
for (;;) {
DWORD drc = GetModuleFileName(handle, path.str, path.size);
if (drc == 0) { // Error occurred.
status = KMP_I18N_ABSENT;
goto end;
}
if (drc < path.size) {
path.used = drc;
break;
}
__kmp_str_buf_reserve(&path, path.size * 2);
}
// Now construct the name of message catalog.
kmp_str_fname fname;
__kmp_str_fname_init(&fname, path.str);
__kmp_str_buf_clear(&path);
__kmp_str_buf_print(&path, "%s%lu/%s", fname.dir,
(unsigned long)(locale_id), name);
__kmp_str_fname_free(&fname);
}
// For security reasons, use LoadLibraryEx() and load message catalog as a
// data file.
cat = LoadLibraryEx(path.str, NULL, LOAD_LIBRARY_AS_DATAFILE);
status = (cat == KMP_I18N_NULLCAT ? KMP_I18N_ABSENT : KMP_I18N_OPENED);
if (status == KMP_I18N_ABSENT) {
if (__kmp_generate_warnings > kmp_warnings_low) {
// AC: only issue warning in case explicitly asked to
DWORD error = GetLastError();
// Infinite recursion will not occur -- status is KMP_I18N_ABSENT now, so
// __kmp_i18n_catgets() will not try to open catalog but will return
// default message.
/* If message catalog for another architecture found (e.g. OpenMP RTL for
IA-32 architecture opens libompui.dll for Intel(R) 64) Windows* OS
returns error 193 (ERROR_BAD_EXE_FORMAT). However, FormatMessage fails
to return a message for this error, so user will see:
OMP: Warning #2: Cannot open message catalog "1041\libompui.dll":
OMP: System error #193: (No system error message available)
OMP: Info #3: Default messages will be used.
Issue hint in this case so cause of trouble is more understandable. */
kmp_msg_t err_code = KMP_SYSERRCODE(error);
__kmp_msg(kmp_ms_warning, KMP_MSG(CantOpenMessageCatalog, path.str),
err_code,
(error == ERROR_BAD_EXE_FORMAT
? KMP_HNT(BadExeFormat, path.str, KMP_ARCH_STR)
: __kmp_msg_null),
__kmp_msg_null);
if (__kmp_generate_warnings == kmp_warnings_off) {
__kmp_str_free(&err_code.str);
}
KMP_INFORM(WillUseDefaultMessages);
}
} else { // status == KMP_I18N_OPENED
int section = get_section(kmp_i18n_prp_Version);
int number = get_number(kmp_i18n_prp_Version);
char const *expected = __kmp_i18n_default_table.sect[section].str[number];
kmp_str_buf_t version; // Actual version of the catalog.
__kmp_str_buf_init(&version);
__kmp_str_buf_print(&version, "%s", ___catgets(kmp_i18n_prp_Version));
// String returned by catgets is invalid after closing catalog, so copy it.
if (strcmp(version.str, expected) != 0) {
// Close bad catalog.
__kmp_i18n_catclose();
status = KMP_I18N_ABSENT; // And mark it as absent.
if (__kmp_generate_warnings > kmp_warnings_low) {
// And now print a warning using default messages.
__kmp_msg(kmp_ms_warning,
KMP_MSG(WrongMessageCatalog, path.str, version.str, expected),
__kmp_msg_null);
KMP_INFORM(WillUseDefaultMessages);
} // __kmp_generate_warnings
}
__kmp_str_buf_free(&version);
}
code_page = get_code_page();
end:
__kmp_str_buf_free(&path);
return;
} // func __kmp_i18n_do_catopen
void __kmp_i18n_catclose() {
if (status == KMP_I18N_OPENED) {
KMP_DEBUG_ASSERT(cat != KMP_I18N_NULLCAT);
kmp_i18n_table_free(&table);
FreeLibrary(cat);
cat = KMP_I18N_NULLCAT;
}
code_page = default_code_page;
status = KMP_I18N_CLOSED;
} // func __kmp_i18n_catclose
/* We use FormatMessage() to get strings from catalog, get system error
messages, etc. FormatMessage() tends to return Windows* OS-style
end-of-lines, "\r\n". When string is printed, printf() also replaces all the
occurrences of "\n" with "\r\n" (again!), so sequences like "\r\r\r\n"
appear in output. It is not too good.
Additional mess comes from message catalog: Our catalog source en_US.mc file
(generated by message-converter.pl) contains only "\n" characters, but
en_US_msg_1033.bin file (produced by mc.exe) may contain "\r\n" or just "\n".
This mess goes from en_US_msg_1033.bin file to message catalog,
libompui.dll. For example, message
Error
(there is "\n" at the end) is compiled by mc.exe to "Error\r\n", while
OMP: Error %1!d!: %2!s!\n
(there is "\n" at the end as well) is compiled to "OMP: Error %1!d!:
%2!s!\r\n\n".
Thus, stripping all "\r" normalizes string and returns it to canonical form,
so printf() will produce correct end-of-line sequences.
___strip_crs() serves for this purpose: it removes all the occurrences of
"\r" in-place and returns new length of string. */
static int ___strip_crs(char *str) {
int in = 0; // Input character index.
int out = 0; // Output character index.
for (;;) {
if (str[in] != '\r') {
str[out] = str[in];
++out;
}
if (str[in] == 0) {
break;
}
++in;
}
return out - 1;
} // func __strip_crs
static char const *___catgets(kmp_i18n_id_t id) {
char *result = NULL;
PVOID addr = NULL;
wchar_t *wmsg = NULL;
DWORD wlen = 0;
char *msg = NULL;
int len = 0;
int rc;
KMP_DEBUG_ASSERT(cat != KMP_I18N_NULLCAT);
wlen = // wlen does *not* include terminating null.
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_HMODULE |
FORMAT_MESSAGE_IGNORE_INSERTS,
cat, id,
0, // LangId
(LPWSTR)&addr,
0, // Size in elements, not in bytes.
NULL);
if (wlen <= 0) {
goto end;
}
wmsg = (wchar_t *)addr; // Warning: wmsg may be not nul-terminated!
// Calculate length of multibyte message.
// Since wlen does not include terminating null, len does not include it also.
len = WideCharToMultiByte(code_page,
0, // Flags.
wmsg, wlen, // Wide buffer and size.
NULL, 0, // Buffer and size.
NULL, NULL // Default char and used default char.
);
if (len <= 0) {
goto end;
}
// Allocate memory.
msg = (char *)KMP_INTERNAL_MALLOC(len + 1);
// Convert wide message to multibyte one.
rc = WideCharToMultiByte(code_page,
0, // Flags.
wmsg, wlen, // Wide buffer and size.
msg, len, // Buffer and size.
NULL, NULL // Default char and used default char.
);
if (rc <= 0 || rc > len) {
goto end;
}
KMP_DEBUG_ASSERT(rc == len);
len = rc;
msg[len] = 0; // Put terminating null to the end.
// Stripping all "\r" before stripping last end-of-line simplifies the task.
len = ___strip_crs(msg);
// Every message in catalog is terminated with "\n". Strip it.
if (len >= 1 && msg[len - 1] == '\n') {
--len;
msg[len] = 0;
}
// Everything looks ok.
result = msg;
msg = NULL;
end:
if (msg != NULL) {
KMP_INTERNAL_FREE(msg);
}
if (wmsg != NULL) {
LocalFree(wmsg);
}
return result;
} // ___catgets
char const *__kmp_i18n_catgets(kmp_i18n_id_t id) {
int section = get_section(id);
int number = get_number(id);
char const *message = NULL;
if (1 <= section && section <= __kmp_i18n_default_table.size) {
if (1 <= number && number <= __kmp_i18n_default_table.sect[section].size) {
if (status == KMP_I18N_CLOSED) {
__kmp_i18n_catopen();
}
if (cat != KMP_I18N_NULLCAT) {
if (table.size == 0) {
table.sect = (kmp_i18n_section_t *)KMP_INTERNAL_CALLOC(
(__kmp_i18n_default_table.size + 2), sizeof(kmp_i18n_section_t));
table.size = __kmp_i18n_default_table.size;
}
if (table.sect[section].size == 0) {
table.sect[section].str = (const char **)KMP_INTERNAL_CALLOC(
__kmp_i18n_default_table.sect[section].size + 2,
sizeof(char const *));
table.sect[section].size =
__kmp_i18n_default_table.sect[section].size;
}
if (table.sect[section].str[number] == NULL) {
table.sect[section].str[number] = ___catgets(id);
}
message = table.sect[section].str[number];
}
if (message == NULL) {
// Catalog is not opened or message is not found, return default
// message.
message = __kmp_i18n_default_table.sect[section].str[number];
}
}
}
if (message == NULL) {
message = no_message_available;
}
return message;
} // func __kmp_i18n_catgets
#endif // KMP_OS_WINDOWS
// -----------------------------------------------------------------------------
#ifndef KMP_I18N_OK
#error I18n support is not implemented for this OS.
#endif // KMP_I18N_OK
// -----------------------------------------------------------------------------
void __kmp_i18n_dump_catalog(kmp_str_buf_t *buffer) {
struct kmp_i18n_id_range_t {
kmp_i18n_id_t first;
kmp_i18n_id_t last;
}; // struct kmp_i18n_id_range_t
static struct kmp_i18n_id_range_t ranges[] = {
{kmp_i18n_prp_first, kmp_i18n_prp_last},
{kmp_i18n_str_first, kmp_i18n_str_last},
{kmp_i18n_fmt_first, kmp_i18n_fmt_last},
{kmp_i18n_msg_first, kmp_i18n_msg_last},
{kmp_i18n_hnt_first, kmp_i18n_hnt_last}}; // ranges
int num_of_ranges = sizeof(ranges) / sizeof(struct kmp_i18n_id_range_t);
int range;
kmp_i18n_id_t id;
for (range = 0; range < num_of_ranges; ++range) {
__kmp_str_buf_print(buffer, "*** Set #%d ***\n", range + 1);
for (id = (kmp_i18n_id_t)(ranges[range].first + 1); id < ranges[range].last;
id = (kmp_i18n_id_t)(id + 1)) {
__kmp_str_buf_print(buffer, "%d: <<%s>>\n", id, __kmp_i18n_catgets(id));
}
}
__kmp_printf("%s", buffer->str);
} // __kmp_i18n_dump_catalog
// -----------------------------------------------------------------------------
kmp_msg_t __kmp_msg_format(unsigned id_arg, ...) {
kmp_msg_t msg;
va_list args;
kmp_str_buf_t buffer;
__kmp_str_buf_init(&buffer);
va_start(args, id_arg);
// We use unsigned for the ID argument and explicitly cast it here to the
// right enumerator because variadic functions are not compatible with
// default promotions.
kmp_i18n_id_t id = (kmp_i18n_id_t)id_arg;
#if KMP_OS_UNIX
// On Linux* OS and OS X*, printf() family functions process parameter
// numbers, for example: "%2$s %1$s".
__kmp_str_buf_vprint(&buffer, __kmp_i18n_catgets(id), args);
#elif KMP_OS_WINDOWS
// On Windows, printf() family functions does not recognize GNU style
// parameter numbers, so we have to use FormatMessage() instead. It recognizes
// parameter numbers, e. g.: "%2!s! "%1!s!".
{
LPTSTR str = NULL;
int len;
FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
__kmp_i18n_catgets(id), 0, 0, (LPTSTR)(&str), 0, &args);
len = ___strip_crs(str);
__kmp_str_buf_cat(&buffer, str, len);
LocalFree(str);
}
#else
#error
#endif
va_end(args);
__kmp_str_buf_detach(&buffer);
msg.type = (kmp_msg_type_t)(id >> 16);
msg.num = id & 0xFFFF;
msg.str = buffer.str;
msg.len = buffer.used;
return msg;
} // __kmp_msg_format
// -----------------------------------------------------------------------------
static char *sys_error(int err) {
char *message = NULL;
#if KMP_OS_WINDOWS
LPVOID buffer = NULL;
int len;
DWORD rc;
rc = FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language.
(LPTSTR)&buffer, 0, NULL);
if (rc > 0) {
// Message formatted. Copy it (so we can free it later with normal free().
message = __kmp_str_format("%s", (char *)buffer);
len = ___strip_crs(message); // Delete carriage returns if any.
// Strip trailing newlines.
while (len > 0 && message[len - 1] == '\n') {
--len;
}
message[len] = 0;
} else {
// FormatMessage() failed to format system error message. GetLastError()
// would give us error code, which we would convert to message... this it
// dangerous recursion, which cannot clarify original error, so we will not
// even start it.
}
if (buffer != NULL) {
LocalFree(buffer);
}
#else // Non-Windows* OS: Linux* OS or OS X*
/* There are 2 incompatible versions of strerror_r:
char * strerror_r( int, char *, size_t ); // GNU version
int strerror_r( int, char *, size_t ); // XSI version
*/
#if (defined(__GLIBC__) && defined(_GNU_SOURCE)) || \
(defined(__BIONIC__) && defined(_GNU_SOURCE) && \
__ANDROID_API__ >= __ANDROID_API_M__)
// GNU version of strerror_r.
char buffer[2048];
char *const err_msg = strerror_r(err, buffer, sizeof(buffer));
// Do not eliminate this assignment to temporary variable, otherwise compiler
// would not issue warning if strerror_r() returns `int' instead of expected
// `char *'.
message = __kmp_str_format("%s", err_msg);
#else // OS X*, FreeBSD* etc.
// XSI version of strerror_r.
int size = 2048;
char *buffer = (char *)KMP_INTERNAL_MALLOC(size);
int rc;
if (buffer == NULL) {
KMP_FATAL(MemoryAllocFailed);
}
rc = strerror_r(err, buffer, size);
if (rc == -1) {
rc = errno; // XSI version sets errno.
}
while (rc == ERANGE) { // ERANGE means the buffer is too small.
KMP_INTERNAL_FREE(buffer);
size *= 2;
buffer = (char *)KMP_INTERNAL_MALLOC(size);
if (buffer == NULL) {
KMP_FATAL(MemoryAllocFailed);
}
rc = strerror_r(err, buffer, size);
if (rc == -1) {
rc = errno; // XSI version sets errno.
}
}
if (rc == 0) {
message = buffer;
} else { // Buffer is unused. Free it.
KMP_INTERNAL_FREE(buffer);
}
#endif
#endif /* KMP_OS_WINDOWS */
if (message == NULL) {
// TODO: I18n this message.
message = __kmp_str_format("%s", "(No system error message available)");
}
return message;
} // sys_error
// -----------------------------------------------------------------------------
kmp_msg_t __kmp_msg_error_code(int code) {
kmp_msg_t msg;
msg.type = kmp_mt_syserr;
msg.num = code;
msg.str = sys_error(code);
msg.len = KMP_STRLEN(msg.str);
return msg;
} // __kmp_msg_error_code
// -----------------------------------------------------------------------------
kmp_msg_t __kmp_msg_error_mesg(char const *mesg) {
kmp_msg_t msg;
msg.type = kmp_mt_syserr;
msg.num = 0;
msg.str = __kmp_str_format("%s", mesg);
msg.len = KMP_STRLEN(msg.str);
return msg;
} // __kmp_msg_error_mesg
// -----------------------------------------------------------------------------
void __kmp_msg(kmp_msg_severity_t severity, kmp_msg_t message, va_list args) {
kmp_i18n_id_t format; // format identifier
kmp_msg_t fmsg; // formatted message
kmp_str_buf_t buffer;
if (severity != kmp_ms_fatal && __kmp_generate_warnings == kmp_warnings_off)
return; // no reason to form a string in order to not print it
__kmp_str_buf_init(&buffer);
// Format the primary message.
switch (severity) {
case kmp_ms_inform: {
format = kmp_i18n_fmt_Info;
} break;
case kmp_ms_warning: {
format = kmp_i18n_fmt_Warning;
} break;
case kmp_ms_fatal: {
format = kmp_i18n_fmt_Fatal;
} break;
default: {
KMP_DEBUG_ASSERT(0);
}
}
fmsg = __kmp_msg_format(format, message.num, message.str);
__kmp_str_free(&message.str);
__kmp_str_buf_cat(&buffer, fmsg.str, fmsg.len);
__kmp_str_free(&fmsg.str);
// Format other messages.
for (;;) {
message = va_arg(args, kmp_msg_t);
if (message.type == kmp_mt_dummy && message.str == NULL) {
break;
}
switch (message.type) {
case kmp_mt_hint: {
format = kmp_i18n_fmt_Hint;
// we cannot skip %1$ and only use %2$ to print the message without the
// number
fmsg = __kmp_msg_format(format, message.str);
} break;
case kmp_mt_syserr: {
format = kmp_i18n_fmt_SysErr;
fmsg = __kmp_msg_format(format, message.num, message.str);
} break;
default: {
KMP_DEBUG_ASSERT(0);
}
}
__kmp_str_free(&message.str);
__kmp_str_buf_cat(&buffer, fmsg.str, fmsg.len);
__kmp_str_free(&fmsg.str);
}
// Print formatted messages.
// This lock prevents multiple fatal errors on the same problem.
// __kmp_acquire_bootstrap_lock( & lock ); // GEH - This lock causing tests
// to hang on OS X*.
__kmp_printf("%s", buffer.str);
__kmp_str_buf_free(&buffer);
// __kmp_release_bootstrap_lock( & lock ); // GEH - this lock causing tests
// to hang on OS X*.
} // __kmp_msg
void __kmp_msg(kmp_msg_severity_t severity, kmp_msg_t message, ...) {
va_list args;
va_start(args, message);
__kmp_msg(severity, message, args);
va_end(args);
}
void __kmp_fatal(kmp_msg_t message, ...) {
va_list args;
va_start(args, message);
__kmp_msg(kmp_ms_fatal, message, args);
va_end(args);
#if KMP_OS_WINDOWS
// Delay to give message a chance to appear before reaping
__kmp_thread_sleep(500);
#endif
__kmp_abort_process();
} // __kmp_fatal
// end of file //

178
third_party/openmp/kmp_i18n.h vendored Normal file
View file

@ -0,0 +1,178 @@
/*
* kmp_i18n.h
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef KMP_I18N_H
#define KMP_I18N_H
#include "kmp_str.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
/* kmp_i18n_id.inc defines kmp_i18n_id_t type. It is an enumeration with
identifiers of all the messages in the catalog. There is one special
identifier: kmp_i18n_null, which denotes absence of message. */
#include "kmp_i18n_id.inc" // Generated file. Do not edit it manually.
/* Low-level functions handling message catalog. __kmp_i18n_open() opens message
catalog, __kmp_i18n_closes() it. Explicit opening is not required: if message
catalog is not yet open, __kmp_i18n_catgets() will open it implicitly.
However, catalog should be explicitly closed, otherwise resources (mamory,
handles) may leak.
__kmp_i18n_catgets() returns read-only string. It should not be freed.
KMP_I18N_STR macro simplifies access to strings in message catalog a bit.
Following two lines are equivalent:
__kmp_i18n_catgets( kmp_i18n_str_Warning )
KMP_I18N_STR( Warning )
*/
void __kmp_i18n_catopen();
void __kmp_i18n_catclose();
char const *__kmp_i18n_catgets(kmp_i18n_id_t id);
#define KMP_I18N_STR(id) __kmp_i18n_catgets(kmp_i18n_str_##id)
/* High-level interface for printing strings targeted to the user.
All the strings are divided into 3 types:
* messages,
* hints,
* system errors.
There are 3 kind of message severities:
* informational messages,
* warnings (non-fatal errors),
* fatal errors.
For example:
OMP: Warning #2: Cannot open message catalog "libguide.cat": (1)
OMP: System error #2: No such file or directory (2)
OMP: Hint: Please check NLSPATH environment variable. (3)
OMP: Info #3: Default messages will be used. (4)
where
(1) is a message of warning severity,
(2) is a system error caused the previous warning,
(3) is a hint for the user how to fix the problem,
(4) is a message of informational severity.
Usage in complex cases (message is accompanied with hints and system errors):
int error = errno; // We need save errno immediately, because it may
// be changed.
__kmp_msg(
kmp_ms_warning, // Severity
KMP_MSG( CantOpenMessageCatalog, name ), // Primary message
KMP_ERR( error ), // System error
KMP_HNT( CheckNLSPATH ), // Hint
__kmp_msg_null // Variadic argument list finisher
);
Usage in simple cases (just a message, no system errors or hints):
KMP_INFORM( WillUseDefaultMessages );
KMP_WARNING( CantOpenMessageCatalog, name );
KMP_FATAL( StackOverlap );
KMP_SYSFAIL( "pthread_create", status );
KMP_CHECK_SYSFAIL( "pthread_create", status );
KMP_CHECK_SYSFAIL_ERRNO( "gettimeofday", status );
*/
enum kmp_msg_type {
kmp_mt_dummy = 0, // Special type for internal purposes.
kmp_mt_mesg =
4, // Primary OpenMP message, could be information, warning, or fatal.
kmp_mt_hint = 5, // Hint to the user.
kmp_mt_syserr = -1 // System error message.
}; // enum kmp_msg_type
typedef enum kmp_msg_type kmp_msg_type_t;
struct kmp_msg {
kmp_msg_type_t type;
int num;
char *str;
size_t len;
}; // struct kmp_message
typedef struct kmp_msg kmp_msg_t;
// Special message to denote the end of variadic list of arguments.
extern kmp_msg_t __kmp_msg_null;
// Helper functions. Creates messages either from message catalog or from
// system. Note: these functions allocate memory. You should pass created
// messages to __kmp_msg() function, it will print messages and destroy them.
kmp_msg_t __kmp_msg_format(unsigned id_arg, ...);
kmp_msg_t __kmp_msg_error_code(int code);
kmp_msg_t __kmp_msg_error_mesg(char const *mesg);
// Helper macros to make calls shorter.
#define KMP_MSG(...) __kmp_msg_format(kmp_i18n_msg_##__VA_ARGS__)
#define KMP_HNT(...) __kmp_msg_format(kmp_i18n_hnt_##__VA_ARGS__)
#define KMP_SYSERRCODE(code) __kmp_msg_error_code(code)
#define KMP_SYSERRMESG(mesg) __kmp_msg_error_mesg(mesg)
#define KMP_ERR KMP_SYSERRCODE
// Message severity.
enum kmp_msg_severity {
kmp_ms_inform, // Just information for the user.
kmp_ms_warning, // Non-fatal error, execution continues.
kmp_ms_fatal // Fatal error, program aborts.
}; // enum kmp_msg_severity
typedef enum kmp_msg_severity kmp_msg_severity_t;
// Primary function for printing messages for the user. The first message is
// mandatory. Any number of system errors and hints may be specified. Argument
// list must be finished with __kmp_msg_null.
void __kmp_msg(kmp_msg_severity_t severity, kmp_msg_t message, ...);
KMP_NORETURN void __kmp_fatal(kmp_msg_t message, ...);
// Helper macros to make calls shorter in simple cases.
#define KMP_INFORM(...) \
__kmp_msg(kmp_ms_inform, KMP_MSG(__VA_ARGS__), __kmp_msg_null)
#define KMP_WARNING(...) \
__kmp_msg(kmp_ms_warning, KMP_MSG(__VA_ARGS__), __kmp_msg_null)
#define KMP_FATAL(...) __kmp_fatal(KMP_MSG(__VA_ARGS__), __kmp_msg_null)
#define KMP_SYSFAIL(func, error) \
__kmp_fatal(KMP_MSG(FunctionError, func), KMP_SYSERRCODE(error), \
__kmp_msg_null)
// Check error, if not zero, generate fatal error message.
#define KMP_CHECK_SYSFAIL(func, error) \
{ \
if (error) { \
KMP_SYSFAIL(func, error); \
} \
}
// Check status, if not zero, generate fatal error message using errno.
#define KMP_CHECK_SYSFAIL_ERRNO(func, status) \
{ \
if (status != 0) { \
int error = errno; \
KMP_SYSFAIL(func, error); \
} \
}
#ifdef KMP_DEBUG
void __kmp_i18n_dump_catalog(kmp_str_buf_t *buffer);
#endif // KMP_DEBUG
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // KMP_I18N_H
// end of file //

489
third_party/openmp/kmp_i18n_default.inc vendored Normal file
View file

@ -0,0 +1,489 @@
// Do not edit this file! //
// The file was generated from en_US.txt by message-converter.pl on Sun Jan 28 19:00:54 2024. //
static char const *
__kmp_i18n_default_meta[] =
{
NULL,
"English",
"USA",
"1033",
"2",
"20170523",
NULL
};
static char const *
__kmp_i18n_default_strings[] =
{
NULL,
"Error",
"(unknown file)",
"not a number",
"bad unit",
"illegal characters",
"value too large",
"value too small",
"value is not a multiple of 4k",
"Unknown processor topology",
"Cannot open /proc/cpuinfo",
"/proc/cpuinfo",
"cpuinfo file invalid (No processor records)",
"cpuinfo file invalid (Too many processor records)",
"Cannot rewind cpuinfo file",
"cpuinfo file invalid (long line)",
"cpuinfo file contains too many entries",
"cpuinfo file missing processor field",
"cpuinfo file missing physical id field",
"cpuinfo file invalid (missing val)",
"cpuinfo file invalid (duplicate field)",
"Physical node/pkg/core/thread ids not unique",
"APIC not present",
"Invalid cpuid info",
"APIC ids not unique",
"Inconsistent cpuid info",
"Out of heap memory",
"Memory allocation failed",
"core",
"thread",
"package",
"node",
"<undef>",
"decoding legacy APIC ids",
"parsing /proc/cpuinfo",
"value is not defined",
"Effective settings:",
"User settings:",
"warning: pointers or size don't make sense",
"CPU",
"TPU",
"TPUs per package",
"HT enabled",
"HT disabled",
"decoding x2APIC ids",
"cpuid leaf 11 not supported",
"cpuid leaf 4 not supported",
"thread ids not unique",
"using pthread info",
"legacy APIC ids not unique",
"x2APIC ids not unique",
"OPENMP DISPLAY ENVIRONMENT BEGIN",
"OPENMP DISPLAY ENVIRONMENT END",
"[device]",
"[host]",
"tile",
"tiles",
"threads",
"cores",
"socket",
"sockets",
"die",
"dice",
"module",
"modules",
"L1 cache",
"L1 caches",
"L2 cache",
"L2 caches",
"L3 cache",
"L3 caches",
"NUMA domain",
"NUMA domains",
"processor group",
"processor groups",
"unknown",
"cpuid leaf 31 not supported",
"Hwloc api failure",
"LL cache",
"LL caches",
NULL
};
static char const *
__kmp_i18n_default_formats[] =
{
NULL,
"OMP: Info #%1$d: %2$s\n",
"OMP: Warning #%1$d: %2$s\n",
"OMP: Error #%1$d: %2$s\n",
"OMP: System error #%1$d: %2$s\n",
"OMP: Hint %1$s\n",
"%1$s pragma (at %2$s:%3$s():%4$s)",
NULL
};
static char const *
__kmp_i18n_default_messages[] =
{
NULL,
"Library is \"serial\".",
"Cannot open message catalog \"%1$s\":",
"Default messages will be used.",
"%1$s: Lock is uninitialized",
"%1$s: Lock was initialized as simple, but used as nestable",
"%1$s: Lock was initialized as nestable, but used as simple",
"%1$s: Lock is already owned by requesting thread",
"%1$s: Lock is still owned by a thread",
"%1$s: Attempt to release a lock not owned by any thread",
"%1$s: Attempt to release a lock owned by another thread",
"Stack overflow detected for OpenMP thread #%1$d",
"Stack overlap detected. ",
"Assertion failure at %1$s(%2$d).",
"Unable to register a new user thread.",
"Initializing %1$s, but found %2$s already initialized.",
"Cannot open file \"%1$s\" for reading:",
"Getting environment variable \"%1$s\" failed:",
"Setting environment variable \"%1$s\" failed:",
"Getting environment failed:",
"%1$s=\"%2$s\": Wrong value, boolean expected.",
"No Helper Thread support built in this OMP library.",
"Helper thread failed to soft terminate.",
"Buffer overflow detected.",
"Real-time scheduling policy is not supported.",
"OMP application is running at maximum priority with real-time scheduling policy. ",
"Changing priority of the monitor thread failed:",
"Deadlocks are highly possible due to monitor thread starvation.",
"Unable to set monitor thread stack size to %1$lu bytes:",
"Unable to set OMP thread stack size to %1$lu bytes:",
"Thread attribute initialization failed:",
"Thread attribute destroying failed:",
"OMP thread joinable state setting failed:",
"Monitor thread joinable state setting failed:",
"System unable to allocate necessary resources for OMP thread:",
"System unable to allocate necessary resources for the monitor thread:",
"Unable to terminate OMP thread:",
"Wrong schedule type %1$d, see <omp.h> or <omp_lib.h> file for the list of values supported.",
"Unknown scheduling type \"%1$d\".",
"%1$s value \"%2$s\" is invalid.",
"%1$s value \"%2$s\" is too small.",
"%1$s value \"%2$s\" is too large.",
"%1$s: \"%2$s\" is an invalid value; ignored.",
"%1$s release value \"%2$s\" is invalid.",
"%1$s gather value \"%2$s\" is invalid.",
"%1$s supported only on debug builds; ignored.",
"Syntax error: Usage: %1$s=[ routine=<func> | filename=<file> | range=<lb>:<ub> | excl_range=<lb>:<ub> ],...",
"Unbalanced quotes in %1$s.",
"Empty string specified for %1$s; ignored.",
"%1$s value is too long; ignored.",
"%1$s: Invalid clause in \"%2$s\".",
"Empty clause in %1$s.",
"%1$s value \"%2$s\" is invalid chunk size.",
"%1$s value \"%2$s\" is to large chunk size.",
"%1$s value \"%2$s\" is ignored.",
"Cannot get processor frequency, using zero KMP_ITT_PREPARE_DELAY.",
"%1$s must be set prior to first parallel region; ignored.",
"%1$s: parameter has been specified already, ignoring \"%2$s\".",
"%1$s: parameter invalid, ignoring \"%2$s\".",
"%1$s: too many integer parameters specified, ignoring \"%2$s\".",
"%1$s: too many integer parameters specified for logical or physical type, ignoring \"%2$d\".",
"%1$s: '%2$s' type does not take any integer parameters, ignoring them.",
"%1$s: proclist not specified with explicit affinity type, using \"none\".",
"%1$s: proclist specified, setting affinity type to \"explicit\".",
"%1$s: proclist specified without \"explicit\" affinity type, proclist ignored.",
"%1$s: syntax error, not using affinity.",
"%1$s: range error (zero stride), not using affinity.",
"%1$s: range error (%2$d > %3$d), not using affinity.",
"%1$s: range error (%2$d < %3$d & stride < 0), not using affinity.",
"%1$s: range error ((%2$d-%3$d)/%4$d too big), not using affinity.",
"%1$s: %2$s is defined. %3$s will be ignored.",
"%1$s: affinity not supported, using \"disabled\".",
"%1$s: affinity only supported for Intel(R) Architecture Processors.",
"%1$s: getaffinity system call not supported.",
"%1$s: setaffinity system call not supported.",
"%1$s: pthread_aff_set_np call not found.",
"%1$s: pthread_get_num_resources_np call not found.",
"%1$s: the OS kernel does not support affinity.",
"%1$s: pthread_get_num_resources_np returned %2$d.",
"%1$s: cannot determine proper affinity mask size.",
"%1$s=\"%2$s\": %3$s.",
"%1$s: extra trailing characters ignored: \"%2$s\".",
"%1$s: unknown method \"%2$s\".",
"KMP_STATS_TIMER: clock_gettime is undefined, using gettimeofday.",
"KMP_STATS_TIMER: \"%1$s\" needs additional parameter, e.g. 'clock_gettime,2'. Using gettimeofday.",
"KMP_STATS_TIMER: clock_gettime parameter \"%1$s\" is invalid, using gettimeofday.",
"KMP_STATS_TIMER: clock_gettime failed, using gettimeofday.",
"KMP_STATS_TIMER: clock function unknown (ignoring value \"%1$s\").",
"Unknown scheduling type detected.",
"Too many threads to use analytical guided scheduling - switching to iterative guided scheduling.",
"ittnotify: Lookup of \"%1$s\" function in \"%2$s\" library failed.",
"ittnotify: Loading \"%1$s\" library failed.",
"ittnotify: All itt notifications disabled.",
"ittnotify: Object state itt notifications disabled.",
"ittnotify: Mark itt notifications disabled.",
"ittnotify: Unloading \"%1$s\" library failed.",
"Cannot form a team with %1$d threads, using %2$d instead.",
"Requested number of active parallel levels \"%1$d\" is negative; ignored.",
"Requested number of active parallel levels \"%1$d\" exceeds supported limit; the following limit value will be used: \"%1$d\".",
"kmp_set_library must only be called from the top level serial thread; ignored.",
"Fatal system error detected.",
"Out of heap memory.",
"Clearing __KMP_REGISTERED_LIB env var failed.",
"Registering library with env var failed.",
"%1$s value \"%2$d\" will be used.",
"%1$s value \"%2$u\" will be used.",
"%1$s value \"%2$s\" will be used.",
"%1$s value \"%2$s\" will be used.",
"Mixing other barrier patterns with dist is prohibited. Using dist for all barrier patterns.",
"%1$s maximum value \"%2$d\" will be used.",
"%1$s minimum value \"%2$d\" will be used.",
"Memory allocation failed.",
"File name too long.",
"Lock table overflow.",
"Too many threads to use threadprivate directive.",
"%1$s: invalid mask.",
"Wrong definition.",
"Windows* OS: TLS Set Value failed.",
"Windows* OS: TLS out of indexes.",
"PDONE directive must be nested within a DO directive.",
"Cannot get number of available CPUs.",
"Assumed number of CPUs is 2.",
"Error initializing affinity - not using affinity.",
"Threads may migrate across all available OS procs (granularity setting too coarse).",
"Ignoring invalid OS proc ID %1$d.",
"No valid OS proc IDs specified - not using affinity.",
"%1$s - using \"flat\" OS <-> physical proc mapping.",
"%1$s: %2$s - using \"flat\" OS <-> physical proc mapping.",
"%1$s, line %2$d: %3$s - using \"flat\" OS <-> physical proc mapping.",
"%1$s: %2$s - exiting.",
"%1$s, line %2$d: %3$s - exiting.",
"Construct identifier invalid.",
"Thread identifier invalid.",
"runtime library not initialized.",
"Inconsistent THREADPRIVATE common block declarations are non-conforming and are unsupported. Either all threadprivate common blocks must be declared identically, or the largest instance of each threadprivate common block must be referenced first during the run.",
"Cannot set thread affinity mask.",
"Cannot set thread priority.",
"Cannot create thread.",
"Cannot create event.",
"Cannot set event.",
"Cannot close handle.",
"Unknown library type: %1$d.",
"Monitor did not reap properly.",
"Worker thread failed to join.",
"Cannot change thread affinity mask.",
"%1$s: Threads may migrate across %2$d innermost levels of machine",
"%1$s: decrease to %2$d threads",
"%1$s: increase to %2$d threads",
"%1$s: Internal thread %2$d bound to OS proc set %3$s",
"%1$s: Affinity capable, using cpuinfo file",
"%1$s: Affinity capable, using global cpuid info",
"%1$s: Affinity capable, using default \"flat\" topology",
"%1$s: Affinity not capable, using local cpuid info",
"%1$s: Affinity not capable, using cpuinfo file",
"%1$s: Affinity not capable, assuming \"flat\" topology",
"%1$s: Initial OS proc set respected: %2$s",
"%1$s: Initial OS proc set not respected: %2$s",
"%1$s: %2$d available OS procs",
"%1$s: Uniform topology",
"%1$s: Nonuniform topology",
"%1$s: %2$d packages x %3$d cores/pkg x %4$d threads/core (%5$d total cores)",
"%1$s: OS proc to physical thread map ([] => level not in map):",
"%1$s: OS proc <n> maps to <n>th package core 0",
"%1$s: OS proc %2$d maps to package %3$d [core %4$d] [thread %5$d]",
"%1$s: OS proc %2$d maps to [package %3$d] [core %4$d] [thread %5$d]",
"%1$s: OS proc %2$d maps to [package %3$d] [core %4$d] thread %5$d",
"%1$s: OS proc %2$d maps to [package %3$d] core %4$d [thread %5$d]",
"%1$s: OS proc %2$d maps to package %3$d [core %4$d] [thread %5$d]",
"%1$s: OS proc %2$d maps to [package %3$d] core %4$d thread %5$d",
"%1$s: OS proc %2$d maps to package %3$d core %4$d [thread %5$d]",
"%1$s: OS proc %2$d maps to package %3$d [core %4$d] thread %5$d",
"%1$s: OS proc %2$d maps to package %3$d core %4$d thread %5$d",
"%1$s: OS proc %2$d maps to %3$s",
"%1$s: Internal thread %2$d changed affinity mask from %3$s to %4$s",
"%1$s: OS proc %2$d maps to package %3$d, CPU %4$d, TPU %5$d",
"%1$s: OS proc %2$d maps to package %3$d, CPU %4$d",
"%1$s: HT enabled; %2$d packages; %3$d TPU; %4$d TPUs per package",
"%1$s: HT disabled; %2$d packages",
"Threads encountered barriers in different order. ",
"Function %1$s failed:",
"%1$s: %2$s packages x %3$d cores/pkg x %4$d threads/core (%5$d total cores)",
"Incompatible message catalog \"%1$s\": Version \"%2$s\" found, version \"%3$s\" expected.",
"%1$s: ignored because %2$s has been defined",
"%1$s: overrides %3$s specified before",
"%1$s: Tiles are only supported if KMP_TOPOLOGY_METHOD=hwloc, using granularity=package instead",
"%1$s: Tiles requested but were not detected on this HW, using granularity=package instead",
"%1$s: %2$d packages x %3$d tiles/pkg x %4$d cores/tile x %5$d threads/core (%6$d total cores)",
"%1$s: %2$d packages x %3$d nodes/pkg x %4$d cores/node x %5$d threads/core (%6$d total cores)",
"%1$s: %2$d packages x %3$d nodes/pkg x %4$d tiles/node x %5$d cores/tile x %6$d threads/core (%7$d total cores)",
"OMPT: Cannot determine workshare type; using the default (loop) instead. This issue is fixed in an up-to-date compiler.",
"Allocator %1$s is not available, will use default allocator.",
"%1$s: %2$s (%3$d total cores)",
"%1$s: granularity setting: %2$s does not exist in topology. Using granularity=%3$s instead.",
"%1$s: hybrid core type detected: %2$d %3$s cores.",
"%1$s: %2$d with core efficiency %3$d.",
"%1$s must be bound to a work-sharing or work-queuing construct with an \"ordered\" clause",
"Detected end of %1$s without first executing a corresponding beginning.",
"Iteration range too large in %1$s.",
"%1$s must not have a loop increment that evaluates to zero.",
"Expected end of %1$s; %2$s, however, has most recently begun execution.",
"%1$s is incorrectly nested within %2$s",
"%1$s cannot be executed multiple times during execution of one parallel iteration/section of %2$s",
"%1$s is incorrectly nested within %2$s of the same name",
"%1$s is incorrectly nested within %2$s that does not have an \"ordered\" clause",
"%1$s is incorrectly nested within %2$s but not within any of its \"task\" constructs",
"One thread at %1$s while another thread is at %2$s.",
"Cannot connect to %1$s",
"Cannot connect to %1$s - Using %2$s",
"%1$s does not support %2$s. Continuing without using %2$s.",
"%1$s does not support %2$s for %3$s. Continuing without using %2$s.",
"Static %1$s does not support %2$s. Continuing without using %2$s.",
"KMP_DYNAMIC_MODE=irml cannot be used with KMP_USE_IRML=0",
"ittnotify: Unknown group \"%2$s\" specified in environment variable \"%1$s\".",
"ittnotify: Environment variable \"%1$s\" too long: Actual lengths is %2$lu, max allowed length is %3$lu.",
"%1$s: Affinity capable, using global cpuid leaf 11 info",
"%1$s: Affinity not capable, using local cpuid leaf 11 info",
"%1$s: %2$s.",
"%1$s: %2$s - %3$s.",
"%1$s: OS proc to physical thread map:",
"%1$s: using \"flat\" OS <-> physical proc mapping.",
"%1$s: parsing %2$s.",
"%1$s - exiting.",
"Incompatible %1$s library with version %2$s found.",
"ittnotify: Function %1$s failed:",
"ittnotify: Error #%1$d.",
"%1$s must be set prior to first parallel region or certain API calls; ignored.",
"Lock initialized at %1$s(%2$d) was not destroyed",
"Cannot determine machine load balance - Using %1$s",
"%1$s: Affinity not capable, using pthread info",
"%1$s: Affinity capable, using pthread info",
"Loading \"%1$s\" library failed:",
"Lookup of \"%1$s\" function failed:",
"Buffer too small.",
"Error #%1$d.",
"%1$s: Invalid symbols found. Check the value \"%2$s\".",
"%1$s: Spaces between digits are not allowed \"%2$s\".",
"%1$s: %2$s - parsing %3$s.",
"%1$s cannot be specified via kmp_set_defaults() on this machine because it has more than one processor group.",
"Cannot use affinity type \"%1$s\" with multiple Windows* OS processor groups, using \"%2$s\".",
"Cannot use affinity granularity \"%1$s\" with multiple Windows* OS processor groups, using \"%2$s\".",
"%1$s: Mapping Windows* OS processor group <i> proc <j> to OS proc 64*<i>+<j>.",
"%1$s: OS proc %2$d maps to Windows* OS processor group %3$d proc %4$d",
"%1$s: Affinity balanced is not available.",
"%1$s: granularity=core will be used.",
"%1$s must be set prior to first OMP lock call or critical section; ignored.",
"futex system call not supported; %1$s=%2$s ignored.",
"%1$s: granularity=%2$s will be used.",
"%1$s: invalid value \"%2$s\", valid format is \"N<item>[@N][,...][,Nt] (<item> can be S, N, L2, C, T for Socket, NUMA Node, L2 Cache, Core, Thread)\".",
"KMP_HW_SUBSET ignored: unsupported architecture.",
"KMP_HW_SUBSET ignored: too many cores requested.",
"%1$s: syntax error, using %2$s.",
"%1$s: Adaptive locks are not supported; using queuing.",
"%1$s: Invalid symbols found. Check the value \"%2$s\".",
"%1$s: Spaces between digits are not allowed \"%2$s\".",
"%1$s: pid %2$d tid %3$d thread %4$d bound to OS proc set %5$s",
"%1$s error: parallel loop increment and condition are inconsistent.",
"libgomp cancellation is not currently supported.",
"KMP_HW_SUBSET ignored: non-uniform topology.",
"KMP_HW_SUBSET ignored: only three-level topology is supported.",
"%1$s: granularity=%2$s is not supported with KMP_TOPOLOGY_METHOD=group. Using \"granularity=fine\".",
"%1$s: granularity=group is not supported with KMP_AFFINITY=%2$s. Using \"granularity=core\".",
"KMP_HW_SUBSET ignored: too many sockets requested.",
"KMP_HW_SUBSET \"o\" offset designator deprecated, please use @ prefix for offset value.",
"%1$s: Affinity capable, using hwloc.",
"%1$s: Ignoring hwloc mechanism.",
"%1$s: Hwloc failed in %2$s. Relying on internal affinity mechanisms.",
"%1$s must be set prior to OpenMP runtime library initialization; ignored.",
"You have enabled the use of umonitor/umwait. If the CPU doesn't have that enabled you'll get an illegal instruction exception.",
"%1$s variable deprecated, please use %2$s instead.",
"KMP_FORCE_REDUCTION: %1$s method is not supported; using critical.",
"KMP_HW_SUBSET ignored: unsupported item requested for non-HWLOC topology method (KMP_TOPOLOGY_METHOD)",
"KMP_HW_SUBSET ignored: too many NUMA Nodes requested.",
"KMP_HW_SUBSET ignored: too many L2 Caches requested.",
"KMP_HW_SUBSET ignored: too many Procs requested.",
"Hierarchy ignored: unsupported level: %1$s.",
"OMP: pid %1$s tid %2$s thread %3$s bound to OS proc set {%4$s}",
"%1$s routine deprecated, please use %2$s instead.",
"libgomp compatibility layer does not support OpenMP feature: %1$s",
"KMP_HW_SUBSET ignored: too many Dies requested.",
"%1$s: Affinity capable, using global cpuid leaf %2$d info",
"%1$s: Affinity not capable, using local cpuid leaf %2$d info",
"%1$s: Affinity not capable, using hwloc.",
"%1$s: Encountered user-directed error: %2$s.",
"%1$s: Encountered user-directed warning: %2$s.",
"Failed to create teams between lower bound (%1$d) and upper bound (%2$d).",
"KMP_HW_SUBSET ignored: %1$s: too many requested.",
"KMP_HW_SUBSET ignored: %1$s: level not detected in machine topology.",
"KMP_HW_SUBSET ignored: %1$s, %2$s: layers are equivalent, please only specify one.",
"KMP_HW_SUBSET ignored: %1$s layer should come after %2$s.",
"%1$s: topology layer \"%2$s\" is equivalent to \"%3$s\".",
"%1$s: granularity=%2$s is too coarse, setting granularity=group.",
"%1$s: \"%2$s\" value is deprecated. Please use \"%3$s\" instead.",
"num_teams value must be positive, it is %1$d, using %2$d instead.",
"KMP_HW_SUBSET ignored: %1$s, %2$s: attributes are ambiguous, please only specify one.",
"KMP_HW_SUBSET ignored: %1$s: attribute specified more than once.",
"KMP_HW_SUBSET ignored: %1$s: attribute value %2$s is invalid.",
"KMP_HW_SUBSET ignored: all hardware resources would be filtered, please reduce the filter.",
"KMP_HW_SUBSET ignored: Too many attributes specified. This machine is not a hybrid architecutre.",
"KMP_HW_SUBSET: ignoring %1$s attribute. This machine is not a hybrid architecutre.",
"Target memory not available, will use default allocator.",
"%1$s ignored: This machine is not a hybrid architecutre. Using \"%2$s\" instead.",
"%1$s ignored: %2$s is not available. Using \"%3$s\" instead.",
NULL
};
static char const *
__kmp_i18n_default_hints[] =
{
NULL,
"Please submit a bug report with this message, compile and run commands used, and machine configuration info including native compiler and operating system versions. Faster response will be obtained by including all program sources. For information on submitting this issue, please see https://github.com/llvm/llvm-project/issues/.",
"Check NLSPATH environment variable, its value is \"%1$s\".",
"Please try changing the shell stack limit or adjusting the OMP_STACKSIZE environment variable.",
"Consider unsetting KMP_DEVICE_THREAD_LIMIT (KMP_ALL_THREADS), KMP_TEAMS_THREAD_LIMIT, and OMP_THREAD_LIMIT (if any are set).",
"Consider setting KMP_ALL_THREADPRIVATE to a value larger than %1$d.",
"This could also be due to a system-related limit on the number of threads.",
"This means that multiple copies of the OpenMP runtime have been linked into the program. That is dangerous, since it can degrade performance or cause incorrect results. The best thing to do is to ensure that only a single OpenMP runtime is linked into the process, e.g. by avoiding static linking of the OpenMP runtime in any library. As an unsafe, unsupported, undocumented workaround you can set the environment variable KMP_DUPLICATE_LIB_OK=TRUE to allow the program to continue to execute, but that may cause crashes or silently produce incorrect results. For more information, please see http://openmp.llvm.org/",
"This name is specified in environment variable KMP_CPUINFO_FILE.",
"Seems application required too much memory.",
"Use \"0\", \"FALSE\". \".F.\", \"off\", \"no\" as false values, \"1\", \"TRUE\", \".T.\", \"on\", \"yes\" as true values.",
"Perhaps too many threads.",
"Decrease priority of application. This will allow the monitor thread run at higher priority than other threads.",
"Try changing KMP_MONITOR_STACKSIZE or the shell stack limit.",
"Try changing OMP_STACKSIZE and/or the shell stack limit.",
"Try increasing OMP_STACKSIZE or the shell stack limit.",
"Try decreasing OMP_STACKSIZE.",
"Try decreasing the value of OMP_NUM_THREADS.",
"Try increasing KMP_MONITOR_STACKSIZE.",
"Try decreasing KMP_MONITOR_STACKSIZE.",
"Try decreasing the number of threads in use simultaneously.",
"Will use default schedule type (%1$s).",
"It could be a result of using an older OMP library with a newer compiler or memory corruption. You may check the proper OMP library is linked to the application.",
"Check %1$s environment variable, its value is \"%2$s\".",
"You may want to use an %1$s library that supports %2$s interface with version %3$s.",
"You may want to use an %1$s library with version %2$s.",
"System error #193 is \"Bad format of EXE or DLL file\". Usually it means the file is found, but it is corrupted or a file for another architecture. Check whether \"%1$s\" is a file for %2$s architecture.",
"System-related limit on the number of threads.",
"Try setting new bounds (preferably less than or equal to %1$d) for num_teams clause.",
"Valid values are from %1$d to %2$d.",
NULL
};
struct kmp_i18n_section {
int size;
char const ** str;
}; // struct kmp_i18n_section
typedef struct kmp_i18n_section kmp_i18n_section_t;
static kmp_i18n_section_t
__kmp_i18n_sections[] =
{
{ 0, NULL },
{ 5, __kmp_i18n_default_meta },
{ 79, __kmp_i18n_default_strings },
{ 6, __kmp_i18n_default_formats },
{ 301, __kmp_i18n_default_messages },
{ 29, __kmp_i18n_default_hints },
{ 0, NULL }
};
struct kmp_i18n_table {
int size;
kmp_i18n_section_t * sect;
}; // struct kmp_i18n_table
typedef struct kmp_i18n_table kmp_i18n_table_t;
static kmp_i18n_table_t __kmp_i18n_default_table =
{
5,
__kmp_i18n_sections
};
// end of file //

456
third_party/openmp/kmp_i18n_id.inc vendored Normal file
View file

@ -0,0 +1,456 @@
// Do not edit this file! //
// The file was generated from en_US.txt by message-converter.pl on Sun Jan 28 19:00:54 2024. //
enum kmp_i18n_id {
// A special id for absence of message.
kmp_i18n_null = 0,
// Set #1, meta.
kmp_i18n_prp_first = 65536,
kmp_i18n_prp_Language,
kmp_i18n_prp_Country,
kmp_i18n_prp_LangId,
kmp_i18n_prp_Version,
kmp_i18n_prp_Revision,
kmp_i18n_prp_last,
// Set #2, strings.
kmp_i18n_str_first = 131072,
kmp_i18n_str_Error,
kmp_i18n_str_UnknownFile,
kmp_i18n_str_NotANumber,
kmp_i18n_str_BadUnit,
kmp_i18n_str_IllegalCharacters,
kmp_i18n_str_ValueTooLarge,
kmp_i18n_str_ValueTooSmall,
kmp_i18n_str_NotMultiple4K,
kmp_i18n_str_UnknownTopology,
kmp_i18n_str_CantOpenCpuinfo,
kmp_i18n_str_ProcCpuinfo,
kmp_i18n_str_NoProcRecords,
kmp_i18n_str_TooManyProcRecords,
kmp_i18n_str_CantRewindCpuinfo,
kmp_i18n_str_LongLineCpuinfo,
kmp_i18n_str_TooManyEntries,
kmp_i18n_str_MissingProcField,
kmp_i18n_str_MissingPhysicalIDField,
kmp_i18n_str_MissingValCpuinfo,
kmp_i18n_str_DuplicateFieldCpuinfo,
kmp_i18n_str_PhysicalIDsNotUnique,
kmp_i18n_str_ApicNotPresent,
kmp_i18n_str_InvalidCpuidInfo,
kmp_i18n_str_OBSOLETE1,
kmp_i18n_str_InconsistentCpuidInfo,
kmp_i18n_str_OutOfHeapMemory,
kmp_i18n_str_MemoryAllocFailed,
kmp_i18n_str_Core,
kmp_i18n_str_Thread,
kmp_i18n_str_Package,
kmp_i18n_str_Node,
kmp_i18n_str_OBSOLETE2,
kmp_i18n_str_DecodingLegacyAPIC,
kmp_i18n_str_OBSOLETE3,
kmp_i18n_str_NotDefined,
kmp_i18n_str_EffectiveSettings,
kmp_i18n_str_UserSettings,
kmp_i18n_str_StorageMapWarning,
kmp_i18n_str_OBSOLETE4,
kmp_i18n_str_OBSOLETE5,
kmp_i18n_str_OBSOLETE6,
kmp_i18n_str_OBSOLETE7,
kmp_i18n_str_OBSOLETE8,
kmp_i18n_str_Decodingx2APIC,
kmp_i18n_str_NoLeaf11Support,
kmp_i18n_str_NoLeaf4Support,
kmp_i18n_str_ThreadIDsNotUnique,
kmp_i18n_str_UsingPthread,
kmp_i18n_str_LegacyApicIDsNotUnique,
kmp_i18n_str_x2ApicIDsNotUnique,
kmp_i18n_str_DisplayEnvBegin,
kmp_i18n_str_DisplayEnvEnd,
kmp_i18n_str_Device,
kmp_i18n_str_Host,
kmp_i18n_str_Tile,
kmp_i18n_str_Tiles,
kmp_i18n_str_Threads,
kmp_i18n_str_Cores,
kmp_i18n_str_Socket,
kmp_i18n_str_Sockets,
kmp_i18n_str_Die,
kmp_i18n_str_Dice,
kmp_i18n_str_Module,
kmp_i18n_str_Modules,
kmp_i18n_str_L1Cache,
kmp_i18n_str_L1Caches,
kmp_i18n_str_L2Cache,
kmp_i18n_str_L2Caches,
kmp_i18n_str_L3Cache,
kmp_i18n_str_L3Caches,
kmp_i18n_str_NumaDomain,
kmp_i18n_str_NumaDomains,
kmp_i18n_str_ProcGroup,
kmp_i18n_str_ProcGroups,
kmp_i18n_str_Unknown,
kmp_i18n_str_NoLeaf31Support,
kmp_i18n_str_HwlocFailed,
kmp_i18n_str_LLCache,
kmp_i18n_str_LLCaches,
kmp_i18n_str_last,
// Set #3, formats.
kmp_i18n_fmt_first = 196608,
kmp_i18n_fmt_Info,
kmp_i18n_fmt_Warning,
kmp_i18n_fmt_Fatal,
kmp_i18n_fmt_SysErr,
kmp_i18n_fmt_Hint,
kmp_i18n_fmt_Pragma,
kmp_i18n_fmt_last,
// Set #4, messages.
kmp_i18n_msg_first = 262144,
kmp_i18n_msg_LibraryIsSerial,
kmp_i18n_msg_CantOpenMessageCatalog,
kmp_i18n_msg_WillUseDefaultMessages,
kmp_i18n_msg_LockIsUninitialized,
kmp_i18n_msg_LockSimpleUsedAsNestable,
kmp_i18n_msg_LockNestableUsedAsSimple,
kmp_i18n_msg_LockIsAlreadyOwned,
kmp_i18n_msg_LockStillOwned,
kmp_i18n_msg_LockUnsettingFree,
kmp_i18n_msg_LockUnsettingSetByAnother,
kmp_i18n_msg_StackOverflow,
kmp_i18n_msg_StackOverlap,
kmp_i18n_msg_AssertionFailure,
kmp_i18n_msg_CantRegisterNewThread,
kmp_i18n_msg_DuplicateLibrary,
kmp_i18n_msg_CantOpenFileForReading,
kmp_i18n_msg_CantGetEnvVar,
kmp_i18n_msg_CantSetEnvVar,
kmp_i18n_msg_CantGetEnvironment,
kmp_i18n_msg_BadBoolValue,
kmp_i18n_msg_SSPNotBuiltIn,
kmp_i18n_msg_SPPSotfTerminateFailed,
kmp_i18n_msg_BufferOverflow,
kmp_i18n_msg_RealTimeSchedNotSupported,
kmp_i18n_msg_RunningAtMaxPriority,
kmp_i18n_msg_CantChangeMonitorPriority,
kmp_i18n_msg_MonitorWillStarve,
kmp_i18n_msg_CantSetMonitorStackSize,
kmp_i18n_msg_CantSetWorkerStackSize,
kmp_i18n_msg_CantInitThreadAttrs,
kmp_i18n_msg_CantDestroyThreadAttrs,
kmp_i18n_msg_CantSetWorkerState,
kmp_i18n_msg_CantSetMonitorState,
kmp_i18n_msg_NoResourcesForWorkerThread,
kmp_i18n_msg_NoResourcesForMonitorThread,
kmp_i18n_msg_CantTerminateWorkerThread,
kmp_i18n_msg_ScheduleKindOutOfRange,
kmp_i18n_msg_UnknownSchedulingType,
kmp_i18n_msg_InvalidValue,
kmp_i18n_msg_SmallValue,
kmp_i18n_msg_LargeValue,
kmp_i18n_msg_StgInvalidValue,
kmp_i18n_msg_BarrReleaseValueInvalid,
kmp_i18n_msg_BarrGatherValueInvalid,
kmp_i18n_msg_OBSOLETE9,
kmp_i18n_msg_ParRangeSyntax,
kmp_i18n_msg_UnbalancedQuotes,
kmp_i18n_msg_EmptyString,
kmp_i18n_msg_LongValue,
kmp_i18n_msg_InvalidClause,
kmp_i18n_msg_EmptyClause,
kmp_i18n_msg_InvalidChunk,
kmp_i18n_msg_LargeChunk,
kmp_i18n_msg_IgnoreChunk,
kmp_i18n_msg_CantGetProcFreq,
kmp_i18n_msg_EnvParallelWarn,
kmp_i18n_msg_AffParamDefined,
kmp_i18n_msg_AffInvalidParam,
kmp_i18n_msg_AffManyParams,
kmp_i18n_msg_AffManyParamsForLogic,
kmp_i18n_msg_AffNoParam,
kmp_i18n_msg_AffNoProcList,
kmp_i18n_msg_AffProcListNoType,
kmp_i18n_msg_AffProcListNotExplicit,
kmp_i18n_msg_AffSyntaxError,
kmp_i18n_msg_AffZeroStride,
kmp_i18n_msg_AffStartGreaterEnd,
kmp_i18n_msg_AffStrideLessZero,
kmp_i18n_msg_AffRangeTooBig,
kmp_i18n_msg_OBSOLETE10,
kmp_i18n_msg_AffNotSupported,
kmp_i18n_msg_OBSOLETE11,
kmp_i18n_msg_GetAffSysCallNotSupported,
kmp_i18n_msg_SetAffSysCallNotSupported,
kmp_i18n_msg_OBSOLETE12,
kmp_i18n_msg_OBSOLETE13,
kmp_i18n_msg_OBSOLETE14,
kmp_i18n_msg_OBSOLETE15,
kmp_i18n_msg_AffCantGetMaskSize,
kmp_i18n_msg_ParseSizeIntWarn,
kmp_i18n_msg_ParseExtraCharsWarn,
kmp_i18n_msg_UnknownForceReduction,
kmp_i18n_msg_TimerUseGettimeofday,
kmp_i18n_msg_TimerNeedMoreParam,
kmp_i18n_msg_TimerInvalidParam,
kmp_i18n_msg_TimerGettimeFailed,
kmp_i18n_msg_TimerUnknownFunction,
kmp_i18n_msg_UnknownSchedTypeDetected,
kmp_i18n_msg_DispatchManyThreads,
kmp_i18n_msg_IttLookupFailed,
kmp_i18n_msg_IttLoadLibFailed,
kmp_i18n_msg_IttAllNotifDisabled,
kmp_i18n_msg_IttObjNotifDisabled,
kmp_i18n_msg_IttMarkNotifDisabled,
kmp_i18n_msg_IttUnloadLibFailed,
kmp_i18n_msg_CantFormThrTeam,
kmp_i18n_msg_ActiveLevelsNegative,
kmp_i18n_msg_ActiveLevelsExceedLimit,
kmp_i18n_msg_SetLibraryIncorrectCall,
kmp_i18n_msg_FatalSysError,
kmp_i18n_msg_OutOfHeapMemory,
kmp_i18n_msg_OBSOLETE16,
kmp_i18n_msg_OBSOLETE17,
kmp_i18n_msg_Using_int_Value,
kmp_i18n_msg_Using_uint_Value,
kmp_i18n_msg_Using_uint64_Value,
kmp_i18n_msg_Using_str_Value,
kmp_i18n_msg_BarrierPatternOverride,
kmp_i18n_msg_MaxValueUsing,
kmp_i18n_msg_MinValueUsing,
kmp_i18n_msg_MemoryAllocFailed,
kmp_i18n_msg_FileNameTooLong,
kmp_i18n_msg_OBSOLETE18,
kmp_i18n_msg_ManyThreadsForTPDirective,
kmp_i18n_msg_AffinityInvalidMask,
kmp_i18n_msg_WrongDefinition,
kmp_i18n_msg_TLSSetValueFailed,
kmp_i18n_msg_TLSOutOfIndexes,
kmp_i18n_msg_OBSOLETE19,
kmp_i18n_msg_CantGetNumAvailCPU,
kmp_i18n_msg_AssumedNumCPU,
kmp_i18n_msg_ErrorInitializeAffinity,
kmp_i18n_msg_AffThreadsMayMigrate,
kmp_i18n_msg_AffIgnoreInvalidProcID,
kmp_i18n_msg_AffNoValidProcID,
kmp_i18n_msg_UsingFlatOS,
kmp_i18n_msg_UsingFlatOSFile,
kmp_i18n_msg_UsingFlatOSFileLine,
kmp_i18n_msg_FileMsgExiting,
kmp_i18n_msg_FileLineMsgExiting,
kmp_i18n_msg_ConstructIdentInvalid,
kmp_i18n_msg_ThreadIdentInvalid,
kmp_i18n_msg_RTLNotInitialized,
kmp_i18n_msg_TPCommonBlocksInconsist,
kmp_i18n_msg_CantSetThreadAffMask,
kmp_i18n_msg_CantSetThreadPriority,
kmp_i18n_msg_CantCreateThread,
kmp_i18n_msg_CantCreateEvent,
kmp_i18n_msg_CantSetEvent,
kmp_i18n_msg_CantCloseHandle,
kmp_i18n_msg_UnknownLibraryType,
kmp_i18n_msg_ReapMonitorError,
kmp_i18n_msg_ReapWorkerError,
kmp_i18n_msg_ChangeThreadAffMaskError,
kmp_i18n_msg_ThreadsMigrate,
kmp_i18n_msg_DecreaseToThreads,
kmp_i18n_msg_IncreaseToThreads,
kmp_i18n_msg_OBSOLETE20,
kmp_i18n_msg_AffCapableUseCpuinfo,
kmp_i18n_msg_AffUseGlobCpuid,
kmp_i18n_msg_AffCapableUseFlat,
kmp_i18n_msg_AffNotCapableUseLocCpuid,
kmp_i18n_msg_AffNotCapableUseCpuinfo,
kmp_i18n_msg_AffFlatTopology,
kmp_i18n_msg_InitOSProcSetRespect,
kmp_i18n_msg_InitOSProcSetNotRespect,
kmp_i18n_msg_AvailableOSProc,
kmp_i18n_msg_Uniform,
kmp_i18n_msg_NonUniform,
kmp_i18n_msg_Topology,
kmp_i18n_msg_OBSOLETE21,
kmp_i18n_msg_OSProcToPackage,
kmp_i18n_msg_OBSOLETE22,
kmp_i18n_msg_OBSOLETE23,
kmp_i18n_msg_OBSOLETE24,
kmp_i18n_msg_OBSOLETE25,
kmp_i18n_msg_OBSOLETE26,
kmp_i18n_msg_OBSOLETE27,
kmp_i18n_msg_OBSOLETE28,
kmp_i18n_msg_OBSOLETE29,
kmp_i18n_msg_OBSOLETE30,
kmp_i18n_msg_OSProcMapToPack,
kmp_i18n_msg_OBSOLETE31,
kmp_i18n_msg_OBSOLETE32,
kmp_i18n_msg_OBSOLETE33,
kmp_i18n_msg_OBSOLETE34,
kmp_i18n_msg_OBSOLETE35,
kmp_i18n_msg_BarriersInDifferentOrder,
kmp_i18n_msg_FunctionError,
kmp_i18n_msg_TopologyExtra,
kmp_i18n_msg_WrongMessageCatalog,
kmp_i18n_msg_StgIgnored,
kmp_i18n_msg_OBSOLETE36,
kmp_i18n_msg_AffTilesNoHWLOC,
kmp_i18n_msg_AffTilesNoTiles,
kmp_i18n_msg_TopologyExtraTile,
kmp_i18n_msg_TopologyExtraNode,
kmp_i18n_msg_TopologyExtraNoTi,
kmp_i18n_msg_OmptOutdatedWorkshare,
kmp_i18n_msg_OmpNoAllocator,
kmp_i18n_msg_TopologyGeneric,
kmp_i18n_msg_AffGranularityBad,
kmp_i18n_msg_TopologyHybrid,
kmp_i18n_msg_TopologyHybridCoreEff,
kmp_i18n_msg_CnsBoundToWorksharing,
kmp_i18n_msg_CnsDetectedEnd,
kmp_i18n_msg_CnsIterationRangeTooLarge,
kmp_i18n_msg_CnsLoopIncrZeroProhibited,
kmp_i18n_msg_CnsExpectedEnd,
kmp_i18n_msg_CnsInvalidNesting,
kmp_i18n_msg_CnsMultipleNesting,
kmp_i18n_msg_CnsNestingSameName,
kmp_i18n_msg_CnsNoOrderedClause,
kmp_i18n_msg_CnsNotInTaskConstruct,
kmp_i18n_msg_CnsThreadsAtBarrier,
kmp_i18n_msg_CantConnect,
kmp_i18n_msg_CantConnectUsing,
kmp_i18n_msg_LibNotSupport,
kmp_i18n_msg_LibNotSupportFor,
kmp_i18n_msg_StaticLibNotSupport,
kmp_i18n_msg_OBSOLETE37,
kmp_i18n_msg_IttUnknownGroup,
kmp_i18n_msg_IttEnvVarTooLong,
kmp_i18n_msg_OBSOLETE38,
kmp_i18n_msg_OBSOLETE39,
kmp_i18n_msg_AffInfoStr,
kmp_i18n_msg_AffInfoStrStr,
kmp_i18n_msg_OSProcToPhysicalThreadMap,
kmp_i18n_msg_AffUsingFlatOS,
kmp_i18n_msg_AffParseFilename,
kmp_i18n_msg_MsgExiting,
kmp_i18n_msg_IncompatibleLibrary,
kmp_i18n_msg_IttFunctionError,
kmp_i18n_msg_IttUnknownError,
kmp_i18n_msg_EnvMiddleWarn,
kmp_i18n_msg_CnsLockNotDestroyed,
kmp_i18n_msg_CantLoadBalUsing,
kmp_i18n_msg_AffNotCapableUsePthread,
kmp_i18n_msg_AffUsePthread,
kmp_i18n_msg_OBSOLETE40,
kmp_i18n_msg_OBSOLETE41,
kmp_i18n_msg_OBSOLETE42,
kmp_i18n_msg_OBSOLETE43,
kmp_i18n_msg_NthSyntaxError,
kmp_i18n_msg_NthSpacesNotAllowed,
kmp_i18n_msg_AffStrParseFilename,
kmp_i18n_msg_OBSOLETE44,
kmp_i18n_msg_AffTypeCantUseMultGroups,
kmp_i18n_msg_AffGranCantUseMultGroups,
kmp_i18n_msg_AffWindowsProcGroupMap,
kmp_i18n_msg_AffOSProcToGroup,
kmp_i18n_msg_AffBalancedNotAvail,
kmp_i18n_msg_OBSOLETE45,
kmp_i18n_msg_EnvLockWarn,
kmp_i18n_msg_FutexNotSupported,
kmp_i18n_msg_AffGranUsing,
kmp_i18n_msg_AffHWSubsetInvalid,
kmp_i18n_msg_AffHWSubsetUnsupported,
kmp_i18n_msg_AffHWSubsetManyCores,
kmp_i18n_msg_SyntaxErrorUsing,
kmp_i18n_msg_AdaptiveNotSupported,
kmp_i18n_msg_EnvSyntaxError,
kmp_i18n_msg_EnvSpacesNotAllowed,
kmp_i18n_msg_BoundToOSProcSet,
kmp_i18n_msg_CnsLoopIncrIllegal,
kmp_i18n_msg_NoGompCancellation,
kmp_i18n_msg_AffHWSubsetNonUniform,
kmp_i18n_msg_AffHWSubsetNonThreeLevel,
kmp_i18n_msg_AffGranTopGroup,
kmp_i18n_msg_AffGranGroupType,
kmp_i18n_msg_AffHWSubsetManySockets,
kmp_i18n_msg_AffHWSubsetDeprecated,
kmp_i18n_msg_AffUsingHwloc,
kmp_i18n_msg_AffIgnoringHwloc,
kmp_i18n_msg_AffHwlocErrorOccurred,
kmp_i18n_msg_EnvSerialWarn,
kmp_i18n_msg_EnvMwaitWarn,
kmp_i18n_msg_EnvVarDeprecated,
kmp_i18n_msg_RedMethodNotSupported,
kmp_i18n_msg_AffHWSubsetNoHWLOC,
kmp_i18n_msg_AffHWSubsetManyNodes,
kmp_i18n_msg_AffHWSubsetManyTiles,
kmp_i18n_msg_AffHWSubsetManyProcs,
kmp_i18n_msg_HierSchedInvalid,
kmp_i18n_msg_AffFormatDefault,
kmp_i18n_msg_APIDeprecated,
kmp_i18n_msg_GompFeatureNotSupported,
kmp_i18n_msg_AffHWSubsetManyDies,
kmp_i18n_msg_AffUseGlobCpuidL,
kmp_i18n_msg_AffNotCapableUseLocCpuidL,
kmp_i18n_msg_AffNotUsingHwloc,
kmp_i18n_msg_UserDirectedError,
kmp_i18n_msg_UserDirectedWarning,
kmp_i18n_msg_FailedToCreateTeam,
kmp_i18n_msg_AffHWSubsetManyGeneric,
kmp_i18n_msg_AffHWSubsetNotExistGeneric,
kmp_i18n_msg_AffHWSubsetEqvLayers,
kmp_i18n_msg_AffHWSubsetOutOfOrder,
kmp_i18n_msg_AffEqualTopologyTypes,
kmp_i18n_msg_AffGranTooCoarseProcGroup,
kmp_i18n_msg_StgDeprecatedValue,
kmp_i18n_msg_NumTeamsNotPositive,
kmp_i18n_msg_AffHWSubsetIncompat,
kmp_i18n_msg_AffHWSubsetAttrRepeat,
kmp_i18n_msg_AffHWSubsetAttrInvalid,
kmp_i18n_msg_AffHWSubsetAllFiltered,
kmp_i18n_msg_AffHWSubsetAttrsNonHybrid,
kmp_i18n_msg_AffHWSubsetIgnoringAttr,
kmp_i18n_msg_TargetMemNotAvailable,
kmp_i18n_msg_AffIgnoringNonHybrid,
kmp_i18n_msg_AffIgnoringNotAvailable,
kmp_i18n_msg_last,
// Set #5, hints.
kmp_i18n_hnt_first = 327680,
kmp_i18n_hnt_SubmitBugReport,
kmp_i18n_hnt_OBSOLETE46,
kmp_i18n_hnt_ChangeStackLimit,
kmp_i18n_hnt_Unset_ALL_THREADS,
kmp_i18n_hnt_Set_ALL_THREADPRIVATE,
kmp_i18n_hnt_PossibleSystemLimitOnThreads,
kmp_i18n_hnt_DuplicateLibrary,
kmp_i18n_hnt_NameComesFrom_CPUINFO_FILE,
kmp_i18n_hnt_NotEnoughMemory,
kmp_i18n_hnt_ValidBoolValues,
kmp_i18n_hnt_BufferOverflow,
kmp_i18n_hnt_RunningAtMaxPriority,
kmp_i18n_hnt_ChangeMonitorStackSize,
kmp_i18n_hnt_ChangeWorkerStackSize,
kmp_i18n_hnt_IncreaseWorkerStackSize,
kmp_i18n_hnt_DecreaseWorkerStackSize,
kmp_i18n_hnt_Decrease_NUM_THREADS,
kmp_i18n_hnt_IncreaseMonitorStackSize,
kmp_i18n_hnt_DecreaseMonitorStackSize,
kmp_i18n_hnt_DecreaseNumberOfThreadsInUse,
kmp_i18n_hnt_DefaultScheduleKindUsed,
kmp_i18n_hnt_GetNewerLibrary,
kmp_i18n_hnt_CheckEnvVar,
kmp_i18n_hnt_OBSOLETE47,
kmp_i18n_hnt_OBSOLETE48,
kmp_i18n_hnt_BadExeFormat,
kmp_i18n_hnt_SystemLimitOnThreads,
kmp_i18n_hnt_SetNewBound,
kmp_i18n_hnt_ValidValuesRange,
kmp_i18n_hnt_last,
kmp_i18n_xxx_lastest
}; // enum kmp_i18n_id
typedef enum kmp_i18n_id kmp_i18n_id_t;
// end of file //

215
third_party/openmp/kmp_io.cpp vendored Normal file
View file

@ -0,0 +1,215 @@
/*
* kmp_io.cpp -- RTL IO
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef __ABSOFT_WIN
#include <sys/types.h>
#endif
#include "kmp.h" // KMP_GTID_DNE, __kmp_debug_buf, etc
#include "kmp_io.h"
#include "kmp_lock.h"
#include "kmp_os.h"
#include "kmp_str.h"
#if KMP_OS_WINDOWS
#if KMP_MSVC_COMPAT
#pragma warning(push)
#pragma warning(disable : 271 310)
#endif
#include <windows.h>
#if KMP_MSVC_COMPAT
#pragma warning(pop)
#endif
#endif
/* ------------------------------------------------------------------------ */
kmp_bootstrap_lock_t __kmp_stdio_lock = KMP_BOOTSTRAP_LOCK_INITIALIZER(
__kmp_stdio_lock); /* Control stdio functions */
kmp_bootstrap_lock_t __kmp_console_lock = KMP_BOOTSTRAP_LOCK_INITIALIZER(
__kmp_console_lock); /* Control console initialization */
#if KMP_OS_WINDOWS
static HANDLE __kmp_stdout = NULL;
static HANDLE __kmp_stderr = NULL;
static int __kmp_console_exists = FALSE;
static kmp_str_buf_t __kmp_console_buf;
void __kmp_close_console(void) {
/* wait until user presses return before closing window */
/* TODO only close if a window was opened */
if (__kmp_console_exists) {
__kmp_stdout = NULL;
__kmp_stderr = NULL;
__kmp_str_buf_free(&__kmp_console_buf);
__kmp_console_exists = FALSE;
}
}
/* For windows, call this before stdout, stderr, or stdin are used.
It opens a console window and starts processing */
static void __kmp_redirect_output(void) {
__kmp_acquire_bootstrap_lock(&__kmp_console_lock);
if (!__kmp_console_exists) {
HANDLE ho;
HANDLE he;
__kmp_str_buf_init(&__kmp_console_buf);
AllocConsole();
// We do not check the result of AllocConsole because
// 1. the call is harmless
// 2. it is not clear how to communicate failue
// 3. we will detect failure later when we get handle(s)
ho = GetStdHandle(STD_OUTPUT_HANDLE);
if (ho == INVALID_HANDLE_VALUE || ho == NULL) {
DWORD err = GetLastError();
// TODO: output error somehow (maybe message box)
(void)err;
__kmp_stdout = NULL;
} else {
__kmp_stdout = ho; // temporary code, need new global for ho
}
he = GetStdHandle(STD_ERROR_HANDLE);
if (he == INVALID_HANDLE_VALUE || he == NULL) {
DWORD err = GetLastError();
// TODO: output error somehow (maybe message box)
(void)err;
__kmp_stderr = NULL;
} else {
__kmp_stderr = he; // temporary code, need new global
}
__kmp_console_exists = TRUE;
}
__kmp_release_bootstrap_lock(&__kmp_console_lock);
}
#else
#define __kmp_stderr (stderr)
#define __kmp_stdout (stdout)
#endif /* KMP_OS_WINDOWS */
void __kmp_vprintf(enum kmp_io out_stream, char const *format, va_list ap) {
#if KMP_OS_WINDOWS
if (!__kmp_console_exists) {
__kmp_redirect_output();
}
if (!__kmp_stderr && out_stream == kmp_err) {
return;
}
if (!__kmp_stdout && out_stream == kmp_out) {
return;
}
#endif /* KMP_OS_WINDOWS */
auto stream = ((out_stream == kmp_out) ? __kmp_stdout : __kmp_stderr);
if (__kmp_debug_buf && __kmp_debug_buffer != NULL) {
int dc = __kmp_debug_count++ % __kmp_debug_buf_lines;
char *db = &__kmp_debug_buffer[dc * __kmp_debug_buf_chars];
int chars = 0;
#ifdef KMP_DEBUG_PIDS
chars = KMP_SNPRINTF(db, __kmp_debug_buf_chars,
"pid=%d: ", (kmp_int32)getpid());
#endif
chars += KMP_VSNPRINTF(db, __kmp_debug_buf_chars, format, ap);
if (chars + 1 > __kmp_debug_buf_chars) {
if (chars + 1 > __kmp_debug_buf_warn_chars) {
#if KMP_OS_WINDOWS
DWORD count;
__kmp_str_buf_print(&__kmp_console_buf,
"OMP warning: Debugging buffer "
"overflow; increase "
"KMP_DEBUG_BUF_CHARS to %d\n",
chars + 1);
WriteFile(stream, __kmp_console_buf.str, __kmp_console_buf.used, &count,
NULL);
__kmp_str_buf_clear(&__kmp_console_buf);
#else
fprintf(stream,
"OMP warning: Debugging buffer overflow; "
"increase KMP_DEBUG_BUF_CHARS to %d\n",
chars + 1);
fflush(stream);
#endif
__kmp_debug_buf_warn_chars = chars + 1;
}
/* terminate string if overflow occurred */
db[__kmp_debug_buf_chars - 2] = '\n';
db[__kmp_debug_buf_chars - 1] = '\0';
}
} else {
#if KMP_OS_WINDOWS
DWORD count;
#ifdef KMP_DEBUG_PIDS
__kmp_str_buf_print(&__kmp_console_buf, "pid=%d: ", (kmp_int32)getpid());
#endif
__kmp_str_buf_vprint(&__kmp_console_buf, format, ap);
WriteFile(stream, __kmp_console_buf.str, __kmp_console_buf.used, &count,
NULL);
__kmp_str_buf_clear(&__kmp_console_buf);
#else
#ifdef KMP_DEBUG_PIDS
fprintf(stream, "pid=%d: ", (kmp_int32)getpid());
#endif
vfprintf(stream, format, ap);
fflush(stream);
#endif
}
}
void __kmp_printf(char const *format, ...) {
va_list ap;
va_start(ap, format);
__kmp_acquire_bootstrap_lock(&__kmp_stdio_lock);
__kmp_vprintf(kmp_err, format, ap);
__kmp_release_bootstrap_lock(&__kmp_stdio_lock);
va_end(ap);
}
void __kmp_printf_no_lock(char const *format, ...) {
va_list ap;
va_start(ap, format);
__kmp_vprintf(kmp_err, format, ap);
va_end(ap);
}
void __kmp_fprintf(enum kmp_io stream, char const *format, ...) {
va_list ap;
va_start(ap, format);
__kmp_acquire_bootstrap_lock(&__kmp_stdio_lock);
__kmp_vprintf(stream, format, ap);
__kmp_release_bootstrap_lock(&__kmp_stdio_lock);
va_end(ap);
}

38
third_party/openmp/kmp_io.h vendored Normal file
View file

@ -0,0 +1,38 @@
/*
* kmp_io.h -- RTL IO header file.
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef KMP_IO_H
#define KMP_IO_H
#ifdef __cplusplus
extern "C" {
#endif
/* ------------------------------------------------------------------------ */
enum kmp_io { kmp_out = 0, kmp_err };
extern kmp_bootstrap_lock_t __kmp_stdio_lock; /* Control stdio functions */
extern kmp_bootstrap_lock_t
__kmp_console_lock; /* Control console initialization */
extern void __kmp_vprintf(enum kmp_io stream, char const *format, va_list ap);
extern void __kmp_printf(char const *format, ...);
extern void __kmp_printf_no_lock(char const *format, ...);
extern void __kmp_fprintf(enum kmp_io stream, char const *format, ...);
extern void __kmp_close_console(void);
#ifdef __cplusplus
}
#endif
#endif /* KMP_IO_H */

159
third_party/openmp/kmp_itt.cpp vendored Normal file
View file

@ -0,0 +1,159 @@
#include "kmp_config.h"
#if USE_ITT_BUILD
/*
* kmp_itt.cpp -- ITT Notify interface.
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "kmp_itt.h"
#if KMP_DEBUG
#include "kmp_itt.inc"
#endif
#if USE_ITT_NOTIFY
// #include "ittnotify_config.h"
__itt_global __kmp_ittapi_clean_global;
extern __itt_global __kmp_itt__ittapi_global;
kmp_itthash_t __kmp_itt_barrier_domains = {{0}, 0};
kmp_itthash_t __kmp_itt_region_domains = {{0}, 0};
__itt_domain *metadata_domain = NULL;
__itt_string_handle *string_handle_imbl = NULL;
__itt_string_handle *string_handle_loop = NULL;
__itt_string_handle *string_handle_sngl = NULL;
#include "kmp_i18n.h"
#include "kmp_str.h"
#include "kmp_version.h"
KMP_BUILD_ASSERT(sizeof(kmp_itt_mark_t) == sizeof(__itt_mark_type));
/* Previously used warnings:
KMP_WARNING( IttAllNotifDisabled );
KMP_WARNING( IttObjNotifDisabled );
KMP_WARNING( IttMarkNotifDisabled );
KMP_WARNING( IttUnloadLibFailed, libittnotify );
*/
kmp_int32 __kmp_itt_prepare_delay = 0;
kmp_bootstrap_lock_t __kmp_itt_debug_lock =
KMP_BOOTSTRAP_LOCK_INITIALIZER(__kmp_itt_debug_lock);
#endif // USE_ITT_NOTIFY
void __kmp_itt_reset() {
#if USE_ITT_NOTIFY
__kmp_itt__ittapi_global = __kmp_ittapi_clean_global;
#endif
}
void __kmp_itt_initialize() {
// ITTNotify library is loaded and initialized at first call to any ittnotify
// function, so we do not need to explicitly load it any more. Just report OMP
// RTL version to ITTNotify.
#if USE_ITT_NOTIFY
// Backup a clean global state
__kmp_ittapi_clean_global = __kmp_itt__ittapi_global;
// Report OpenMP RTL version.
kmp_str_buf_t buf;
__itt_mark_type version;
__kmp_str_buf_init(&buf);
__kmp_str_buf_print(&buf, "OMP RTL Version %d.%d.%d", __kmp_version_major,
__kmp_version_minor, __kmp_version_build);
if (__itt_api_version_ptr != NULL) {
__kmp_str_buf_print(&buf, ":%s", __itt_api_version());
}
version = __itt_mark_create(buf.str);
__itt_mark(version, NULL);
__kmp_str_buf_free(&buf);
#endif
} // __kmp_itt_initialize
void __kmp_itt_destroy() {
#if USE_ITT_NOTIFY
__kmp_itt_fini_ittlib();
#endif
} // __kmp_itt_destroy
extern "C" void __itt_error_handler(__itt_error_code err, va_list args) {
switch (err) {
case __itt_error_no_module: {
char const *library = va_arg(args, char const *);
#if KMP_OS_WINDOWS
int sys_err = va_arg(args, int);
kmp_msg_t err_code = KMP_SYSERRCODE(sys_err);
__kmp_msg(kmp_ms_warning, KMP_MSG(IttLoadLibFailed, library), err_code,
__kmp_msg_null);
if (__kmp_generate_warnings == kmp_warnings_off) {
__kmp_str_free(&err_code.str);
}
#else
char const *sys_err = va_arg(args, char const *);
kmp_msg_t err_code = KMP_SYSERRMESG(sys_err);
__kmp_msg(kmp_ms_warning, KMP_MSG(IttLoadLibFailed, library), err_code,
__kmp_msg_null);
if (__kmp_generate_warnings == kmp_warnings_off) {
__kmp_str_free(&err_code.str);
}
#endif
} break;
case __itt_error_no_symbol: {
char const *library = va_arg(args, char const *);
char const *symbol = va_arg(args, char const *);
KMP_WARNING(IttLookupFailed, symbol, library);
} break;
case __itt_error_unknown_group: {
char const *var = va_arg(args, char const *);
char const *group = va_arg(args, char const *);
KMP_WARNING(IttUnknownGroup, var, group);
} break;
case __itt_error_env_too_long: {
char const *var = va_arg(args, char const *);
size_t act_len = va_arg(args, size_t);
size_t max_len = va_arg(args, size_t);
KMP_WARNING(IttEnvVarTooLong, var, (unsigned long)act_len,
(unsigned long)max_len);
} break;
case __itt_error_cant_read_env: {
char const *var = va_arg(args, char const *);
int sys_err = va_arg(args, int);
kmp_msg_t err_code = KMP_ERR(sys_err);
__kmp_msg(kmp_ms_warning, KMP_MSG(CantGetEnvVar, var), err_code,
__kmp_msg_null);
if (__kmp_generate_warnings == kmp_warnings_off) {
__kmp_str_free(&err_code.str);
}
} break;
case __itt_error_system: {
char const *func = va_arg(args, char const *);
int sys_err = va_arg(args, int);
kmp_msg_t err_code = KMP_SYSERRCODE(sys_err);
__kmp_msg(kmp_ms_warning, KMP_MSG(IttFunctionError, func), err_code,
__kmp_msg_null);
if (__kmp_generate_warnings == kmp_warnings_off) {
__kmp_str_free(&err_code.str);
}
} break;
default: {
KMP_WARNING(IttUnknownError, err);
}
}
} // __itt_error_handler
#endif /* USE_ITT_BUILD */

348
third_party/openmp/kmp_itt.h vendored Normal file
View file

@ -0,0 +1,348 @@
#if USE_ITT_BUILD
/*
* kmp_itt.h -- ITT Notify interface.
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef KMP_ITT_H
#define KMP_ITT_H
#include "kmp_lock.h"
#define INTEL_ITTNOTIFY_API_PRIVATE
// #include "ittnotify.h"
// #include "legacy/ittnotify.h"
#if KMP_DEBUG
#define __kmp_inline // Turn off inlining in debug mode.
#else
#define __kmp_inline static inline
#endif
#if USE_ITT_NOTIFY
extern kmp_int32 __kmp_itt_prepare_delay;
#ifdef __cplusplus
extern "C" void __kmp_itt_fini_ittlib(void);
#else
extern void __kmp_itt_fini_ittlib(void);
#endif
#endif
// Simplify the handling of an argument that is only required when USE_ITT_BUILD
// is enabled.
#define USE_ITT_BUILD_ARG(x) , x
void __kmp_itt_initialize();
void __kmp_itt_destroy();
void __kmp_itt_reset();
// -----------------------------------------------------------------------------
// New stuff for reporting high-level constructs.
// Note the naming convention:
// __kmp_itt_xxxing() function should be called before action, while
// __kmp_itt_xxxed() function should be called after action.
// --- Parallel region reporting ---
__kmp_inline void
__kmp_itt_region_forking(int gtid, int team_size,
int barriers); // Primary only, before forking threads.
__kmp_inline void
__kmp_itt_region_joined(int gtid); // Primary only, after joining threads.
// (*) Note: A thread may execute tasks after this point, though.
// --- Frame reporting ---
// region=0: no regions, region=1: parallel, region=2: serialized parallel
__kmp_inline void __kmp_itt_frame_submit(int gtid, __itt_timestamp begin,
__itt_timestamp end, int imbalance,
ident_t *loc, int team_size,
int region = 0);
// --- Metadata reporting ---
// begin/end - begin/end timestamps of a barrier frame, imbalance - aggregated
// wait time value, reduction -if this is a reduction barrier
__kmp_inline void __kmp_itt_metadata_imbalance(int gtid, kmp_uint64 begin,
kmp_uint64 end,
kmp_uint64 imbalance,
kmp_uint64 reduction);
// sched_type: 0 - static, 1 - dynamic, 2 - guided, 3 - custom (all others);
// iterations - loop trip count, chunk - chunk size
__kmp_inline void __kmp_itt_metadata_loop(ident_t *loc, kmp_uint64 sched_type,
kmp_uint64 iterations,
kmp_uint64 chunk);
__kmp_inline void __kmp_itt_metadata_single(ident_t *loc);
// --- Barrier reporting ---
__kmp_inline void *__kmp_itt_barrier_object(int gtid, int bt, int set_name = 0,
int delta = 0);
__kmp_inline void __kmp_itt_barrier_starting(int gtid, void *object);
__kmp_inline void __kmp_itt_barrier_middle(int gtid, void *object);
__kmp_inline void __kmp_itt_barrier_finished(int gtid, void *object);
// --- Taskwait reporting ---
__kmp_inline void *__kmp_itt_taskwait_object(int gtid);
__kmp_inline void __kmp_itt_taskwait_starting(int gtid, void *object);
__kmp_inline void __kmp_itt_taskwait_finished(int gtid, void *object);
#define KMP_ITT_TASKWAIT_STARTING(obj) \
if (UNLIKELY(__itt_sync_create_ptr)) { \
obj = __kmp_itt_taskwait_object(gtid); \
if (obj != NULL) { \
__kmp_itt_taskwait_starting(gtid, obj); \
} \
}
#define KMP_ITT_TASKWAIT_FINISHED(obj) \
if (UNLIKELY(obj != NULL)) \
__kmp_itt_taskwait_finished(gtid, obj);
// --- Task reporting ---
__kmp_inline void __kmp_itt_task_starting(void *object);
__kmp_inline void __kmp_itt_task_finished(void *object);
// --- Lock reporting ---
#if KMP_USE_DYNAMIC_LOCK
__kmp_inline void __kmp_itt_lock_creating(kmp_user_lock_p lock,
const ident_t *);
#else
__kmp_inline void __kmp_itt_lock_creating(kmp_user_lock_p lock);
#endif
__kmp_inline void __kmp_itt_lock_acquiring(kmp_user_lock_p lock);
__kmp_inline void __kmp_itt_lock_acquired(kmp_user_lock_p lock);
__kmp_inline void __kmp_itt_lock_releasing(kmp_user_lock_p lock);
__kmp_inline void __kmp_itt_lock_cancelled(kmp_user_lock_p lock);
__kmp_inline void __kmp_itt_lock_destroyed(kmp_user_lock_p lock);
// --- Critical reporting ---
#if KMP_USE_DYNAMIC_LOCK
__kmp_inline void __kmp_itt_critical_creating(kmp_user_lock_p lock,
const ident_t *);
#else
__kmp_inline void __kmp_itt_critical_creating(kmp_user_lock_p lock);
#endif
__kmp_inline void __kmp_itt_critical_acquiring(kmp_user_lock_p lock);
__kmp_inline void __kmp_itt_critical_acquired(kmp_user_lock_p lock);
__kmp_inline void __kmp_itt_critical_releasing(kmp_user_lock_p lock);
__kmp_inline void __kmp_itt_critical_destroyed(kmp_user_lock_p lock);
// --- Single reporting ---
__kmp_inline void __kmp_itt_single_start(int gtid);
__kmp_inline void __kmp_itt_single_end(int gtid);
// --- Ordered reporting ---
__kmp_inline void __kmp_itt_ordered_init(int gtid);
__kmp_inline void __kmp_itt_ordered_prep(int gtid);
__kmp_inline void __kmp_itt_ordered_start(int gtid);
__kmp_inline void __kmp_itt_ordered_end(int gtid);
// --- Threads reporting ---
__kmp_inline void __kmp_itt_thread_ignore();
__kmp_inline void __kmp_itt_thread_name(int gtid);
// --- System objects ---
__kmp_inline void __kmp_itt_system_object_created(void *object,
char const *name);
// --- Stack stitching ---
__kmp_inline __itt_caller __kmp_itt_stack_caller_create(void);
__kmp_inline void __kmp_itt_stack_caller_destroy(__itt_caller);
__kmp_inline void __kmp_itt_stack_callee_enter(__itt_caller);
__kmp_inline void __kmp_itt_stack_callee_leave(__itt_caller);
// -----------------------------------------------------------------------------
// Old stuff for reporting low-level internal synchronization.
#if USE_ITT_NOTIFY
/* Support for SSC marks, which are used by SDE
http://software.intel.com/en-us/articles/intel-software-development-emulator
to mark points in instruction traces that represent spin-loops and are
therefore uninteresting when collecting traces for architecture simulation.
*/
#ifndef INCLUDE_SSC_MARKS
#define INCLUDE_SSC_MARKS (KMP_OS_LINUX && KMP_ARCH_X86_64)
#endif
/* Linux 64 only for now */
#if (INCLUDE_SSC_MARKS && KMP_OS_LINUX && KMP_ARCH_X86_64)
// Portable (at least for gcc and icc) code to insert the necessary instructions
// to set %ebx and execute the unlikely no-op.
#if defined(__INTEL_COMPILER)
#define INSERT_SSC_MARK(tag) __SSC_MARK(tag)
#else
#define INSERT_SSC_MARK(tag) \
__asm__ __volatile__("movl %0, %%ebx; .byte 0x64, 0x67, 0x90 " ::"i"(tag) \
: "%ebx")
#endif
#else
#define INSERT_SSC_MARK(tag) ((void)0)
#endif
/* Markers for the start and end of regions that represent polling and are
therefore uninteresting to architectural simulations 0x4376 and 0x4377 are
arbitrary numbers that should be unique in the space of SSC tags, but there
is no central issuing authority rather randomness is expected to work. */
#define SSC_MARK_SPIN_START() INSERT_SSC_MARK(0x4376)
#define SSC_MARK_SPIN_END() INSERT_SSC_MARK(0x4377)
// Markers for architecture simulation.
// FORKING : Before the primary thread forks.
// JOINING : At the start of the join.
// INVOKING : Before the threads invoke microtasks.
// DISPATCH_INIT: At the start of dynamically scheduled loop.
// DISPATCH_NEXT: After claming next iteration of dynamically scheduled loop.
#define SSC_MARK_FORKING() INSERT_SSC_MARK(0xd693)
#define SSC_MARK_JOINING() INSERT_SSC_MARK(0xd694)
#define SSC_MARK_INVOKING() INSERT_SSC_MARK(0xd695)
#define SSC_MARK_DISPATCH_INIT() INSERT_SSC_MARK(0xd696)
#define SSC_MARK_DISPATCH_NEXT() INSERT_SSC_MARK(0xd697)
// The object is an address that associates a specific set of the prepare,
// acquire, release, and cancel operations.
/* Sync prepare indicates a thread is going to start waiting for another thread
to send a release event. This operation should be done just before the
thread begins checking for the existence of the release event */
/* Sync cancel indicates a thread is cancelling a wait on another thread and
continuing execution without waiting for the other thread to release it */
/* Sync acquired indicates a thread has received a release event from another
thread and has stopped waiting. This operation must occur only after the
release event is received. */
/* Sync release indicates a thread is going to send a release event to another
thread so it will stop waiting and continue execution. This operation must
just happen before the release event. */
#define KMP_FSYNC_PREPARE(obj) __itt_fsync_prepare((void *)(obj))
#define KMP_FSYNC_CANCEL(obj) __itt_fsync_cancel((void *)(obj))
#define KMP_FSYNC_ACQUIRED(obj) __itt_fsync_acquired((void *)(obj))
#define KMP_FSYNC_RELEASING(obj) __itt_fsync_releasing((void *)(obj))
/* In case of waiting in a spin loop, ITT wants KMP_FSYNC_PREPARE() to be called
with a delay (and not called at all if waiting time is small). So, in spin
loops, do not use KMP_FSYNC_PREPARE(), but use KMP_FSYNC_SPIN_INIT() (before
spin loop), KMP_FSYNC_SPIN_PREPARE() (whithin the spin loop), and
KMP_FSYNC_SPIN_ACQUIRED(). See KMP_WAIT() for example. */
#undef KMP_FSYNC_SPIN_INIT
#define KMP_FSYNC_SPIN_INIT(obj, spin) \
int sync_iters = 0; \
if (__itt_fsync_prepare_ptr) { \
if (obj == NULL) { \
obj = spin; \
} /* if */ \
} /* if */ \
SSC_MARK_SPIN_START()
#undef KMP_FSYNC_SPIN_PREPARE
#define KMP_FSYNC_SPIN_PREPARE(obj) \
do { \
if (__itt_fsync_prepare_ptr && sync_iters < __kmp_itt_prepare_delay) { \
++sync_iters; \
if (sync_iters >= __kmp_itt_prepare_delay) { \
KMP_FSYNC_PREPARE((void *)obj); \
} /* if */ \
} /* if */ \
} while (0)
#undef KMP_FSYNC_SPIN_ACQUIRED
#define KMP_FSYNC_SPIN_ACQUIRED(obj) \
do { \
SSC_MARK_SPIN_END(); \
if (sync_iters >= __kmp_itt_prepare_delay) { \
KMP_FSYNC_ACQUIRED((void *)obj); \
} /* if */ \
} while (0)
/* ITT will not report objects created within KMP_ITT_IGNORE(), e. g.:
KMP_ITT_IGNORE(
ptr = malloc( size );
);
*/
#define KMP_ITT_IGNORE(statement) \
do { \
__itt_state_t __itt_state_; \
if (__itt_state_get_ptr) { \
__itt_state_ = __itt_state_get(); \
__itt_obj_mode_set(__itt_obj_prop_ignore, __itt_obj_state_set); \
} /* if */ \
{ statement } \
if (__itt_state_get_ptr) { \
__itt_state_set(__itt_state_); \
} /* if */ \
} while (0)
// Maximum number of frame domains to use (maps to
// different OpenMP regions in the user source code).
const int KMP_MAX_FRAME_DOMAINS = 997;
typedef struct kmp_itthash_entry {
ident_t *loc;
int team_size;
__itt_domain *d;
struct kmp_itthash_entry *next_in_bucket;
} kmp_itthash_entry_t;
typedef struct kmp_itthash {
kmp_itthash_entry_t *buckets[KMP_MAX_FRAME_DOMAINS];
int count; // just a heuristic to limit number of entries
} kmp_itthash_t;
extern kmp_itthash_t __kmp_itt_region_domains;
extern kmp_itthash_t __kmp_itt_barrier_domains;
extern __itt_domain *metadata_domain;
extern __itt_string_handle *string_handle_imbl;
extern __itt_string_handle *string_handle_loop;
extern __itt_string_handle *string_handle_sngl;
#else
// Null definitions of the synchronization tracing functions.
#define KMP_FSYNC_PREPARE(obj) ((void)0)
#define KMP_FSYNC_CANCEL(obj) ((void)0)
#define KMP_FSYNC_ACQUIRED(obj) ((void)0)
#define KMP_FSYNC_RELEASING(obj) ((void)0)
#define KMP_FSYNC_SPIN_INIT(obj, spin) ((void)0)
#define KMP_FSYNC_SPIN_PREPARE(obj) ((void)0)
#define KMP_FSYNC_SPIN_ACQUIRED(obj) ((void)0)
#define KMP_ITT_IGNORE(stmt) \
do { \
stmt \
} while (0)
#endif // USE_ITT_NOTIFY
#if !KMP_DEBUG
// In release mode include definitions of inline functions.
#include "kmp_itt.inc"
#endif
#endif // KMP_ITT_H
#else /* USE_ITT_BUILD */
// Null definitions of the synchronization tracing functions.
// If USE_ITT_BULID is not enabled, USE_ITT_NOTIFY cannot be either.
// By defining these we avoid unpleasant ifdef tests in many places.
#define KMP_FSYNC_PREPARE(obj) ((void)0)
#define KMP_FSYNC_CANCEL(obj) ((void)0)
#define KMP_FSYNC_ACQUIRED(obj) ((void)0)
#define KMP_FSYNC_RELEASING(obj) ((void)0)
#define KMP_FSYNC_SPIN_INIT(obj, spin) ((void)0)
#define KMP_FSYNC_SPIN_PREPARE(obj) ((void)0)
#define KMP_FSYNC_SPIN_ACQUIRED(obj) ((void)0)
#define KMP_ITT_IGNORE(stmt) \
do { \
stmt \
} while (0)
#define USE_ITT_BUILD_ARG(x)
#endif /* USE_ITT_BUILD */

978
third_party/openmp/kmp_itt.inc vendored Normal file
View file

@ -0,0 +1,978 @@
#if USE_ITT_BUILD
/*
* kmp_itt.inl -- Inline functions of ITT Notify.
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// Inline function definitions. This file should be included into kmp_itt.h file
// for production build (to let compiler inline functions) or into kmp_itt.c
// file for debug build (to reduce the number of files to recompile and save
// build time).
#include "kmp.h"
#include "kmp_str.h"
#if KMP_ITT_DEBUG
extern kmp_bootstrap_lock_t __kmp_itt_debug_lock;
#define KMP_ITT_DEBUG_LOCK() \
{ __kmp_acquire_bootstrap_lock(&__kmp_itt_debug_lock); }
#define KMP_ITT_DEBUG_PRINT(...) \
{ \
fprintf(stderr, "#%02d: ", __kmp_get_gtid()); \
fprintf(stderr, __VA_ARGS__); \
fflush(stderr); \
__kmp_release_bootstrap_lock(&__kmp_itt_debug_lock); \
}
#else
#define KMP_ITT_DEBUG_LOCK()
#define KMP_ITT_DEBUG_PRINT(...)
#endif // KMP_ITT_DEBUG
// Ensure that the functions are static if they're supposed to be being inlined.
// Otherwise they cannot be used in more than one file, since there will be
// multiple definitions.
#if KMP_DEBUG
#define LINKAGE
#else
#define LINKAGE static inline
#endif
// ZCA interface used by Intel(R) Inspector. Intel(R) Parallel Amplifier uses
// this API to support user-defined synchronization primitives, but does not use
// ZCA; it would be safe to turn this off until wider support becomes available.
#if USE_ITT_ZCA
#ifdef __INTEL_COMPILER
#if __INTEL_COMPILER >= 1200
#undef __itt_sync_acquired
#undef __itt_sync_releasing
#define __itt_sync_acquired(addr) \
__notify_zc_intrinsic((char *)"sync_acquired", addr)
#define __itt_sync_releasing(addr) \
__notify_intrinsic((char *)"sync_releasing", addr)
#endif
#endif
#endif
static kmp_bootstrap_lock_t metadata_lock =
KMP_BOOTSTRAP_LOCK_INITIALIZER(metadata_lock);
#if USE_ITT_NOTIFY
LINKAGE size_t __kmp_itthash_hash(kmp_intptr_t addr, size_t hsize) {
return ((addr >> 6) ^ (addr >> 2)) % hsize;
}
LINKAGE kmp_itthash_entry *__kmp_itthash_find(kmp_info_t *thread,
kmp_itthash_t *h, ident_t *loc,
int team_size) {
kmp_itthash_entry_t *entry;
size_t bucket = __kmp_itthash_hash((kmp_intptr_t)loc, KMP_MAX_FRAME_DOMAINS);
for (entry = h->buckets[bucket]; entry; entry = entry->next_in_bucket)
if (entry->loc == loc && entry->team_size == team_size)
break;
if (entry == NULL) {
// two foreign threads could report frames concurrently
int cnt = KMP_TEST_THEN_INC32(&h->count);
if (cnt >= KMP_MAX_FRAME_DOMAINS) {
KMP_TEST_THEN_DEC32(&h->count); // revert the count
return entry; // too many entries
}
// create new entry
entry = (kmp_itthash_entry_t *)__kmp_thread_malloc(
thread, sizeof(kmp_itthash_entry_t));
entry->loc = loc;
entry->team_size = team_size;
entry->d = NULL;
entry->next_in_bucket = h->buckets[bucket];
while (!KMP_COMPARE_AND_STORE_PTR(&h->buckets[bucket],
entry->next_in_bucket, entry)) {
KMP_CPU_PAUSE();
entry->next_in_bucket = h->buckets[bucket];
}
}
#if KMP_DEBUG
else {
// check the contents of the location info is unique
KMP_DEBUG_ASSERT(loc->psource == entry->loc->psource);
}
#endif
return entry;
}
#endif
/* Parallel region reporting.
* __kmp_itt_region_forking should be called by primary thread of a team.
Exact moment of call does not matter, but it should be completed before any
thread of this team calls __kmp_itt_region_starting.
* __kmp_itt_region_starting should be called by each thread of a team just
before entering parallel region body.
* __kmp_itt_region_finished should be called by each thread of a team right
after returning from parallel region body.
* __kmp_itt_region_joined should be called by primary thread of a team, after
all threads called __kmp_itt_region_finished.
Note: Thread waiting at join barrier (after __kmp_itt_region_finished) can
execute some more user code -- such a thread can execute tasks.
Note: The overhead of logging region_starting and region_finished in each
thread is too large, so these calls are not used. */
LINKAGE void __kmp_itt_region_forking(int gtid, int team_size, int barriers) {
#if USE_ITT_NOTIFY
kmp_team_t *team = __kmp_team_from_gtid(gtid);
if (team->t.t_active_level > 1) {
// The frame notifications are only supported for the outermost teams.
return;
}
kmp_info_t *th = __kmp_thread_from_gtid(gtid);
ident_t *loc = th->th.th_ident;
if (!loc) {
// no sense to report a region without location info
return;
}
kmp_itthash_entry *e;
e = __kmp_itthash_find(th, &__kmp_itt_region_domains, loc, team_size);
if (e == NULL)
return; // too many entries in the hash
if (e->d == NULL) {
// Transform compiler-generated region location into the format
// that the tools more or less standardized on:
// "<func>$omp$parallel@[file:]<line>[:<col>]"
char *buff = NULL;
kmp_str_loc_t str_loc =
__kmp_str_loc_init(loc->psource, /* init_fname */ false);
buff = __kmp_str_format("%s$omp$parallel:%d@%s:%d:%d", str_loc.func,
team_size, str_loc.file, str_loc.line, str_loc.col);
__itt_suppress_push(__itt_suppress_memory_errors);
e->d = __itt_domain_create(buff);
KMP_ASSERT(e->d != NULL);
__itt_suppress_pop();
__kmp_str_free(&buff);
if (barriers) {
kmp_itthash_entry *e;
e = __kmp_itthash_find(th, &__kmp_itt_barrier_domains, loc, 0);
if (e != NULL) {
KMP_DEBUG_ASSERT(e->d == NULL);
char *buff = NULL;
buff = __kmp_str_format("%s$omp$barrier@%s:%d", str_loc.func,
str_loc.file, str_loc.line);
__itt_suppress_push(__itt_suppress_memory_errors);
e->d = __itt_domain_create(buff);
KMP_ASSERT(e->d != NULL);
__itt_suppress_pop();
__kmp_str_free(&buff);
}
}
__kmp_str_loc_free(&str_loc);
}
__itt_frame_begin_v3(e->d, NULL);
KMP_ITT_DEBUG_LOCK();
KMP_ITT_DEBUG_PRINT("[frm beg] gtid=%d, domain=%p, loc:%p\n", gtid, e->d,
loc);
#endif
} // __kmp_itt_region_forking
// -----------------------------------------------------------------------------
LINKAGE void __kmp_itt_frame_submit(int gtid, __itt_timestamp begin,
__itt_timestamp end, int imbalance,
ident_t *loc, int team_size, int region) {
#if USE_ITT_NOTIFY
if (!loc) {
// no sense to report a region without location info
return;
}
kmp_info_t *th = __kmp_thread_from_gtid(gtid);
if (region) {
kmp_team_t *team = __kmp_team_from_gtid(gtid);
int serialized = (region == 2 ? 1 : 0);
if (team->t.t_active_level + serialized > 1) {
// The frame notifications are only supported for the outermost teams.
return;
}
// Check region domain has not been created before.
kmp_itthash_entry *e;
e = __kmp_itthash_find(th, &__kmp_itt_region_domains, loc, team_size);
if (e == NULL)
return; // too many entries in the hash
if (e->d == NULL) { // new entry, need to calculate domain
// Transform compiler-generated region location into the format
// that the tools more or less standardized on:
// "<func>$omp$parallel:team_size@[file:]<line>[:<col>]"
char *buff = NULL;
kmp_str_loc_t str_loc =
__kmp_str_loc_init(loc->psource, /* init_fname */ false);
buff =
__kmp_str_format("%s$omp$parallel:%d@%s:%d:%d", str_loc.func,
team_size, str_loc.file, str_loc.line, str_loc.col);
__itt_suppress_push(__itt_suppress_memory_errors);
e->d = __itt_domain_create(buff);
KMP_ASSERT(e->d != NULL);
__itt_suppress_pop();
__kmp_str_free(&buff);
__kmp_str_loc_free(&str_loc);
}
__itt_frame_submit_v3(e->d, NULL, begin, end);
KMP_ITT_DEBUG_LOCK();
KMP_ITT_DEBUG_PRINT(
"[reg sub] gtid=%d, domain=%p, region:%d, loc:%p, beg:%llu, end:%llu\n",
gtid, e->d, region, loc, begin, end);
return;
} else { // called for barrier reporting
kmp_itthash_entry *e;
e = __kmp_itthash_find(th, &__kmp_itt_barrier_domains, loc, 0);
if (e == NULL)
return; // too many entries in the hash
if (e->d == NULL) { // new entry, need to calculate domain
// Transform compiler-generated region location into the format
// that the tools more or less standardized on:
// "<func>$omp$frame@[file:]<line>[:<col>]"
kmp_str_loc_t str_loc =
__kmp_str_loc_init(loc->psource, /* init_fname */ false);
char *buff = NULL;
if (imbalance) {
buff =
__kmp_str_format("%s$omp$barrier-imbalance:%d@%s:%d", str_loc.func,
team_size, str_loc.file, str_loc.line);
} else {
buff = __kmp_str_format("%s$omp$barrier@%s:%d", str_loc.func,
str_loc.file, str_loc.line);
}
__itt_suppress_push(__itt_suppress_memory_errors);
e->d = __itt_domain_create(buff);
KMP_ASSERT(e->d != NULL);
__itt_suppress_pop();
__kmp_str_free(&buff);
__kmp_str_loc_free(&str_loc);
}
__itt_frame_submit_v3(e->d, NULL, begin, end);
KMP_ITT_DEBUG_LOCK();
KMP_ITT_DEBUG_PRINT(
"[frm sub] gtid=%d, domain=%p, loc:%p, beg:%llu, end:%llu\n", gtid,
e->d, loc, begin, end);
}
#endif
} // __kmp_itt_frame_submit
// -----------------------------------------------------------------------------
LINKAGE void __kmp_itt_metadata_imbalance(int gtid, kmp_uint64 begin,
kmp_uint64 end, kmp_uint64 imbalance,
kmp_uint64 reduction) {
#if USE_ITT_NOTIFY
if (metadata_domain == NULL) {
__kmp_acquire_bootstrap_lock(&metadata_lock);
if (metadata_domain == NULL) {
__itt_suppress_push(__itt_suppress_memory_errors);
metadata_domain = __itt_domain_create("OMP Metadata");
string_handle_imbl = __itt_string_handle_create("omp_metadata_imbalance");
string_handle_loop = __itt_string_handle_create("omp_metadata_loop");
string_handle_sngl = __itt_string_handle_create("omp_metadata_single");
__itt_suppress_pop();
}
__kmp_release_bootstrap_lock(&metadata_lock);
}
kmp_uint64 imbalance_data[4];
imbalance_data[0] = begin;
imbalance_data[1] = end;
imbalance_data[2] = imbalance;
imbalance_data[3] = reduction;
__itt_metadata_add(metadata_domain, __itt_null, string_handle_imbl,
__itt_metadata_u64, 4, imbalance_data);
#endif
} // __kmp_itt_metadata_imbalance
// -----------------------------------------------------------------------------
LINKAGE void __kmp_itt_metadata_loop(ident_t *loc, kmp_uint64 sched_type,
kmp_uint64 iterations, kmp_uint64 chunk) {
#if USE_ITT_NOTIFY
if (metadata_domain == NULL) {
__kmp_acquire_bootstrap_lock(&metadata_lock);
if (metadata_domain == NULL) {
__itt_suppress_push(__itt_suppress_memory_errors);
metadata_domain = __itt_domain_create("OMP Metadata");
string_handle_imbl = __itt_string_handle_create("omp_metadata_imbalance");
string_handle_loop = __itt_string_handle_create("omp_metadata_loop");
string_handle_sngl = __itt_string_handle_create("omp_metadata_single");
__itt_suppress_pop();
}
__kmp_release_bootstrap_lock(&metadata_lock);
}
// Parse line and column from psource string: ";file;func;line;col;;"
KMP_DEBUG_ASSERT(loc->psource);
kmp_uint64 loop_data[5];
int line, col;
__kmp_str_loc_numbers(loc->psource, &line, &col);
loop_data[0] = line;
loop_data[1] = col;
loop_data[2] = sched_type;
loop_data[3] = iterations;
loop_data[4] = chunk;
__itt_metadata_add(metadata_domain, __itt_null, string_handle_loop,
__itt_metadata_u64, 5, loop_data);
#endif
} // __kmp_itt_metadata_loop
// -----------------------------------------------------------------------------
LINKAGE void __kmp_itt_metadata_single(ident_t *loc) {
#if USE_ITT_NOTIFY
if (metadata_domain == NULL) {
__kmp_acquire_bootstrap_lock(&metadata_lock);
if (metadata_domain == NULL) {
__itt_suppress_push(__itt_suppress_memory_errors);
metadata_domain = __itt_domain_create("OMP Metadata");
string_handle_imbl = __itt_string_handle_create("omp_metadata_imbalance");
string_handle_loop = __itt_string_handle_create("omp_metadata_loop");
string_handle_sngl = __itt_string_handle_create("omp_metadata_single");
__itt_suppress_pop();
}
__kmp_release_bootstrap_lock(&metadata_lock);
}
int line, col;
__kmp_str_loc_numbers(loc->psource, &line, &col);
kmp_uint64 single_data[2];
single_data[0] = line;
single_data[1] = col;
__itt_metadata_add(metadata_domain, __itt_null, string_handle_sngl,
__itt_metadata_u64, 2, single_data);
#endif
} // __kmp_itt_metadata_single
// -----------------------------------------------------------------------------
LINKAGE void __kmp_itt_region_starting(int gtid) {
#if USE_ITT_NOTIFY
#endif
} // __kmp_itt_region_starting
// -----------------------------------------------------------------------------
LINKAGE void __kmp_itt_region_finished(int gtid) {
#if USE_ITT_NOTIFY
#endif
} // __kmp_itt_region_finished
// ----------------------------------------------------------------------------
LINKAGE void __kmp_itt_region_joined(int gtid) {
#if USE_ITT_NOTIFY
kmp_team_t *team = __kmp_team_from_gtid(gtid);
if (team->t.t_active_level > 1) {
// The frame notifications are only supported for the outermost teams.
return;
}
kmp_info_t *th = __kmp_thread_from_gtid(gtid);
ident_t *loc = th->th.th_ident;
if (loc) {
kmp_itthash_entry *e = __kmp_itthash_find(th, &__kmp_itt_region_domains,
loc, th->th.th_team_nproc);
if (e == NULL)
return; // too many entries in the hash
KMP_DEBUG_ASSERT(e->d);
KMP_ITT_DEBUG_LOCK();
__itt_frame_end_v3(e->d, NULL);
KMP_ITT_DEBUG_PRINT("[frm end] gtid=%d, domain=%p, loc:%p\n", gtid, e->d,
loc);
}
#endif
} // __kmp_itt_region_joined
/* Barriers reporting.
A barrier consists of two phases:
1. Gather -- primary thread waits for all worker threads to arrive; each
worker thread registers arrival and goes further.
2. Release -- each worker thread waits until primary thread lets it go;
primary thread lets worker threads go.
Function should be called by each thread:
* __kmp_itt_barrier_starting() -- before arriving to the gather phase.
* __kmp_itt_barrier_middle() -- between gather and release phases.
* __kmp_itt_barrier_finished() -- after release phase.
Note: Call __kmp_itt_barrier_object() before call to
__kmp_itt_barrier_starting() and save result in local variable.
__kmp_itt_barrier_object(), being called too late (e. g. after gather phase)
would return itt sync object for the next barrier!
ITT need an address (void *) to be specified as a sync object. OpenMP RTL
does not have barrier object or barrier data structure. Barrier is just a
counter in team and thread structures. We could use an address of team
structure as a barrier sync object, but ITT wants different objects for
different barriers (even whithin the same team). So let us use team address
as barrier sync object for the first barrier, then increase it by one for the
next barrier, and so on (but wrap it not to use addresses outside of team
structure). */
void *__kmp_itt_barrier_object(int gtid, int bt, int set_name,
int delta // 0 (current barrier) is default
// value; specify -1 to get previous
// barrier.
) {
void *object = NULL;
#if USE_ITT_NOTIFY
kmp_info_t *thr = __kmp_thread_from_gtid(gtid);
kmp_team_t *team = thr->th.th_team;
// NOTE: If the function is called from __kmp_fork_barrier, team pointer can
// be NULL. This "if" helps to avoid crash. However, this is not complete
// solution, and reporting fork/join barriers to ITT should be revisited.
if (team != NULL) {
// Primary thread increases b_arrived by KMP_BARRIER_STATE_BUMP each time.
// Divide b_arrived by KMP_BARRIER_STATE_BUMP to get plain barrier counter.
kmp_uint64 counter =
team->t.t_bar[bt].b_arrived / KMP_BARRIER_STATE_BUMP + delta;
// Now form the barrier id. Encode barrier type (bt) in barrier id too, so
// barriers of different types do not have the same ids.
KMP_BUILD_ASSERT(sizeof(kmp_team_t) >= bs_last_barrier);
// This condition is a must (we would have zero divide otherwise).
KMP_BUILD_ASSERT(sizeof(kmp_team_t) >= 2 * bs_last_barrier);
// More strong condition: make sure we have room at least for two
// different ids (for each barrier type).
object = reinterpret_cast<void *>(
(kmp_uintptr_t)(team) +
(kmp_uintptr_t)counter % (sizeof(kmp_team_t) / bs_last_barrier) *
bs_last_barrier +
bt);
KMP_ITT_DEBUG_LOCK();
KMP_ITT_DEBUG_PRINT("[bar obj] type=%d, counter=%lld, object=%p\n", bt,
counter, object);
if (set_name) {
ident_t const *loc = NULL;
char const *src = NULL;
char const *type = "OMP Barrier";
switch (bt) {
case bs_plain_barrier: {
// For plain barrier compiler calls __kmpc_barrier() function, which
// saves location in thr->th.th_ident.
loc = thr->th.th_ident;
// Get the barrier type from flags provided by compiler.
kmp_int32 expl = 0;
kmp_uint32 impl = 0;
if (loc != NULL) {
src = loc->psource;
expl = (loc->flags & KMP_IDENT_BARRIER_EXPL) != 0;
impl = (loc->flags & KMP_IDENT_BARRIER_IMPL) != 0;
}
if (impl) {
switch (loc->flags & KMP_IDENT_BARRIER_IMPL_MASK) {
case KMP_IDENT_BARRIER_IMPL_FOR: {
type = "OMP For Barrier";
} break;
case KMP_IDENT_BARRIER_IMPL_SECTIONS: {
type = "OMP Sections Barrier";
} break;
case KMP_IDENT_BARRIER_IMPL_SINGLE: {
type = "OMP Single Barrier";
} break;
case KMP_IDENT_BARRIER_IMPL_WORKSHARE: {
type = "OMP Workshare Barrier";
} break;
default: {
type = "OMP Implicit Barrier";
KMP_DEBUG_ASSERT(0);
}
}
} else if (expl) {
type = "OMP Explicit Barrier";
}
} break;
case bs_forkjoin_barrier: {
// In case of fork/join barrier we can read thr->th.th_ident, because it
// contains location of last passed construct (while join barrier is not
// such one). Use th_ident of primary thread instead --
// __kmp_join_call() called by the primary thread saves location.
//
// AC: cannot read from primary thread because __kmp_join_call may not
// be called yet, so we read the location from team. This is the
// same location. Team is valid on entry to join barrier where this
// happens.
loc = team->t.t_ident;
if (loc != NULL) {
src = loc->psource;
}
type = "OMP Join Barrier";
} break;
}
KMP_ITT_DEBUG_LOCK();
__itt_sync_create(object, type, src, __itt_attr_barrier);
KMP_ITT_DEBUG_PRINT(
"[bar sta] scre( %p, \"%s\", \"%s\", __itt_attr_barrier )\n", object,
type, src);
}
}
#endif
return object;
} // __kmp_itt_barrier_object
// -----------------------------------------------------------------------------
void __kmp_itt_barrier_starting(int gtid, void *object) {
#if USE_ITT_NOTIFY
if (!KMP_MASTER_GTID(gtid)) {
KMP_ITT_DEBUG_LOCK();
__itt_sync_releasing(object);
KMP_ITT_DEBUG_PRINT("[bar sta] srel( %p )\n", object);
}
KMP_ITT_DEBUG_LOCK();
__itt_sync_prepare(object);
KMP_ITT_DEBUG_PRINT("[bar sta] spre( %p )\n", object);
#endif
} // __kmp_itt_barrier_starting
// -----------------------------------------------------------------------------
void __kmp_itt_barrier_middle(int gtid, void *object) {
#if USE_ITT_NOTIFY
if (KMP_MASTER_GTID(gtid)) {
KMP_ITT_DEBUG_LOCK();
__itt_sync_acquired(object);
KMP_ITT_DEBUG_PRINT("[bar mid] sacq( %p )\n", object);
KMP_ITT_DEBUG_LOCK();
__itt_sync_releasing(object);
KMP_ITT_DEBUG_PRINT("[bar mid] srel( %p )\n", object);
} else {
}
#endif
} // __kmp_itt_barrier_middle
// -----------------------------------------------------------------------------
void __kmp_itt_barrier_finished(int gtid, void *object) {
#if USE_ITT_NOTIFY
if (KMP_MASTER_GTID(gtid)) {
} else {
KMP_ITT_DEBUG_LOCK();
__itt_sync_acquired(object);
KMP_ITT_DEBUG_PRINT("[bar end] sacq( %p )\n", object);
}
#endif
} // __kmp_itt_barrier_finished
/* Taskwait reporting.
ITT need an address (void *) to be specified as a sync object. OpenMP RTL
does not have taskwait structure, so we need to construct something. */
void *__kmp_itt_taskwait_object(int gtid) {
void *object = NULL;
#if USE_ITT_NOTIFY
if (UNLIKELY(__itt_sync_create_ptr)) {
kmp_info_t *thread = __kmp_thread_from_gtid(gtid);
kmp_taskdata_t *taskdata = thread->th.th_current_task;
object = reinterpret_cast<void *>(kmp_uintptr_t(taskdata) +
taskdata->td_taskwait_counter %
sizeof(kmp_taskdata_t));
}
#endif
return object;
} // __kmp_itt_taskwait_object
void __kmp_itt_taskwait_starting(int gtid, void *object) {
#if USE_ITT_NOTIFY
kmp_info_t *thread = __kmp_thread_from_gtid(gtid);
kmp_taskdata_t *taskdata = thread->th.th_current_task;
ident_t const *loc = taskdata->td_taskwait_ident;
char const *src = (loc == NULL ? NULL : loc->psource);
KMP_ITT_DEBUG_LOCK();
__itt_sync_create(object, "OMP Taskwait", src, 0);
KMP_ITT_DEBUG_PRINT("[twa sta] scre( %p, \"OMP Taskwait\", \"%s\", 0 )\n",
object, src);
KMP_ITT_DEBUG_LOCK();
__itt_sync_prepare(object);
KMP_ITT_DEBUG_PRINT("[twa sta] spre( %p )\n", object);
#endif
} // __kmp_itt_taskwait_starting
void __kmp_itt_taskwait_finished(int gtid, void *object) {
#if USE_ITT_NOTIFY
KMP_ITT_DEBUG_LOCK();
__itt_sync_acquired(object);
KMP_ITT_DEBUG_PRINT("[twa end] sacq( %p )\n", object);
KMP_ITT_DEBUG_LOCK();
__itt_sync_destroy(object);
KMP_ITT_DEBUG_PRINT("[twa end] sdes( %p )\n", object);
#endif
} // __kmp_itt_taskwait_finished
/* Task reporting.
Only those tasks are reported which are executed by a thread spinning at
barrier (or taskwait). Synch object passed to the function must be barrier of
taskwait the threads waiting at. */
void __kmp_itt_task_starting(
void *object // ITT sync object: barrier or taskwait.
) {
#if USE_ITT_NOTIFY
if (UNLIKELY(object != NULL)) {
KMP_ITT_DEBUG_LOCK();
__itt_sync_cancel(object);
KMP_ITT_DEBUG_PRINT("[tsk sta] scan( %p )\n", object);
}
#endif
} // __kmp_itt_task_starting
// -----------------------------------------------------------------------------
void __kmp_itt_task_finished(
void *object // ITT sync object: barrier or taskwait.
) {
#if USE_ITT_NOTIFY
KMP_ITT_DEBUG_LOCK();
__itt_sync_prepare(object);
KMP_ITT_DEBUG_PRINT("[tsk end] spre( %p )\n", object);
#endif
} // __kmp_itt_task_finished
/* Lock reporting.
* __kmp_itt_lock_creating( lock ) should be called *before* the first lock
operation (set/unset). It is not a real event shown to the user but just
setting a name for synchronization object. `lock' is an address of sync
object, the same address should be used in all subsequent calls.
* __kmp_itt_lock_acquiring() should be called before setting the lock.
* __kmp_itt_lock_acquired() should be called after setting the lock.
* __kmp_itt_lock_realeasing() should be called before unsetting the lock.
* __kmp_itt_lock_cancelled() should be called after thread cancelled waiting
for the lock.
* __kmp_itt_lock_destroyed( lock ) should be called after the last lock
operation. After __kmp_itt_lock_destroyed() all the references to the same
address will be considered as another sync object, not related with the
original one. */
#if KMP_USE_DYNAMIC_LOCK
// Takes location information directly
__kmp_inline void ___kmp_itt_lock_init(kmp_user_lock_p lock, char const *type,
const ident_t *loc) {
#if USE_ITT_NOTIFY
if (__itt_sync_create_ptr) {
char const *src = (loc == NULL ? NULL : loc->psource);
KMP_ITT_DEBUG_LOCK();
__itt_sync_create(lock, type, src, 0);
KMP_ITT_DEBUG_PRINT("[lck ini] scre( %p, \"%s\", \"%s\", 0 )\n", lock, type,
src);
}
#endif
}
#else // KMP_USE_DYNAMIC_LOCK
// Internal guts -- common code for locks and critical sections, do not call
// directly.
__kmp_inline void ___kmp_itt_lock_init(kmp_user_lock_p lock, char const *type) {
#if USE_ITT_NOTIFY
if (__itt_sync_create_ptr) {
ident_t const *loc = NULL;
if (__kmp_get_user_lock_location_ != NULL)
loc = __kmp_get_user_lock_location_((lock));
char const *src = (loc == NULL ? NULL : loc->psource);
KMP_ITT_DEBUG_LOCK();
__itt_sync_create(lock, type, src, 0);
KMP_ITT_DEBUG_PRINT("[lck ini] scre( %p, \"%s\", \"%s\", 0 )\n", lock, type,
src);
}
#endif
} // ___kmp_itt_lock_init
#endif // KMP_USE_DYNAMIC_LOCK
// Internal guts -- common code for locks and critical sections, do not call
// directly.
__kmp_inline void ___kmp_itt_lock_fini(kmp_user_lock_p lock, char const *type) {
#if USE_ITT_NOTIFY
KMP_ITT_DEBUG_LOCK();
__itt_sync_destroy(lock);
KMP_ITT_DEBUG_PRINT("[lck dst] sdes( %p )\n", lock);
#endif
} // ___kmp_itt_lock_fini
// -----------------------------------------------------------------------------
#if KMP_USE_DYNAMIC_LOCK
void __kmp_itt_lock_creating(kmp_user_lock_p lock, const ident_t *loc) {
___kmp_itt_lock_init(lock, "OMP Lock", loc);
}
#else
void __kmp_itt_lock_creating(kmp_user_lock_p lock) {
___kmp_itt_lock_init(lock, "OMP Lock");
} // __kmp_itt_lock_creating
#endif
void __kmp_itt_lock_acquiring(kmp_user_lock_p lock) {
#if KMP_USE_DYNAMIC_LOCK && USE_ITT_NOTIFY
// postpone lock object access
if (__itt_sync_prepare_ptr) {
if (KMP_EXTRACT_D_TAG(lock) == 0) {
kmp_indirect_lock_t *ilk = KMP_LOOKUP_I_LOCK(lock);
__itt_sync_prepare(ilk->lock);
} else {
__itt_sync_prepare(lock);
}
}
#else
__itt_sync_prepare(lock);
#endif
} // __kmp_itt_lock_acquiring
void __kmp_itt_lock_acquired(kmp_user_lock_p lock) {
#if KMP_USE_DYNAMIC_LOCK && USE_ITT_NOTIFY
// postpone lock object access
if (__itt_sync_acquired_ptr) {
if (KMP_EXTRACT_D_TAG(lock) == 0) {
kmp_indirect_lock_t *ilk = KMP_LOOKUP_I_LOCK(lock);
__itt_sync_acquired(ilk->lock);
} else {
__itt_sync_acquired(lock);
}
}
#else
__itt_sync_acquired(lock);
#endif
} // __kmp_itt_lock_acquired
void __kmp_itt_lock_releasing(kmp_user_lock_p lock) {
#if KMP_USE_DYNAMIC_LOCK && USE_ITT_NOTIFY
if (__itt_sync_releasing_ptr) {
if (KMP_EXTRACT_D_TAG(lock) == 0) {
kmp_indirect_lock_t *ilk = KMP_LOOKUP_I_LOCK(lock);
__itt_sync_releasing(ilk->lock);
} else {
__itt_sync_releasing(lock);
}
}
#else
__itt_sync_releasing(lock);
#endif
} // __kmp_itt_lock_releasing
void __kmp_itt_lock_cancelled(kmp_user_lock_p lock) {
#if KMP_USE_DYNAMIC_LOCK && USE_ITT_NOTIFY
if (__itt_sync_cancel_ptr) {
if (KMP_EXTRACT_D_TAG(lock) == 0) {
kmp_indirect_lock_t *ilk = KMP_LOOKUP_I_LOCK(lock);
__itt_sync_cancel(ilk->lock);
} else {
__itt_sync_cancel(lock);
}
}
#else
__itt_sync_cancel(lock);
#endif
} // __kmp_itt_lock_cancelled
void __kmp_itt_lock_destroyed(kmp_user_lock_p lock) {
___kmp_itt_lock_fini(lock, "OMP Lock");
} // __kmp_itt_lock_destroyed
/* Critical reporting.
Critical sections are treated exactly as locks (but have different object
type). */
#if KMP_USE_DYNAMIC_LOCK
void __kmp_itt_critical_creating(kmp_user_lock_p lock, const ident_t *loc) {
___kmp_itt_lock_init(lock, "OMP Critical", loc);
}
#else
void __kmp_itt_critical_creating(kmp_user_lock_p lock) {
___kmp_itt_lock_init(lock, "OMP Critical");
} // __kmp_itt_critical_creating
#endif
void __kmp_itt_critical_acquiring(kmp_user_lock_p lock) {
__itt_sync_prepare(lock);
} // __kmp_itt_critical_acquiring
void __kmp_itt_critical_acquired(kmp_user_lock_p lock) {
__itt_sync_acquired(lock);
} // __kmp_itt_critical_acquired
void __kmp_itt_critical_releasing(kmp_user_lock_p lock) {
__itt_sync_releasing(lock);
} // __kmp_itt_critical_releasing
void __kmp_itt_critical_destroyed(kmp_user_lock_p lock) {
___kmp_itt_lock_fini(lock, "OMP Critical");
} // __kmp_itt_critical_destroyed
/* Single reporting. */
void __kmp_itt_single_start(int gtid) {
#if USE_ITT_NOTIFY
if (__itt_mark_create_ptr || KMP_ITT_DEBUG) {
kmp_info_t *thr = __kmp_thread_from_gtid((gtid));
ident_t *loc = thr->th.th_ident;
char const *src = (loc == NULL ? NULL : loc->psource);
kmp_str_buf_t name;
__kmp_str_buf_init(&name);
__kmp_str_buf_print(&name, "OMP Single-%s", src);
KMP_ITT_DEBUG_LOCK();
thr->th.th_itt_mark_single = __itt_mark_create(name.str);
KMP_ITT_DEBUG_PRINT("[sin sta] mcre( \"%s\") -> %d\n", name.str,
thr->th.th_itt_mark_single);
__kmp_str_buf_free(&name);
KMP_ITT_DEBUG_LOCK();
__itt_mark(thr->th.th_itt_mark_single, NULL);
KMP_ITT_DEBUG_PRINT("[sin sta] mark( %d, NULL )\n",
thr->th.th_itt_mark_single);
}
#endif
} // __kmp_itt_single_start
void __kmp_itt_single_end(int gtid) {
#if USE_ITT_NOTIFY
__itt_mark_type mark = __kmp_thread_from_gtid(gtid)->th.th_itt_mark_single;
KMP_ITT_DEBUG_LOCK();
__itt_mark_off(mark);
KMP_ITT_DEBUG_PRINT("[sin end] moff( %d )\n", mark);
#endif
} // __kmp_itt_single_end
/* Ordered reporting.
* __kmp_itt_ordered_init is called by each thread *before* first using sync
object. ITT team would like it to be called once, but it requires extra
synchronization.
* __kmp_itt_ordered_prep is called when thread is going to enter ordered
section (before synchronization).
* __kmp_itt_ordered_start is called just before entering user code (after
synchronization).
* __kmp_itt_ordered_end is called after returning from user code.
Sync object is th->th.th_dispatch->th_dispatch_sh_current.
Events are not generated in case of serialized team. */
void __kmp_itt_ordered_init(int gtid) {
#if USE_ITT_NOTIFY
if (__itt_sync_create_ptr) {
kmp_info_t *thr = __kmp_thread_from_gtid(gtid);
ident_t const *loc = thr->th.th_ident;
char const *src = (loc == NULL ? NULL : loc->psource);
__itt_sync_create(thr->th.th_dispatch->th_dispatch_sh_current,
"OMP Ordered", src, 0);
}
#endif
} // __kmp_itt_ordered_init
void __kmp_itt_ordered_prep(int gtid) {
#if USE_ITT_NOTIFY
if (__itt_sync_create_ptr) {
kmp_team_t *t = __kmp_team_from_gtid(gtid);
if (!t->t.t_serialized) {
kmp_info_t *th = __kmp_thread_from_gtid(gtid);
__itt_sync_prepare(th->th.th_dispatch->th_dispatch_sh_current);
}
}
#endif
} // __kmp_itt_ordered_prep
void __kmp_itt_ordered_start(int gtid) {
#if USE_ITT_NOTIFY
if (__itt_sync_create_ptr) {
kmp_team_t *t = __kmp_team_from_gtid(gtid);
if (!t->t.t_serialized) {
kmp_info_t *th = __kmp_thread_from_gtid(gtid);
__itt_sync_acquired(th->th.th_dispatch->th_dispatch_sh_current);
}
}
#endif
} // __kmp_itt_ordered_start
void __kmp_itt_ordered_end(int gtid) {
#if USE_ITT_NOTIFY
if (__itt_sync_create_ptr) {
kmp_team_t *t = __kmp_team_from_gtid(gtid);
if (!t->t.t_serialized) {
kmp_info_t *th = __kmp_thread_from_gtid(gtid);
__itt_sync_releasing(th->th.th_dispatch->th_dispatch_sh_current);
}
}
#endif
} // __kmp_itt_ordered_end
/* Threads reporting. */
void __kmp_itt_thread_ignore() {
__itt_thr_ignore();
} // __kmp_itt_thread_ignore
void __kmp_itt_thread_name(int gtid) {
#if USE_ITT_NOTIFY
if (__itt_thr_name_set_ptr) {
kmp_str_buf_t name;
__kmp_str_buf_init(&name);
if (KMP_MASTER_GTID(gtid)) {
__kmp_str_buf_print(&name, "OMP Primary Thread #%d", gtid);
} else {
__kmp_str_buf_print(&name, "OMP Worker Thread #%d", gtid);
}
KMP_ITT_DEBUG_LOCK();
__itt_thr_name_set(name.str, name.used);
KMP_ITT_DEBUG_PRINT("[thr nam] name( \"%s\")\n", name.str);
__kmp_str_buf_free(&name);
}
#endif
} // __kmp_itt_thread_name
/* System object reporting.
ITT catches operations with system sync objects (like Windows* OS on IA-32
architecture API critical sections and events). We only need to specify
name ("OMP Scheduler") for the object to let ITT know it is an object used
by OpenMP RTL for internal purposes. */
void __kmp_itt_system_object_created(void *object, char const *name) {
#if USE_ITT_NOTIFY
KMP_ITT_DEBUG_LOCK();
__itt_sync_create(object, "OMP Scheduler", name, 0);
KMP_ITT_DEBUG_PRINT("[sys obj] scre( %p, \"OMP Scheduler\", \"%s\", 0 )\n",
object, name);
#endif
} // __kmp_itt_system_object_created
/* Stack stitching api.
Primary thread calls "create" and put the stitching id into team structure.
Workers read the stitching id and call "enter" / "leave" api.
Primary thread calls "destroy" at the end of the parallel region. */
__itt_caller __kmp_itt_stack_caller_create() {
#if USE_ITT_NOTIFY
if (!__itt_stack_caller_create_ptr)
return NULL;
KMP_ITT_DEBUG_LOCK();
__itt_caller id = __itt_stack_caller_create();
KMP_ITT_DEBUG_PRINT("[stk cre] %p\n", id);
return id;
#endif
return NULL;
}
void __kmp_itt_stack_caller_destroy(__itt_caller id) {
#if USE_ITT_NOTIFY
if (__itt_stack_caller_destroy_ptr) {
KMP_ITT_DEBUG_LOCK();
__itt_stack_caller_destroy(id);
KMP_ITT_DEBUG_PRINT("[stk des] %p\n", id);
}
#endif
}
void __kmp_itt_stack_callee_enter(__itt_caller id) {
#if USE_ITT_NOTIFY
if (__itt_stack_callee_enter_ptr) {
KMP_ITT_DEBUG_LOCK();
__itt_stack_callee_enter(id);
KMP_ITT_DEBUG_PRINT("[stk ent] %p\n", id);
}
#endif
}
void __kmp_itt_stack_callee_leave(__itt_caller id) {
#if USE_ITT_NOTIFY
if (__itt_stack_callee_leave_ptr) {
KMP_ITT_DEBUG_LOCK();
__itt_stack_callee_leave(id);
KMP_ITT_DEBUG_PRINT("[stk lea] %p\n", id);
}
#endif
}
#endif /* USE_ITT_BUILD */

4052
third_party/openmp/kmp_lock.cpp vendored Normal file

File diff suppressed because it is too large Load diff

1296
third_party/openmp/kmp_lock.h vendored Normal file

File diff suppressed because it is too large Load diff

235
third_party/openmp/kmp_omp.h vendored Normal file
View file

@ -0,0 +1,235 @@
#if USE_DEBUGGER
/*
* kmp_omp.h -- OpenMP definition for kmp_omp_struct_info_t.
* This is for information about runtime library structures.
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
/* THIS FILE SHOULD NOT BE MODIFIED IN IDB INTERFACE LIBRARY CODE
It should instead be modified in the OpenMP runtime and copied to the
interface library code. This way we can minimize the problems that this is
sure to cause having two copies of the same file.
Files live in libomp and libomp_db/src/include */
/* CHANGE THIS WHEN STRUCTURES BELOW CHANGE
Before we release this to a customer, please don't change this value. After
it is released and stable, then any new updates to the structures or data
structure traversal algorithms need to change this value. */
#define KMP_OMP_VERSION 9
typedef struct {
kmp_int32 offset;
kmp_int32 size;
} offset_and_size_t;
typedef struct {
kmp_uint64 addr;
kmp_int32 size;
kmp_int32 padding;
} addr_and_size_t;
typedef struct {
kmp_uint64 flags; // Flags for future extensions.
kmp_uint64
file; // Pointer to name of source file where the parallel region is.
kmp_uint64 func; // Pointer to name of routine where the parallel region is.
kmp_int32 begin; // Beginning of source line range.
kmp_int32 end; // End of source line range.
kmp_int32 num_threads; // Specified number of threads.
} kmp_omp_nthr_item_t;
typedef struct {
kmp_int32 num; // Number of items in the array.
kmp_uint64 array; // Address of array of kmp_omp_num_threads_item_t.
} kmp_omp_nthr_info_t;
/* This structure is known to the idb interface library */
typedef struct {
/* Change this only if you make a fundamental data structure change here */
kmp_int32 lib_version;
/* sanity check. Only should be checked if versions are identical
* This is also used for backward compatibility to get the runtime
* structure size if it the runtime is older than the interface */
kmp_int32 sizeof_this_structure;
/* OpenMP RTL version info. */
addr_and_size_t major;
addr_and_size_t minor;
addr_and_size_t build;
addr_and_size_t openmp_version;
addr_and_size_t banner;
/* Various globals. */
addr_and_size_t threads; // Pointer to __kmp_threads.
addr_and_size_t roots; // Pointer to __kmp_root.
addr_and_size_t capacity; // Pointer to __kmp_threads_capacity.
#if KMP_USE_MONITOR
addr_and_size_t monitor; // Pointer to __kmp_monitor.
#endif
#if !KMP_USE_DYNAMIC_LOCK
addr_and_size_t lock_table; // Pointer to __kmp_lock_table.
#endif
addr_and_size_t func_microtask;
addr_and_size_t func_fork;
addr_and_size_t func_fork_teams;
addr_and_size_t team_counter;
addr_and_size_t task_counter;
addr_and_size_t nthr_info;
kmp_int32 address_width;
kmp_int32 indexed_locks;
kmp_int32 last_barrier; // The end in enum barrier_type
kmp_int32 deque_size; // TASK_DEQUE_SIZE
/* thread structure information. */
kmp_int32 th_sizeof_struct;
offset_and_size_t th_info; // descriptor for thread
offset_and_size_t th_team; // team for this thread
offset_and_size_t th_root; // root for this thread
offset_and_size_t th_serial_team; // serial team under this thread
offset_and_size_t th_ident; // location for this thread (if available)
offset_and_size_t th_spin_here; // is thread waiting for lock (if available)
offset_and_size_t
th_next_waiting; // next thread waiting for lock (if available)
offset_and_size_t th_task_team; // task team struct
offset_and_size_t th_current_task; // innermost task being executed
offset_and_size_t
th_task_state; // alternating 0/1 for task team identification
offset_and_size_t th_bar;
offset_and_size_t th_b_worker_arrived; // the worker increases it by 1 when it
// arrives to the barrier
/* teams information */
offset_and_size_t th_teams_microtask; // entry address for teams construct
offset_and_size_t th_teams_level; // initial level of teams construct
offset_and_size_t th_teams_nteams; // number of teams in a league
offset_and_size_t
th_teams_nth; // number of threads in each team of the league
/* kmp_desc structure (for info field above) */
kmp_int32 ds_sizeof_struct;
offset_and_size_t ds_tid; // team thread id
offset_and_size_t ds_gtid; // global thread id
offset_and_size_t ds_thread; // native thread id
/* team structure information */
kmp_int32 t_sizeof_struct;
offset_and_size_t t_master_tid; // tid of primary thread in parent team
offset_and_size_t t_ident; // location of parallel region
offset_and_size_t t_parent; // parent team
offset_and_size_t t_nproc; // # team threads
offset_and_size_t t_threads; // array of threads
offset_and_size_t t_serialized; // # levels of serialized teams
offset_and_size_t t_id; // unique team id
offset_and_size_t t_pkfn;
offset_and_size_t t_task_team; // task team structure
offset_and_size_t t_implicit_task; // taskdata for the thread's implicit task
offset_and_size_t t_cancel_request;
offset_and_size_t t_bar;
offset_and_size_t
t_b_master_arrived; // incremented when primary thread reaches barrier
offset_and_size_t
t_b_team_arrived; // increased by one when all the threads arrived
/* root structure information */
kmp_int32 r_sizeof_struct;
offset_and_size_t r_root_team; // team at root
offset_and_size_t r_hot_team; // hot team for this root
offset_and_size_t r_uber_thread; // root thread
offset_and_size_t r_root_id; // unique root id (if available)
/* ident structure information */
kmp_int32 id_sizeof_struct;
offset_and_size_t
id_psource; /* address of string ";file;func;line1;line2;;". */
offset_and_size_t id_flags;
/* lock structure information */
kmp_int32 lk_sizeof_struct;
offset_and_size_t lk_initialized;
offset_and_size_t lk_location;
offset_and_size_t lk_tail_id;
offset_and_size_t lk_head_id;
offset_and_size_t lk_next_ticket;
offset_and_size_t lk_now_serving;
offset_and_size_t lk_owner_id;
offset_and_size_t lk_depth_locked;
offset_and_size_t lk_lock_flags;
#if !KMP_USE_DYNAMIC_LOCK
/* lock_table_t */
kmp_int32 lt_size_of_struct; /* Size and layout of kmp_lock_table_t. */
offset_and_size_t lt_used;
offset_and_size_t lt_allocated;
offset_and_size_t lt_table;
#endif
/* task_team_t */
kmp_int32 tt_sizeof_struct;
offset_and_size_t tt_threads_data;
offset_and_size_t tt_found_tasks;
offset_and_size_t tt_nproc;
offset_and_size_t tt_unfinished_threads;
offset_and_size_t tt_active;
/* kmp_taskdata_t */
kmp_int32 td_sizeof_struct;
offset_and_size_t td_task_id; // task id
offset_and_size_t td_flags; // task flags
offset_and_size_t td_team; // team for this task
offset_and_size_t td_parent; // parent task
offset_and_size_t td_level; // task testing level
offset_and_size_t td_ident; // task identifier
offset_and_size_t td_allocated_child_tasks; // child tasks (+ current task)
// not yet deallocated
offset_and_size_t td_incomplete_child_tasks; // child tasks not yet complete
/* Taskwait */
offset_and_size_t td_taskwait_ident;
offset_and_size_t td_taskwait_counter;
offset_and_size_t
td_taskwait_thread; // gtid + 1 of thread encountered taskwait
/* Taskgroup */
offset_and_size_t td_taskgroup; // pointer to the current taskgroup
offset_and_size_t
td_task_count; // number of allocated and not yet complete tasks
offset_and_size_t td_cancel; // request for cancellation of this taskgroup
/* Task dependency */
offset_and_size_t
td_depnode; // pointer to graph node if the task has dependencies
offset_and_size_t dn_node;
offset_and_size_t dn_next;
offset_and_size_t dn_successors;
offset_and_size_t dn_task;
offset_and_size_t dn_npredecessors;
offset_and_size_t dn_nrefs;
offset_and_size_t dn_routine;
/* kmp_thread_data_t */
kmp_int32 hd_sizeof_struct;
offset_and_size_t hd_deque;
offset_and_size_t hd_deque_size;
offset_and_size_t hd_deque_head;
offset_and_size_t hd_deque_tail;
offset_and_size_t hd_deque_ntasks;
offset_and_size_t hd_deque_last_stolen;
// The last field of stable version.
kmp_uint64 last_field;
} kmp_omp_struct_info_t;
#endif /* USE_DEBUGGER */
/* end of file */

1319
third_party/openmp/kmp_os.h vendored Normal file

File diff suppressed because it is too large Load diff

261
third_party/openmp/kmp_platform.h vendored Normal file
View file

@ -0,0 +1,261 @@
/*
* kmp_platform.h -- header for determining operating system and architecture
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef KMP_PLATFORM_H
#define KMP_PLATFORM_H
/* ---------------------- Operating system recognition ------------------- */
#define KMP_OS_LINUX 0
#define KMP_OS_DRAGONFLY 0
#define KMP_OS_FREEBSD 0
#define KMP_OS_NETBSD 0
#define KMP_OS_OPENBSD 0
#define KMP_OS_DARWIN 0
#define KMP_OS_WINDOWS 0
#define KMP_OS_HURD 0
#define KMP_OS_SOLARIS 0
#define KMP_OS_WASI 0
#define KMP_OS_UNIX 0 /* disjunction of KMP_OS_LINUX, KMP_OS_DARWIN etc. */
#ifdef _WIN32
#undef KMP_OS_WINDOWS
#define KMP_OS_WINDOWS 1
#endif
#if (defined __APPLE__ && defined __MACH__)
#undef KMP_OS_DARWIN
#define KMP_OS_DARWIN 1
#endif
// in some ppc64 linux installations, only the second condition is met
#if (defined __linux) || defined(__COSMOPOLITAN__)
#undef KMP_OS_LINUX
#define KMP_OS_LINUX 1
#elif (defined __linux__)
#undef KMP_OS_LINUX
#define KMP_OS_LINUX 1
#else
#endif
#if (defined __DragonFly__)
#undef KMP_OS_DRAGONFLY
#define KMP_OS_DRAGONFLY 1
#endif
#if (defined __FreeBSD__)
#undef KMP_OS_FREEBSD
#define KMP_OS_FREEBSD 1
#endif
#if (defined __NetBSD__)
#undef KMP_OS_NETBSD
#define KMP_OS_NETBSD 1
#endif
#if (defined __OpenBSD__)
#undef KMP_OS_OPENBSD
#define KMP_OS_OPENBSD 1
#endif
#if (defined __GNU__)
#undef KMP_OS_HURD
#define KMP_OS_HURD 1
#endif
#if (defined __sun__ && defined __svr4__)
#undef KMP_OS_SOLARIS
#define KMP_OS_SOLARIS 1
#endif
#if (defined __wasi__) || (defined __EMSCRIPTEN__)
#undef KMP_OS_WASI
#define KMP_OS_WASI 1
#endif
#if (defined _AIX)
#undef KMP_OS_AIX
#define KMP_OS_AIX 1
#endif
#if (1 != KMP_OS_LINUX + KMP_OS_DRAGONFLY + KMP_OS_FREEBSD + KMP_OS_NETBSD + \
KMP_OS_OPENBSD + KMP_OS_DARWIN + KMP_OS_WINDOWS + KMP_OS_HURD + \
KMP_OS_SOLARIS + KMP_OS_WASI + KMP_OS_AIX)
#error Unknown OS
#endif
#if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || \
KMP_OS_OPENBSD || KMP_OS_DARWIN || KMP_OS_HURD || KMP_OS_SOLARIS || \
KMP_OS_WASI || KMP_OS_AIX
#undef KMP_OS_UNIX
#define KMP_OS_UNIX 1
#endif
/* ---------------------- Architecture recognition ------------------- */
#define KMP_ARCH_X86 0
#define KMP_ARCH_X86_64 0
#define KMP_ARCH_AARCH64 0
#define KMP_ARCH_PPC64_ELFv1 0
#define KMP_ARCH_PPC64_ELFv2 0
#define KMP_ARCH_PPC64_XCOFF 0
#define KMP_ARCH_PPC_XCOFF 0
#define KMP_ARCH_MIPS 0
#define KMP_ARCH_MIPS64 0
#define KMP_ARCH_RISCV64 0
#define KMP_ARCH_LOONGARCH64 0
#define KMP_ARCH_VE 0
#define KMP_ARCH_S390X 0
#if KMP_OS_WINDOWS
#if defined(_M_AMD64) || defined(__x86_64)
#undef KMP_ARCH_X86_64
#define KMP_ARCH_X86_64 1
#elif defined(__aarch64__) || defined(_M_ARM64)
#undef KMP_ARCH_AARCH64
#define KMP_ARCH_AARCH64 1
#elif defined(__arm__) || defined(_M_ARM)
#undef KMP_ARCH_ARMV7
#define KMP_ARCH_ARMV7 1
#else
#undef KMP_ARCH_X86
#define KMP_ARCH_X86 1
#endif
#endif
#if KMP_OS_UNIX
#if defined __x86_64
#undef KMP_ARCH_X86_64
#define KMP_ARCH_X86_64 1
#elif defined __i386
#undef KMP_ARCH_X86
#define KMP_ARCH_X86 1
#elif defined __powerpc64__
#if defined(_CALL_ELF)
#if _CALL_ELF == 2
#undef KMP_ARCH_PPC64_ELFv2
#define KMP_ARCH_PPC64_ELFv2 1
#else
#undef KMP_ARCH_PPC64_ELFv1
#define KMP_ARCH_PPC64_ELFv1 1
#endif
#elif defined KMP_OS_AIX
#undef KMP_ARCH_PPC64_XCOFF
#define KMP_ARCH_PPC64_XCOFF 1
#endif
#elif defined(__powerpc__) && defined(KMP_OS_AIX)
#undef KMP_ARCH_PPC_XCOFF
#define KMP_ARCH_PPC_XCOFF 1
#undef KMP_ARCH_PPC
#define KMP_ARCH_PPC 1
#elif defined __aarch64__
#undef KMP_ARCH_AARCH64
#define KMP_ARCH_AARCH64 1
#elif defined __mips__
#if defined __mips64
#undef KMP_ARCH_MIPS64
#define KMP_ARCH_MIPS64 1
#else
#undef KMP_ARCH_MIPS
#define KMP_ARCH_MIPS 1
#endif
#elif defined __riscv && __riscv_xlen == 64
#undef KMP_ARCH_RISCV64
#define KMP_ARCH_RISCV64 1
#elif defined __loongarch__ && __loongarch_grlen == 64
#undef KMP_ARCH_LOONGARCH64
#define KMP_ARCH_LOONGARCH64 1
#elif defined __ve__
#undef KMP_ARCH_VE
#define KMP_ARCH_VE 1
#elif defined __s390x__
#undef KMP_ARCH_S390X
#define KMP_ARCH_S390X 1
#endif
#endif
#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7R__) || \
defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7VE__)
#define KMP_ARCH_ARMV7 1
#endif
#if defined(KMP_ARCH_ARMV7) || defined(__ARM_ARCH_6__) || \
defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || \
defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6T2__) || \
defined(__ARM_ARCH_6ZK__)
#define KMP_ARCH_ARMV6 1
#endif
#if defined(KMP_ARCH_ARMV6) || defined(__ARM_ARCH_5T__) || \
defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) || \
defined(__ARM_ARCH_5TEJ__)
#define KMP_ARCH_ARMV5 1
#endif
#if defined(KMP_ARCH_ARMV5) || defined(__ARM_ARCH_4__) || \
defined(__ARM_ARCH_4T__)
#define KMP_ARCH_ARMV4 1
#endif
#if defined(KMP_ARCH_ARMV4) || defined(__ARM_ARCH_3__) || \
defined(__ARM_ARCH_3M__)
#define KMP_ARCH_ARMV3 1
#endif
#if defined(KMP_ARCH_ARMV3) || defined(__ARM_ARCH_2__)
#define KMP_ARCH_ARMV2 1
#endif
#if defined(KMP_ARCH_ARMV2)
#define KMP_ARCH_ARM 1
#endif
#if defined(__wasm32__)
#define KMP_ARCH_WASM 1
#endif
#define KMP_ARCH_PPC64 \
(KMP_ARCH_PPC64_ELFv2 || KMP_ARCH_PPC64_ELFv1 || KMP_ARCH_PPC64_XCOFF)
#if defined(__MIC__) || defined(__MIC2__)
#define KMP_MIC 1
#if __MIC2__ || __KNC__
#define KMP_MIC1 0
#define KMP_MIC2 1
#else
#define KMP_MIC1 1
#define KMP_MIC2 0
#endif
#else
#define KMP_MIC 0
#define KMP_MIC1 0
#define KMP_MIC2 0
#endif
/* Specify 32 bit architectures here */
#define KMP_32_BIT_ARCH \
(KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_MIPS || KMP_ARCH_WASM || \
KMP_ARCH_PPC)
// Platforms which support Intel(R) Many Integrated Core Architecture
#define KMP_MIC_SUPPORTED \
((KMP_ARCH_X86 || KMP_ARCH_X86_64) && (KMP_OS_LINUX || KMP_OS_WINDOWS))
// TODO: Fixme - This is clever, but really fugly
#if (1 != KMP_ARCH_X86 + KMP_ARCH_X86_64 + KMP_ARCH_ARM + KMP_ARCH_PPC64 + \
KMP_ARCH_AARCH64 + KMP_ARCH_MIPS + KMP_ARCH_MIPS64 + \
KMP_ARCH_RISCV64 + KMP_ARCH_LOONGARCH64 + KMP_ARCH_VE + \
KMP_ARCH_S390X + KMP_ARCH_WASM + KMP_ARCH_PPC)
#error Unknown or unsupported architecture
#endif
#endif // KMP_PLATFORM_H

9351
third_party/openmp/kmp_runtime.cpp vendored Normal file

File diff suppressed because it is too large Load diff

87
third_party/openmp/kmp_safe_c_api.h vendored Normal file
View file

@ -0,0 +1,87 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef KMP_SAFE_C_API_H
#define KMP_SAFE_C_API_H
#include <type_traits>
#include "kmp_platform.h"
#include <string.h>
// Replacement for banned C API
// Not every unsafe call listed here is handled now, but keeping everything
// in one place should be handy for future maintenance.
#if KMP_OS_WINDOWS && KMP_MSVC_COMPAT
#define RSIZE_MAX_STR (4UL << 10) // 4KB
// _malloca was suggested, but it is not a drop-in replacement for _alloca
#define KMP_ALLOCA _alloca
#define KMP_MEMCPY_S memcpy_s
#define KMP_SNPRINTF sprintf_s
#define KMP_SSCANF sscanf_s
#define KMP_STRCPY_S strcpy_s
#define KMP_STRNCPY_S strncpy_s
#define KMP_STRNCAT_S strncat_s
// Use this only when buffer size is unknown
#define KMP_MEMCPY(dst, src, cnt) memcpy_s(dst, cnt, src, cnt)
template <typename T, bool B = std::is_array<T>::value>
struct kmp_get_rmax_t {};
template <typename T> struct kmp_get_rmax_t<T, false> {
static const size_t value = RSIZE_MAX_STR;
};
template <typename T> struct kmp_get_rmax_t<T, true> {
static const size_t value = sizeof(T);
};
#define KMP_STRLEN(str) strnlen_s(str, kmp_get_rmax_t<decltype(str)>::value)
// Use this only when buffer size is unknown
#define KMP_STRNCPY(dst, src, cnt) strncpy_s(dst, cnt, src, cnt)
// _TRUNCATE insures buffer size > max string to print.
#define KMP_VSNPRINTF(dst, cnt, fmt, arg) \
vsnprintf_s(dst, cnt, _TRUNCATE, fmt, arg)
#else // KMP_OS_WINDOWS
// For now, these macros use the existing API.
#if KMP_OS_NETBSD
#define KMP_ALLOCA __builtin_alloca
#else
#define KMP_ALLOCA alloca
#endif
#define KMP_MEMCPY_S(dst, bsz, src, cnt) memcpy(dst, src, cnt)
#define KMP_SNPRINTF snprintf
#define KMP_SSCANF sscanf
#define KMP_STRCPY_S(dst, bsz, src) strcpy(dst, src)
#define KMP_STRNCPY_S(dst, bsz, src, cnt) strncpy(dst, src, cnt)
#define KMP_STRNCAT_S(dst, bsz, src, cnt) strncat(dst, src, cnt)
#define KMP_VSNPRINTF vsnprintf
#define KMP_STRNCPY strncpy
#define KMP_STRLEN strlen
#define KMP_MEMCPY memcpy
#endif // KMP_OS_WINDOWS
// Offer truncated version of strncpy
static inline void __kmp_strncpy_truncate(char *buffer, size_t buf_size,
char const *src, size_t src_size) {
if (src_size >= buf_size) {
src_size = buf_size - 1;
}
KMP_STRNCPY_S(buffer, buf_size, src, src_size);
buffer[src_size] = '\0';
}
#endif // KMP_SAFE_C_API_H

1092
third_party/openmp/kmp_sched.cpp vendored Normal file

File diff suppressed because it is too large Load diff

6636
third_party/openmp/kmp_settings.cpp vendored Normal file

File diff suppressed because it is too large Load diff

69
third_party/openmp/kmp_settings.h vendored Normal file
View file

@ -0,0 +1,69 @@
/*
* kmp_settings.h -- Initialize environment variables
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef KMP_SETTINGS_H
#define KMP_SETTINGS_H
void __kmp_reset_global_vars(void);
void __kmp_env_initialize(char const *);
void __kmp_env_print();
void __kmp_env_print_2();
void __kmp_display_env_impl(int display_env, int display_env_verbose);
#if OMPD_SUPPORT
void __kmp_env_dump();
#endif
int __kmp_initial_threads_capacity(int req_nproc);
void __kmp_init_dflt_team_nth();
int __kmp_default_tp_capacity(int, int, int);
#if KMP_MIC
#define KMP_STR_BUF_PRINT_NAME \
__kmp_str_buf_print(buffer, " %s %s", KMP_I18N_STR(Device), name)
#define KMP_STR_BUF_PRINT_NAME_EX(x) \
__kmp_str_buf_print(buffer, " %s %s='", KMP_I18N_STR(Device), x)
#define KMP_STR_BUF_PRINT_BOOL_EX(n, v, t, f) \
__kmp_str_buf_print(buffer, " %s %s='%s'\n", KMP_I18N_STR(Device), n, \
(v) ? t : f)
#define KMP_STR_BUF_PRINT_BOOL \
KMP_STR_BUF_PRINT_BOOL_EX(name, value, "TRUE", "FALSE")
#define KMP_STR_BUF_PRINT_INT \
__kmp_str_buf_print(buffer, " %s %s='%d'\n", KMP_I18N_STR(Device), name, \
value)
#define KMP_STR_BUF_PRINT_UINT64 \
__kmp_str_buf_print(buffer, " %s %s='%" KMP_UINT64_SPEC "'\n", \
KMP_I18N_STR(Device), name, value);
#define KMP_STR_BUF_PRINT_STR \
__kmp_str_buf_print(buffer, " %s %s='%s'\n", KMP_I18N_STR(Device), name, \
value)
#else
#define KMP_STR_BUF_PRINT_NAME \
__kmp_str_buf_print(buffer, " %s %s", KMP_I18N_STR(Host), name)
#define KMP_STR_BUF_PRINT_NAME_EX(x) \
__kmp_str_buf_print(buffer, " %s %s='", KMP_I18N_STR(Host), x)
#define KMP_STR_BUF_PRINT_BOOL_EX(n, v, t, f) \
__kmp_str_buf_print(buffer, " %s %s='%s'\n", KMP_I18N_STR(Host), n, \
(v) ? t : f)
#define KMP_STR_BUF_PRINT_BOOL \
KMP_STR_BUF_PRINT_BOOL_EX(name, value, "TRUE", "FALSE")
#define KMP_STR_BUF_PRINT_INT \
__kmp_str_buf_print(buffer, " %s %s='%d'\n", KMP_I18N_STR(Host), name, value)
#define KMP_STR_BUF_PRINT_UINT64 \
__kmp_str_buf_print(buffer, " %s %s='%" KMP_UINT64_SPEC "'\n", \
KMP_I18N_STR(Host), name, value);
#define KMP_STR_BUF_PRINT_STR \
__kmp_str_buf_print(buffer, " %s %s='%s'\n", KMP_I18N_STR(Host), name, value)
#endif
#endif // KMP_SETTINGS_H
// end of file //

929
third_party/openmp/kmp_stats.cpp vendored Normal file
View file

@ -0,0 +1,929 @@
/** @file kmp_stats.cpp
* Statistics gathering and processing.
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "kmp.h"
#include "kmp_lock.h"
#include "kmp_stats.h"
#include "kmp_str.h"
#include <algorithm>
#include <ctime>
#include <iomanip>
#include <sstream>
#include <stdlib.h> // for atexit
#include <cmath>
#if LIBOMP_STATS
#define STRINGIZE2(x) #x
#define STRINGIZE(x) STRINGIZE2(x)
#define expandName(name, flags, ignore) {STRINGIZE(name), flags},
statInfo timeStat::timerInfo[] = {
KMP_FOREACH_TIMER(expandName, 0){"TIMER_LAST", 0}};
const statInfo counter::counterInfo[] = {
KMP_FOREACH_COUNTER(expandName, 0){"COUNTER_LAST", 0}};
#undef expandName
#define expandName(ignore1, ignore2, ignore3) {0.0, 0.0, 0.0},
kmp_stats_output_module::rgb_color kmp_stats_output_module::timerColorInfo[] = {
KMP_FOREACH_TIMER(expandName, 0){0.0, 0.0, 0.0}};
#undef expandName
const kmp_stats_output_module::rgb_color
kmp_stats_output_module::globalColorArray[] = {
{1.0, 0.0, 0.0}, // red
{1.0, 0.6, 0.0}, // orange
{1.0, 1.0, 0.0}, // yellow
{0.0, 1.0, 0.0}, // green
{0.0, 0.0, 1.0}, // blue
{0.6, 0.2, 0.8}, // purple
{1.0, 0.0, 1.0}, // magenta
{0.0, 0.4, 0.2}, // dark green
{1.0, 1.0, 0.6}, // light yellow
{0.6, 0.4, 0.6}, // dirty purple
{0.0, 1.0, 1.0}, // cyan
{1.0, 0.4, 0.8}, // pink
{0.5, 0.5, 0.5}, // grey
{0.8, 0.7, 0.5}, // brown
{0.6, 0.6, 1.0}, // light blue
{1.0, 0.7, 0.5}, // peach
{0.8, 0.5, 1.0}, // lavender
{0.6, 0.0, 0.0}, // dark red
{0.7, 0.6, 0.0}, // gold
{0.0, 0.0, 0.0} // black
};
// Ensure that the atexit handler only runs once.
static uint32_t statsPrinted = 0;
// output interface
static kmp_stats_output_module *__kmp_stats_global_output = NULL;
double logHistogram::binMax[] = {1.e1l, 1.e2l, 1.e3l, 1.e4l, 1.e5l, 1.e6l,
1.e7l, 1.e8l, 1.e9l, 1.e10l, 1.e11l, 1.e12l,
1.e13l, 1.e14l, 1.e15l, 1.e16l, 1.e17l, 1.e18l,
1.e19l, 1.e20l, 1.e21l, 1.e22l, 1.e23l, 1.e24l,
1.e25l, 1.e26l, 1.e27l, 1.e28l, 1.e29l, 1.e30l,
// Always have infinity be the last value
std::numeric_limits<double>::infinity()};
/* ************* statistic member functions ************* */
void statistic::addSample(double sample) {
sample -= offset;
KMP_DEBUG_ASSERT(std::isfinite(sample));
double delta = sample - meanVal;
sampleCount = sampleCount + 1;
meanVal = meanVal + delta / sampleCount;
m2 = m2 + delta * (sample - meanVal);
minVal = std::min(minVal, sample);
maxVal = std::max(maxVal, sample);
if (collectingHist)
hist.addSample(sample);
}
statistic &statistic::operator+=(const statistic &other) {
if (other.sampleCount == 0)
return *this;
if (sampleCount == 0) {
*this = other;
return *this;
}
uint64_t newSampleCount = sampleCount + other.sampleCount;
double dnsc = double(newSampleCount);
double dsc = double(sampleCount);
double dscBydnsc = dsc / dnsc;
double dosc = double(other.sampleCount);
double delta = other.meanVal - meanVal;
// Try to order these calculations to avoid overflows. If this were Fortran,
// then the compiler would not be able to re-order over brackets. In C++ it
// may be legal to do that (we certainly hope it doesn't, and CC+ Programming
// Language 2nd edition suggests it shouldn't, since it says that exploitation
// of associativity can only be made if the operation really is associative
// (which floating addition isn't...)).
meanVal = meanVal * dscBydnsc + other.meanVal * (1 - dscBydnsc);
m2 = m2 + other.m2 + dscBydnsc * dosc * delta * delta;
minVal = std::min(minVal, other.minVal);
maxVal = std::max(maxVal, other.maxVal);
sampleCount = newSampleCount;
if (collectingHist)
hist += other.hist;
return *this;
}
void statistic::scale(double factor) {
minVal = minVal * factor;
maxVal = maxVal * factor;
meanVal = meanVal * factor;
m2 = m2 * factor * factor;
return;
}
std::string statistic::format(char unit, bool total) const {
std::string result = formatSI((double)sampleCount, 9, ' ');
if (sampleCount == 0) {
result = result + std::string(", ") + formatSI(0.0, 9, unit);
result = result + std::string(", ") + formatSI(0.0, 9, unit);
result = result + std::string(", ") + formatSI(0.0, 9, unit);
if (total)
result = result + std::string(", ") + formatSI(0.0, 9, unit);
result = result + std::string(", ") + formatSI(0.0, 9, unit);
} else {
result = result + std::string(", ") + formatSI(minVal, 9, unit);
result = result + std::string(", ") + formatSI(meanVal, 9, unit);
result = result + std::string(", ") + formatSI(maxVal, 9, unit);
if (total)
result =
result + std::string(", ") + formatSI(meanVal * sampleCount, 9, unit);
result = result + std::string(", ") + formatSI(getSD(), 9, unit);
}
return result;
}
/* ************* histogram member functions ************* */
// Lowest bin that has anything in it
int logHistogram::minBin() const {
for (int i = 0; i < numBins; i++) {
if (bins[i].count != 0)
return i - logOffset;
}
return -logOffset;
}
// Highest bin that has anything in it
int logHistogram::maxBin() const {
for (int i = numBins - 1; i >= 0; i--) {
if (bins[i].count != 0)
return i - logOffset;
}
return -logOffset;
}
// Which bin does this sample belong in ?
uint32_t logHistogram::findBin(double sample) {
double v = std::fabs(sample);
// Simply loop up looking which bin to put it in.
// According to a micro-architect this is likely to be faster than a binary
// search, since
// it will only have one branch mis-predict
for (int b = 0; b < numBins - 1; b++)
if (binMax[b] > v)
return b;
return numBins - 1;
}
void logHistogram::addSample(double sample) {
if (sample == 0.0) {
zeroCount += 1;
#ifdef KMP_DEBUG
_total++;
check();
#endif
return;
}
KMP_DEBUG_ASSERT(std::isfinite(sample));
uint32_t bin = findBin(sample);
KMP_DEBUG_ASSERT(0 <= bin && bin < numBins);
bins[bin].count += 1;
bins[bin].total += sample;
#ifdef KMP_DEBUG
_total++;
check();
#endif
}
// This may not be the format we want, but it'll do for now
std::string logHistogram::format(char unit) const {
std::stringstream result;
result << "Bin, Count, Total\n";
if (zeroCount) {
result << "0, " << formatSI(zeroCount, 9, ' ') << ", ",
formatSI(0.0, 9, unit);
if (count(minBin()) == 0)
return result.str();
result << "\n";
}
for (int i = minBin(); i <= maxBin(); i++) {
result << "10**" << i << "<=v<";
if (i + 1 == numBins - 1)
result << "infinity, ";
else
result << "10**" << (i + 1) << ", ";
result << formatSI(count(i), 9, ' ') << ", " << formatSI(total(i), 9, unit);
if (i != maxBin())
result << "\n";
}
return result.str();
}
/* ************* explicitTimer member functions ************* */
void explicitTimer::start(tsc_tick_count tick) {
startTime = tick;
totalPauseTime = 0;
if (timeStat::logEvent(timerEnumValue)) {
__kmp_stats_thread_ptr->incrementNestValue();
}
return;
}
void explicitTimer::stop(tsc_tick_count tick,
kmp_stats_list *stats_ptr /* = nullptr */) {
if (startTime.getValue() == 0)
return;
stat->addSample(((tick - startTime) - totalPauseTime).ticks());
if (timeStat::logEvent(timerEnumValue)) {
if (!stats_ptr)
stats_ptr = __kmp_stats_thread_ptr;
stats_ptr->push_event(
startTime.getValue() - __kmp_stats_start_time.getValue(),
tick.getValue() - __kmp_stats_start_time.getValue(),
__kmp_stats_thread_ptr->getNestValue(), timerEnumValue);
stats_ptr->decrementNestValue();
}
/* We accept the risk that we drop a sample because it really did start at
t==0. */
startTime = 0;
return;
}
/* ************* partitionedTimers member functions ************* */
partitionedTimers::partitionedTimers() { timer_stack.reserve(8); }
// initialize the partitioned timers to an initial timer
void partitionedTimers::init(explicitTimer timer) {
KMP_DEBUG_ASSERT(this->timer_stack.size() == 0);
timer_stack.push_back(timer);
timer_stack.back().start(tsc_tick_count::now());
}
// stop/save the current timer, and start the new timer (timer_pair)
// There is a special condition where if the current timer is equal to
// the one you are trying to push, then it only manipulates the stack,
// and it won't stop/start the currently running timer.
void partitionedTimers::push(explicitTimer timer) {
// get the current timer
// pause current timer
// push new timer
// start the new timer
explicitTimer *current_timer, *new_timer;
size_t stack_size;
KMP_DEBUG_ASSERT(this->timer_stack.size() > 0);
timer_stack.push_back(timer);
stack_size = timer_stack.size();
current_timer = &(timer_stack[stack_size - 2]);
new_timer = &(timer_stack[stack_size - 1]);
tsc_tick_count tick = tsc_tick_count::now();
current_timer->pause(tick);
new_timer->start(tick);
}
// stop/discard the current timer, and start the previously saved timer
void partitionedTimers::pop() {
// get the current timer
// stop current timer (record event/sample)
// pop current timer
// get the new current timer and resume
explicitTimer *old_timer, *new_timer;
size_t stack_size = timer_stack.size();
KMP_DEBUG_ASSERT(stack_size > 1);
old_timer = &(timer_stack[stack_size - 1]);
new_timer = &(timer_stack[stack_size - 2]);
tsc_tick_count tick = tsc_tick_count::now();
old_timer->stop(tick);
new_timer->resume(tick);
timer_stack.pop_back();
}
void partitionedTimers::exchange(explicitTimer timer) {
// get the current timer
// stop current timer (record event/sample)
// push new timer
// start the new timer
explicitTimer *current_timer, *new_timer;
size_t stack_size;
KMP_DEBUG_ASSERT(this->timer_stack.size() > 0);
tsc_tick_count tick = tsc_tick_count::now();
stack_size = timer_stack.size();
current_timer = &(timer_stack[stack_size - 1]);
current_timer->stop(tick);
timer_stack.pop_back();
timer_stack.push_back(timer);
new_timer = &(timer_stack[stack_size - 1]);
new_timer->start(tick);
}
// Wind up all the currently running timers.
// This pops off all the timers from the stack and clears the stack
// After this is called, init() must be run again to initialize the
// stack of timers
void partitionedTimers::windup() {
while (timer_stack.size() > 1) {
this->pop();
}
// Pop the timer from the init() call
if (timer_stack.size() > 0) {
timer_stack.back().stop(tsc_tick_count::now());
timer_stack.pop_back();
}
}
/* ************* kmp_stats_event_vector member functions ************* */
void kmp_stats_event_vector::deallocate() {
__kmp_free(events);
internal_size = 0;
allocated_size = 0;
events = NULL;
}
// This function is for qsort() which requires the compare function to return
// either a negative number if event1 < event2, a positive number if event1 >
// event2 or zero if event1 == event2. This sorts by start time (lowest to
// highest).
int compare_two_events(const void *event1, const void *event2) {
const kmp_stats_event *ev1 = RCAST(const kmp_stats_event *, event1);
const kmp_stats_event *ev2 = RCAST(const kmp_stats_event *, event2);
if (ev1->getStart() < ev2->getStart())
return -1;
else if (ev1->getStart() > ev2->getStart())
return 1;
else
return 0;
}
void kmp_stats_event_vector::sort() {
qsort(events, internal_size, sizeof(kmp_stats_event), compare_two_events);
}
/* ************* kmp_stats_list member functions ************* */
// returns a pointer to newly created stats node
kmp_stats_list *kmp_stats_list::push_back(int gtid) {
kmp_stats_list *newnode =
(kmp_stats_list *)__kmp_allocate(sizeof(kmp_stats_list));
// placement new, only requires space and pointer and initializes (so
// __kmp_allocate instead of C++ new[] is used)
new (newnode) kmp_stats_list();
newnode->setGtid(gtid);
newnode->prev = this->prev;
newnode->next = this;
newnode->prev->next = newnode;
newnode->next->prev = newnode;
return newnode;
}
void kmp_stats_list::deallocate() {
kmp_stats_list *ptr = this->next;
kmp_stats_list *delptr = this->next;
while (ptr != this) {
delptr = ptr;
ptr = ptr->next;
// placement new means we have to explicitly call destructor.
delptr->_event_vector.deallocate();
delptr->~kmp_stats_list();
__kmp_free(delptr);
}
}
kmp_stats_list::iterator kmp_stats_list::begin() {
kmp_stats_list::iterator it;
it.ptr = this->next;
return it;
}
kmp_stats_list::iterator kmp_stats_list::end() {
kmp_stats_list::iterator it;
it.ptr = this;
return it;
}
int kmp_stats_list::size() {
int retval;
kmp_stats_list::iterator it;
for (retval = 0, it = begin(); it != end(); it++, retval++) {
}
return retval;
}
/* ************* kmp_stats_list::iterator member functions ************* */
kmp_stats_list::iterator::iterator() : ptr(NULL) {}
kmp_stats_list::iterator::~iterator() {}
kmp_stats_list::iterator kmp_stats_list::iterator::operator++() {
this->ptr = this->ptr->next;
return *this;
}
kmp_stats_list::iterator kmp_stats_list::iterator::operator++(int dummy) {
this->ptr = this->ptr->next;
return *this;
}
kmp_stats_list::iterator kmp_stats_list::iterator::operator--() {
this->ptr = this->ptr->prev;
return *this;
}
kmp_stats_list::iterator kmp_stats_list::iterator::operator--(int dummy) {
this->ptr = this->ptr->prev;
return *this;
}
bool kmp_stats_list::iterator::operator!=(const kmp_stats_list::iterator &rhs) {
return this->ptr != rhs.ptr;
}
bool kmp_stats_list::iterator::operator==(const kmp_stats_list::iterator &rhs) {
return this->ptr == rhs.ptr;
}
kmp_stats_list *kmp_stats_list::iterator::operator*() const {
return this->ptr;
}
/* ************* kmp_stats_output_module functions ************** */
const char *kmp_stats_output_module::eventsFileName = NULL;
const char *kmp_stats_output_module::plotFileName = NULL;
int kmp_stats_output_module::printPerThreadFlag = 0;
int kmp_stats_output_module::printPerThreadEventsFlag = 0;
static char const *lastName(char *name) {
int l = (int)strlen(name);
for (int i = l - 1; i >= 0; --i) {
if (name[i] == '.')
name[i] = '_';
if (name[i] == '/')
return name + i + 1;
}
return name;
}
/* Read the name of the executable from /proc/self/cmdline */
static char const *getImageName(char *buffer, size_t buflen) {
FILE *f = fopen("/proc/self/cmdline", "r");
buffer[0] = char(0);
if (!f)
return buffer;
// The file contains char(0) delimited words from the commandline.
// This just returns the last filename component of the first word on the
// line.
size_t n = fread(buffer, 1, buflen, f);
if (n == 0) {
fclose(f);
KMP_CHECK_SYSFAIL("fread", 1)
}
fclose(f);
buffer[buflen - 1] = char(0);
return lastName(buffer);
}
static void getTime(char *buffer, size_t buflen, bool underscores = false) {
time_t timer;
time(&timer);
struct tm *tm_info = localtime(&timer);
if (underscores)
strftime(buffer, buflen, "%Y-%m-%d_%H%M%S", tm_info);
else
strftime(buffer, buflen, "%Y-%m-%d %H%M%S", tm_info);
}
/* Generate a stats file name, expanding prototypes */
static std::string generateFilename(char const *prototype,
char const *imageName) {
std::string res;
for (int i = 0; prototype[i] != char(0); i++) {
char ch = prototype[i];
if (ch == '%') {
i++;
if (prototype[i] == char(0))
break;
switch (prototype[i]) {
case 't': // Insert time and date
{
char date[26];
getTime(date, sizeof(date), true);
res += date;
} break;
case 'e': // Insert executable name
res += imageName;
break;
case 'p': // Insert pid
{
std::stringstream ss;
ss << getpid();
res += ss.str();
} break;
default:
res += prototype[i];
break;
}
} else
res += ch;
}
return res;
}
// init() is called very near the beginning of execution time in the constructor
// of __kmp_stats_global_output
void kmp_stats_output_module::init() {
char *statsFileName = getenv("KMP_STATS_FILE");
eventsFileName = getenv("KMP_STATS_EVENTS_FILE");
plotFileName = getenv("KMP_STATS_PLOT_FILE");
char *threadStats = getenv("KMP_STATS_THREADS");
char *threadEvents = getenv("KMP_STATS_EVENTS");
// set the stats output filenames based on environment variables and defaults
if (statsFileName) {
char imageName[1024];
// Process any escapes (e.g., %p, %e, %t) in the name
outputFileName = generateFilename(
statsFileName, getImageName(&imageName[0], sizeof(imageName)));
}
eventsFileName = eventsFileName ? eventsFileName : "events.dat";
plotFileName = plotFileName ? plotFileName : "events.plt";
// set the flags based on environment variables matching: true, on, 1, .true.
// , .t. , yes
printPerThreadFlag = __kmp_str_match_true(threadStats);
printPerThreadEventsFlag = __kmp_str_match_true(threadEvents);
if (printPerThreadEventsFlag) {
// assigns a color to each timer for printing
setupEventColors();
} else {
// will clear flag so that no event will be logged
timeStat::clearEventFlags();
}
}
void kmp_stats_output_module::setupEventColors() {
int i;
int globalColorIndex = 0;
int numGlobalColors = sizeof(globalColorArray) / sizeof(rgb_color);
for (i = 0; i < TIMER_LAST; i++) {
if (timeStat::logEvent((timer_e)i)) {
timerColorInfo[i] = globalColorArray[globalColorIndex];
globalColorIndex = (globalColorIndex + 1) % numGlobalColors;
}
}
}
void kmp_stats_output_module::printTimerStats(FILE *statsOut,
statistic const *theStats,
statistic const *totalStats) {
fprintf(statsOut,
"Timer, SampleCount, Min, "
"Mean, Max, Total, SD\n");
for (timer_e s = timer_e(0); s < TIMER_LAST; s = timer_e(s + 1)) {
statistic const *stat = &theStats[s];
char tag = timeStat::noUnits(s) ? ' ' : 'T';
fprintf(statsOut, "%-35s, %s\n", timeStat::name(s),
stat->format(tag, true).c_str());
}
// Also print the Total_ versions of times.
for (timer_e s = timer_e(0); s < TIMER_LAST; s = timer_e(s + 1)) {
char tag = timeStat::noUnits(s) ? ' ' : 'T';
if (totalStats && !timeStat::noTotal(s))
fprintf(statsOut, "Total_%-29s, %s\n", timeStat::name(s),
totalStats[s].format(tag, true).c_str());
}
// Print histogram of statistics
if (theStats[0].haveHist()) {
fprintf(statsOut, "\nTimer distributions\n");
for (int s = 0; s < TIMER_LAST; s++) {
statistic const *stat = &theStats[s];
if (stat->getCount() != 0) {
char tag = timeStat::noUnits(timer_e(s)) ? ' ' : 'T';
fprintf(statsOut, "%s\n", timeStat::name(timer_e(s)));
fprintf(statsOut, "%s\n", stat->getHist()->format(tag).c_str());
}
}
}
}
void kmp_stats_output_module::printCounterStats(FILE *statsOut,
statistic const *theStats) {
fprintf(statsOut, "Counter, ThreadCount, Min, Mean, "
" Max, Total, SD\n");
for (int s = 0; s < COUNTER_LAST; s++) {
statistic const *stat = &theStats[s];
fprintf(statsOut, "%-25s, %s\n", counter::name(counter_e(s)),
stat->format(' ', true).c_str());
}
// Print histogram of counters
if (theStats[0].haveHist()) {
fprintf(statsOut, "\nCounter distributions\n");
for (int s = 0; s < COUNTER_LAST; s++) {
statistic const *stat = &theStats[s];
if (stat->getCount() != 0) {
fprintf(statsOut, "%s\n", counter::name(counter_e(s)));
fprintf(statsOut, "%s\n", stat->getHist()->format(' ').c_str());
}
}
}
}
void kmp_stats_output_module::printCounters(FILE *statsOut,
counter const *theCounters) {
// We print all the counters even if they are zero.
// That makes it easier to slice them into a spreadsheet if you need to.
fprintf(statsOut, "\nCounter, Count\n");
for (int c = 0; c < COUNTER_LAST; c++) {
counter const *stat = &theCounters[c];
fprintf(statsOut, "%-25s, %s\n", counter::name(counter_e(c)),
formatSI((double)stat->getValue(), 9, ' ').c_str());
}
}
void kmp_stats_output_module::printEvents(FILE *eventsOut,
kmp_stats_event_vector *theEvents,
int gtid) {
// sort by start time before printing
theEvents->sort();
for (int i = 0; i < theEvents->size(); i++) {
kmp_stats_event ev = theEvents->at(i);
rgb_color color = getEventColor(ev.getTimerName());
fprintf(eventsOut, "%d %llu %llu %1.1f rgb(%1.1f,%1.1f,%1.1f) %s\n", gtid,
static_cast<unsigned long long>(ev.getStart()),
static_cast<unsigned long long>(ev.getStop()),
1.2 - (ev.getNestLevel() * 0.2), color.r, color.g, color.b,
timeStat::name(ev.getTimerName()));
}
return;
}
void kmp_stats_output_module::windupExplicitTimers() {
// Wind up any explicit timers. We assume that it's fair at this point to just
// walk all the explicit timers in all threads and say "it's over".
// If the timer wasn't running, this won't record anything anyway.
kmp_stats_list::iterator it;
for (it = __kmp_stats_list->begin(); it != __kmp_stats_list->end(); it++) {
kmp_stats_list *ptr = *it;
ptr->getPartitionedTimers()->windup();
ptr->endLife();
}
}
void kmp_stats_output_module::printPloticusFile() {
int i;
int size = __kmp_stats_list->size();
kmp_safe_raii_file_t plotOut(plotFileName, "w+");
fprintf(plotOut, "#proc page\n"
" pagesize: 15 10\n"
" scale: 1.0\n\n");
fprintf(plotOut,
"#proc getdata\n"
" file: %s\n\n",
eventsFileName);
fprintf(plotOut,
"#proc areadef\n"
" title: OpenMP Sampling Timeline\n"
" titledetails: align=center size=16\n"
" rectangle: 1 1 13 9\n"
" xautorange: datafield=2,3\n"
" yautorange: -1 %d\n\n",
size);
fprintf(plotOut, "#proc xaxis\n"
" stubs: inc\n"
" stubdetails: size=12\n"
" label: Time (ticks)\n"
" labeldetails: size=14\n\n");
fprintf(plotOut,
"#proc yaxis\n"
" stubs: inc 1\n"
" stubrange: 0 %d\n"
" stubdetails: size=12\n"
" label: Thread #\n"
" labeldetails: size=14\n\n",
size - 1);
fprintf(plotOut, "#proc bars\n"
" exactcolorfield: 5\n"
" axis: x\n"
" locfield: 1\n"
" segmentfields: 2 3\n"
" barwidthfield: 4\n\n");
// create legend entries corresponding to the timer color
for (i = 0; i < TIMER_LAST; i++) {
if (timeStat::logEvent((timer_e)i)) {
rgb_color c = getEventColor((timer_e)i);
fprintf(plotOut,
"#proc legendentry\n"
" sampletype: color\n"
" label: %s\n"
" details: rgb(%1.1f,%1.1f,%1.1f)\n\n",
timeStat::name((timer_e)i), c.r, c.g, c.b);
}
}
fprintf(plotOut, "#proc legend\n"
" format: down\n"
" location: max max\n\n");
return;
}
static void outputEnvVariable(FILE *statsOut, char const *name) {
char const *value = getenv(name);
fprintf(statsOut, "# %s = %s\n", name, value ? value : "*unspecified*");
}
/* Print some useful information about
* the date and time this experiment ran.
* the machine on which it ran.
We output all of this as stylised comments, though we may decide to parse
some of it. */
void kmp_stats_output_module::printHeaderInfo(FILE *statsOut) {
std::time_t now = std::time(0);
char buffer[40];
char hostName[80];
std::strftime(&buffer[0], sizeof(buffer), "%c", std::localtime(&now));
fprintf(statsOut, "# Time of run: %s\n", &buffer[0]);
if (gethostname(&hostName[0], sizeof(hostName)) == 0)
fprintf(statsOut, "# Hostname: %s\n", &hostName[0]);
#if KMP_ARCH_X86 || KMP_ARCH_X86_64
fprintf(statsOut, "# CPU: %s\n", &__kmp_cpuinfo.name[0]);
fprintf(statsOut, "# Family: %d, Model: %d, Stepping: %d\n",
__kmp_cpuinfo.family, __kmp_cpuinfo.model, __kmp_cpuinfo.stepping);
if (__kmp_cpuinfo.frequency == 0)
fprintf(statsOut, "# Nominal frequency: Unknown\n");
else
fprintf(statsOut, "# Nominal frequency: %sz\n",
formatSI(double(__kmp_cpuinfo.frequency), 9, 'H').c_str());
outputEnvVariable(statsOut, "KMP_HW_SUBSET");
outputEnvVariable(statsOut, "KMP_AFFINITY");
outputEnvVariable(statsOut, "KMP_BLOCKTIME");
outputEnvVariable(statsOut, "KMP_LIBRARY");
fprintf(statsOut, "# Production runtime built " __DATE__ " " __TIME__ "\n");
#endif
}
void kmp_stats_output_module::outputStats(const char *heading) {
// Stop all the explicit timers in all threads
// Do this before declaring the local statistics because thay have
// constructors so will take time to create.
windupExplicitTimers();
statistic allStats[TIMER_LAST];
statistic totalStats[TIMER_LAST]; /* Synthesized, cross threads versions of
normal timer stats */
statistic allCounters[COUNTER_LAST];
kmp_safe_raii_file_t statsOut;
if (!outputFileName.empty()) {
statsOut.open(outputFileName.c_str(), "a+");
} else {
statsOut.set_stderr();
}
kmp_safe_raii_file_t eventsOut;
if (eventPrintingEnabled()) {
eventsOut.open(eventsFileName, "w+");
}
printHeaderInfo(statsOut);
fprintf(statsOut, "%s\n", heading);
// Accumulate across threads.
kmp_stats_list::iterator it;
for (it = __kmp_stats_list->begin(); it != __kmp_stats_list->end(); it++) {
int t = (*it)->getGtid();
// Output per thread stats if requested.
if (printPerThreadFlag) {
fprintf(statsOut, "Thread %d\n", t);
printTimerStats(statsOut, (*it)->getTimers(), 0);
printCounters(statsOut, (*it)->getCounters());
fprintf(statsOut, "\n");
}
// Output per thread events if requested.
if (eventPrintingEnabled()) {
kmp_stats_event_vector events = (*it)->getEventVector();
printEvents(eventsOut, &events, t);
}
// Accumulate timers.
for (timer_e s = timer_e(0); s < TIMER_LAST; s = timer_e(s + 1)) {
// See if we should ignore this timer when aggregating
if ((timeStat::masterOnly(s) && (t != 0)) || // Timer only valid on
// primary thread and this thread is worker
(timeStat::workerOnly(s) && (t == 0)) // Timer only valid on worker
// and this thread is the primary thread
) {
continue;
}
statistic *threadStat = (*it)->getTimer(s);
allStats[s] += *threadStat;
// Add Total stats for timers that are valid in more than one thread
if (!timeStat::noTotal(s))
totalStats[s].addSample(threadStat->getTotal());
}
// Accumulate counters.
for (counter_e c = counter_e(0); c < COUNTER_LAST; c = counter_e(c + 1)) {
if (counter::masterOnly(c) && t != 0)
continue;
allCounters[c].addSample((double)(*it)->getCounter(c)->getValue());
}
}
if (eventPrintingEnabled()) {
printPloticusFile();
}
fprintf(statsOut, "Aggregate for all threads\n");
printTimerStats(statsOut, &allStats[0], &totalStats[0]);
fprintf(statsOut, "\n");
printCounterStats(statsOut, &allCounters[0]);
}
/* ************* exported C functions ************** */
// no name mangling for these functions, we want the c files to be able to get
// at these functions
extern "C" {
void __kmp_reset_stats() {
kmp_stats_list::iterator it;
for (it = __kmp_stats_list->begin(); it != __kmp_stats_list->end(); it++) {
timeStat *timers = (*it)->getTimers();
counter *counters = (*it)->getCounters();
for (int t = 0; t < TIMER_LAST; t++)
timers[t].reset();
for (int c = 0; c < COUNTER_LAST; c++)
counters[c].reset();
// reset the event vector so all previous events are "erased"
(*it)->resetEventVector();
}
}
// This function will reset all stats and stop all threads' explicit timers if
// they haven't been stopped already.
void __kmp_output_stats(const char *heading) {
__kmp_stats_global_output->outputStats(heading);
__kmp_reset_stats();
}
void __kmp_accumulate_stats_at_exit(void) {
// Only do this once.
if (KMP_XCHG_FIXED32(&statsPrinted, 1) != 0)
return;
__kmp_output_stats("Statistics on exit");
}
void __kmp_stats_init(void) {
__kmp_init_tas_lock(&__kmp_stats_lock);
__kmp_stats_start_time = tsc_tick_count::now();
__kmp_stats_global_output = new kmp_stats_output_module();
__kmp_stats_list = new kmp_stats_list();
}
void __kmp_stats_fini(void) {
__kmp_accumulate_stats_at_exit();
__kmp_stats_list->deallocate();
delete __kmp_stats_global_output;
delete __kmp_stats_list;
}
} // extern "C"
#endif // LIBOMP_STATS

1021
third_party/openmp/kmp_stats.h vendored Normal file

File diff suppressed because it is too large Load diff

130
third_party/openmp/kmp_stats_timing.cpp vendored Normal file
View file

@ -0,0 +1,130 @@
/** @file kmp_stats_timing.cpp
* Timing functions
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include <stdlib.h>
#include <unistd.h>
#include <iomanip>
#include <iostream>
#include <sstream>
#include "kmp.h"
#include "kmp_stats_timing.h"
using namespace std;
#if KMP_HAVE_TICK_TIME
#if KMP_MIC
double tsc_tick_count::tick_time() {
// pretty bad assumption of 1GHz clock for MIC
return 1 / ((double)1000 * 1.e6);
}
#elif KMP_ARCH_X86 || KMP_ARCH_X86_64
#include <string.h>
// Extract the value from the CPUID information
double tsc_tick_count::tick_time() {
static double result = 0.0;
if (result == 0.0) {
kmp_cpuid_t cpuinfo;
char brand[256];
__kmp_x86_cpuid(0x80000000, 0, &cpuinfo);
memset(brand, 0, sizeof(brand));
int ids = cpuinfo.eax;
for (unsigned int i = 2; i < (ids ^ 0x80000000) + 2; i++)
__kmp_x86_cpuid(i | 0x80000000, 0,
(kmp_cpuid_t *)(brand + (i - 2) * sizeof(kmp_cpuid_t)));
char *start = &brand[0];
for (; *start == ' '; start++)
;
char *end = brand + KMP_STRLEN(brand) - 3;
uint64_t multiplier;
if (*end == 'M')
multiplier = 1000LL * 1000LL;
else if (*end == 'G')
multiplier = 1000LL * 1000LL * 1000LL;
else if (*end == 'T')
multiplier = 1000LL * 1000LL * 1000LL * 1000LL;
else {
cout << "Error determining multiplier '" << *end << "'\n";
exit(-1);
}
*end = 0;
while (*end != ' ')
end--;
end++;
double freq = strtod(end, &start);
if (freq == 0.0) {
cout << "Error calculating frequency " << end << "\n";
exit(-1);
}
result = ((double)1.0) / (freq * multiplier);
}
return result;
}
#endif
#endif
static bool useSI = true;
// Return a formatted string after normalising the value into
// engineering style and using a suitable unit prefix (e.g. ms, us, ns).
std::string formatSI(double interval, int width, char unit) {
std::stringstream os;
if (useSI) {
// Preserve accuracy for small numbers, since we only multiply and the
// positive powers of ten are precisely representable.
static struct {
double scale;
char prefix;
} ranges[] = {{1.e21, 'y'}, {1.e18, 'z'}, {1.e15, 'a'}, {1.e12, 'f'},
{1.e9, 'p'}, {1.e6, 'n'}, {1.e3, 'u'}, {1.0, 'm'},
{1.e-3, ' '}, {1.e-6, 'k'}, {1.e-9, 'M'}, {1.e-12, 'G'},
{1.e-15, 'T'}, {1.e-18, 'P'}, {1.e-21, 'E'}, {1.e-24, 'Z'},
{1.e-27, 'Y'}};
if (interval == 0.0) {
os << std::setw(width - 3) << std::right << "0.00" << std::setw(3)
<< unit;
return os.str();
}
bool negative = false;
if (interval < 0.0) {
negative = true;
interval = -interval;
}
for (int i = 0; i < (int)(sizeof(ranges) / sizeof(ranges[0])); i++) {
if (interval * ranges[i].scale < 1.e0) {
interval = interval * 1000.e0 * ranges[i].scale;
os << std::fixed << std::setprecision(2) << std::setw(width - 3)
<< std::right << (negative ? -interval : interval) << std::setw(2)
<< ranges[i].prefix << std::setw(1) << unit;
return os.str();
}
}
}
os << std::setprecision(2) << std::fixed << std::right << std::setw(width - 3)
<< interval << std::setw(3) << unit;
return os.str();
}

116
third_party/openmp/kmp_stats_timing.h vendored Normal file
View file

@ -0,0 +1,116 @@
#ifndef KMP_STATS_TIMING_H
#define KMP_STATS_TIMING_H
/** @file kmp_stats_timing.h
* Access to real time clock and timers.
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "kmp_os.h"
#include <limits>
#include <stdint.h>
#include <string>
#if KMP_HAVE_X86INTRIN_H
#include <x86intrin.h>
#endif
#include "libc/nexgen32e/rdtsc.h"
class tsc_tick_count {
private:
int64_t my_count;
public:
class tsc_interval_t {
int64_t value;
explicit tsc_interval_t(int64_t _value) : value(_value) {}
public:
tsc_interval_t() : value(0) {} // Construct 0 time duration
#if KMP_HAVE_TICK_TIME
double seconds() const; // Return the length of a time interval in seconds
#endif
double ticks() const { return double(value); }
int64_t getValue() const { return value; }
tsc_interval_t &operator=(int64_t nvalue) {
value = nvalue;
return *this;
}
friend class tsc_tick_count;
friend tsc_interval_t operator-(const tsc_tick_count &t1,
const tsc_tick_count &t0);
friend tsc_interval_t operator-(const tsc_tick_count::tsc_interval_t &i1,
const tsc_tick_count::tsc_interval_t &i0);
friend tsc_interval_t &operator+=(tsc_tick_count::tsc_interval_t &i1,
const tsc_tick_count::tsc_interval_t &i0);
};
#if KMP_HAVE___BUILTIN_READCYCLECOUNTER
tsc_tick_count()
: my_count(static_cast<int64_t>(__builtin_readcyclecounter())) {}
#elif KMP_HAVE___RDTSC
tsc_tick_count() : my_count(static_cast<int64_t>(rdtsc())) {}
#else
#error Must have high resolution timer defined
#endif
tsc_tick_count(int64_t value) : my_count(value) {}
int64_t getValue() const { return my_count; }
tsc_tick_count later(tsc_tick_count const other) const {
return my_count > other.my_count ? (*this) : other;
}
tsc_tick_count earlier(tsc_tick_count const other) const {
return my_count < other.my_count ? (*this) : other;
}
#if KMP_HAVE_TICK_TIME
static double tick_time(); // returns seconds per cycle (period) of clock
#endif
static tsc_tick_count now() {
return tsc_tick_count();
} // returns the rdtsc register value
friend tsc_tick_count::tsc_interval_t operator-(const tsc_tick_count &t1,
const tsc_tick_count &t0);
};
inline tsc_tick_count::tsc_interval_t operator-(const tsc_tick_count &t1,
const tsc_tick_count &t0) {
return tsc_tick_count::tsc_interval_t(t1.my_count - t0.my_count);
}
inline tsc_tick_count::tsc_interval_t
operator-(const tsc_tick_count::tsc_interval_t &i1,
const tsc_tick_count::tsc_interval_t &i0) {
return tsc_tick_count::tsc_interval_t(i1.value - i0.value);
}
inline tsc_tick_count::tsc_interval_t &
operator+=(tsc_tick_count::tsc_interval_t &i1,
const tsc_tick_count::tsc_interval_t &i0) {
i1.value += i0.value;
return i1;
}
#if KMP_HAVE_TICK_TIME
inline double tsc_tick_count::tsc_interval_t::seconds() const {
return value * tick_time();
}
#endif
extern std::string formatSI(double interval, int width, char unit);
inline std::string formatSeconds(double interval, int width) {
return formatSI(interval, width, 'S');
}
inline std::string formatTicks(double interval, int width) {
return formatSI(interval, width, 'T');
}
#endif // KMP_STATS_TIMING_H

840
third_party/openmp/kmp_str.cpp vendored Normal file
View file

@ -0,0 +1,840 @@
/*
* kmp_str.cpp -- String manipulation routines.
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "kmp_str.h"
#include <stdarg.h> // va_*
#include <stdio.h> // vsnprintf()
#include <stdlib.h> // malloc(), realloc()
#include "kmp.h"
#include "kmp_i18n.h"
/* String buffer.
Usage:
// Declare buffer and initialize it.
kmp_str_buf_t buffer;
__kmp_str_buf_init( & buffer );
// Print to buffer.
__kmp_str_buf_print(& buffer, "Error in file \"%s\" line %d\n", "foo.c", 12);
__kmp_str_buf_print(& buffer, " <%s>\n", line);
// Use buffer contents. buffer.str is a pointer to data, buffer.used is a
// number of printed characters (not including terminating zero).
write( fd, buffer.str, buffer.used );
// Free buffer.
__kmp_str_buf_free( & buffer );
// Alternatively, you can detach allocated memory from buffer:
__kmp_str_buf_detach( & buffer );
return buffer.str; // That memory should be freed eventually.
Notes:
* Buffer users may use buffer.str and buffer.used. Users should not change
any fields of buffer directly.
* buffer.str is never NULL. If buffer is empty, buffer.str points to empty
string ("").
* For performance reasons, buffer uses stack memory (buffer.bulk) first. If
stack memory is exhausted, buffer allocates memory on heap by malloc(), and
reallocates it by realloc() as amount of used memory grows.
* Buffer doubles amount of allocated memory each time it is exhausted.
*/
// TODO: __kmp_str_buf_print() can use thread local memory allocator.
#define KMP_STR_BUF_INVARIANT(b) \
{ \
KMP_DEBUG_ASSERT((b)->str != NULL); \
KMP_DEBUG_ASSERT((b)->size >= sizeof((b)->bulk)); \
KMP_DEBUG_ASSERT((b)->size % sizeof((b)->bulk) == 0); \
KMP_DEBUG_ASSERT((unsigned)(b)->used < (b)->size); \
KMP_DEBUG_ASSERT( \
(b)->size == sizeof((b)->bulk) ? (b)->str == &(b)->bulk[0] : 1); \
KMP_DEBUG_ASSERT((b)->size > sizeof((b)->bulk) ? (b)->str != &(b)->bulk[0] \
: 1); \
}
void __kmp_str_buf_clear(kmp_str_buf_t *buffer) {
KMP_STR_BUF_INVARIANT(buffer);
if (buffer->used > 0) {
buffer->used = 0;
buffer->str[0] = 0;
}
KMP_STR_BUF_INVARIANT(buffer);
} // __kmp_str_buf_clear
void __kmp_str_buf_reserve(kmp_str_buf_t *buffer, size_t size) {
KMP_STR_BUF_INVARIANT(buffer);
KMP_DEBUG_ASSERT(size >= 0);
if (buffer->size < (unsigned int)size) {
// Calculate buffer size.
do {
buffer->size *= 2;
} while (buffer->size < (unsigned int)size);
// Enlarge buffer.
if (buffer->str == &buffer->bulk[0]) {
buffer->str = (char *)KMP_INTERNAL_MALLOC(buffer->size);
if (buffer->str == NULL) {
KMP_FATAL(MemoryAllocFailed);
}
KMP_MEMCPY_S(buffer->str, buffer->size, buffer->bulk, buffer->used + 1);
} else {
buffer->str = (char *)KMP_INTERNAL_REALLOC(buffer->str, buffer->size);
if (buffer->str == NULL) {
KMP_FATAL(MemoryAllocFailed);
}
}
}
KMP_DEBUG_ASSERT(buffer->size > 0);
KMP_DEBUG_ASSERT(buffer->size >= (unsigned)size);
KMP_STR_BUF_INVARIANT(buffer);
} // __kmp_str_buf_reserve
void __kmp_str_buf_detach(kmp_str_buf_t *buffer) {
KMP_STR_BUF_INVARIANT(buffer);
// If internal bulk is used, allocate memory and copy it.
if (buffer->size <= sizeof(buffer->bulk)) {
buffer->str = (char *)KMP_INTERNAL_MALLOC(buffer->size);
if (buffer->str == NULL) {
KMP_FATAL(MemoryAllocFailed);
}
KMP_MEMCPY_S(buffer->str, buffer->size, buffer->bulk, buffer->used + 1);
}
} // __kmp_str_buf_detach
void __kmp_str_buf_free(kmp_str_buf_t *buffer) {
KMP_STR_BUF_INVARIANT(buffer);
if (buffer->size > sizeof(buffer->bulk)) {
KMP_INTERNAL_FREE(buffer->str);
}
buffer->str = buffer->bulk;
buffer->size = sizeof(buffer->bulk);
buffer->used = 0;
KMP_STR_BUF_INVARIANT(buffer);
} // __kmp_str_buf_free
void __kmp_str_buf_cat(kmp_str_buf_t *buffer, char const *str, size_t len) {
KMP_STR_BUF_INVARIANT(buffer);
KMP_DEBUG_ASSERT(str != NULL);
KMP_DEBUG_ASSERT(len >= 0);
__kmp_str_buf_reserve(buffer, buffer->used + len + 1);
buffer->str[buffer->used] = '\0';
KMP_STRNCAT_S(buffer->str + buffer->used, len + 1, str, len);
__kmp_type_convert(buffer->used + len, &(buffer->used));
KMP_STR_BUF_INVARIANT(buffer);
} // __kmp_str_buf_cat
void __kmp_str_buf_catbuf(kmp_str_buf_t *dest, const kmp_str_buf_t *src) {
KMP_DEBUG_ASSERT(dest);
KMP_DEBUG_ASSERT(src);
KMP_STR_BUF_INVARIANT(dest);
KMP_STR_BUF_INVARIANT(src);
if (!src->str || !src->used)
return;
__kmp_str_buf_reserve(dest, dest->used + src->used + 1);
dest->str[dest->used] = '\0';
KMP_STRNCAT_S(dest->str + dest->used, src->used + 1, src->str, src->used);
dest->used += src->used;
KMP_STR_BUF_INVARIANT(dest);
} // __kmp_str_buf_catbuf
// Return the number of characters written
int __kmp_str_buf_vprint(kmp_str_buf_t *buffer, char const *format,
va_list args) {
int rc;
KMP_STR_BUF_INVARIANT(buffer);
for (;;) {
int const free = buffer->size - buffer->used;
int size;
// Try to format string.
{
/* On Linux* OS Intel(R) 64, vsnprintf() modifies args argument, so
vsnprintf() crashes if it is called for the second time with the same
args. To prevent the crash, we have to pass a fresh intact copy of args
to vsnprintf() on each iteration.
Unfortunately, standard va_copy() macro is not available on Windows*
OS. However, it seems vsnprintf() does not modify args argument on
Windows* OS.
*/
#if !KMP_OS_WINDOWS
va_list _args;
va_copy(_args, args); // Make copy of args.
#define args _args // Substitute args with its copy, _args.
#endif // KMP_OS_WINDOWS
rc = KMP_VSNPRINTF(buffer->str + buffer->used, free, format, args);
#if !KMP_OS_WINDOWS
#undef args // Remove substitution.
va_end(_args);
#endif // KMP_OS_WINDOWS
}
// No errors, string has been formatted.
if (rc >= 0 && rc < free) {
buffer->used += rc;
break;
}
// Error occurred, buffer is too small.
if (rc >= 0) {
// C99-conforming implementation of vsnprintf returns required buffer size
size = buffer->used + rc + 1;
} else {
// Older implementations just return -1. Double buffer size.
size = buffer->size * 2;
}
// Enlarge buffer.
__kmp_str_buf_reserve(buffer, size);
// And try again.
}
KMP_DEBUG_ASSERT(buffer->size > 0);
KMP_STR_BUF_INVARIANT(buffer);
return rc;
} // __kmp_str_buf_vprint
// Return the number of characters written
int __kmp_str_buf_print(kmp_str_buf_t *buffer, char const *format, ...) {
int rc;
va_list args;
va_start(args, format);
rc = __kmp_str_buf_vprint(buffer, format, args);
va_end(args);
return rc;
} // __kmp_str_buf_print
/* The function prints specified size to buffer. Size is expressed using biggest
possible unit, for example 1024 is printed as "1k". */
void __kmp_str_buf_print_size(kmp_str_buf_t *buf, size_t size) {
char const *names[] = {"", "k", "M", "G", "T", "P", "E", "Z", "Y"};
int const units = sizeof(names) / sizeof(char const *);
int u = 0;
if (size > 0) {
while ((size % 1024 == 0) && (u + 1 < units)) {
size = size / 1024;
++u;
}
}
__kmp_str_buf_print(buf, "%" KMP_SIZE_T_SPEC "%s", size, names[u]);
} // __kmp_str_buf_print_size
void __kmp_str_fname_init(kmp_str_fname_t *fname, char const *path) {
fname->path = NULL;
fname->dir = NULL;
fname->base = NULL;
if (path != NULL) {
char *slash = NULL; // Pointer to the last character of dir.
char *base = NULL; // Pointer to the beginning of basename.
fname->path = __kmp_str_format("%s", path);
// Original code used strdup() function to copy a string, but on Windows* OS
// Intel(R) 64 it causes assertion id debug heap, so I had to replace
// strdup with __kmp_str_format().
if (KMP_OS_WINDOWS) {
__kmp_str_replace(fname->path, '\\', '/');
}
fname->dir = __kmp_str_format("%s", fname->path);
slash = strrchr(fname->dir, '/');
if (KMP_OS_WINDOWS &&
slash == NULL) { // On Windows* OS, if slash not found,
char first = (char)TOLOWER(fname->dir[0]); // look for drive.
if ('a' <= first && first <= 'z' && fname->dir[1] == ':') {
slash = &fname->dir[1];
}
}
base = (slash == NULL ? fname->dir : slash + 1);
fname->base = __kmp_str_format("%s", base); // Copy basename
*base = 0; // and truncate dir.
}
} // kmp_str_fname_init
void __kmp_str_fname_free(kmp_str_fname_t *fname) {
__kmp_str_free(&fname->path);
__kmp_str_free(&fname->dir);
__kmp_str_free(&fname->base);
} // kmp_str_fname_free
int __kmp_str_fname_match(kmp_str_fname_t const *fname, char const *pattern) {
int dir_match = 1;
int base_match = 1;
if (pattern != NULL) {
kmp_str_fname_t ptrn;
__kmp_str_fname_init(&ptrn, pattern);
dir_match = strcmp(ptrn.dir, "*/") == 0 ||
(fname->dir != NULL && __kmp_str_eqf(fname->dir, ptrn.dir));
base_match = strcmp(ptrn.base, "*") == 0 ||
(fname->base != NULL && __kmp_str_eqf(fname->base, ptrn.base));
__kmp_str_fname_free(&ptrn);
}
return dir_match && base_match;
} // __kmp_str_fname_match
// Get the numeric fields from source location string.
// For clang these fields are Line/Col of the start of the construct.
// For icc these are LineBegin/LineEnd of the construct.
// Function is fast as it does not duplicate string (which involves memory
// allocation), and parses the string in place.
void __kmp_str_loc_numbers(char const *Psource, int *LineBeg,
int *LineEndOrCol) {
char *Str;
KMP_DEBUG_ASSERT(LineBeg);
KMP_DEBUG_ASSERT(LineEndOrCol);
// Parse Psource string ";file;func;line;line_end_or_column;;" to get
// numbers only, skipping string fields "file" and "func".
// Find 1-st semicolon.
KMP_DEBUG_ASSERT(Psource);
#ifdef __cplusplus
Str = strchr(CCAST(char *, Psource), ';');
#else
Str = strchr(Psource, ';');
#endif
// Check returned pointer to see if the format of Psource is broken.
if (Str) {
// Find 2-nd semicolon.
Str = strchr(Str + 1, ';');
}
if (Str) {
// Find 3-rd semicolon.
Str = strchr(Str + 1, ';');
}
if (Str) {
// Read begin line number.
*LineBeg = atoi(Str + 1);
// Find 4-th semicolon.
Str = strchr(Str + 1, ';');
} else {
// Broken format of input string, cannot read the number.
*LineBeg = 0;
}
if (Str) {
// Read end line or column number.
*LineEndOrCol = atoi(Str + 1);
} else {
// Broken format of input string, cannot read the number.
*LineEndOrCol = 0;
}
}
kmp_str_loc_t __kmp_str_loc_init(char const *psource, bool init_fname) {
kmp_str_loc_t loc;
loc._bulk = NULL;
loc.file = NULL;
loc.func = NULL;
loc.line = 0;
loc.col = 0;
if (psource != NULL) {
char *str = NULL;
char *dummy = NULL;
char *line = NULL;
char *col = NULL;
// Copy psource to keep it intact.
loc._bulk = __kmp_str_format("%s", psource);
// Parse psource string: ";file;func;line;col;;"
str = loc._bulk;
__kmp_str_split(str, ';', &dummy, &str);
__kmp_str_split(str, ';', &loc.file, &str);
__kmp_str_split(str, ';', &loc.func, &str);
__kmp_str_split(str, ';', &line, &str);
__kmp_str_split(str, ';', &col, &str);
// Convert line and col into numberic values.
if (line != NULL) {
loc.line = atoi(line);
if (loc.line < 0) {
loc.line = 0;
}
}
if (col != NULL) {
loc.col = atoi(col);
if (loc.col < 0) {
loc.col = 0;
}
}
}
__kmp_str_fname_init(&loc.fname, init_fname ? loc.file : NULL);
return loc;
} // kmp_str_loc_init
void __kmp_str_loc_free(kmp_str_loc_t *loc) {
__kmp_str_fname_free(&loc->fname);
__kmp_str_free(&(loc->_bulk));
loc->file = NULL;
loc->func = NULL;
} // kmp_str_loc_free
/* This function is intended to compare file names. On Windows* OS file names
are case-insensitive, so functions performs case-insensitive comparison. On
Linux* OS it performs case-sensitive comparison. Note: The function returns
*true* if strings are *equal*. */
int __kmp_str_eqf( // True, if strings are equal, false otherwise.
char const *lhs, // First string.
char const *rhs // Second string.
) {
int result;
#if KMP_OS_WINDOWS
result = (_stricmp(lhs, rhs) == 0);
#else
result = (strcmp(lhs, rhs) == 0);
#endif
return result;
} // __kmp_str_eqf
/* This function is like sprintf, but it *allocates* new buffer, which must be
freed eventually by __kmp_str_free(). The function is very convenient for
constructing strings, it successfully replaces strdup(), strcat(), it frees
programmer from buffer allocations and helps to avoid buffer overflows.
Examples:
str = __kmp_str_format("%s", orig); //strdup() doesn't care about buffer size
__kmp_str_free( & str );
str = __kmp_str_format( "%s%s", orig1, orig2 ); // strcat(), doesn't care
// about buffer size.
__kmp_str_free( & str );
str = __kmp_str_format( "%s/%s.txt", path, file ); // constructing string.
__kmp_str_free( & str );
Performance note:
This function allocates memory with malloc() calls, so do not call it from
performance-critical code. In performance-critical code consider using
kmp_str_buf_t instead, since it uses stack-allocated buffer for short
strings.
Why does this function use malloc()?
1. __kmp_allocate() returns cache-aligned memory allocated with malloc().
There are no reasons in using __kmp_allocate() for strings due to extra
overhead while cache-aligned memory is not necessary.
2. __kmp_thread_malloc() cannot be used because it requires pointer to thread
structure. We need to perform string operations during library startup
(for example, in __kmp_register_library_startup()) when no thread
structures are allocated yet.
So standard malloc() is the only available option.
*/
char *__kmp_str_format( // Allocated string.
char const *format, // Format string.
... // Other parameters.
) {
va_list args;
int size = 512;
char *buffer = NULL;
int rc;
// Allocate buffer.
buffer = (char *)KMP_INTERNAL_MALLOC(size);
if (buffer == NULL) {
KMP_FATAL(MemoryAllocFailed);
}
for (;;) {
// Try to format string.
va_start(args, format);
rc = KMP_VSNPRINTF(buffer, size, format, args);
va_end(args);
// No errors, string has been formatted.
if (rc >= 0 && rc < size) {
break;
}
// Error occurred, buffer is too small.
if (rc >= 0) {
// C99-conforming implementation of vsnprintf returns required buffer
// size.
size = rc + 1;
} else {
// Older implementations just return -1.
size = size * 2;
}
// Enlarge buffer and try again.
buffer = (char *)KMP_INTERNAL_REALLOC(buffer, size);
if (buffer == NULL) {
KMP_FATAL(MemoryAllocFailed);
}
}
return buffer;
} // func __kmp_str_format
void __kmp_str_free(char **str) {
KMP_DEBUG_ASSERT(str != NULL);
KMP_INTERNAL_FREE(*str);
*str = NULL;
} // func __kmp_str_free
/* If len is zero, returns true iff target and data have exact case-insensitive
match. If len is negative, returns true iff target is a case-insensitive
substring of data. If len is positive, returns true iff target is a
case-insensitive substring of data or vice versa, and neither is shorter than
len. */
int __kmp_str_match(char const *target, int len, char const *data) {
int i;
if (target == NULL || data == NULL) {
return FALSE;
}
for (i = 0; target[i] && data[i]; ++i) {
if (TOLOWER(target[i]) != TOLOWER(data[i])) {
return FALSE;
}
}
return ((len > 0) ? i >= len : (!target[i] && (len || !data[i])));
} // __kmp_str_match
// If data contains all of target, returns true, otherwise returns false.
// len should be the length of target
bool __kmp_str_contains(char const *target, int len, char const *data) {
int i = 0, j = 0, start = 0;
if (target == NULL || data == NULL) {
return FALSE;
}
while (target[i]) {
if (!data[j])
return FALSE;
if (TOLOWER(target[i]) != TOLOWER(data[j])) {
j = start + 1;
start = j;
i = 0;
} else {
if (i == 0)
start = j;
j++;
i++;
}
}
return i == len;
} // __kmp_str_contains
int __kmp_str_match_false(char const *data) {
int result =
__kmp_str_match("false", 1, data) || __kmp_str_match("off", 2, data) ||
__kmp_str_match("0", 1, data) || __kmp_str_match(".false.", 2, data) ||
__kmp_str_match(".f.", 2, data) || __kmp_str_match("no", 1, data) ||
__kmp_str_match("disabled", 0, data);
return result;
} // __kmp_str_match_false
int __kmp_str_match_true(char const *data) {
int result =
__kmp_str_match("true", 1, data) || __kmp_str_match("on", 2, data) ||
__kmp_str_match("1", 1, data) || __kmp_str_match(".true.", 2, data) ||
__kmp_str_match(".t.", 2, data) || __kmp_str_match("yes", 1, data) ||
__kmp_str_match("enabled", 0, data);
return result;
} // __kmp_str_match_true
void __kmp_str_replace(char *str, char search_for, char replace_with) {
char *found = NULL;
found = strchr(str, search_for);
while (found) {
*found = replace_with;
found = strchr(found + 1, search_for);
}
} // __kmp_str_replace
void __kmp_str_split(char *str, // I: String to split.
char delim, // I: Character to split on.
char **head, // O: Pointer to head (may be NULL).
char **tail // O: Pointer to tail (may be NULL).
) {
char *h = str;
char *t = NULL;
if (str != NULL) {
char *ptr = strchr(str, delim);
if (ptr != NULL) {
*ptr = 0;
t = ptr + 1;
}
}
if (head != NULL) {
*head = h;
}
if (tail != NULL) {
*tail = t;
}
} // __kmp_str_split
/* strtok_r() is not available on Windows* OS. This function reimplements
strtok_r(). */
char *__kmp_str_token(
char *str, // String to split into tokens. Note: String *is* modified!
char const *delim, // Delimiters.
char **buf // Internal buffer.
) {
char *token = NULL;
#if KMP_OS_WINDOWS
// On Windows* OS there is no strtok_r() function. Let us implement it.
if (str != NULL) {
*buf = str; // First call, initialize buf.
}
*buf += strspn(*buf, delim); // Skip leading delimiters.
if (**buf != 0) { // Rest of the string is not yet empty.
token = *buf; // Use it as result.
*buf += strcspn(*buf, delim); // Skip non-delimiters.
if (**buf != 0) { // Rest of the string is not yet empty.
**buf = 0; // Terminate token here.
*buf += 1; // Advance buf to start with the next token next time.
}
}
#else
// On Linux* OS and OS X*, strtok_r() is available. Let us use it.
token = strtok_r(str, delim, buf);
#endif
return token;
} // __kmp_str_token
int __kmp_basic_str_to_int(char const *str) {
int result;
char const *t;
result = 0;
for (t = str; *t != '\0'; ++t) {
if (*t < '0' || *t > '9')
break;
result = (result * 10) + (*t - '0');
}
return result;
}
int __kmp_str_to_int(char const *str, char sentinel) {
int result, factor;
char const *t;
result = 0;
for (t = str; *t != '\0'; ++t) {
if (*t < '0' || *t > '9')
break;
result = (result * 10) + (*t - '0');
}
switch (*t) {
case '\0': /* the current default for no suffix is bytes */
factor = 1;
break;
case 'b':
case 'B': /* bytes */
++t;
factor = 1;
break;
case 'k':
case 'K': /* kilo-bytes */
++t;
factor = 1024;
break;
case 'm':
case 'M': /* mega-bytes */
++t;
factor = (1024 * 1024);
break;
default:
if (*t != sentinel)
return (-1);
t = "";
factor = 1;
}
if (result > (INT_MAX / factor))
result = INT_MAX;
else
result *= factor;
return (*t != 0 ? 0 : result);
} // __kmp_str_to_int
/* The routine parses input string. It is expected it is a unsigned integer with
optional unit. Units are: "b" for bytes, "kb" or just "k" for kilobytes, "mb"
or "m" for megabytes, ..., "yb" or "y" for yottabytes. :-) Unit name is
case-insensitive. The routine returns 0 if everything is ok, or error code:
-1 in case of overflow, -2 in case of unknown unit. *size is set to parsed
value. In case of overflow *size is set to KMP_SIZE_T_MAX, in case of unknown
unit *size is set to zero. */
void __kmp_str_to_size( // R: Error code.
char const *str, // I: String of characters, unsigned number and unit ("b",
// "kb", etc).
size_t *out, // O: Parsed number.
size_t dfactor, // I: The factor if none of the letters specified.
char const **error // O: Null if everything is ok, error message otherwise.
) {
size_t value = 0;
size_t factor = 0;
int overflow = 0;
int i = 0;
int digit;
KMP_DEBUG_ASSERT(str != NULL);
// Skip spaces.
while (str[i] == ' ' || str[i] == '\t') {
++i;
}
// Parse number.
if (str[i] < '0' || str[i] > '9') {
*error = KMP_I18N_STR(NotANumber);
return;
}
do {
digit = str[i] - '0';
overflow = overflow || (value > (KMP_SIZE_T_MAX - digit) / 10);
value = (value * 10) + digit;
++i;
} while (str[i] >= '0' && str[i] <= '9');
// Skip spaces.
while (str[i] == ' ' || str[i] == '\t') {
++i;
}
// Parse unit.
#define _case(ch, exp) \
case ch: \
case ch - ('a' - 'A'): { \
size_t shift = (exp)*10; \
++i; \
if (shift < sizeof(size_t) * 8) { \
factor = (size_t)(1) << shift; \
} else { \
overflow = 1; \
} \
} break;
switch (str[i]) {
_case('k', 1); // Kilo
_case('m', 2); // Mega
_case('g', 3); // Giga
_case('t', 4); // Tera
_case('p', 5); // Peta
_case('e', 6); // Exa
_case('z', 7); // Zetta
_case('y', 8); // Yotta
// Oops. No more units...
}
#undef _case
if (str[i] == 'b' || str[i] == 'B') { // Skip optional "b".
if (factor == 0) {
factor = 1;
}
++i;
}
if (!(str[i] == ' ' || str[i] == '\t' || str[i] == 0)) { // Bad unit
*error = KMP_I18N_STR(BadUnit);
return;
}
if (factor == 0) {
factor = dfactor;
}
// Apply factor.
overflow = overflow || (value > (KMP_SIZE_T_MAX / factor));
value *= factor;
// Skip spaces.
while (str[i] == ' ' || str[i] == '\t') {
++i;
}
if (str[i] != 0) {
*error = KMP_I18N_STR(IllegalCharacters);
return;
}
if (overflow) {
*error = KMP_I18N_STR(ValueTooLarge);
*out = KMP_SIZE_T_MAX;
return;
}
*error = NULL;
*out = value;
} // __kmp_str_to_size
void __kmp_str_to_uint( // R: Error code.
char const *str, // I: String of characters, unsigned number.
kmp_uint64 *out, // O: Parsed number.
char const **error // O: Null if everything is ok, error message otherwise.
) {
size_t value = 0;
int overflow = 0;
int i = 0;
int digit;
KMP_DEBUG_ASSERT(str != NULL);
// Skip spaces.
while (str[i] == ' ' || str[i] == '\t') {
++i;
}
// Parse number.
if (str[i] < '0' || str[i] > '9') {
*error = KMP_I18N_STR(NotANumber);
return;
}
do {
digit = str[i] - '0';
overflow = overflow || (value > (KMP_SIZE_T_MAX - digit) / 10);
value = (value * 10) + digit;
++i;
} while (str[i] >= '0' && str[i] <= '9');
// Skip spaces.
while (str[i] == ' ' || str[i] == '\t') {
++i;
}
if (str[i] != 0) {
*error = KMP_I18N_STR(IllegalCharacters);
return;
}
if (overflow) {
*error = KMP_I18N_STR(ValueTooLarge);
*out = (kmp_uint64)-1;
return;
}
*error = NULL;
*out = value;
} // __kmp_str_to_unit
// end of file //

128
third_party/openmp/kmp_str.h vendored Normal file
View file

@ -0,0 +1,128 @@
/*
* kmp_str.h -- String manipulation routines.
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef KMP_STR_H
#define KMP_STR_H
#include <stdarg.h>
#include <string.h>
#include "kmp_os.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#if KMP_OS_WINDOWS
#define strdup _strdup
#endif
/* some macros to replace ctype.h functions */
#define TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) + 'a' - 'A') : (c))
struct kmp_str_buf {
char *str; // Pointer to buffer content, read only.
unsigned int size; // Do not change this field!
int used; // Number of characters printed to buffer, read only.
char bulk[512]; // Do not use this field!
}; // struct kmp_str_buf
typedef struct kmp_str_buf kmp_str_buf_t;
#define __kmp_str_buf_init(b) \
{ \
(b)->str = (b)->bulk; \
(b)->size = sizeof((b)->bulk); \
(b)->used = 0; \
(b)->bulk[0] = 0; \
}
void __kmp_str_buf_clear(kmp_str_buf_t *buffer);
void __kmp_str_buf_reserve(kmp_str_buf_t *buffer, size_t size);
void __kmp_str_buf_detach(kmp_str_buf_t *buffer);
void __kmp_str_buf_free(kmp_str_buf_t *buffer);
void __kmp_str_buf_cat(kmp_str_buf_t *buffer, char const *str, size_t len);
void __kmp_str_buf_catbuf(kmp_str_buf_t *dest, const kmp_str_buf_t *src);
int __kmp_str_buf_vprint(kmp_str_buf_t *buffer, char const *format,
va_list args);
int __kmp_str_buf_print(kmp_str_buf_t *buffer, char const *format, ...);
void __kmp_str_buf_print_size(kmp_str_buf_t *buffer, size_t size);
/* File name parser.
Usage:
kmp_str_fname_t fname = __kmp_str_fname_init( path );
// Use fname.path (copy of original path ), fname.dir, fname.base.
// Note fname.dir concatenated with fname.base gives exact copy of path.
__kmp_str_fname_free( & fname );
*/
struct kmp_str_fname {
char *path;
char *dir;
char *base;
}; // struct kmp_str_fname
typedef struct kmp_str_fname kmp_str_fname_t;
void __kmp_str_fname_init(kmp_str_fname_t *fname, char const *path);
void __kmp_str_fname_free(kmp_str_fname_t *fname);
// Compares file name with specified pattern. If pattern is NULL, any fname
// matched.
int __kmp_str_fname_match(kmp_str_fname_t const *fname, char const *pattern);
/* The compiler provides source locations in string form
";file;func;line;col;;". It is not convenient for manipulation. This
structure keeps source location in more convenient form.
Usage:
kmp_str_loc_t loc = __kmp_str_loc_init(ident->psource, false);
// use loc.file, loc.func, loc.line, loc.col.
// loc.fname is available if second argument of __kmp_str_loc_init is true.
__kmp_str_loc_free( & loc );
If psource is NULL or does not follow format above, file and/or func may be
NULL pointers.
*/
struct kmp_str_loc {
char *_bulk; // Do not use thid field.
kmp_str_fname_t fname; // Will be initialized if init_fname is true.
char *file;
char *func;
int line;
int col;
}; // struct kmp_str_loc
typedef struct kmp_str_loc kmp_str_loc_t;
kmp_str_loc_t __kmp_str_loc_init(char const *psource, bool init_fname);
void __kmp_str_loc_numbers(char const *Psource, int *Line, int *Col);
void __kmp_str_loc_free(kmp_str_loc_t *loc);
int __kmp_str_eqf(char const *lhs, char const *rhs);
char *__kmp_str_format(char const *format, ...);
void __kmp_str_free(char **str);
int __kmp_str_match(char const *target, int len, char const *data);
bool __kmp_str_contains(char const *target, int len, char const *data);
int __kmp_str_match_false(char const *data);
int __kmp_str_match_true(char const *data);
void __kmp_str_replace(char *str, char search_for, char replace_with);
void __kmp_str_split(char *str, char delim, char **head, char **tail);
char *__kmp_str_token(char *str, char const *delim, char **buf);
int __kmp_basic_str_to_int(char const *str);
int __kmp_str_to_int(char const *str, char sentinel);
void __kmp_str_to_size(char const *str, size_t *out, size_t dfactor,
char const **error);
void __kmp_str_to_uint(char const *str, kmp_uint64 *out, char const **error);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // KMP_STR_H
// end of file //

55
third_party/openmp/kmp_stub.h vendored Normal file
View file

@ -0,0 +1,55 @@
/*
* kmp_stub.h
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef KMP_STUB_H
#define KMP_STUB_H
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
void __kmps_set_blocktime(int arg);
int __kmps_get_blocktime(void);
void __kmps_set_dynamic(int arg);
int __kmps_get_dynamic(void);
void __kmps_set_library(int arg);
int __kmps_get_library(void);
void __kmps_set_nested(int arg);
int __kmps_get_nested(void);
void __kmps_set_stacksize(size_t arg);
size_t __kmps_get_stacksize();
#ifndef KMP_SCHED_TYPE_DEFINED
#define KMP_SCHED_TYPE_DEFINED
typedef enum kmp_sched {
kmp_sched_static = 1, // mapped to kmp_sch_static_chunked (33)
kmp_sched_dynamic = 2, // mapped to kmp_sch_dynamic_chunked (35)
kmp_sched_guided = 3, // mapped to kmp_sch_guided_chunked (36)
kmp_sched_auto = 4, // mapped to kmp_sch_auto (38)
kmp_sched_default = kmp_sched_static // default scheduling
} kmp_sched_t;
#endif
void __kmps_set_schedule(kmp_sched_t kind, int modifier);
void __kmps_get_schedule(kmp_sched_t *kind, int *modifier);
kmp_proc_bind_t __kmps_get_proc_bind(void);
double __kmps_get_wtime();
double __kmps_get_wtick();
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // KMP_STUB_H
// end of file //

1039
third_party/openmp/kmp_taskdeps.cpp vendored Normal file

File diff suppressed because it is too large Load diff

209
third_party/openmp/kmp_taskdeps.h vendored Normal file
View file

@ -0,0 +1,209 @@
/*
* kmp_taskdeps.h
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef KMP_TASKDEPS_H
#define KMP_TASKDEPS_H
#include "kmp.h"
#define KMP_ACQUIRE_DEPNODE(gtid, n) __kmp_acquire_lock(&(n)->dn.lock, (gtid))
#define KMP_RELEASE_DEPNODE(gtid, n) __kmp_release_lock(&(n)->dn.lock, (gtid))
static inline void __kmp_node_deref(kmp_info_t *thread, kmp_depnode_t *node) {
if (!node)
return;
kmp_int32 n = KMP_ATOMIC_DEC(&node->dn.nrefs) - 1;
KMP_DEBUG_ASSERT(n >= 0);
if (n == 0) {
#if USE_ITT_BUILD && USE_ITT_NOTIFY
__itt_sync_destroy(node);
#endif
KMP_ASSERT(node->dn.nrefs == 0);
#if USE_FAST_MEMORY
__kmp_fast_free(thread, node);
#else
__kmp_thread_free(thread, node);
#endif
}
}
static inline void __kmp_depnode_list_free(kmp_info_t *thread,
kmp_depnode_list *list) {
kmp_depnode_list *next;
for (; list; list = next) {
next = list->next;
__kmp_node_deref(thread, list->node);
#if USE_FAST_MEMORY
__kmp_fast_free(thread, list);
#else
__kmp_thread_free(thread, list);
#endif
}
}
static inline void __kmp_dephash_free_entries(kmp_info_t *thread,
kmp_dephash_t *h) {
for (size_t i = 0; i < h->size; i++) {
if (h->buckets[i]) {
kmp_dephash_entry_t *next;
for (kmp_dephash_entry_t *entry = h->buckets[i]; entry; entry = next) {
next = entry->next_in_bucket;
__kmp_depnode_list_free(thread, entry->last_set);
__kmp_depnode_list_free(thread, entry->prev_set);
__kmp_node_deref(thread, entry->last_out);
if (entry->mtx_lock) {
__kmp_destroy_lock(entry->mtx_lock);
__kmp_free(entry->mtx_lock);
}
#if USE_FAST_MEMORY
__kmp_fast_free(thread, entry);
#else
__kmp_thread_free(thread, entry);
#endif
}
h->buckets[i] = 0;
}
}
__kmp_node_deref(thread, h->last_all);
h->last_all = NULL;
}
static inline void __kmp_dephash_free(kmp_info_t *thread, kmp_dephash_t *h) {
__kmp_dephash_free_entries(thread, h);
#if USE_FAST_MEMORY
__kmp_fast_free(thread, h);
#else
__kmp_thread_free(thread, h);
#endif
}
extern void __kmpc_give_task(kmp_task_t *ptask, kmp_int32 start);
static inline void __kmp_release_deps(kmp_int32 gtid, kmp_taskdata_t *task) {
#if OMPX_TASKGRAPH
if (task->is_taskgraph && !(__kmp_tdg_is_recording(task->tdg->tdg_status))) {
kmp_node_info_t *TaskInfo = &(task->tdg->record_map[task->td_task_id]);
for (int i = 0; i < TaskInfo->nsuccessors; i++) {
kmp_int32 successorNumber = TaskInfo->successors[i];
kmp_node_info_t *successor = &(task->tdg->record_map[successorNumber]);
kmp_int32 npredecessors = KMP_ATOMIC_DEC(&successor->npredecessors_counter) - 1;
if (successor->task != nullptr && npredecessors == 0) {
__kmp_omp_task(gtid, successor->task, false);
}
}
return;
}
#endif
kmp_info_t *thread = __kmp_threads[gtid];
kmp_depnode_t *node = task->td_depnode;
// Check mutexinoutset dependencies, release locks
if (UNLIKELY(node && (node->dn.mtx_num_locks < 0))) {
// negative num_locks means all locks were acquired
node->dn.mtx_num_locks = -node->dn.mtx_num_locks;
for (int i = node->dn.mtx_num_locks - 1; i >= 0; --i) {
KMP_DEBUG_ASSERT(node->dn.mtx_locks[i] != NULL);
__kmp_release_lock(node->dn.mtx_locks[i], gtid);
}
}
if (task->td_dephash) {
KA_TRACE(
40, ("__kmp_release_deps: T#%d freeing dependencies hash of task %p.\n",
gtid, task));
__kmp_dephash_free(thread, task->td_dephash);
task->td_dephash = NULL;
}
if (!node)
return;
KA_TRACE(20, ("__kmp_release_deps: T#%d notifying successors of task %p.\n",
gtid, task));
KMP_ACQUIRE_DEPNODE(gtid, node);
#if OMPX_TASKGRAPH
if (!task->is_taskgraph ||
(task->is_taskgraph && !__kmp_tdg_is_recording(task->tdg->tdg_status)))
#endif
node->dn.task =
NULL; // mark this task as finished, so no new dependencies are generated
KMP_RELEASE_DEPNODE(gtid, node);
kmp_depnode_list_t *next;
kmp_taskdata_t *next_taskdata;
for (kmp_depnode_list_t *p = node->dn.successors; p; p = next) {
kmp_depnode_t *successor = p->node;
#if USE_ITT_BUILD && USE_ITT_NOTIFY
__itt_sync_releasing(successor);
#endif
kmp_int32 npredecessors = KMP_ATOMIC_DEC(&successor->dn.npredecessors) - 1;
// successor task can be NULL for wait_depends or because deps are still
// being processed
if (npredecessors == 0) {
#if USE_ITT_BUILD && USE_ITT_NOTIFY
__itt_sync_acquired(successor);
#endif
KMP_MB();
if (successor->dn.task) {
KA_TRACE(20, ("__kmp_release_deps: T#%d successor %p of %p scheduled "
"for execution.\n",
gtid, successor->dn.task, task));
// If a regular task depending on a hidden helper task, when the
// hidden helper task is done, the regular task should be executed by
// its encountering team.
if (KMP_HIDDEN_HELPER_THREAD(gtid)) {
// Hidden helper thread can only execute hidden helper tasks
KMP_ASSERT(task->td_flags.hidden_helper);
next_taskdata = KMP_TASK_TO_TASKDATA(successor->dn.task);
// If the dependent task is a regular task, we need to push to its
// encountering thread's queue; otherwise, it can be pushed to its own
// queue.
if (!next_taskdata->td_flags.hidden_helper) {
kmp_int32 encountering_gtid =
next_taskdata->td_alloc_thread->th.th_info.ds.ds_gtid;
kmp_int32 encountering_tid = __kmp_tid_from_gtid(encountering_gtid);
__kmpc_give_task(successor->dn.task, encountering_tid);
} else {
__kmp_omp_task(gtid, successor->dn.task, false);
}
} else {
__kmp_omp_task(gtid, successor->dn.task, false);
}
}
}
next = p->next;
__kmp_node_deref(thread, p->node);
#if USE_FAST_MEMORY
__kmp_fast_free(thread, p);
#else
__kmp_thread_free(thread, p);
#endif
}
__kmp_node_deref(thread, node);
KA_TRACE(
20,
("__kmp_release_deps: T#%d all successors of %p notified of completion\n",
gtid, task));
}
#endif // KMP_TASKDEPS_H

5717
third_party/openmp/kmp_tasking.cpp vendored Normal file

File diff suppressed because it is too large Load diff

798
third_party/openmp/kmp_threadprivate.cpp vendored Normal file
View file

@ -0,0 +1,798 @@
/*
* kmp_threadprivate.cpp -- OpenMP threadprivate support library
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "kmp.h"
#include "kmp_i18n.h"
#include "kmp_itt.h"
#define USE_CHECKS_COMMON
#define KMP_INLINE_SUBR 1
void kmp_threadprivate_insert_private_data(int gtid, void *pc_addr,
void *data_addr, size_t pc_size);
struct private_common *kmp_threadprivate_insert(int gtid, void *pc_addr,
void *data_addr,
size_t pc_size);
struct shared_table __kmp_threadprivate_d_table;
static
#ifdef KMP_INLINE_SUBR
__forceinline
#endif
struct private_common *
__kmp_threadprivate_find_task_common(struct common_table *tbl, int gtid,
void *pc_addr)
{
struct private_common *tn;
#ifdef KMP_TASK_COMMON_DEBUG
KC_TRACE(10, ("__kmp_threadprivate_find_task_common: thread#%d, called with "
"address %p\n",
gtid, pc_addr));
dump_list();
#endif
for (tn = tbl->data[KMP_HASH(pc_addr)]; tn; tn = tn->next) {
if (tn->gbl_addr == pc_addr) {
#ifdef KMP_TASK_COMMON_DEBUG
KC_TRACE(10, ("__kmp_threadprivate_find_task_common: thread#%d, found "
"node %p on list\n",
gtid, pc_addr));
#endif
return tn;
}
}
return 0;
}
static
#ifdef KMP_INLINE_SUBR
__forceinline
#endif
struct shared_common *
__kmp_find_shared_task_common(struct shared_table *tbl, int gtid,
void *pc_addr) {
struct shared_common *tn;
for (tn = tbl->data[KMP_HASH(pc_addr)]; tn; tn = tn->next) {
if (tn->gbl_addr == pc_addr) {
#ifdef KMP_TASK_COMMON_DEBUG
KC_TRACE(
10,
("__kmp_find_shared_task_common: thread#%d, found node %p on list\n",
gtid, pc_addr));
#endif
return tn;
}
}
return 0;
}
// Create a template for the data initialized storage. Either the template is
// NULL indicating zero fill, or the template is a copy of the original data.
static struct private_data *__kmp_init_common_data(void *pc_addr,
size_t pc_size) {
struct private_data *d;
size_t i;
char *p;
d = (struct private_data *)__kmp_allocate(sizeof(struct private_data));
/*
d->data = 0; // AC: commented out because __kmp_allocate zeroes the
memory
d->next = 0;
*/
d->size = pc_size;
d->more = 1;
p = (char *)pc_addr;
for (i = pc_size; i > 0; --i) {
if (*p++ != '\0') {
d->data = __kmp_allocate(pc_size);
KMP_MEMCPY(d->data, pc_addr, pc_size);
break;
}
}
return d;
}
// Initialize the data area from the template.
static void __kmp_copy_common_data(void *pc_addr, struct private_data *d) {
char *addr = (char *)pc_addr;
for (size_t offset = 0; d != 0; d = d->next) {
for (int i = d->more; i > 0; --i) {
if (d->data == 0)
memset(&addr[offset], '\0', d->size);
else
KMP_MEMCPY(&addr[offset], d->data, d->size);
offset += d->size;
}
}
}
/* we are called from __kmp_serial_initialize() with __kmp_initz_lock held. */
void __kmp_common_initialize(void) {
if (!TCR_4(__kmp_init_common)) {
int q;
#ifdef KMP_DEBUG
int gtid;
#endif
__kmp_threadpriv_cache_list = NULL;
#ifdef KMP_DEBUG
/* verify the uber masters were initialized */
for (gtid = 0; gtid < __kmp_threads_capacity; gtid++)
if (__kmp_root[gtid]) {
KMP_DEBUG_ASSERT(__kmp_root[gtid]->r.r_uber_thread);
for (q = 0; q < KMP_HASH_TABLE_SIZE; ++q)
KMP_DEBUG_ASSERT(
!__kmp_root[gtid]->r.r_uber_thread->th.th_pri_common->data[q]);
/* __kmp_root[ gitd ]-> r.r_uber_thread ->
* th.th_pri_common -> data[ q ] = 0;*/
}
#endif /* KMP_DEBUG */
for (q = 0; q < KMP_HASH_TABLE_SIZE; ++q)
__kmp_threadprivate_d_table.data[q] = 0;
TCW_4(__kmp_init_common, TRUE);
}
}
/* Call all destructors for threadprivate data belonging to all threads.
Currently unused! */
void __kmp_common_destroy(void) {
if (TCR_4(__kmp_init_common)) {
int q;
TCW_4(__kmp_init_common, FALSE);
for (q = 0; q < KMP_HASH_TABLE_SIZE; ++q) {
int gtid;
struct private_common *tn;
struct shared_common *d_tn;
/* C++ destructors need to be called once per thread before exiting.
Don't call destructors for primary thread though unless we used copy
constructor */
for (d_tn = __kmp_threadprivate_d_table.data[q]; d_tn;
d_tn = d_tn->next) {
if (d_tn->is_vec) {
if (d_tn->dt.dtorv != 0) {
for (gtid = 0; gtid < __kmp_all_nth; ++gtid) {
if (__kmp_threads[gtid]) {
if ((__kmp_foreign_tp) ? (!KMP_INITIAL_GTID(gtid))
: (!KMP_UBER_GTID(gtid))) {
tn = __kmp_threadprivate_find_task_common(
__kmp_threads[gtid]->th.th_pri_common, gtid,
d_tn->gbl_addr);
if (tn) {
(*d_tn->dt.dtorv)(tn->par_addr, d_tn->vec_len);
}
}
}
}
if (d_tn->obj_init != 0) {
(*d_tn->dt.dtorv)(d_tn->obj_init, d_tn->vec_len);
}
}
} else {
if (d_tn->dt.dtor != 0) {
for (gtid = 0; gtid < __kmp_all_nth; ++gtid) {
if (__kmp_threads[gtid]) {
if ((__kmp_foreign_tp) ? (!KMP_INITIAL_GTID(gtid))
: (!KMP_UBER_GTID(gtid))) {
tn = __kmp_threadprivate_find_task_common(
__kmp_threads[gtid]->th.th_pri_common, gtid,
d_tn->gbl_addr);
if (tn) {
(*d_tn->dt.dtor)(tn->par_addr);
}
}
}
}
if (d_tn->obj_init != 0) {
(*d_tn->dt.dtor)(d_tn->obj_init);
}
}
}
}
__kmp_threadprivate_d_table.data[q] = 0;
}
}
}
/* Call all destructors for threadprivate data belonging to this thread */
void __kmp_common_destroy_gtid(int gtid) {
struct private_common *tn;
struct shared_common *d_tn;
if (!TCR_4(__kmp_init_gtid)) {
// This is possible when one of multiple roots initiates early library
// termination in a sequential region while other teams are active, and its
// child threads are about to end.
return;
}
KC_TRACE(10, ("__kmp_common_destroy_gtid: T#%d called\n", gtid));
if ((__kmp_foreign_tp) ? (!KMP_INITIAL_GTID(gtid)) : (!KMP_UBER_GTID(gtid))) {
if (TCR_4(__kmp_init_common)) {
/* Cannot do this here since not all threads have destroyed their data */
/* TCW_4(__kmp_init_common, FALSE); */
for (tn = __kmp_threads[gtid]->th.th_pri_head; tn; tn = tn->link) {
d_tn = __kmp_find_shared_task_common(&__kmp_threadprivate_d_table, gtid,
tn->gbl_addr);
if (d_tn == NULL)
continue;
if (d_tn->is_vec) {
if (d_tn->dt.dtorv != 0) {
(void)(*d_tn->dt.dtorv)(tn->par_addr, d_tn->vec_len);
}
if (d_tn->obj_init != 0) {
(void)(*d_tn->dt.dtorv)(d_tn->obj_init, d_tn->vec_len);
}
} else {
if (d_tn->dt.dtor != 0) {
(void)(*d_tn->dt.dtor)(tn->par_addr);
}
if (d_tn->obj_init != 0) {
(void)(*d_tn->dt.dtor)(d_tn->obj_init);
}
}
}
KC_TRACE(30, ("__kmp_common_destroy_gtid: T#%d threadprivate destructors "
"complete\n",
gtid));
}
}
}
#ifdef KMP_TASK_COMMON_DEBUG
static void dump_list(void) {
int p, q;
for (p = 0; p < __kmp_all_nth; ++p) {
if (!__kmp_threads[p])
continue;
for (q = 0; q < KMP_HASH_TABLE_SIZE; ++q) {
if (__kmp_threads[p]->th.th_pri_common->data[q]) {
struct private_common *tn;
KC_TRACE(10, ("\tdump_list: gtid:%d addresses\n", p));
for (tn = __kmp_threads[p]->th.th_pri_common->data[q]; tn;
tn = tn->next) {
KC_TRACE(10,
("\tdump_list: THREADPRIVATE: Serial %p -> Parallel %p\n",
tn->gbl_addr, tn->par_addr));
}
}
}
}
}
#endif /* KMP_TASK_COMMON_DEBUG */
// NOTE: this routine is to be called only from the serial part of the program.
void kmp_threadprivate_insert_private_data(int gtid, void *pc_addr,
void *data_addr, size_t pc_size) {
struct shared_common **lnk_tn, *d_tn;
KMP_DEBUG_ASSERT(__kmp_threads[gtid] &&
__kmp_threads[gtid]->th.th_root->r.r_active == 0);
d_tn = __kmp_find_shared_task_common(&__kmp_threadprivate_d_table, gtid,
pc_addr);
if (d_tn == 0) {
d_tn = (struct shared_common *)__kmp_allocate(sizeof(struct shared_common));
d_tn->gbl_addr = pc_addr;
d_tn->pod_init = __kmp_init_common_data(data_addr, pc_size);
/*
d_tn->obj_init = 0; // AC: commented out because __kmp_allocate
zeroes the memory
d_tn->ct.ctor = 0;
d_tn->cct.cctor = 0;;
d_tn->dt.dtor = 0;
d_tn->is_vec = FALSE;
d_tn->vec_len = 0L;
*/
d_tn->cmn_size = pc_size;
__kmp_acquire_lock(&__kmp_global_lock, gtid);
lnk_tn = &(__kmp_threadprivate_d_table.data[KMP_HASH(pc_addr)]);
d_tn->next = *lnk_tn;
*lnk_tn = d_tn;
__kmp_release_lock(&__kmp_global_lock, gtid);
}
}
struct private_common *kmp_threadprivate_insert(int gtid, void *pc_addr,
void *data_addr,
size_t pc_size) {
struct private_common *tn, **tt;
struct shared_common *d_tn;
/* +++++++++ START OF CRITICAL SECTION +++++++++ */
__kmp_acquire_lock(&__kmp_global_lock, gtid);
tn = (struct private_common *)__kmp_allocate(sizeof(struct private_common));
tn->gbl_addr = pc_addr;
d_tn = __kmp_find_shared_task_common(
&__kmp_threadprivate_d_table, gtid,
pc_addr); /* Only the MASTER data table exists. */
if (d_tn != 0) {
/* This threadprivate variable has already been seen. */
if (d_tn->pod_init == 0 && d_tn->obj_init == 0) {
d_tn->cmn_size = pc_size;
if (d_tn->is_vec) {
if (d_tn->ct.ctorv != 0) {
/* Construct from scratch so no prototype exists */
d_tn->obj_init = 0;
} else if (d_tn->cct.cctorv != 0) {
/* Now data initialize the prototype since it was previously
* registered */
d_tn->obj_init = (void *)__kmp_allocate(d_tn->cmn_size);
(void)(*d_tn->cct.cctorv)(d_tn->obj_init, pc_addr, d_tn->vec_len);
} else {
d_tn->pod_init = __kmp_init_common_data(data_addr, d_tn->cmn_size);
}
} else {
if (d_tn->ct.ctor != 0) {
/* Construct from scratch so no prototype exists */
d_tn->obj_init = 0;
} else if (d_tn->cct.cctor != 0) {
/* Now data initialize the prototype since it was previously
registered */
d_tn->obj_init = (void *)__kmp_allocate(d_tn->cmn_size);
(void)(*d_tn->cct.cctor)(d_tn->obj_init, pc_addr);
} else {
d_tn->pod_init = __kmp_init_common_data(data_addr, d_tn->cmn_size);
}
}
}
} else {
struct shared_common **lnk_tn;
d_tn = (struct shared_common *)__kmp_allocate(sizeof(struct shared_common));
d_tn->gbl_addr = pc_addr;
d_tn->cmn_size = pc_size;
d_tn->pod_init = __kmp_init_common_data(data_addr, pc_size);
/*
d_tn->obj_init = 0; // AC: commented out because __kmp_allocate
zeroes the memory
d_tn->ct.ctor = 0;
d_tn->cct.cctor = 0;
d_tn->dt.dtor = 0;
d_tn->is_vec = FALSE;
d_tn->vec_len = 0L;
*/
lnk_tn = &(__kmp_threadprivate_d_table.data[KMP_HASH(pc_addr)]);
d_tn->next = *lnk_tn;
*lnk_tn = d_tn;
}
tn->cmn_size = d_tn->cmn_size;
if ((__kmp_foreign_tp) ? (KMP_INITIAL_GTID(gtid)) : (KMP_UBER_GTID(gtid))) {
tn->par_addr = (void *)pc_addr;
} else {
tn->par_addr = (void *)__kmp_allocate(tn->cmn_size);
}
__kmp_release_lock(&__kmp_global_lock, gtid);
/* +++++++++ END OF CRITICAL SECTION +++++++++ */
#ifdef USE_CHECKS_COMMON
if (pc_size > d_tn->cmn_size) {
KC_TRACE(
10, ("__kmp_threadprivate_insert: THREADPRIVATE: %p (%" KMP_UINTPTR_SPEC
" ,%" KMP_UINTPTR_SPEC ")\n",
pc_addr, pc_size, d_tn->cmn_size));
KMP_FATAL(TPCommonBlocksInconsist);
}
#endif /* USE_CHECKS_COMMON */
tt = &(__kmp_threads[gtid]->th.th_pri_common->data[KMP_HASH(pc_addr)]);
#ifdef KMP_TASK_COMMON_DEBUG
if (*tt != 0) {
KC_TRACE(
10,
("__kmp_threadprivate_insert: WARNING! thread#%d: collision on %p\n",
gtid, pc_addr));
}
#endif
tn->next = *tt;
*tt = tn;
#ifdef KMP_TASK_COMMON_DEBUG
KC_TRACE(10,
("__kmp_threadprivate_insert: thread#%d, inserted node %p on list\n",
gtid, pc_addr));
dump_list();
#endif
/* Link the node into a simple list */
tn->link = __kmp_threads[gtid]->th.th_pri_head;
__kmp_threads[gtid]->th.th_pri_head = tn;
if ((__kmp_foreign_tp) ? (KMP_INITIAL_GTID(gtid)) : (KMP_UBER_GTID(gtid)))
return tn;
/* if C++ object with copy constructor, use it;
* else if C++ object with constructor, use it for the non-primary thread
copies only;
* else use pod_init and memcpy
*
* C++ constructors need to be called once for each non-primary thread on
* allocate
* C++ copy constructors need to be called once for each thread on allocate */
/* C++ object with constructors/destructors; don't call constructors for
primary thread though */
if (d_tn->is_vec) {
if (d_tn->ct.ctorv != 0) {
(void)(*d_tn->ct.ctorv)(tn->par_addr, d_tn->vec_len);
} else if (d_tn->cct.cctorv != 0) {
(void)(*d_tn->cct.cctorv)(tn->par_addr, d_tn->obj_init, d_tn->vec_len);
} else if (tn->par_addr != tn->gbl_addr) {
__kmp_copy_common_data(tn->par_addr, d_tn->pod_init);
}
} else {
if (d_tn->ct.ctor != 0) {
(void)(*d_tn->ct.ctor)(tn->par_addr);
} else if (d_tn->cct.cctor != 0) {
(void)(*d_tn->cct.cctor)(tn->par_addr, d_tn->obj_init);
} else if (tn->par_addr != tn->gbl_addr) {
__kmp_copy_common_data(tn->par_addr, d_tn->pod_init);
}
}
/* !BUILD_OPENMP_C
if (tn->par_addr != tn->gbl_addr)
__kmp_copy_common_data( tn->par_addr, d_tn->pod_init ); */
return tn;
}
/* ------------------------------------------------------------------------ */
/* We are currently parallel, and we know the thread id. */
/* ------------------------------------------------------------------------ */
/*!
@ingroup THREADPRIVATE
@param loc source location information
@param data pointer to data being privatized
@param ctor pointer to constructor function for data
@param cctor pointer to copy constructor function for data
@param dtor pointer to destructor function for data
Register constructors and destructors for thread private data.
This function is called when executing in parallel, when we know the thread id.
*/
void __kmpc_threadprivate_register(ident_t *loc, void *data, kmpc_ctor ctor,
kmpc_cctor cctor, kmpc_dtor dtor) {
struct shared_common *d_tn, **lnk_tn;
KC_TRACE(10, ("__kmpc_threadprivate_register: called\n"));
#ifdef USE_CHECKS_COMMON
/* copy constructor must be zero for current code gen (Nov 2002 - jph) */
KMP_ASSERT(cctor == 0);
#endif /* USE_CHECKS_COMMON */
/* Only the global data table exists. */
d_tn = __kmp_find_shared_task_common(&__kmp_threadprivate_d_table, -1, data);
if (d_tn == 0) {
d_tn = (struct shared_common *)__kmp_allocate(sizeof(struct shared_common));
d_tn->gbl_addr = data;
d_tn->ct.ctor = ctor;
d_tn->cct.cctor = cctor;
d_tn->dt.dtor = dtor;
/*
d_tn->is_vec = FALSE; // AC: commented out because __kmp_allocate
zeroes the memory
d_tn->vec_len = 0L;
d_tn->obj_init = 0;
d_tn->pod_init = 0;
*/
lnk_tn = &(__kmp_threadprivate_d_table.data[KMP_HASH(data)]);
d_tn->next = *lnk_tn;
*lnk_tn = d_tn;
}
}
void *__kmpc_threadprivate(ident_t *loc, kmp_int32 global_tid, void *data,
size_t size) {
void *ret;
struct private_common *tn;
KC_TRACE(10, ("__kmpc_threadprivate: T#%d called\n", global_tid));
#ifdef USE_CHECKS_COMMON
if (!__kmp_init_serial)
KMP_FATAL(RTLNotInitialized);
#endif /* USE_CHECKS_COMMON */
if (!__kmp_threads[global_tid]->th.th_root->r.r_active && !__kmp_foreign_tp) {
/* The parallel address will NEVER overlap with the data_address */
/* dkp: 3rd arg to kmp_threadprivate_insert_private_data() is the
* data_address; use data_address = data */
KC_TRACE(20, ("__kmpc_threadprivate: T#%d inserting private data\n",
global_tid));
kmp_threadprivate_insert_private_data(global_tid, data, data, size);
ret = data;
} else {
KC_TRACE(
50,
("__kmpc_threadprivate: T#%d try to find private data at address %p\n",
global_tid, data));
tn = __kmp_threadprivate_find_task_common(
__kmp_threads[global_tid]->th.th_pri_common, global_tid, data);
if (tn) {
KC_TRACE(20, ("__kmpc_threadprivate: T#%d found data\n", global_tid));
#ifdef USE_CHECKS_COMMON
if ((size_t)size > tn->cmn_size) {
KC_TRACE(10, ("THREADPRIVATE: %p (%" KMP_UINTPTR_SPEC
" ,%" KMP_UINTPTR_SPEC ")\n",
data, size, tn->cmn_size));
KMP_FATAL(TPCommonBlocksInconsist);
}
#endif /* USE_CHECKS_COMMON */
} else {
/* The parallel address will NEVER overlap with the data_address */
/* dkp: 3rd arg to kmp_threadprivate_insert() is the data_address; use
* data_address = data */
KC_TRACE(20, ("__kmpc_threadprivate: T#%d inserting data\n", global_tid));
tn = kmp_threadprivate_insert(global_tid, data, data, size);
}
ret = tn->par_addr;
}
KC_TRACE(10, ("__kmpc_threadprivate: T#%d exiting; return value = %p\n",
global_tid, ret));
return ret;
}
static kmp_cached_addr_t *__kmp_find_cache(void *data) {
kmp_cached_addr_t *ptr = __kmp_threadpriv_cache_list;
while (ptr && ptr->data != data)
ptr = ptr->next;
return ptr;
}
/*!
@ingroup THREADPRIVATE
@param loc source location information
@param global_tid global thread number
@param data pointer to data to privatize
@param size size of data to privatize
@param cache pointer to cache
@return pointer to private storage
Allocate private storage for threadprivate data.
*/
void *
__kmpc_threadprivate_cached(ident_t *loc,
kmp_int32 global_tid, // gtid.
void *data, // Pointer to original global variable.
size_t size, // Size of original global variable.
void ***cache) {
KC_TRACE(10, ("__kmpc_threadprivate_cached: T#%d called with cache: %p, "
"address: %p, size: %" KMP_SIZE_T_SPEC "\n",
global_tid, *cache, data, size));
if (TCR_PTR(*cache) == 0) {
__kmp_acquire_lock(&__kmp_global_lock, global_tid);
if (TCR_PTR(*cache) == 0) {
__kmp_acquire_bootstrap_lock(&__kmp_tp_cached_lock);
// Compiler often passes in NULL cache, even if it's already been created
void **my_cache;
kmp_cached_addr_t *tp_cache_addr;
// Look for an existing cache
tp_cache_addr = __kmp_find_cache(data);
if (!tp_cache_addr) { // Cache was never created; do it now
__kmp_tp_cached = 1;
KMP_ITT_IGNORE(my_cache = (void **)__kmp_allocate(
sizeof(void *) * __kmp_tp_capacity +
sizeof(kmp_cached_addr_t)););
// No need to zero the allocated memory; __kmp_allocate does that.
KC_TRACE(50, ("__kmpc_threadprivate_cached: T#%d allocated cache at "
"address %p\n",
global_tid, my_cache));
/* TODO: free all this memory in __kmp_common_destroy using
* __kmp_threadpriv_cache_list */
/* Add address of mycache to linked list for cleanup later */
tp_cache_addr = (kmp_cached_addr_t *)&my_cache[__kmp_tp_capacity];
tp_cache_addr->addr = my_cache;
tp_cache_addr->data = data;
tp_cache_addr->compiler_cache = cache;
tp_cache_addr->next = __kmp_threadpriv_cache_list;
__kmp_threadpriv_cache_list = tp_cache_addr;
} else { // A cache was already created; use it
my_cache = tp_cache_addr->addr;
tp_cache_addr->compiler_cache = cache;
}
KMP_MB();
TCW_PTR(*cache, my_cache);
__kmp_release_bootstrap_lock(&__kmp_tp_cached_lock);
KMP_MB();
}
__kmp_release_lock(&__kmp_global_lock, global_tid);
}
void *ret;
if ((ret = TCR_PTR((*cache)[global_tid])) == 0) {
ret = __kmpc_threadprivate(loc, global_tid, data, (size_t)size);
TCW_PTR((*cache)[global_tid], ret);
}
KC_TRACE(10,
("__kmpc_threadprivate_cached: T#%d exiting; return value = %p\n",
global_tid, ret));
return ret;
}
// This function should only be called when both __kmp_tp_cached_lock and
// kmp_forkjoin_lock are held.
void __kmp_threadprivate_resize_cache(int newCapacity) {
KC_TRACE(10, ("__kmp_threadprivate_resize_cache: called with size: %d\n",
newCapacity));
kmp_cached_addr_t *ptr = __kmp_threadpriv_cache_list;
while (ptr) {
if (ptr->data) { // this location has an active cache; resize it
void **my_cache;
KMP_ITT_IGNORE(my_cache =
(void **)__kmp_allocate(sizeof(void *) * newCapacity +
sizeof(kmp_cached_addr_t)););
// No need to zero the allocated memory; __kmp_allocate does that.
KC_TRACE(50, ("__kmp_threadprivate_resize_cache: allocated cache at %p\n",
my_cache));
// Now copy old cache into new cache
void **old_cache = ptr->addr;
for (int i = 0; i < __kmp_tp_capacity; ++i) {
my_cache[i] = old_cache[i];
}
// Add address of new my_cache to linked list for cleanup later
kmp_cached_addr_t *tp_cache_addr;
tp_cache_addr = (kmp_cached_addr_t *)&my_cache[newCapacity];
tp_cache_addr->addr = my_cache;
tp_cache_addr->data = ptr->data;
tp_cache_addr->compiler_cache = ptr->compiler_cache;
tp_cache_addr->next = __kmp_threadpriv_cache_list;
__kmp_threadpriv_cache_list = tp_cache_addr;
// Copy new cache to compiler's location: We can copy directly
// to (*compiler_cache) if compiler guarantees it will keep
// using the same location for the cache. This is not yet true
// for some compilers, in which case we have to check if
// compiler_cache is still pointing at old cache, and if so, we
// can point it at the new cache with an atomic compare&swap
// operation. (Old method will always work, but we should shift
// to new method (commented line below) when Intel and Clang
// compilers use new method.)
(void)KMP_COMPARE_AND_STORE_PTR(tp_cache_addr->compiler_cache, old_cache,
my_cache);
// TCW_PTR(*(tp_cache_addr->compiler_cache), my_cache);
// If the store doesn't happen here, the compiler's old behavior will
// inevitably call __kmpc_threadprivate_cache with a new location for the
// cache, and that function will store the resized cache there at that
// point.
// Nullify old cache's data pointer so we skip it next time
ptr->data = NULL;
}
ptr = ptr->next;
}
// After all caches are resized, update __kmp_tp_capacity to the new size
*(volatile int *)&__kmp_tp_capacity = newCapacity;
}
/*!
@ingroup THREADPRIVATE
@param loc source location information
@param data pointer to data being privatized
@param ctor pointer to constructor function for data
@param cctor pointer to copy constructor function for data
@param dtor pointer to destructor function for data
@param vector_length length of the vector (bytes or elements?)
Register vector constructors and destructors for thread private data.
*/
void __kmpc_threadprivate_register_vec(ident_t *loc, void *data,
kmpc_ctor_vec ctor, kmpc_cctor_vec cctor,
kmpc_dtor_vec dtor,
size_t vector_length) {
struct shared_common *d_tn, **lnk_tn;
KC_TRACE(10, ("__kmpc_threadprivate_register_vec: called\n"));
#ifdef USE_CHECKS_COMMON
/* copy constructor must be zero for current code gen (Nov 2002 - jph) */
KMP_ASSERT(cctor == 0);
#endif /* USE_CHECKS_COMMON */
d_tn = __kmp_find_shared_task_common(
&__kmp_threadprivate_d_table, -1,
data); /* Only the global data table exists. */
if (d_tn == 0) {
d_tn = (struct shared_common *)__kmp_allocate(sizeof(struct shared_common));
d_tn->gbl_addr = data;
d_tn->ct.ctorv = ctor;
d_tn->cct.cctorv = cctor;
d_tn->dt.dtorv = dtor;
d_tn->is_vec = TRUE;
d_tn->vec_len = (size_t)vector_length;
// d_tn->obj_init = 0; // AC: __kmp_allocate zeroes the memory
// d_tn->pod_init = 0;
lnk_tn = &(__kmp_threadprivate_d_table.data[KMP_HASH(data)]);
d_tn->next = *lnk_tn;
*lnk_tn = d_tn;
}
}
void __kmp_cleanup_threadprivate_caches() {
kmp_cached_addr_t *ptr = __kmp_threadpriv_cache_list;
while (ptr) {
void **cache = ptr->addr;
__kmp_threadpriv_cache_list = ptr->next;
if (*ptr->compiler_cache)
*ptr->compiler_cache = NULL;
ptr->compiler_cache = NULL;
ptr->data = NULL;
ptr->addr = NULL;
ptr->next = NULL;
// Threadprivate data pointed at by cache entries are destroyed at end of
// __kmp_launch_thread with __kmp_common_destroy_gtid.
__kmp_free(cache); // implicitly frees ptr too
ptr = __kmp_threadpriv_cache_list;
}
}

420
third_party/openmp/kmp_utility.cpp vendored Normal file
View file

@ -0,0 +1,420 @@
/*
* kmp_utility.cpp -- Utility routines for the OpenMP support library.
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "kmp.h"
#include "kmp_i18n.h"
#include "kmp_str.h"
#include "kmp_wrapper_getpid.h"
#include <float.h>
static const char *unknown = "unknown";
#if KMP_ARCH_X86 || KMP_ARCH_X86_64
/* NOTE: If called before serial_initialize (i.e. from runtime_initialize), then
the debugging package has not been initialized yet, and only "0" will print
debugging output since the environment variables have not been read. */
#ifdef KMP_DEBUG
static int trace_level = 5;
#endif
/* LOG_ID_BITS = ( 1 + floor( log_2( max( log_per_phy - 1, 1 ))))
* APIC_ID = (PHY_ID << LOG_ID_BITS) | LOG_ID
* PHY_ID = APIC_ID >> LOG_ID_BITS
*/
int __kmp_get_physical_id(int log_per_phy, int apic_id) {
int index_lsb, index_msb, temp;
if (log_per_phy > 1) {
index_lsb = 0;
index_msb = 31;
temp = log_per_phy;
while ((temp & 1) == 0) {
temp >>= 1;
index_lsb++;
}
temp = log_per_phy;
while ((temp & 0x80000000) == 0) {
temp <<= 1;
index_msb--;
}
/* If >1 bits were set in log_per_phy, choose next higher power of 2 */
if (index_lsb != index_msb)
index_msb++;
return ((int)(apic_id >> index_msb));
}
return apic_id;
}
/*
* LOG_ID_BITS = ( 1 + floor( log_2( max( log_per_phy - 1, 1 ))))
* APIC_ID = (PHY_ID << LOG_ID_BITS) | LOG_ID
* LOG_ID = APIC_ID & (( 1 << LOG_ID_BITS ) - 1 )
*/
int __kmp_get_logical_id(int log_per_phy, int apic_id) {
unsigned current_bit;
int bits_seen;
if (log_per_phy <= 1)
return (0);
bits_seen = 0;
for (current_bit = 1; log_per_phy != 0; current_bit <<= 1) {
if (log_per_phy & current_bit) {
log_per_phy &= ~current_bit;
bits_seen++;
}
}
/* If exactly 1 bit was set in log_per_phy, choose next lower power of 2 */
if (bits_seen == 1) {
current_bit >>= 1;
}
return ((int)((current_bit - 1) & apic_id));
}
static kmp_uint64 __kmp_parse_frequency( // R: Frequency in Hz.
char const *frequency // I: Float number and unit: MHz, GHz, or TGz.
) {
double value = 0.0;
char *unit = NULL;
kmp_uint64 result = 0; /* Zero is a better unknown value than all ones. */
if (frequency == NULL) {
return result;
}
value = strtod(frequency, &unit);
if (0 < value &&
value <= DBL_MAX) { // Good value (not overflow, underflow, etc).
if (strcmp(unit, "MHz") == 0) {
value = value * 1.0E+6;
} else if (strcmp(unit, "GHz") == 0) {
value = value * 1.0E+9;
} else if (strcmp(unit, "THz") == 0) {
value = value * 1.0E+12;
} else { // Wrong unit.
return result;
}
result = (kmp_uint64)value; // rounds down
}
return result;
} // func __kmp_parse_cpu_frequency
void __kmp_query_cpuid(kmp_cpuinfo_t *p) {
struct kmp_cpuid buf;
int max_arg;
int log_per_phy;
#ifdef KMP_DEBUG
int cflush_size;
#endif
p->initialized = 1;
p->flags.sse2 = 1; // Assume SSE2 by default.
__kmp_x86_cpuid(0, 0, &buf);
KA_TRACE(trace_level,
("INFO: CPUID %d: EAX=0x%08X EBX=0x%08X ECX=0x%08X EDX=0x%08X\n", 0,
buf.eax, buf.ebx, buf.ecx, buf.edx));
max_arg = buf.eax;
p->apic_id = -1;
if (max_arg >= 1) {
int i;
kmp_uint32 t, data[4];
__kmp_x86_cpuid(1, 0, &buf);
KA_TRACE(trace_level,
("INFO: CPUID %d: EAX=0x%08X EBX=0x%08X ECX=0x%08X EDX=0x%08X\n",
1, buf.eax, buf.ebx, buf.ecx, buf.edx));
{
#define get_value(reg, lo, mask) (((reg) >> (lo)) & (mask))
p->signature = buf.eax;
p->family = get_value(buf.eax, 20, 0xff) + get_value(buf.eax, 8, 0x0f);
p->model =
(get_value(buf.eax, 16, 0x0f) << 4) + get_value(buf.eax, 4, 0x0f);
p->stepping = get_value(buf.eax, 0, 0x0f);
#undef get_value
KA_TRACE(trace_level, (" family = %d, model = %d, stepping = %d\n",
p->family, p->model, p->stepping));
}
for (t = buf.ebx, i = 0; i < 4; t >>= 8, ++i) {
data[i] = (t & 0xff);
}
p->flags.sse2 = (buf.edx >> 26) & 1;
#ifdef KMP_DEBUG
if ((buf.edx >> 4) & 1) {
/* TSC - Timestamp Counter Available */
KA_TRACE(trace_level, (" TSC"));
}
if ((buf.edx >> 8) & 1) {
/* CX8 - CMPXCHG8B Instruction Available */
KA_TRACE(trace_level, (" CX8"));
}
if ((buf.edx >> 9) & 1) {
/* APIC - Local APIC Present (multi-processor operation support */
KA_TRACE(trace_level, (" APIC"));
}
if ((buf.edx >> 15) & 1) {
/* CMOV - Conditional MOVe Instruction Available */
KA_TRACE(trace_level, (" CMOV"));
}
if ((buf.edx >> 18) & 1) {
/* PSN - Processor Serial Number Available */
KA_TRACE(trace_level, (" PSN"));
}
if ((buf.edx >> 19) & 1) {
/* CLFLUSH - Cache Flush Instruction Available */
cflush_size =
data[1] * 8; /* Bits 15-08: CLFLUSH line size = 8 (64 bytes) */
KA_TRACE(trace_level, (" CLFLUSH(%db)", cflush_size));
}
if ((buf.edx >> 21) & 1) {
/* DTES - Debug Trace & EMON Store */
KA_TRACE(trace_level, (" DTES"));
}
if ((buf.edx >> 22) & 1) {
/* ACPI - ACPI Support Available */
KA_TRACE(trace_level, (" ACPI"));
}
if ((buf.edx >> 23) & 1) {
/* MMX - Multimedia Extensions */
KA_TRACE(trace_level, (" MMX"));
}
if ((buf.edx >> 25) & 1) {
/* SSE - SSE Instructions */
KA_TRACE(trace_level, (" SSE"));
}
if ((buf.edx >> 26) & 1) {
/* SSE2 - SSE2 Instructions */
KA_TRACE(trace_level, (" SSE2"));
}
if ((buf.edx >> 27) & 1) {
/* SLFSNP - Self-Snooping Cache */
KA_TRACE(trace_level, (" SLFSNP"));
}
#endif /* KMP_DEBUG */
if ((buf.edx >> 28) & 1) {
/* Bits 23-16: Logical Processors per Physical Processor (1 for P4) */
log_per_phy = data[2];
p->apic_id = data[3]; /* Bits 31-24: Processor Initial APIC ID (X) */
KA_TRACE(trace_level, (" HT(%d TPUs)", log_per_phy));
p->physical_id = __kmp_get_physical_id(log_per_phy, p->apic_id);
p->logical_id = __kmp_get_logical_id(log_per_phy, p->apic_id);
}
#ifdef KMP_DEBUG
if ((buf.edx >> 29) & 1) {
/* ATHROTL - Automatic Throttle Control */
KA_TRACE(trace_level, (" ATHROTL"));
}
KA_TRACE(trace_level, (" ]\n"));
for (i = 2; i <= max_arg; ++i) {
__kmp_x86_cpuid(i, 0, &buf);
KA_TRACE(trace_level,
("INFO: CPUID %d: EAX=0x%08X EBX=0x%08X ECX=0x%08X EDX=0x%08X\n",
i, buf.eax, buf.ebx, buf.ecx, buf.edx));
}
#endif
p->flags.rtm = 0;
p->flags.hybrid = 0;
if (max_arg > 7) {
/* RTM bit CPUID.07:EBX, bit 11 */
/* HYRBID bit CPUID.07:EDX, bit 15 */
__kmp_x86_cpuid(7, 0, &buf);
p->flags.rtm = (buf.ebx >> 11) & 1;
p->flags.hybrid = (buf.edx >> 15) & 1;
if (p->flags.rtm) {
KA_TRACE(trace_level, (" RTM"));
}
if (p->flags.hybrid) {
KA_TRACE(trace_level, (" HYBRID"));
}
}
}
{ // Parse CPU brand string for frequency, saving the string for later.
int i;
kmp_cpuid_t *base = (kmp_cpuid_t *)&p->name[0];
// Get CPU brand string.
for (i = 0; i < 3; ++i) {
__kmp_x86_cpuid(0x80000002 + i, 0, base + i);
}
p->name[sizeof(p->name) - 1] = 0; // Just in case. ;-)
KA_TRACE(trace_level, ("cpu brand string: \"%s\"\n", &p->name[0]));
// Parse frequency.
p->frequency = __kmp_parse_frequency(strrchr(&p->name[0], ' '));
KA_TRACE(trace_level,
("cpu frequency from brand string: %" KMP_UINT64_SPEC "\n",
p->frequency));
}
}
#endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
void __kmp_expand_host_name(char *buffer, size_t size) {
KMP_DEBUG_ASSERT(size >= sizeof(unknown));
#if KMP_OS_WINDOWS
{
DWORD s = size;
if (!GetComputerNameA(buffer, &s))
KMP_STRCPY_S(buffer, size, unknown);
}
#elif KMP_OS_WASI
KMP_STRCPY_S(buffer, size, unknown);
#else
buffer[size - 2] = 0;
if (gethostname(buffer, size) || buffer[size - 2] != 0)
KMP_STRCPY_S(buffer, size, unknown);
#endif
}
/* Expand the meta characters in the filename:
* Currently defined characters are:
* %H the hostname
* %P the number of threads used.
* %I the unique identifier for this run.
*/
void __kmp_expand_file_name(char *result, size_t rlen, char *pattern) {
char *pos = result, *end = result + rlen - 1;
char buffer[256];
int default_cpu_width = 1;
int snp_result;
KMP_DEBUG_ASSERT(rlen > 0);
*end = 0;
{
int i;
for (i = __kmp_xproc; i >= 10; i /= 10, ++default_cpu_width)
;
}
if (pattern != NULL) {
while (*pattern != '\0' && pos < end) {
if (*pattern != '%') {
*pos++ = *pattern++;
} else {
char *old_pattern = pattern;
int width = 1;
int cpu_width = default_cpu_width;
++pattern;
if (*pattern >= '0' && *pattern <= '9') {
width = 0;
do {
width = (width * 10) + *pattern++ - '0';
} while (*pattern >= '0' && *pattern <= '9');
if (width < 0 || width > 1024)
width = 1;
cpu_width = width;
}
switch (*pattern) {
case 'H':
case 'h': {
__kmp_expand_host_name(buffer, sizeof(buffer));
KMP_STRNCPY(pos, buffer, end - pos + 1);
if (*end == 0) {
while (*pos)
++pos;
++pattern;
} else
pos = end;
} break;
case 'P':
case 'p': {
snp_result = KMP_SNPRINTF(pos, end - pos + 1, "%0*d", cpu_width,
__kmp_dflt_team_nth);
if (snp_result >= 0 && snp_result <= end - pos) {
while (*pos)
++pos;
++pattern;
} else
pos = end;
} break;
case 'I':
case 'i': {
pid_t id = getpid();
#if (KMP_ARCH_X86_64 || KMP_ARCH_AARCH64) && defined(__MINGW32__)
snp_result = KMP_SNPRINTF(pos, end - pos + 1, "%0*lld", width, id);
#else
snp_result = KMP_SNPRINTF(pos, end - pos + 1, "%0*d", width, id);
#endif
if (snp_result >= 0 && snp_result <= end - pos) {
while (*pos)
++pos;
++pattern;
} else
pos = end;
break;
}
case '%': {
*pos++ = '%';
++pattern;
break;
}
default: {
*pos++ = '%';
pattern = old_pattern + 1;
break;
}
}
}
}
/* TODO: How do we get rid of this? */
if (*pattern != '\0')
KMP_FATAL(FileNameTooLong);
}
*pos = '\0';
}
#if !OMPT_SUPPORT
extern "C" {
typedef struct ompt_start_tool_result_t ompt_start_tool_result_t;
// Define symbols expected by VERSION script
ompt_start_tool_result_t *ompt_start_tool(unsigned int omp_version,
const char *runtime_version) {
return nullptr;
}
void ompt_libomp_connect(ompt_start_tool_result_t *result) { result = nullptr; }
}
#endif

55
third_party/openmp/kmp_utils.h vendored Normal file
View file

@ -0,0 +1,55 @@
/*
* kmp_utils.h -- Utilities that used internally
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef __KMP_UTILS_H__
#define __KMP_UTILS_H__
#include <cstddef>
#include "kmp.h"
/// A simple pure header implementation of VLA that aims to replace uses of
/// actual VLA, which can cause compile warning. This class by default creates a
/// stack buffer that can accomodate \p N elements. If the number of elements is
/// greater than \p N, then a heap buffer will be allocated and used to
/// accomodate the elements. Similar to the actual VLA, we don't check boundary
/// (for now), so we will not store the number of elements. We can always revise
/// it later.
template <typename T, unsigned N = 8> class SimpleVLA final {
T StackBuffer[N];
T *HeapBuffer = nullptr;
T *Ptr = StackBuffer;
public:
SimpleVLA() = delete;
SimpleVLA(const SimpleVLA &) = delete;
SimpleVLA(SimpleVLA &&) = delete;
SimpleVLA &operator=(const SimpleVLA &) = delete;
SimpleVLA &operator=(SimpleVLA &&) = delete;
explicit SimpleVLA(unsigned NumOfElements) noexcept {
if (NumOfElements > N) {
HeapBuffer =
reinterpret_cast<T *>(__kmp_allocate(NumOfElements * sizeof(T)));
Ptr = HeapBuffer;
}
}
~SimpleVLA() {
if (HeapBuffer)
__kmp_free(HeapBuffer);
}
operator T *() noexcept { return Ptr; }
operator const T *() const noexcept { return Ptr; }
};
#endif

204
third_party/openmp/kmp_version.cpp vendored Normal file
View file

@ -0,0 +1,204 @@
/*
* kmp_version.cpp
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "kmp.h"
#include "kmp_io.h"
#include "kmp_version.h"
// Replace with snapshot date YYYYMMDD for promotion build.
#define KMP_VERSION_BUILD 20140926
// Helper macros to convert value of macro to string literal.
#define _stringer(x) #x
#define stringer(x) _stringer(x)
// Detect compiler.
#if KMP_COMPILER_ICX
#define KMP_COMPILER __VERSION__
#elif KMP_COMPILER_ICC
#if __INTEL_COMPILER == 1010
#define KMP_COMPILER "Intel(R) C++ Compiler 10.1"
#elif __INTEL_COMPILER == 1100
#define KMP_COMPILER "Intel(R) C++ Compiler 11.0"
#elif __INTEL_COMPILER == 1110
#define KMP_COMPILER "Intel(R) C++ Compiler 11.1"
#elif __INTEL_COMPILER == 1200
#define KMP_COMPILER "Intel(R) C++ Compiler 12.0"
#elif __INTEL_COMPILER == 1210
#define KMP_COMPILER "Intel(R) C++ Compiler 12.1"
#elif __INTEL_COMPILER == 1300
#define KMP_COMPILER "Intel(R) C++ Compiler 13.0"
#elif __INTEL_COMPILER == 1310
#define KMP_COMPILER "Intel(R) C++ Compiler 13.1"
#elif __INTEL_COMPILER == 1400
#define KMP_COMPILER "Intel(R) C++ Compiler 14.0"
#elif __INTEL_COMPILER == 1410
#define KMP_COMPILER "Intel(R) C++ Compiler 14.1"
#elif __INTEL_COMPILER == 1500
#define KMP_COMPILER "Intel(R) C++ Compiler 15.0"
#elif __INTEL_COMPILER == 1600
#define KMP_COMPILER "Intel(R) C++ Compiler 16.0"
#elif __INTEL_COMPILER == 1700
#define KMP_COMPILER "Intel(R) C++ Compiler 17.0"
#elif __INTEL_COMPILER == 1800
#define KMP_COMPILER "Intel(R) C++ Compiler 18.0"
#elif __INTEL_COMPILER == 1900
#define KMP_COMPILER "Intel(R) C++ Compiler 19.0"
#elif __INTEL_COMPILER == 1910
#define KMP_COMPILER "Intel(R) C++ Compiler 19.1"
#elif __INTEL_COMPILER > 1910
#define KMP_COMPILER \
"Intel(R) C++ Compiler Classic " stringer(__INTEL_COMPILER) "." stringer( \
__INTEL_COMPILER_UPDATE)
#endif
#elif KMP_COMPILER_CLANG
#define KMP_COMPILER \
"Clang " stringer(__clang_major__) "." stringer(__clang_minor__)
#elif KMP_COMPILER_GCC
#define KMP_COMPILER "GCC " stringer(__GNUC__) "." stringer(__GNUC_MINOR__)
#elif KMP_COMPILER_MSVC
#define KMP_COMPILER "MSVC " stringer(_MSC_FULL_VER)
#endif
#ifndef KMP_COMPILER
#warning "Unknown compiler"
#define KMP_COMPILER "unknown compiler"
#endif
// Detect librray type (perf, stub).
#ifdef KMP_STUB
#define KMP_LIB_TYPE "stub"
#else
#define KMP_LIB_TYPE "performance"
#endif // KMP_LIB_TYPE
// Detect link type (static, dynamic).
#if KMP_DYNAMIC_LIB
#define KMP_LINK_TYPE "dynamic"
#else
#define KMP_LINK_TYPE "static"
#endif // KMP_LINK_TYPE
// Finally, define strings.
#define KMP_LIBRARY KMP_LIB_TYPE " library (" KMP_LINK_TYPE ")"
#define KMP_COPYRIGHT ""
int const __kmp_version_major = KMP_VERSION_MAJOR;
int const __kmp_version_minor = KMP_VERSION_MINOR;
int const __kmp_version_build = KMP_VERSION_BUILD;
int const __kmp_openmp_version = 201611;
/* Do NOT change the format of this string! Intel(R) Thread Profiler checks for
a specific format some changes in the recognition routine there need to be
made before this is changed. */
char const __kmp_copyright[] = KMP_VERSION_PREFIX KMP_LIBRARY
" ver. " stringer(KMP_VERSION_MAJOR) "." stringer(
KMP_VERSION_MINOR) "." stringer(KMP_VERSION_BUILD) " " KMP_COPYRIGHT;
char const __kmp_version_copyright[] = KMP_VERSION_PREFIX KMP_COPYRIGHT;
char const __kmp_version_lib_ver[] =
KMP_VERSION_PREFIX "version: " stringer(KMP_VERSION_MAJOR) "." stringer(
KMP_VERSION_MINOR) "." stringer(KMP_VERSION_BUILD);
char const __kmp_version_lib_type[] =
KMP_VERSION_PREFIX "library type: " KMP_LIB_TYPE;
char const __kmp_version_link_type[] =
KMP_VERSION_PREFIX "link type: " KMP_LINK_TYPE;
char const __kmp_version_build_time[] = KMP_VERSION_PREFIX "build time: "
"no_timestamp";
#if KMP_MIC2
char const __kmp_version_target_env[] =
KMP_VERSION_PREFIX "target environment: MIC2";
#endif
char const __kmp_version_build_compiler[] =
KMP_VERSION_PREFIX "build compiler: " KMP_COMPILER;
// Called at serial initialization time.
static int __kmp_version_1_printed = FALSE;
void __kmp_print_version_1(void) {
if (__kmp_version_1_printed) {
return;
}
__kmp_version_1_printed = TRUE;
#ifndef KMP_STUB
kmp_str_buf_t buffer;
__kmp_str_buf_init(&buffer);
// Print version strings skipping initial magic.
__kmp_str_buf_print(&buffer, "%s\n",
&__kmp_version_lib_ver[KMP_VERSION_MAGIC_LEN]);
__kmp_str_buf_print(&buffer, "%s\n",
&__kmp_version_lib_type[KMP_VERSION_MAGIC_LEN]);
__kmp_str_buf_print(&buffer, "%s\n",
&__kmp_version_link_type[KMP_VERSION_MAGIC_LEN]);
__kmp_str_buf_print(&buffer, "%s\n",
&__kmp_version_build_time[KMP_VERSION_MAGIC_LEN]);
#if KMP_MIC
__kmp_str_buf_print(&buffer, "%s\n",
&__kmp_version_target_env[KMP_VERSION_MAGIC_LEN]);
#endif
__kmp_str_buf_print(&buffer, "%s\n",
&__kmp_version_build_compiler[KMP_VERSION_MAGIC_LEN]);
#if defined(KMP_GOMP_COMPAT)
__kmp_str_buf_print(&buffer, "%s\n",
&__kmp_version_alt_comp[KMP_VERSION_MAGIC_LEN]);
#endif /* defined(KMP_GOMP_COMPAT) */
__kmp_str_buf_print(&buffer, "%s\n",
&__kmp_version_omp_api[KMP_VERSION_MAGIC_LEN]);
__kmp_str_buf_print(&buffer, "%sdynamic error checking: %s\n",
KMP_VERSION_PREF_STR,
(__kmp_env_consistency_check ? "yes" : "no"));
#ifdef KMP_DEBUG
for (int i = bs_plain_barrier; i < bs_last_barrier; ++i) {
__kmp_str_buf_print(
&buffer, "%s%s barrier branch bits: gather=%u, release=%u\n",
KMP_VERSION_PREF_STR, __kmp_barrier_type_name[i],
__kmp_barrier_gather_branch_bits[i],
__kmp_barrier_release_branch_bits[i]); // __kmp_str_buf_print
}
for (int i = bs_plain_barrier; i < bs_last_barrier; ++i) {
__kmp_str_buf_print(
&buffer, "%s%s barrier pattern: gather=%s, release=%s\n",
KMP_VERSION_PREF_STR, __kmp_barrier_type_name[i],
__kmp_barrier_pattern_name[__kmp_barrier_gather_pattern[i]],
__kmp_barrier_pattern_name
[__kmp_barrier_release_pattern[i]]); // __kmp_str_buf_print
}
__kmp_str_buf_print(&buffer, "%s\n",
&__kmp_version_lock[KMP_VERSION_MAGIC_LEN]);
#endif
__kmp_str_buf_print(
&buffer, "%sthread affinity support: %s\n", KMP_VERSION_PREF_STR,
#if KMP_AFFINITY_SUPPORTED
(KMP_AFFINITY_CAPABLE()
? (__kmp_affinity.type == affinity_none ? "not used" : "yes")
: "no")
#else
"no"
#endif
);
__kmp_printf("%s", buffer.str);
__kmp_str_buf_free(&buffer);
K_DIAG(1, ("KMP_VERSION is true\n"));
#endif // KMP_STUB
} // __kmp_print_version_1
// Called at parallel initialization time.
static int __kmp_version_2_printed = FALSE;
void __kmp_print_version_2(void) {
if (__kmp_version_2_printed) {
return;
}
__kmp_version_2_printed = TRUE;
} // __kmp_print_version_2
// end of file //

66
third_party/openmp/kmp_version.h vendored Normal file
View file

@ -0,0 +1,66 @@
/*
* kmp_version.h -- version number for this release
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef KMP_VERSION_H
#define KMP_VERSION_H
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#ifndef KMP_VERSION_MAJOR
#error KMP_VERSION_MAJOR macro is not defined.
#endif
#define KMP_VERSION_MINOR 0
/* Using "magic" prefix in all the version strings is rather convenient to get
static version info from binaries by using standard utilities "strings" and
"grep", e. g.:
$ strings libomp.so | grep "@(#)"
gives clean list of all version strings in the library. Leading zero helps
to keep version string separate from printable characters which may occurs
just before version string. */
#define KMP_VERSION_MAGIC_STR "\x00@(#) "
#define KMP_VERSION_MAGIC_LEN 6 // Length of KMP_VERSION_MAGIC_STR.
#define KMP_VERSION_PREF_STR "LLVM OMP "
#define KMP_VERSION_PREFIX KMP_VERSION_MAGIC_STR KMP_VERSION_PREF_STR
/* declare all the version string constants for KMP_VERSION env. variable */
extern int const __kmp_version_major;
extern int const __kmp_version_minor;
extern int const __kmp_version_build;
extern int const __kmp_openmp_version;
extern char const
__kmp_copyright[]; // Old variable, kept for compatibility with ITC and ITP.
extern char const __kmp_version_copyright[];
extern char const __kmp_version_lib_ver[];
extern char const __kmp_version_lib_type[];
extern char const __kmp_version_link_type[];
extern char const __kmp_version_build_time[];
extern char const __kmp_version_target_env[];
extern char const __kmp_version_build_compiler[];
extern char const __kmp_version_alt_comp[];
extern char const __kmp_version_omp_api[];
// ??? extern char const __kmp_version_debug[];
extern char const __kmp_version_lock[];
extern char const __kmp_version_nested_stats_reporting[];
extern char const __kmp_version_ftnstdcall[];
extern char const __kmp_version_ftncdecl[];
extern char const __kmp_version_ftnextra[];
void __kmp_print_version_1(void);
void __kmp_print_version_2(void);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif /* KMP_VERSION_H */

51
third_party/openmp/kmp_wait_release.cpp vendored Normal file
View file

@ -0,0 +1,51 @@
/*
* kmp_wait_release.cpp -- Wait/Release implementation
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "kmp_wait_release.h"
void __kmp_wait_64(kmp_info_t *this_thr, kmp_flag_64<> *flag,
int final_spin USE_ITT_BUILD_ARG(void *itt_sync_obj)) {
if (final_spin)
__kmp_wait_template<kmp_flag_64<>, TRUE>(
this_thr, flag USE_ITT_BUILD_ARG(itt_sync_obj));
else
__kmp_wait_template<kmp_flag_64<>, FALSE>(
this_thr, flag USE_ITT_BUILD_ARG(itt_sync_obj));
}
void __kmp_release_64(kmp_flag_64<> *flag) { __kmp_release_template(flag); }
#if KMP_HAVE_MWAIT || KMP_HAVE_UMWAIT
template <bool C, bool S>
void __kmp_mwait_32(int th_gtid, kmp_flag_32<C, S> *flag) {
__kmp_mwait_template(th_gtid, flag);
}
template <bool C, bool S>
void __kmp_mwait_64(int th_gtid, kmp_flag_64<C, S> *flag) {
__kmp_mwait_template(th_gtid, flag);
}
template <bool C, bool S>
void __kmp_atomic_mwait_64(int th_gtid, kmp_atomic_flag_64<C, S> *flag) {
__kmp_mwait_template(th_gtid, flag);
}
void __kmp_mwait_oncore(int th_gtid, kmp_flag_oncore *flag) {
__kmp_mwait_template(th_gtid, flag);
}
template void __kmp_mwait_32<false, false>(int, kmp_flag_32<false, false> *);
template void __kmp_mwait_64<false, true>(int, kmp_flag_64<false, true> *);
template void __kmp_mwait_64<true, false>(int, kmp_flag_64<true, false> *);
template void
__kmp_atomic_mwait_64<false, true>(int, kmp_atomic_flag_64<false, true> *);
template void
__kmp_atomic_mwait_64<true, false>(int, kmp_atomic_flag_64<true, false> *);
#endif

1051
third_party/openmp/kmp_wait_release.h vendored Normal file

File diff suppressed because it is too large Load diff

85
third_party/openmp/kmp_wrapper_getpid.h vendored Normal file
View file

@ -0,0 +1,85 @@
/*
* kmp_wrapper_getpid.h -- getpid() declaration.
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef KMP_WRAPPER_GETPID_H
#define KMP_WRAPPER_GETPID_H
#if KMP_OS_UNIX
// On Unix-like systems (Linux* OS and OS X*) getpid() is declared in standard
// headers.
#if !defined(KMP_OS_AIX)
#include <sys/syscall.h>
#endif
#include <sys/types.h>
#include <unistd.h>
#if KMP_OS_DARWIN
// OS X
#define __kmp_gettid() pthread_mach_thread_np(pthread_self())
#elif defined(__COSMOPOLITAN__)
#include "libc/calls/calls.h"
#define __kmp_gettid() gettid()
#elif KMP_OS_FREEBSD || KMP_OS_DRAGONFLY
#include <pthread_np.h>
#define __kmp_gettid() pthread_getthreadid_np()
#elif KMP_OS_NETBSD
#include <lwp.h>
#define __kmp_gettid() _lwp_self()
#elif KMP_OS_OPENBSD
#define __kmp_gettid() getthrid()
#elif KMP_OS_AIX
#include <pthread.h>
#define __kmp_gettid() pthread_self()
#elif defined(SYS_gettid)
// Hopefully other Unix systems define SYS_gettid syscall for getting os thread
// id
#define __kmp_gettid() syscall(SYS_gettid)
#else
#warning No gettid found, use getpid instead
#define __kmp_gettid() getpid()
#endif
#elif KMP_OS_WINDOWS
// On Windows* OS _getpid() returns int (not pid_t) and is declared in
// "process.h".
#include <process.h>
// Let us simulate Unix.
#if KMP_MSVC_COMPAT
typedef int pid_t;
#endif
#define getpid _getpid
#define __kmp_gettid() GetCurrentThreadId()
#else
#error Unknown or unsupported OS.
#endif
/* TODO: All the libomp source code uses pid_t type for storing the result of
getpid(), it is good. But often it printed as "%d", that is not good, because
it ignores pid_t definition (may pid_t be longer that int?). It seems all pid
prints should be rewritten as:
printf( "%" KMP_UINT64_SPEC, (kmp_uint64) pid );
or (at least) as
printf( "%" KMP_UINT32_SPEC, (kmp_uint32) pid );
(kmp_uint32, kmp_uint64, KMP_UINT64_SPEC, and KMP_UNIT32_SPEC are defined in
"kmp_os.h".) */
#endif // KMP_WRAPPER_GETPID_H
// end of file //

196
third_party/openmp/kmp_wrapper_malloc.h vendored Normal file
View file

@ -0,0 +1,196 @@
/*
* kmp_wrapper_malloc.h -- Wrappers for memory allocation routines
* (malloc(), free(), and others).
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef KMP_WRAPPER_MALLOC_H
#define KMP_WRAPPER_MALLOC_H
/* This header serves for 3 purposes:
1. Declaring standard memory allocation routines in OS-independent way.
2. Passing source location info through memory allocation wrappers.
3. Enabling native memory debugging capabilities.
1. Declaring standard memory allocation routines in OS-independent way.
-----------------------------------------------------------------------
On Linux* OS, alloca() function is declared in <alloca.h> header, while on
Windows* OS there is no <alloca.h> header, function _alloca() (note
underscore!) is declared in <malloc.h>. This header eliminates these
differences, so client code including "kmp_wrapper_malloc.h" can rely on
following routines:
malloc
calloc
realloc
free
alloca
in OS-independent way. It also enables memory tracking capabilities in debug
build. (Currently it is available only on Windows* OS.)
2. Passing source location info through memory allocation wrappers.
-------------------------------------------------------------------
Some tools may help debugging memory errors, for example, report memory
leaks. However, memory allocation wrappers may hinder source location.
For example:
void * aligned_malloc( int size ) {
void * ptr = malloc( size ); // All the memory leaks will be reported at
// this line.
// some adjustments...
return ptr;
};
ptr = aligned_malloc( size ); // Memory leak will *not* be detected here. :-(
To overcome the problem, information about original source location should
be passed through all the memory allocation wrappers, for example:
void * aligned_malloc( int size, char const * file, int line ) {
void * ptr = _malloc_dbg( size, file, line );
// some adjustments...
return ptr;
};
void * ptr = aligned_malloc( size, __FILE__, __LINE__ );
This is a good idea for debug, but passing additional arguments impacts
performance. Disabling extra arguments in release version of the software
introduces too many conditional compilation, which makes code unreadable.
This header defines few macros and functions facilitating it:
void * _aligned_malloc( int size KMP_SRC_LOC_DECL ) {
void * ptr = malloc_src_loc( size KMP_SRC_LOC_PARM );
// some adjustments...
return ptr;
};
#define aligned_malloc( size ) _aligned_malloc( (size) KMP_SRC_LOC_CURR )
// Use macro instead of direct call to function.
void * ptr = aligned_malloc( size ); // Bingo! Memory leak will be
// reported at this line.
3. Enabling native memory debugging capabilities.
-------------------------------------------------
Some platforms may offer memory debugging capabilities. For example, debug
version of Microsoft RTL tracks all memory allocations and can report memory
leaks. This header enables this, and makes report more useful (see "Passing
source location info through memory allocation wrappers").
*/
#include <stdlib.h>
#include "kmp_os.h"
// Include alloca() declaration.
#if KMP_OS_WINDOWS
#include <malloc.h> // Windows* OS: _alloca() declared in "malloc.h".
#if KMP_MSVC_COMPAT
#define alloca _alloca // Allow to use alloca() with no underscore.
#endif
#elif KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_OPENBSD
// Declared in "stdlib.h".
#elif KMP_OS_UNIX
#include <alloca.h> // Linux* OS and OS X*: alloc() declared in "alloca".
#else
#error Unknown or unsupported OS.
#endif
/* KMP_SRC_LOC_DECL -- Declaring source location parameters, to be used in
function declaration.
KMP_SRC_LOC_PARM -- Source location parameters, to be used to pass
parameters to underlying levels.
KMP_SRC_LOC_CURR -- Source location arguments describing current location,
to be used at top-level.
Typical usage:
void * _aligned_malloc( int size KMP_SRC_LOC_DECL ) {
// Note: Comma is missed before KMP_SRC_LOC_DECL.
KE_TRACE( 25, ( "called from %s:%d\n", KMP_SRC_LOC_PARM ) );
...
}
#define aligned_malloc( size ) _aligned_malloc( (size) KMP_SRC_LOC_CURR )
// Use macro instead of direct call to function -- macro passes info
// about current source location to the func.
*/
#if KMP_DEBUG
#define KMP_SRC_LOC_DECL , char const *_file_, int _line_
#define KMP_SRC_LOC_PARM , _file_, _line_
#define KMP_SRC_LOC_CURR , __FILE__, __LINE__
#else
#define KMP_SRC_LOC_DECL
#define KMP_SRC_LOC_PARM
#define KMP_SRC_LOC_CURR
#endif // KMP_DEBUG
/* malloc_src_loc() and free_src_loc() are pseudo-functions (really macros)
with accepts extra arguments (source location info) in debug mode. They
should be used in place of malloc() and free(), this allows enabling native
memory debugging capabilities (if any).
Typical usage:
ptr = malloc_src_loc( size KMP_SRC_LOC_PARM );
// Inside memory allocation wrapper, or
ptr = malloc_src_loc( size KMP_SRC_LOC_CURR );
// Outside of memory allocation wrapper.
*/
#define malloc_src_loc(args) _malloc_src_loc(args)
#define free_src_loc(args) _free_src_loc(args)
/* Depending on build mode (debug or release), malloc_src_loc is declared with
1 or 3 parameters, but calls to malloc_src_loc() are always the same:
... malloc_src_loc( size KMP_SRC_LOC_PARM ); // or KMP_SRC_LOC_CURR
Compiler issues warning/error "too few arguments in macro invocation".
Declaring two macros, malloc_src_loc() and _malloc_src_loc(), overcomes the
problem. */
#if KMP_DEBUG
#if KMP_OS_WINDOWS && _DEBUG && !defined(__MINGW32__)
// KMP_DEBUG != _DEBUG. MS debug RTL is available only if _DEBUG is defined.
// Windows* OS has native memory debugging capabilities. Enable them.
#include <crtdbg.h>
#define KMP_MEM_BLOCK _CLIENT_BLOCK
#define malloc(size) _malloc_dbg((size), KMP_MEM_BLOCK, __FILE__, __LINE__)
#define calloc(num, size) \
_calloc_dbg((num), (size), KMP_MEM_BLOCK, __FILE__, __LINE__)
#define realloc(ptr, size) \
_realloc_dbg((ptr), (size), KMP_MEM_BLOCK, __FILE__, __LINE__)
#define free(ptr) _free_dbg((ptr), KMP_MEM_BLOCK)
#define _malloc_src_loc(size, file, line) \
_malloc_dbg((size), KMP_MEM_BLOCK, (file), (line))
#define _free_src_loc(ptr, file, line) _free_dbg((ptr), KMP_MEM_BLOCK)
#else
// Linux* OS, OS X*, or non-debug Windows* OS.
#define _malloc_src_loc(size, file, line) malloc((size))
#define _free_src_loc(ptr, file, line) free((ptr))
#endif
#else
// In release build malloc_src_loc() and free_src_loc() do not have extra
// parameters.
#define _malloc_src_loc(size) malloc((size))
#define _free_src_loc(ptr) free((ptr))
#endif // KMP_DEBUG
#endif // KMP_WRAPPER_MALLOC_H
// end of file //

1417
third_party/openmp/omp-tools.h vendored Normal file

File diff suppressed because it is too large Load diff

521
third_party/openmp/omp.h vendored Normal file
View file

@ -0,0 +1,521 @@
/*
* include/omp.h.var
*/
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef __OMP_H
# define __OMP_H
# include <stddef.h>
# include <stdlib.h>
# include <stdint.h>
# define KMP_VERSION_MAJOR 5
# define KMP_VERSION_MINOR 0
# define KMP_VERSION_BUILD 31337
# define KMP_BUILD_DATE "2024-01-28"
# ifdef __cplusplus
extern "C" {
# endif
# define omp_set_affinity_format ompc_set_affinity_format
# define omp_get_affinity_format ompc_get_affinity_format
# define omp_display_affinity ompc_display_affinity
# define omp_capture_affinity ompc_capture_affinity
# if defined(_WIN32)
# define __KAI_KMPC_CONVENTION __cdecl
# ifndef __KMP_IMP
# define __KMP_IMP __declspec(dllimport)
# endif
# else
# define __KAI_KMPC_CONVENTION
# ifndef __KMP_IMP
# define __KMP_IMP
# endif
# endif
/* schedule kind constants */
typedef enum omp_sched_t {
omp_sched_static = 1,
omp_sched_dynamic = 2,
omp_sched_guided = 3,
omp_sched_auto = 4,
omp_sched_monotonic = 0x80000000
} omp_sched_t;
/* set API functions */
extern void __KAI_KMPC_CONVENTION omp_set_num_threads (int);
extern void __KAI_KMPC_CONVENTION omp_set_dynamic (int);
extern void __KAI_KMPC_CONVENTION omp_set_nested (int);
extern void __KAI_KMPC_CONVENTION omp_set_max_active_levels (int);
extern void __KAI_KMPC_CONVENTION omp_set_schedule (omp_sched_t, int);
/* query API functions */
extern int __KAI_KMPC_CONVENTION omp_get_num_threads (void);
extern int __KAI_KMPC_CONVENTION omp_get_dynamic (void);
extern int __KAI_KMPC_CONVENTION omp_get_nested (void);
extern int __KAI_KMPC_CONVENTION omp_get_max_threads (void);
extern int __KAI_KMPC_CONVENTION omp_get_thread_num (void);
extern int __KAI_KMPC_CONVENTION omp_get_num_procs (void);
extern int __KAI_KMPC_CONVENTION omp_in_parallel (void);
extern int __KAI_KMPC_CONVENTION omp_in_final (void);
extern int __KAI_KMPC_CONVENTION omp_get_active_level (void);
extern int __KAI_KMPC_CONVENTION omp_get_level (void);
extern int __KAI_KMPC_CONVENTION omp_get_ancestor_thread_num (int);
extern int __KAI_KMPC_CONVENTION omp_get_team_size (int);
extern int __KAI_KMPC_CONVENTION omp_get_thread_limit (void);
extern int __KAI_KMPC_CONVENTION omp_get_max_active_levels (void);
extern void __KAI_KMPC_CONVENTION omp_get_schedule (omp_sched_t *, int *);
extern int __KAI_KMPC_CONVENTION omp_get_max_task_priority (void);
/* lock API functions */
typedef struct omp_lock_t {
void * _lk;
} omp_lock_t;
extern void __KAI_KMPC_CONVENTION omp_init_lock (omp_lock_t *);
extern void __KAI_KMPC_CONVENTION omp_set_lock (omp_lock_t *);
extern void __KAI_KMPC_CONVENTION omp_unset_lock (omp_lock_t *);
extern void __KAI_KMPC_CONVENTION omp_destroy_lock (omp_lock_t *);
extern int __KAI_KMPC_CONVENTION omp_test_lock (omp_lock_t *);
/* nested lock API functions */
typedef struct omp_nest_lock_t {
void * _lk;
} omp_nest_lock_t;
extern void __KAI_KMPC_CONVENTION omp_init_nest_lock (omp_nest_lock_t *);
extern void __KAI_KMPC_CONVENTION omp_set_nest_lock (omp_nest_lock_t *);
extern void __KAI_KMPC_CONVENTION omp_unset_nest_lock (omp_nest_lock_t *);
extern void __KAI_KMPC_CONVENTION omp_destroy_nest_lock (omp_nest_lock_t *);
extern int __KAI_KMPC_CONVENTION omp_test_nest_lock (omp_nest_lock_t *);
/* OpenMP 5.0 Synchronization hints*/
typedef enum omp_sync_hint_t {
omp_sync_hint_none = 0,
omp_lock_hint_none = omp_sync_hint_none,
omp_sync_hint_uncontended = 1,
omp_lock_hint_uncontended = omp_sync_hint_uncontended,
omp_sync_hint_contended = (1<<1),
omp_lock_hint_contended = omp_sync_hint_contended,
omp_sync_hint_nonspeculative = (1<<2),
omp_lock_hint_nonspeculative = omp_sync_hint_nonspeculative,
omp_sync_hint_speculative = (1<<3),
omp_lock_hint_speculative = omp_sync_hint_speculative,
kmp_lock_hint_hle = (1<<16),
kmp_lock_hint_rtm = (1<<17),
kmp_lock_hint_adaptive = (1<<18)
} omp_sync_hint_t;
/* lock hint type for dynamic user lock */
typedef omp_sync_hint_t omp_lock_hint_t;
/* hinted lock initializers */
extern void __KAI_KMPC_CONVENTION omp_init_lock_with_hint(omp_lock_t *, omp_lock_hint_t);
extern void __KAI_KMPC_CONVENTION omp_init_nest_lock_with_hint(omp_nest_lock_t *, omp_lock_hint_t);
/* time API functions */
extern double __KAI_KMPC_CONVENTION omp_get_wtime (void);
extern double __KAI_KMPC_CONVENTION omp_get_wtick (void);
/* OpenMP 4.0 */
extern int __KAI_KMPC_CONVENTION omp_get_default_device (void);
extern void __KAI_KMPC_CONVENTION omp_set_default_device (int);
extern int __KAI_KMPC_CONVENTION omp_is_initial_device (void);
extern int __KAI_KMPC_CONVENTION omp_get_num_devices (void);
extern int __KAI_KMPC_CONVENTION omp_get_num_teams (void);
extern int __KAI_KMPC_CONVENTION omp_get_team_num (void);
extern int __KAI_KMPC_CONVENTION omp_get_cancellation (void);
/* OpenMP 4.5 */
extern int __KAI_KMPC_CONVENTION omp_get_initial_device (void);
extern void* __KAI_KMPC_CONVENTION omp_target_alloc(size_t, int);
extern void __KAI_KMPC_CONVENTION omp_target_free(void *, int);
extern int __KAI_KMPC_CONVENTION omp_target_is_present(const void *, int);
extern int __KAI_KMPC_CONVENTION omp_target_memcpy(void *, const void *, size_t, size_t, size_t, int, int);
extern int __KAI_KMPC_CONVENTION omp_target_memcpy_rect(void *, const void *, size_t, int, const size_t *,
const size_t *, const size_t *, const size_t *, const size_t *, int, int);
extern int __KAI_KMPC_CONVENTION omp_target_associate_ptr(const void *, const void *, size_t, size_t, int);
extern int __KAI_KMPC_CONVENTION omp_target_disassociate_ptr(const void *, int);
/* OpenMP 5.0 */
extern int __KAI_KMPC_CONVENTION omp_get_device_num (void);
typedef void * omp_depend_t;
/* OpenMP 5.1 interop */
typedef intptr_t omp_intptr_t;
/* 0..omp_get_num_interop_properties()-1 are reserved for implementation-defined properties */
typedef enum omp_interop_property {
omp_ipr_fr_id = -1,
omp_ipr_fr_name = -2,
omp_ipr_vendor = -3,
omp_ipr_vendor_name = -4,
omp_ipr_device_num = -5,
omp_ipr_platform = -6,
omp_ipr_device = -7,
omp_ipr_device_context = -8,
omp_ipr_targetsync = -9,
omp_ipr_first = -9
} omp_interop_property_t;
#define omp_interop_none 0
typedef enum omp_interop_rc {
omp_irc_no_value = 1,
omp_irc_success = 0,
omp_irc_empty = -1,
omp_irc_out_of_range = -2,
omp_irc_type_int = -3,
omp_irc_type_ptr = -4,
omp_irc_type_str = -5,
omp_irc_other = -6
} omp_interop_rc_t;
typedef enum omp_interop_fr {
omp_ifr_cuda = 1,
omp_ifr_cuda_driver = 2,
omp_ifr_opencl = 3,
omp_ifr_sycl = 4,
omp_ifr_hip = 5,
omp_ifr_level_zero = 6,
omp_ifr_last = 7
} omp_interop_fr_t;
typedef void * omp_interop_t;
/*!
* The `omp_get_num_interop_properties` routine retrieves the number of implementation-defined properties available for an `omp_interop_t` object.
*/
extern int __KAI_KMPC_CONVENTION omp_get_num_interop_properties(const omp_interop_t);
/*!
* The `omp_get_interop_int` routine retrieves an integer property from an `omp_interop_t` object.
*/
extern omp_intptr_t __KAI_KMPC_CONVENTION omp_get_interop_int(const omp_interop_t, omp_interop_property_t, int *);
/*!
* The `omp_get_interop_ptr` routine retrieves a pointer property from an `omp_interop_t` object.
*/
extern void * __KAI_KMPC_CONVENTION omp_get_interop_ptr(const omp_interop_t, omp_interop_property_t, int *);
/*!
* The `omp_get_interop_str` routine retrieves a string property from an `omp_interop_t` object.
*/
extern const char * __KAI_KMPC_CONVENTION omp_get_interop_str(const omp_interop_t, omp_interop_property_t, int *);
/*!
* The `omp_get_interop_name` routine retrieves a property name from an `omp_interop_t` object.
*/
extern const char * __KAI_KMPC_CONVENTION omp_get_interop_name(const omp_interop_t, omp_interop_property_t);
/*!
* The `omp_get_interop_type_desc` routine retrieves a description of the type of a property associated with an `omp_interop_t` object.
*/
extern const char * __KAI_KMPC_CONVENTION omp_get_interop_type_desc(const omp_interop_t, omp_interop_property_t);
/*!
* The `omp_get_interop_rc_desc` routine retrieves a description of the return code associated with an `omp_interop_t` object.
*/
extern const char * __KAI_KMPC_CONVENTION omp_get_interop_rc_desc(const omp_interop_t, omp_interop_rc_t);
/* OpenMP 5.1 device memory routines */
/*!
* The `omp_target_memcpy_async` routine asynchronously performs a copy between any combination of host and device pointers.
*/
extern int __KAI_KMPC_CONVENTION omp_target_memcpy_async(void *, const void *, size_t, size_t, size_t, int,
int, int, omp_depend_t *);
/*!
* The `omp_target_memcpy_rect_async` routine asynchronously performs a copy between any combination of host and device pointers.
*/
extern int __KAI_KMPC_CONVENTION omp_target_memcpy_rect_async(void *, const void *, size_t, int, const size_t *,
const size_t *, const size_t *, const size_t *, const size_t *, int, int,
int, omp_depend_t *);
/* OpenMP 6.0 device memory routines */
extern void * __KAI_KMPC_CONVENTION omp_target_memset(void *, int, size_t, int);
extern void * __KAI_KMPC_CONVENTION omp_target_memset_async(void *, int, size_t, int, int, omp_depend_t *);
/*!
* The `omp_get_mapped_ptr` routine returns the device pointer that is associated with a host pointer for a given device.
*/
extern void * __KAI_KMPC_CONVENTION omp_get_mapped_ptr(const void *, int);
extern int __KAI_KMPC_CONVENTION omp_target_is_accessible(const void *, size_t, int);
/* kmp API functions */
extern int __KAI_KMPC_CONVENTION kmp_get_stacksize (void);
extern void __KAI_KMPC_CONVENTION kmp_set_stacksize (int);
extern size_t __KAI_KMPC_CONVENTION kmp_get_stacksize_s (void);
extern void __KAI_KMPC_CONVENTION kmp_set_stacksize_s (size_t);
extern int __KAI_KMPC_CONVENTION kmp_get_blocktime (void);
extern int __KAI_KMPC_CONVENTION kmp_get_library (void);
extern void __KAI_KMPC_CONVENTION kmp_set_blocktime (int);
extern void __KAI_KMPC_CONVENTION kmp_set_library (int);
extern void __KAI_KMPC_CONVENTION kmp_set_library_serial (void);
extern void __KAI_KMPC_CONVENTION kmp_set_library_turnaround (void);
extern void __KAI_KMPC_CONVENTION kmp_set_library_throughput (void);
extern void __KAI_KMPC_CONVENTION kmp_set_defaults (char const *);
extern void __KAI_KMPC_CONVENTION kmp_set_disp_num_buffers (int);
/* Intel affinity API */
typedef void * kmp_affinity_mask_t;
extern int __KAI_KMPC_CONVENTION kmp_set_affinity (kmp_affinity_mask_t *);
extern int __KAI_KMPC_CONVENTION kmp_get_affinity (kmp_affinity_mask_t *);
extern int __KAI_KMPC_CONVENTION kmp_get_affinity_max_proc (void);
extern void __KAI_KMPC_CONVENTION kmp_create_affinity_mask (kmp_affinity_mask_t *);
extern void __KAI_KMPC_CONVENTION kmp_destroy_affinity_mask (kmp_affinity_mask_t *);
extern int __KAI_KMPC_CONVENTION kmp_set_affinity_mask_proc (int, kmp_affinity_mask_t *);
extern int __KAI_KMPC_CONVENTION kmp_unset_affinity_mask_proc (int, kmp_affinity_mask_t *);
extern int __KAI_KMPC_CONVENTION kmp_get_affinity_mask_proc (int, kmp_affinity_mask_t *);
/* OpenMP 4.0 affinity API */
typedef enum omp_proc_bind_t {
omp_proc_bind_false = 0,
omp_proc_bind_true = 1,
omp_proc_bind_master = 2,
omp_proc_bind_close = 3,
omp_proc_bind_spread = 4
} omp_proc_bind_t;
extern omp_proc_bind_t __KAI_KMPC_CONVENTION omp_get_proc_bind (void);
/* OpenMP 4.5 affinity API */
extern int __KAI_KMPC_CONVENTION omp_get_num_places (void);
extern int __KAI_KMPC_CONVENTION omp_get_place_num_procs (int);
extern void __KAI_KMPC_CONVENTION omp_get_place_proc_ids (int, int *);
extern int __KAI_KMPC_CONVENTION omp_get_place_num (void);
extern int __KAI_KMPC_CONVENTION omp_get_partition_num_places (void);
extern void __KAI_KMPC_CONVENTION omp_get_partition_place_nums (int *);
extern void * __KAI_KMPC_CONVENTION kmp_malloc (size_t);
extern void * __KAI_KMPC_CONVENTION kmp_aligned_malloc (size_t, size_t);
extern void * __KAI_KMPC_CONVENTION kmp_calloc (size_t, size_t);
extern void * __KAI_KMPC_CONVENTION kmp_realloc (void *, size_t);
extern void __KAI_KMPC_CONVENTION kmp_free (void *);
extern void __KAI_KMPC_CONVENTION kmp_set_warnings_on(void);
extern void __KAI_KMPC_CONVENTION kmp_set_warnings_off(void);
/* OpenMP 5.0 Tool Control */
typedef enum omp_control_tool_result_t {
omp_control_tool_notool = -2,
omp_control_tool_nocallback = -1,
omp_control_tool_success = 0,
omp_control_tool_ignored = 1
} omp_control_tool_result_t;
typedef enum omp_control_tool_t {
omp_control_tool_start = 1,
omp_control_tool_pause = 2,
omp_control_tool_flush = 3,
omp_control_tool_end = 4
} omp_control_tool_t;
extern int __KAI_KMPC_CONVENTION omp_control_tool(int, int, void*);
/* OpenMP 5.0 Memory Management */
typedef uintptr_t omp_uintptr_t;
typedef enum {
omp_atk_sync_hint = 1,
omp_atk_alignment = 2,
omp_atk_access = 3,
omp_atk_pool_size = 4,
omp_atk_fallback = 5,
omp_atk_fb_data = 6,
omp_atk_pinned = 7,
omp_atk_partition = 8
} omp_alloctrait_key_t;
typedef enum {
omp_atv_false = 0,
omp_atv_true = 1,
omp_atv_contended = 3,
omp_atv_uncontended = 4,
omp_atv_serialized = 5,
omp_atv_sequential = omp_atv_serialized, // (deprecated)
omp_atv_private = 6,
omp_atv_all = 7,
omp_atv_thread = 8,
omp_atv_pteam = 9,
omp_atv_cgroup = 10,
omp_atv_default_mem_fb = 11,
omp_atv_null_fb = 12,
omp_atv_abort_fb = 13,
omp_atv_allocator_fb = 14,
omp_atv_environment = 15,
omp_atv_nearest = 16,
omp_atv_blocked = 17,
omp_atv_interleaved = 18
} omp_alloctrait_value_t;
#define omp_atv_default ((omp_uintptr_t)-1)
typedef struct {
omp_alloctrait_key_t key;
omp_uintptr_t value;
} omp_alloctrait_t;
# if defined(_WIN32)
// On Windows cl and icl do not support 64-bit enum, let's use integer then.
typedef omp_uintptr_t omp_allocator_handle_t;
extern __KMP_IMP omp_allocator_handle_t const omp_null_allocator;
extern __KMP_IMP omp_allocator_handle_t const omp_default_mem_alloc;
extern __KMP_IMP omp_allocator_handle_t const omp_large_cap_mem_alloc;
extern __KMP_IMP omp_allocator_handle_t const omp_const_mem_alloc;
extern __KMP_IMP omp_allocator_handle_t const omp_high_bw_mem_alloc;
extern __KMP_IMP omp_allocator_handle_t const omp_low_lat_mem_alloc;
extern __KMP_IMP omp_allocator_handle_t const omp_cgroup_mem_alloc;
extern __KMP_IMP omp_allocator_handle_t const omp_pteam_mem_alloc;
extern __KMP_IMP omp_allocator_handle_t const omp_thread_mem_alloc;
extern __KMP_IMP omp_allocator_handle_t const llvm_omp_target_host_mem_alloc;
extern __KMP_IMP omp_allocator_handle_t const llvm_omp_target_shared_mem_alloc;
extern __KMP_IMP omp_allocator_handle_t const llvm_omp_target_device_mem_alloc;
typedef omp_uintptr_t omp_memspace_handle_t;
extern __KMP_IMP omp_memspace_handle_t const omp_default_mem_space;
extern __KMP_IMP omp_memspace_handle_t const omp_large_cap_mem_space;
extern __KMP_IMP omp_memspace_handle_t const omp_const_mem_space;
extern __KMP_IMP omp_memspace_handle_t const omp_high_bw_mem_space;
extern __KMP_IMP omp_memspace_handle_t const omp_low_lat_mem_space;
extern __KMP_IMP omp_memspace_handle_t const llvm_omp_target_host_mem_space;
extern __KMP_IMP omp_memspace_handle_t const llvm_omp_target_shared_mem_space;
extern __KMP_IMP omp_memspace_handle_t const llvm_omp_target_device_mem_space;
# else
# if __cplusplus >= 201103
typedef enum omp_allocator_handle_t : omp_uintptr_t
# else
typedef enum omp_allocator_handle_t
# endif
{
omp_null_allocator = 0,
omp_default_mem_alloc = 1,
omp_large_cap_mem_alloc = 2,
omp_const_mem_alloc = 3,
omp_high_bw_mem_alloc = 4,
omp_low_lat_mem_alloc = 5,
omp_cgroup_mem_alloc = 6,
omp_pteam_mem_alloc = 7,
omp_thread_mem_alloc = 8,
llvm_omp_target_host_mem_alloc = 100,
llvm_omp_target_shared_mem_alloc = 101,
llvm_omp_target_device_mem_alloc = 102,
KMP_ALLOCATOR_MAX_HANDLE = UINTPTR_MAX
} omp_allocator_handle_t;
# if __cplusplus >= 201103
typedef enum omp_memspace_handle_t : omp_uintptr_t
# else
typedef enum omp_memspace_handle_t
# endif
{
omp_default_mem_space = 0,
omp_large_cap_mem_space = 1,
omp_const_mem_space = 2,
omp_high_bw_mem_space = 3,
omp_low_lat_mem_space = 4,
llvm_omp_target_host_mem_space = 100,
llvm_omp_target_shared_mem_space = 101,
llvm_omp_target_device_mem_space = 102,
KMP_MEMSPACE_MAX_HANDLE = UINTPTR_MAX
} omp_memspace_handle_t;
# endif
extern omp_allocator_handle_t __KAI_KMPC_CONVENTION omp_init_allocator(omp_memspace_handle_t m,
int ntraits, omp_alloctrait_t traits[]);
extern void __KAI_KMPC_CONVENTION omp_destroy_allocator(omp_allocator_handle_t allocator);
extern void __KAI_KMPC_CONVENTION omp_set_default_allocator(omp_allocator_handle_t a);
extern omp_allocator_handle_t __KAI_KMPC_CONVENTION omp_get_default_allocator(void);
# ifdef __cplusplus
extern void *__KAI_KMPC_CONVENTION omp_alloc(size_t size, omp_allocator_handle_t a = omp_null_allocator);
extern void *__KAI_KMPC_CONVENTION omp_aligned_alloc(size_t align, size_t size,
omp_allocator_handle_t a = omp_null_allocator);
extern void *__KAI_KMPC_CONVENTION omp_calloc(size_t nmemb, size_t size,
omp_allocator_handle_t a = omp_null_allocator);
extern void *__KAI_KMPC_CONVENTION omp_aligned_calloc(size_t align, size_t nmemb, size_t size,
omp_allocator_handle_t a = omp_null_allocator);
extern void *__KAI_KMPC_CONVENTION omp_realloc(void *ptr, size_t size,
omp_allocator_handle_t allocator = omp_null_allocator,
omp_allocator_handle_t free_allocator = omp_null_allocator);
extern void __KAI_KMPC_CONVENTION omp_free(void * ptr, omp_allocator_handle_t a = omp_null_allocator);
# else
extern void *__KAI_KMPC_CONVENTION omp_alloc(size_t size, omp_allocator_handle_t a);
extern void *__KAI_KMPC_CONVENTION omp_aligned_alloc(size_t align, size_t size,
omp_allocator_handle_t a);
extern void *__KAI_KMPC_CONVENTION omp_calloc(size_t nmemb, size_t size, omp_allocator_handle_t a);
extern void *__KAI_KMPC_CONVENTION omp_aligned_calloc(size_t align, size_t nmemb, size_t size,
omp_allocator_handle_t a);
extern void *__KAI_KMPC_CONVENTION omp_realloc(void *ptr, size_t size, omp_allocator_handle_t allocator,
omp_allocator_handle_t free_allocator);
extern void __KAI_KMPC_CONVENTION omp_free(void *ptr, omp_allocator_handle_t a);
# endif
/* OpenMP 5.0 Affinity Format */
extern void __KAI_KMPC_CONVENTION omp_set_affinity_format(char const *);
extern size_t __KAI_KMPC_CONVENTION omp_get_affinity_format(char *, size_t);
extern void __KAI_KMPC_CONVENTION omp_display_affinity(char const *);
extern size_t __KAI_KMPC_CONVENTION omp_capture_affinity(char *, size_t, char const *);
/* OpenMP 5.0 events */
# if defined(_WIN32)
// On Windows cl and icl do not support 64-bit enum, let's use integer then.
typedef omp_uintptr_t omp_event_handle_t;
# else
typedef enum omp_event_handle_t { KMP_EVENT_MAX_HANDLE = UINTPTR_MAX } omp_event_handle_t;
# endif
extern void __KAI_KMPC_CONVENTION omp_fulfill_event ( omp_event_handle_t event );
/* OpenMP 5.0 Pause Resources */
typedef enum omp_pause_resource_t {
omp_pause_resume = 0,
omp_pause_soft = 1,
omp_pause_hard = 2
} omp_pause_resource_t;
extern int __KAI_KMPC_CONVENTION omp_pause_resource(omp_pause_resource_t, int);
extern int __KAI_KMPC_CONVENTION omp_pause_resource_all(omp_pause_resource_t);
extern int __KAI_KMPC_CONVENTION omp_get_supported_active_levels(void);
/* OpenMP 5.1 */
extern void __KAI_KMPC_CONVENTION omp_set_num_teams(int num_teams);
extern int __KAI_KMPC_CONVENTION omp_get_max_teams(void);
extern void __KAI_KMPC_CONVENTION omp_set_teams_thread_limit(int limit);
extern int __KAI_KMPC_CONVENTION omp_get_teams_thread_limit(void);
/* OpenMP 5.1 Display Environment */
extern void omp_display_env(int verbose);
# if defined(_OPENMP) && _OPENMP >= 201811
#pragma omp begin declare variant match(device={kind(host)})
static inline int omp_is_initial_device(void) { return 1; }
#pragma omp end declare variant
#pragma omp begin declare variant match(device={kind(nohost)})
static inline int omp_is_initial_device(void) { return 0; }
#pragma omp end declare variant
# endif
/* OpenMP 5.2 */
extern int __KAI_KMPC_CONVENTION omp_in_explicit_task(void);
/* LLVM Extensions */
extern void *llvm_omp_target_dynamic_shared_alloc(void);
# undef __KAI_KMPC_CONVENTION
# undef __KMP_IMP
/* Warning:
The following typedefs are not standard, deprecated and will be removed in a future release.
*/
typedef int omp_int_t;
typedef double omp_wtime_t;
# ifdef __cplusplus
}
# endif
#endif /* __OMP_H */

Some files were not shown because too many files have changed in this diff Show more