Merge branch 'master' of github.com:solisoft/cosmopolitan into feature/OnErrorHook

This commit is contained in:
BONNAURE Olivier 2024-02-05 20:27:34 +01:00
commit 6a76293c4f
795 changed files with 95733 additions and 1673 deletions

View file

@ -116,7 +116,7 @@ ZIPCOPY = build/bootstrap/zipcopy.com
PECHECK = build/bootstrap/pecheck.com
FIXUPOBJ = build/bootstrap/fixupobj.com
MKDIR = build/bootstrap/mkdir.com -p
COMPILE = build/bootstrap/compile.com -V9 -P4096 $(QUOTA)
COMPILE = build/bootstrap/compile.com -V9 -M2048m -P8192 $(QUOTA)
IGNORE := $(shell $(MKDIR) $(TMPDIR))
@ -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,8 @@ COSMOCC_PKGS = \
THIRD_PARTY_AARCH64 \
THIRD_PARTY_LIBCXX \
THIRD_PARTY_LIBCXXABI \
THIRD_PARTY_LIBUNWIND \
THIRD_PARTY_OPENMP \
THIRD_PARTY_INTEL
o/$(MODE)/cosmopolitan.a: \

View file

@ -173,8 +173,6 @@ o/$(MODE)/ape/ape-no-modify-self.o: \
libc/runtime/mman.internal.h \
libc/runtime/pc.internal.h \
libc/sysv/consts/prot.h \
ape/blink-linux-aarch64.gz \
ape/blink-xnu-aarch64.gz \
o/$(MODE)/ape/ape.elf
@$(COMPILE) \
-AOBJECTIFY.S \
@ -202,9 +200,7 @@ o/$(MODE)/ape/ape-copy-self.o: \
libc/runtime/e820.internal.h \
libc/runtime/mman.internal.h \
libc/runtime/pc.internal.h \
libc/sysv/consts/prot.h \
ape/blink-linux-aarch64.gz \
ape/blink-xnu-aarch64.gz
libc/sysv/consts/prot.h
@$(COMPILE) \
-AOBJECTIFY.S \
$(OBJECTIFY.S) \
@ -263,10 +259,6 @@ endif
o/$(MODE)/ape/ape.o: ape/ape.S
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
o/$(MODE)/ape/ape.o: \
ape/blink-linux-aarch64.gz \
ape/blink-xnu-aarch64.gz
o/$(MODE)/ape/ape.lds: \
ape/ape.lds \
ape/macros.internal.h \

View file

@ -700,36 +700,9 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang
#endif /* APE_NO_MODIFY_SELF */
.ascii "exit $?\n"
.ascii "fi\n" // x86_64
// ...
// decentralized section (.apesh)
// ...
.ascii "PHDRS='' <<'@'\n"
.endobj apesh
// elf program headers get inserted here
// because they need to be in the first 4096 bytes
.section .emushprologue,"a",@progbits
emush: .ascii "\n@\n#'\"\n"
.ascii "s=$(uname -s 2>/dev/null) || s=Darwin\n"
// our script is running on a non-x86_64 architecture
// 1. `dd` out the appropriate blink vm blob
// 2. gunzip the blink virtual machine executable
// 3. relaunch this program inside the blink vm
.ascii "o=\"$(command -v \"$0\")\"\n"
.ascii "e=\"${TMPDIR:-${HOME:-.}}/.ape-blink-1.0.0\"\n"
.previous
// ...
// decentralized section (.emush)
// - __static_yoink("blink_linux_aarch64"); // for raspberry pi
// - __static_yoink("blink_xnu_aarch64"); // is apple silicon
// ...
.section .emushepilogue,"a",@progbits
.ascii "echo \"$0: this ape binary lacks $m support\" >&2\n"
.rept 16
.ascii "exit 127\n"
.endr
.ascii "echo error: this ape binary only supports x86_64 >&2\n"
.ascii "exit 1\n"
.previous
.endobj apesh
#ifdef APE_LOADER
.section .ape.loader,"a",@progbits

View file

@ -229,7 +229,6 @@ SECTIONS {
/* Real Mode */
KEEP(*(.head))
KEEP(*(.apesh))
KEEP(*(.text.head))
/* Executable & Linkable Format */
@ -238,10 +237,6 @@ SECTIONS {
KEEP(*(.elf.phdrs))
ape_phdrs_end = .;
KEEP(*(.emushprologue))
KEEP(*(.emush))
KEEP(*(.emushepilogue))
/* OpenBSD */
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
ape_note = .;
@ -301,7 +296,6 @@ SECTIONS {
KEEP(*(.textwindowsprologue))
*(.text.windows)
KEEP(*(.textwindowsepilogue))
KEEP(*(.blink))
*(SORT_BY_ALIGNMENT(.text.modernity))
*(SORT_BY_ALIGNMENT(.text.modernity.*))
*(SORT_BY_ALIGNMENT(.text.hot))
@ -613,29 +607,6 @@ SHSTUB2(ape_loader_dd_count,
? ROUNDUP(ape_loader_end - ape_loader, CONSTANT(COMMONPAGESIZE)) / 64
: 0);
#if defined(APE_IS_SHELL_SCRIPT) && !IsTiny()
#define IDENTITY(X) X
#define APE_DECLARE_FIXED_DECIMAL(F, X) \
X##_quad = DEFINED(X) ? ((F(X) < 1000000000 ? 32 : F(X) / 1000000000 % 10 + 48) << 000 | \
(F(X) < 100000000 ? 32 : F(X) / 100000000 % 10 + 48) << 010 | \
(F(X) < 10000000 ? 32 : F(X) / 10000000 % 10 + 48) << 020 | \
(F(X) < 1000000 ? 32 : F(X) / 1000000 % 10 + 48) << 030 | \
(F(X) < 100000 ? 32 : F(X) / 100000 % 10 + 48) << 040 | \
(F(X) < 10000 ? 32 : F(X) / 10000 % 10 + 48) << 050 | \
(F(X) < 1000 ? 32 : F(X) / 1000 % 10 + 48) << 060 | \
(F(X) < 100 ? 32 : F(X) / 100 % 10 + 48) << 070) : 0; \
X##_short = DEFINED(X) ? ((F(X) < 10 ? 32 : F(X) / 10 % 10 + 48) << 000 | \
(F(X) % 10 + 48) << 010) : 0
APE_DECLARE_FIXED_DECIMAL(RVA, blink_linux_aarch64);
APE_DECLARE_FIXED_DECIMAL(IDENTITY, blink_linux_aarch64_size);
APE_DECLARE_FIXED_DECIMAL(RVA, blink_xnu_aarch64);
APE_DECLARE_FIXED_DECIMAL(IDENTITY, blink_xnu_aarch64_size);
#endif /* APE_IS_SHELL_SCRIPT */
#if SupportsMetal()
v_ape_realsectors = MIN(0x70000 - IMAGE_BASE_REAL, ROUNDUP(RVA(_ezip), 512)) / 512;
v_ape_realbytes = v_ape_realsectors * 512;

View file

@ -59,9 +59,7 @@ for x in .ape \
.ape-1.7 \
.ape-1.8 \
.ape-1.9 \
.ape-1.10 \
.ape-blink-0.9.2 \
.ape-blink-1.0.0; do
.ape-1.10; do
rm -f \
~/$x \
/tmp/$x \

Binary file not shown.

Binary file not shown.

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) $<

View file

@ -152,7 +152,6 @@ o/$(MODE)/examples/picol.com.dbg: \
$(APE_NO_MODIFY_SELF)
@$(APELINK)
o/$(MODE)/examples/nesemu1.o: private QUOTA += -M512m
o/$(MODE)/usr/share/dict/words.zip.o: private ZIPOBJ_FLAGS += -C2
$(EXAMPLES_OBJS): examples/BUILD.mk

View file

@ -142,6 +142,9 @@ libc/isystem/nsync_once.h \
libc/isystem/nsync_time.h \
libc/isystem/nsync_waiter.h \
libc/isystem/numeric \
libc/isystem/omp-tools.h \
libc/isystem/omp.h \
libc/isystem/ompx.h \
libc/isystem/optional \
libc/isystem/ostream \
libc/isystem/paths.h \
@ -251,6 +254,7 @@ libc/isystem/uio.h \
libc/isystem/unistd.h \
libc/isystem/unordered_map \
libc/isystem/unordered_set \
libc/isystem/unwind.h \
libc/isystem/utility \
libc/isystem/utime.h \
libc/isystem/utmp.h \
@ -273,6 +277,8 @@ LIBC_INCS = $(filter %.inc,$(LIBC_FILES))
LIBC_CHECKS = $(LIBC_HDRS_H:%=o/$(MODE)/%.ok)
LIBC_FILES := $(wildcard libc/*)
o/$(MODE)/libc/isystem/ompx.h.ok: private CPPFLAGS += -Wno-unknown-pragmas
.PHONY: o/$(MODE)/libc
o/$(MODE)/libc: o/$(MODE)/libc/calls \
o/$(MODE)/libc/crt \

View file

@ -24,11 +24,15 @@
/**
* Returns true if process is running under qemu-x86_64 or qemu-aarch64.
*/
int IsQemu(void) {
int IsQemuUser(void) {
static char rplus1;
if (!rplus1) {
// qemu doesn't validate the advice argument
// we could also check if __getcwd(0, 0) raises efault
int e = errno;
int r = !sys_madvise(__executable_start, 16384, 127);
errno = e;
return r;
rplus1 = r + 1;
}
return rplus1 - 1;
}

View file

@ -1,7 +1,7 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi
/*-*- 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 2023 Justine Alexandra Roberts Tunney
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
@ -16,43 +16,32 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.internal.h"
#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"
// Blink Virtual Machine for Apple Silicon
//
// If you want to support Apple M1 by embedding an emulator in
// your APE binary that runs automatically, then put this:
//
// __static_yoink("blink_xnu_aarch64");
//
// In your main.c file, to pull it into linkage from the static
// archive. Alternatively, you may simply add blink_xnu_aarch64.o
// as an explicit linker argument.
int sys_getcpu(unsigned *opt_cpu, unsigned *opt_node, void *tcache);
.section .blink,"a",@progbits
.globl blink_xnu_aarch64_size
blink_xnu_aarch64:
.incbin "ape/blink-xnu-aarch64.gz"
.endobj blink_xnu_aarch64,globl
blink_xnu_aarch64_size = . - blink_xnu_aarch64
.section .emush,"a",@progbits
.ascii "if [ \"$s\" = Darwin ] && [ \"$m\" = arm64 ]; then\n"
.ascii "if ! [ -x \"$e\" ]; then\n"
.ascii "echo \"extracting blink-darwin-aarch64 to ${e}\" >&2\n"
.ascii "dd if=\"$o\" bs=1 skip=$(("
.weak blink_xnu_aarch64_quad
.quad blink_xnu_aarch64_quad
.weak blink_xnu_aarch64_short
.short blink_xnu_aarch64_short
.ascii ")) count=$(("
.weak blink_xnu_aarch64_size_quad
.quad blink_xnu_aarch64_size_quad
.weak blink_xnu_aarch64_size_short
.short blink_xnu_aarch64_size_short
.ascii ")) conv=notrunc 2>/dev/null | gunzip >\"$e.$$\"\n"
.ascii "mv -f \"$e.$$\" \"$e\"\n"
.ascii "chmod +x \"$e\"\n"
.ascii "fi\n"
.ascii "exec \"$e\" \"$o\" \"$@\"\n"
.ascii "fi\n"
/**
* 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

@ -8,7 +8,7 @@ namespace __cxxabiv1 {
char *__cxa_demangle(const char *, char *, size_t *, int *);
int __cxa_atexit(void (*)(void *), void *, void *) paramsnonnull((1)) dontthrow;
int __cxa_thread_atexit(void *, void *, void *) dontthrow;
int __cxa_thread_atexit(void (*)(void *), void *, void *) dontthrow;
void __cxa_finalize(void *);
#ifdef __cplusplus

View file

@ -121,7 +121,7 @@ COSMOPOLITAN_C_START_
extern const int __hostos;
int IsQemu(void);
int IsQemuUser(void);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -649,8 +649,9 @@ void abort(void) wontreturn;
#pragma GCC diagnostic ignored "-Wformat-extra-args" /* todo: patch gcc */
#pragma GCC diagnostic ignored "-Wunused-function" /* contradicts dce */
#pragma GCC diagnostic ignored "-Wunused-const-variable" /* sooo ridiculous */
#pragma GCC diagnostic ignored "-Wbuiltin-declaration-mismatch"
#ifndef __cplusplus
#pragma GCC diagnostic ignored "-Wold-style-definition" /* orwellian bulls */
#pragma GCC diagnostic ignored "-Wold-style-definition" /* orwellian bullsh */
#endif
#ifndef __STRICT_ANSI__

View file

@ -103,7 +103,7 @@ void __get_main_stack(void **out_addr, size_t *out_size, int *out_guardsize) {
if (IsWindows()) {
*out_addr = (void *)GetStaticStackAddr(0);
*out_size = GetStaticStackSize();
*out_guardsize = GetGuardSize();
*out_guardsize = getauxval(AT_PAGESZ);
return;
}
int pagesz = getauxval(AT_PAGESZ);

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

@ -112,6 +112,13 @@ struct UbsanOverflowData {
struct UbsanTypeDescriptor *type;
};
struct UbsanDynamicTypeCacheMissData {
struct UbsanSourceLocation location;
struct UbsanTypeDescriptor *type;
void *TypeInfo;
unsigned char TypeCheckKind;
};
struct UbsanFloatCastOverflowData {
#if __GNUC__ + 0 >= 6
struct UbsanSourceLocation location;
@ -145,6 +152,8 @@ upcast of\0\
cast to virtual base of\0\
\0";
uintptr_t __ubsan_vptr_type_cache[128];
static int __ubsan_bits(struct UbsanTypeDescriptor *t) {
return 1 << (t->info >> 1);
}
@ -439,15 +448,22 @@ void __ubsan_handle_divrem_overflow_abort(
__ubsan_handle_divrem_overflow(loc);
}
static bool HandleDynamicTypeCacheMiss(
struct UbsanDynamicTypeCacheMissData *data, uintptr_t ptr, uintptr_t hash) {
return false; // TODO: implement me
}
void __ubsan_handle_dynamic_type_cache_miss(
const struct UbsanSourceLocation *loc) {
__ubsan_abort(loc, "dynamic type cache miss")();
__ubsan_unreachable();
struct UbsanDynamicTypeCacheMissData *data, uintptr_t ptr, uintptr_t hash) {
HandleDynamicTypeCacheMiss(data, ptr, hash);
}
void __ubsan_handle_dynamic_type_cache_miss_abort(
const struct UbsanSourceLocation *loc) {
__ubsan_handle_dynamic_type_cache_miss(loc);
struct UbsanDynamicTypeCacheMissData *data, uintptr_t ptr, uintptr_t hash) {
if (HandleDynamicTypeCacheMiss(data, ptr, hash)) {
__ubsan_abort(&data->location, "dynamic type cache miss")();
__ubsan_unreachable();
}
}
void __ubsan_handle_function_type_mismatch(

3
libc/isystem/omp-tools.h Normal file
View file

@ -0,0 +1,3 @@
#ifndef _OMP_TOOLS_H
#include "third_party/openmp/omp-tools.h"
#endif /* _OMP_TOOLS_H */

3
libc/isystem/omp.h Normal file
View file

@ -0,0 +1,3 @@
#ifndef _OMP_H
#include "third_party/openmp/omp.h"
#endif /* _OMP_H */

3
libc/isystem/ompx.h Normal file
View file

@ -0,0 +1,3 @@
#ifndef _OMPX_H
#include "third_party/openmp/ompx.h"
#endif /* _OMPX_H */

4
libc/isystem/unwind.h Normal file
View file

@ -0,0 +1,4 @@
#ifndef _UNWIND_H
#define _UNWIND_H
#include "third_party/libunwind/include/unwind.h"
#endif /* _UNWIND_H */

View file

@ -1,60 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi
Copyright 2023 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/macros.internal.h"
// Blink Virtual Machine for Linux Arm64
//
// If you want to support Raspberry Pi by embedding an emulator
// in your APE binary that runs automatically, then put this:
//
// __static_yoink("blink_linux_aarch64");
//
// In your main.c file, to pull it into linkage from the static
// archive. Alternatively, you may simply add blink_linux_aarch64.o
// as an explicit linker argument.
.section .blink,"a",@progbits
.globl blink_linux_aarch64_size
blink_linux_aarch64:
.incbin "ape/blink-linux-aarch64.gz"
.endobj blink_linux_aarch64,globl
blink_linux_aarch64_size = . - blink_linux_aarch64
.section .emush,"a",@progbits
.ascii "if [ \"$s\" = Linux ]; then\n"
.ascii "if [ \"$m\" = aarch64 ] || [ \"$m\" = arm64 ]; then\n"
.ascii "if ! [ -x \"$e\" ]; then\n"
.ascii "echo \"extracting blink-linux-aarch64 to ${e}\" >&2\n"
.ascii "dd if=\"$o\" bs=1 skip=$(("
.weak blink_linux_aarch64_quad
.quad blink_linux_aarch64_quad
.weak blink_linux_aarch64_short
.short blink_linux_aarch64_short
.ascii ")) count=$(("
.weak blink_linux_aarch64_size_quad
.quad blink_linux_aarch64_size_quad
.weak blink_linux_aarch64_size_short
.short blink_linux_aarch64_size_short
.ascii ")) conv=notrunc 2>/dev/null | gunzip >\"$e.$$\"\n"
.ascii "mv -f \"$e.$$\" \"$e\"\n"
.ascii "chmod +x \"$e\"\n"
.ascii "fi\n"
.ascii "exec \"$e\" \"$o\" \"$@\"\n"
.ascii "fi\n"
.ascii "fi\n"

View file

@ -31,28 +31,38 @@
// are quite toilsome.
//
// @see www.felixcloutier.com/x86/cpuid
kCpuids:.long 0,0,0,0 # EAX=0 (Basic Processor Info)
.long 0,0,0,0 # EAX=1 (Processor Info)
.long 0,0,0,0 # EAX=2
.long 0,0,0,0 # EAX=7 (Extended Features)
.long 0,0,0,0 # EAX=0x80000001 (NexGen32e)
.long 0,0,0,0 # EAX=0x80000007 (APM)
.long 0,0,0,0 # EAX=16h (CPU Frequency)
kCpuids:.long 0,0,0,0 // EAX=0 (Basic Processor Info)
.long 0,0,0,0 // EAX=1 (Processor Info)
.long 0,0,0,0 // EAX=2
.long 0,0,0,0 // EAX=7 (Extended Features)
.long 0,0,0,0 // EAX=0x80000001 (NexGen32e)
.long 0,0,0,0 // EAX=0x80000007 (APM)
.long 0,0,0,0 // EAX=16h (CPU Frequency)
.long 0,0,0,0 // EAX=7 ECX=1 (Extended Feats)
.endobj kCpuids,globl
.previous
.init.start 201,_init_kCpuids
push %rbx
push $0
push $0x16
push $0xffffffff80000007
push $0xffffffff80000001
push $1
push $7
push $0
push $0x16
push $0
push $0xffffffff80000007
push $0
push $0xffffffff80000001
push $0
push $7
push $0
push $2
push $0
push $1
mov %rdi,%r8
xor %eax,%eax
1: xor %ecx,%ecx
xor %ecx,%ecx
1: nop
#ifdef FEATURELESS
// It's been reported that GDB reverse debugging doesn't
// understand VEX encoding. The workaround is to put:
@ -62,6 +72,7 @@ kCpuids:.long 0,0,0,0 # EAX=0 (Basic Processor Info)
// Inside your ~/.cosmo.mk file.
xor %eax,%eax
xor %ebx,%ebx
xor %ecx,%ecx
xor %edx,%edx
#else
cpuid
@ -74,10 +85,11 @@ kCpuids:.long 0,0,0,0 # EAX=0 (Basic Processor Info)
xchg %eax,%edx
stosl
2: pop %rax
test %eax,%eax # EAX = stacklist->pop()
jz 3f # EAX 0 (EOL sentinel)
cmp KCPUIDS(0H,EAX)(%r8),%al # EAX CPUID.0 max leaf
jbe 1b # CPUID too new to probe
test %eax,%eax // EAX = stacklist->pop()
jz 3f // EAX 0 (EOL sentinel)
pop %rcx // HERE WE GO AGAIN CPUID
cmp KCPUIDS(0H,EAX)(%r8),%al // EAX CPUID.0 max leaf
jbe 1b // CPUID too new to probe
add $4*4,%rdi
jmp 2b
3: nop

View file

@ -8,7 +8,8 @@
#define KCPUIDS_80000001H 4
#define KCPUIDS_80000007H 5
#define KCPUIDS_16H 6
#define KCPUIDS_LEN 7
#define KCPUIDS_7H_1H 7
#define KCPUIDS_LEN 8
#define KCPUIDS_6H -1 /* TBD: Thermal and Power Management */
#define KCPUIDS_DH -1 /* TBD: Extended state features */
#define KCPUIDS_80000008H -1 /* TBD: AMD Miscellaneous */

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

@ -37,6 +37,18 @@
#define _X86_CC_AVXVNNI 0
#endif
#ifdef __AVXVNNIINT8__
#define _X86_CC_AVXVNNIINT8 1
#else
#define _X86_CC_AVXVNNIINT8 0
#endif
#ifdef __AVXVNNIINT16__
#define _X86_CC_AVXVNNIINT16 1
#else
#define _X86_CC_AVXVNNIINT16 0
#endif
#ifdef __AVX512F__
#define _X86_CC_AVX512F 1
#else

View file

@ -28,7 +28,9 @@
#define X86_ARCH_CAPABILITIES 7H, EDX, 29, 0
#define X86_AVX 1H, ECX, 28, _X86_CC_AVX /* sandybridge c. 2012 */
#define X86_AVX2 7H, EBX, 5, _X86_CC_AVX2 /* haswell c. 2013 */
#define X86_AVXVNNI 7H, EAX, 4, _X86_CC_AVXVNNI
#define X86_AVXVNNI 7H_1H, EAX, 4, _X86_CC_AVXVNNI
#define X86_AVXVNNIINT8 7H_1H, EDX, 4, _X86_CC_AVXVNNIINT8
#define X86_AVXVNNIINT16 7H_1H, EDX, 10, _X86_CC_AVXVNNIINT16
#define X86_AVX512BW 7H, EBX, 30, 0
#define X86_AVX512CD 7H, EBX, 28, 0
#define X86_AVX512DQ 7H, EBX, 17, 0

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

@ -23,6 +23,7 @@
#include "libc/runtime/memtrack.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/stack.h"
#include "libc/sysv/consts/auxv.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/prot.h"
@ -42,10 +43,13 @@
void *NewCosmoStack(void) {
char *p;
if ((p = mmap(0, GetStackSize(), PROT_READ | PROT_WRITE,
MAP_STACK | MAP_ANONYMOUS, -1, 0)) != MAP_FAILED) {
MAP_ANONYMOUS |
(IsAarch64() && IsLinux() && IsQemuUser() ? MAP_PRIVATE
: MAP_STACK),
-1, 0)) != MAP_FAILED) {
if (IsAsan()) {
__asan_poison(p + GetStackSize() - 16, 16, kAsanStackOverflow);
__asan_poison(p, GetGuardSize(), kAsanStackOverflow);
__asan_poison(p, getauxval(AT_PAGESZ), kAsanStackOverflow);
}
return p;
} else {

View file

@ -96,7 +96,7 @@ static void __zipos_generate_index(struct Zipos *zipos) {
zipos->index[i] = c;
}
// smoothsort() isn't the fastest algorithm, but it guarantees
// o(logn), won't smash the stack and doesn't depend on malloc
// o(nlogn) won't smash the stack and doesn't depend on malloc
smoothsort_r(zipos->index, zipos->records, sizeof(size_t),
__zipos_compare_names, zipos);
}

22
libc/sock/in6addr_any.c Normal file
View file

@ -0,0 +1,22 @@
/*-*- 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/sock/struct/sockaddr6.h"
#include "libc/sysv/consts/inaddr.h"
const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;

View file

@ -0,0 +1,22 @@
/*-*- 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/sock/struct/sockaddr6.h"
#include "libc/sysv/consts/inaddr.h"
const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;

View file

@ -17,4 +17,7 @@ struct sockaddr_in6 { /* Linux+NT ABI */
uint32_t sin6_scope_id; /* rfc2553 */
};
extern const struct in6_addr in6addr_any;
extern const struct in6_addr in6addr_loopback;
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SOCKADDR6_H_ */

View file

@ -237,7 +237,8 @@ int __vcscanf(int callback(void *), //
case 'F':
case 'g':
case 'G': // floating point number
if (!(charbytes == sizeof(char) || charbytes == sizeof(wchar_t))) {
if (!(charbytes == sizeof(char) ||
charbytes == sizeof(wchar_t))) {
items = -1;
goto Done;
}
@ -361,7 +362,8 @@ int __vcscanf(int callback(void *), //
c = BUFFER;
do {
bool isdigit = c >= '0' && c <= '9';
bool isletter = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
bool isletter =
(c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
if (!(c == '_' || isdigit || isletter)) {
goto Done;
}
@ -485,7 +487,11 @@ int __vcscanf(int callback(void *), //
continue;
ReportConsumed:
n_ptr = va_arg(va, int *);
if (c != -1) {
*n_ptr = consumed - 1; // minus lookahead
} else {
*n_ptr = consumed;
}
continue;
DecodeString:
bufsize = !width ? 32 : rawmode ? width : width + 1;
@ -545,7 +551,7 @@ int __vcscanf(int callback(void *), //
}
++items;
if (ismalloc) {
*va_arg(va, char **) = (void *) buf;
*va_arg(va, char **) = (void *)buf;
}
buf = NULL;
} else {

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

@ -21,7 +21,6 @@
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/intrin/bsf.h"
#include "libc/limits.h"
#include "libc/mem/alg.h"

View file

@ -38,7 +38,7 @@
errno_t pthread_attr_init(pthread_attr_t *attr) {
*attr = (pthread_attr_t){
.__stacksize = GetStackSize(),
.__guardsize = GetGuardSize(),
.__guardsize = getauxval(AT_PAGESZ),
};
return 0;
}

View file

@ -175,6 +175,7 @@ static errno_t pthread_create_impl(pthread_t *thread,
errno = e;
return EAGAIN;
}
dll_init(&pt->list);
pt->pt_start = start_routine;
pt->pt_arg = arg;
@ -215,7 +216,9 @@ static errno_t pthread_create_impl(pthread_t *thread,
_pthread_free(pt, false);
return EINVAL;
}
if (pt->pt_attr.__guardsize == pagesize) {
if (pt->pt_attr.__guardsize == pagesize &&
!(IsAarch64() && IsLinux() && IsQemuUser())) {
// MAP_GROWSDOWN doesn't work very well on qemu-aarch64
pt->pt_attr.__stackaddr =
mmap(0, pt->pt_attr.__stacksize, PROT_READ | PROT_WRITE,
MAP_STACK | MAP_ANONYMOUS, -1, 0);
@ -289,7 +292,6 @@ static errno_t pthread_create_impl(pthread_t *thread,
// add thread to global list
// we add it to the beginning since zombies go at the end
dll_init(&pt->list);
_pthread_lock();
dll_make_first(&_pthread_list, &pt->list);
_pthread_unlock();

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

@ -33,7 +33,7 @@ void SetUpOnce(void) {
}
TEST(__getcwd, zero) {
if (IsQemu()) return;
if (IsQemuUser()) return;
ASSERT_SYS(ERANGE, -1, __getcwd(0, 0));
}

View file

@ -122,7 +122,7 @@ TEST(GetProramExecutableName, weirdArgv0NullEnv) {
TEST(GetProgramExecutableName, movedSelf) {
if (skiptests) return;
if (IsAarch64() && IsQemu()) {
if (IsAarch64() && IsQemuUser()) {
// clang-format off
// TODO(mrdomino): fix: make -j8 m=aarch64 o/aarch64/test/libc/calls/getprogramexecutablename_test.com.ok
// possibly related to the intersection of binfmt_misc and qemu-aarch64

View file

@ -70,7 +70,7 @@ TEST(madvise, subPages) {
TEST(madvise, misalign) {
char *p;
if (!IsLinux()) return; // most platforms don't care
if (IsQemu()) return; // qemu claims to be linux but doesn't care
if (IsQemuUser()) return; // qemu claims to be linux but doesn't care
ASSERT_NE(MAP_FAILED, (p = mmap(0, FRAMESIZE, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)));
ASSERT_SYS(EINVAL, -1, madvise(p + 1, FRAMESIZE - 1, MADV_WILLNEED));
@ -79,7 +79,7 @@ TEST(madvise, misalign) {
TEST(madvise, badAdvice) {
char *p;
if (IsAarch64() && IsQemu()) return; // qemu doesn't validate advice
if (IsAarch64() && IsQemuUser()) return; // qemu doesn't validate advice
ASSERT_NE(MAP_FAILED, (p = mmap(0, FRAMESIZE, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)));
ASSERT_SYS(EINVAL, -1, madvise(p, FRAMESIZE, 127));
@ -88,7 +88,7 @@ TEST(madvise, badAdvice) {
TEST(madvise, missingMemory) {
if (!IsLinux()) return; // most platforms don't care
if (IsQemu()) return; // qemu claims to be linux but doesn't care
if (IsQemuUser()) return; // qemu claims to be linux but doesn't care
ASSERT_SYS(ENOMEM, -1,
madvise((char *)0x83483838000, FRAMESIZE, MADV_WILLNEED));
}

View file

@ -21,6 +21,7 @@
#include "libc/calls/struct/siginfo.h"
#include "libc/calls/struct/ucontext.internal.h"
#include "libc/calls/ucontext.h"
#include "libc/dce.h"
#include "libc/intrin/kprintf.h"
#include "libc/limits.h"
#include "libc/mem/gc.h"

View file

@ -23,7 +23,6 @@
#include "libc/limits.h"
#include "libc/macros.internal.h"
#include "libc/mem/gc.h"
#include "libc/mem/gc.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/sock/sock.h"
@ -126,7 +125,7 @@ TEST(writev, empty_stillPerformsIoOperation) {
ASSERT_NE(-1, (fd = open("file", O_RDONLY)));
errno = 0;
EXPECT_SYS(EBADF, -1, writev(fd, iov, ARRAYLEN(iov)));
if (!(IsAarch64() && IsQemu())) {
if (!(IsAarch64() && IsQemuUser())) {
EXPECT_EQ(-1, writev(fd, NULL, 0));
}
EXPECT_NE(-1, close(fd));

View file

@ -383,7 +383,8 @@ TEST(sscanf, floating_point_infinity) {
TEST(sscanf, floating_point_infinity_double_precision) {
double a = 666.666, b = a, c = b, d = c, e = d, f = e, g = f;
EXPECT_EQ(4, sscanf("inf +INF -iNf InF", "%lf %lf %lf %lf", &a, &b, &c, &d));
EXPECT_EQ(3, sscanf("+infinity -INFINITY iNfInItY", "%lf %lf %lf", &e, &f, &g));
EXPECT_EQ(3,
sscanf("+infinity -INFINITY iNfInItY", "%lf %lf %lf", &e, &f, &g));
EXPECT_TRUE(isinf(a));
EXPECT_TRUE(isinf(b));
EXPECT_TRUE(isinf(c));
@ -394,11 +395,14 @@ TEST(sscanf, floating_point_infinity_double_precision) {
}
TEST(sscanf, floating_point_documentation_examples) {
float a = 666.666f, b = a, c = b, d = c, e = d, f = e, g = f, h = g, i = h, j = i;
float a = 666.666f, b = a, c = b, d = c, e = d, f = e, g = f, h = g, i = h,
j = i;
EXPECT_EQ(2, sscanf("111.11 -2.22", "%f %f", &a, &b));
EXPECT_EQ(3, sscanf("Nan nan(2) inF", "%f %f %f", &c, &d, &e));
EXPECT_EQ(5, sscanf("0X1.BC70A3D70A3D7P+6 1.18973e+4932zzz -0.0000000123junk junk", "%f %f %f %f %f", &f, &g, &h, &i, &j));
EXPECT_EQ(
5, sscanf("0X1.BC70A3D70A3D7P+6 1.18973e+4932zzz -0.0000000123junk junk",
"%f %f %f %f %f", &f, &g, &h, &i, &j));
EXPECT_EQ(111.11f, a);
EXPECT_EQ(-2.22f, b);
@ -413,11 +417,14 @@ TEST(sscanf, floating_point_documentation_examples) {
}
TEST(sscanf, floating_point_documentation_examples_double_precision) {
double a = 666.666, b = a, c = b, d = c, e = d, f = e, g = f, h = g, i = h, j = i;
double a = 666.666, b = a, c = b, d = c, e = d, f = e, g = f, h = g, i = h,
j = i;
EXPECT_EQ(2, sscanf("111.11 -2.22", "%lf %lf", &a, &b));
EXPECT_EQ(3, sscanf("Nan nan(2) inF", "%lf %lf %lf", &c, &d, &e));
EXPECT_EQ(5, sscanf("0X1.BC70A3D70A3D7P+6 1.18973e+4932zzz -0.0000000123junk junk", "%lf %lf %lf %lf %lf", &f, &g, &h, &i, &j));
EXPECT_EQ(
5, sscanf("0X1.BC70A3D70A3D7P+6 1.18973e+4932zzz -0.0000000123junk junk",
"%lf %lf %lf %lf %lf", &f, &g, &h, &i, &j));
EXPECT_EQ(111.11, a);
EXPECT_EQ(-2.22, b);
@ -470,3 +477,16 @@ TEST(fscanf, wantDecimalButGotLetter_returnsZeroMatches) {
EXPECT_EQ(666, x);
fclose(f);
}
TEST(scanf, n) {
int rc;
unsigned int a, b, c, d, port, len;
rc = sscanf("1.2.3.4:1848", "%u.%u.%u.%u:%u%n", &a, &b, &c, &d, &port, &len);
ASSERT_EQ(5, rc);
ASSERT_EQ(1, a);
ASSERT_EQ(2, b);
ASSERT_EQ(3, c);
ASSERT_EQ(4, d);
ASSERT_EQ(1848, port);
ASSERT_EQ(12, len);
}

View file

@ -19,6 +19,7 @@
#include "libc/calls/calls.h"
#include "libc/calls/ucontext.h"
#include "libc/dce.h"
#include "libc/intrin/kprintf.h"
#include "libc/limits.h"
#include "libc/mem/gc.h"
#include "libc/nt/createfile.h"

View file

@ -12,10 +12,13 @@ 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_OPENMP
TEST_LIBCXX_DEPS := \
$(call uniq,$(foreach x,$(TEST_LIBCXX_DIRECTDEPS),$($(x))))
@ -34,6 +37,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 gemmk(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 gemm(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) {
gemmk<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((gemm<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

@ -0,0 +1,32 @@
-- Copyright 2022 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.
local secret1 = GetRandomBytes(32)
local public1 = Curve25519(secret1, "\9")
local secret2 = GetRandomBytes(32)
local public2 = Curve25519(secret2, "\9")
local secret3 = GetRandomBytes(32)
local public3 = Curve25519(secret3, "\9")
local shared_key1 = Curve25519(secret1, public2)
local shared_key2 = Curve25519(secret2, public1)
local shared_key3 = Curve25519(secret2, public3)
local shared_key4 = Curve25519(secret3, public2)
assert(shared_key1 == shared_key2)
assert(shared_key1 ~= shared_key3)
assert(shared_key2 ~= shared_key3)
assert(shared_key4 == shared_key3)

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

@ -74,8 +74,6 @@ o/$(MODE)/third_party/chibicc/test/%.o: \
$(CHIBICC)
@$(COMPILE) -wAOBJECTIFY.c $(CHIBICC) $(CHIBICC_FLAGS) $(OUTPUT_OPTION) -c $<
o/$(MODE)/third_party/chibicc/test/int128_test.o: private QUOTA = -M1024m
endif
.PHONY: o/$(MODE)/third_party/chibicc/test

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

@ -37,7 +37,8 @@ THIRD_PARTY_LIBUNWIND_A_SRCS_CC = \
THIRD_PARTY_LIBUNWIND_A_SRCS_C = \
third_party/libunwind/Unwind-sjlj.c \
third_party/libunwind/UnwindLevel1-gcc-ext.c \
third_party/libunwind/UnwindLevel1.c
third_party/libunwind/UnwindLevel1.c \
third_party/libunwind/gcc_personality_v0.c
THIRD_PARTY_LIBUNWIND_A_SRCS = \
$(THIRD_PARTY_LIBUNWIND_A_SRCS_C) \
@ -68,8 +69,18 @@ $(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 += \
-fexceptions \
-fno-sanitize=all \
-ffunction-sections \
-fdata-sections \
-D_LIBUNWIND_USE_DLADDR=0
$(THIRD_PARTY_LIBUNWIND_A_OBJS): private \
CXXFLAGS += \
-fexceptions \
-fno-sanitize=all \
-ffunction-sections \
-fdata-sections \
-D_LIBUNWIND_USE_DLADDR=0

View file

@ -12,5 +12,6 @@ ORIGIN
Date: Tue, 28 Nov 2023 09:52:28 +0100
LOCAL CHANGES
- Fixed `_Unwind_FunctionContext` struct to be ABI-compatible with code
generated by GCC.
- Fixed `_Unwind_FunctionContext` struct to be ABI-compatible with
code generated by GCC.

View file

@ -0,0 +1,236 @@
//===-- gcc_personality_v0.c - Implement __gcc_personality_v0 -------------===//
//
// 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 "third_party/libunwind/include/unwind.h"
#include "third_party/compiler_rt/int_lib.h"
// Pointer encodings documented at:
// http://refspecs.freestandards.org/LSB_1.3.0/gLSB/gLSB/ehframehdr.html
#define DW_EH_PE_omit 0xff // no data follows
#define DW_EH_PE_absptr 0x00
#define DW_EH_PE_uleb128 0x01
#define DW_EH_PE_udata2 0x02
#define DW_EH_PE_udata4 0x03
#define DW_EH_PE_udata8 0x04
#define DW_EH_PE_sleb128 0x09
#define DW_EH_PE_sdata2 0x0A
#define DW_EH_PE_sdata4 0x0B
#define DW_EH_PE_sdata8 0x0C
#define DW_EH_PE_pcrel 0x10
#define DW_EH_PE_textrel 0x20
#define DW_EH_PE_datarel 0x30
#define DW_EH_PE_funcrel 0x40
#define DW_EH_PE_aligned 0x50
#define DW_EH_PE_indirect 0x80 // gcc extension
// read a uleb128 encoded value and advance pointer
static size_t readULEB128(const uint8_t **data) {
size_t result = 0;
size_t shift = 0;
unsigned char byte;
const uint8_t *p = *data;
do {
byte = *p++;
result |= (byte & 0x7f) << shift;
shift += 7;
} while (byte & 0x80);
*data = p;
return result;
}
// read a pointer encoded value and advance pointer
static uintptr_t readEncodedPointer(const uint8_t **data, uint8_t encoding) {
const uint8_t *p = *data;
uintptr_t result = 0;
if (encoding == DW_EH_PE_omit)
return 0;
// first get value
switch (encoding & 0x0F) {
case DW_EH_PE_absptr:
result = *((const uintptr_t *)p);
p += sizeof(uintptr_t);
break;
case DW_EH_PE_uleb128:
result = readULEB128(&p);
break;
case DW_EH_PE_udata2:
result = *((const uint16_t *)p);
p += sizeof(uint16_t);
break;
case DW_EH_PE_udata4:
result = *((const uint32_t *)p);
p += sizeof(uint32_t);
break;
case DW_EH_PE_udata8:
result = *((const uint64_t *)p);
p += sizeof(uint64_t);
break;
case DW_EH_PE_sdata2:
result = *((const int16_t *)p);
p += sizeof(int16_t);
break;
case DW_EH_PE_sdata4:
result = *((const int32_t *)p);
p += sizeof(int32_t);
break;
case DW_EH_PE_sdata8:
result = *((const int64_t *)p);
p += sizeof(int64_t);
break;
case DW_EH_PE_sleb128:
default:
// not supported
compilerrt_abort();
break;
}
// then add relative offset
switch (encoding & 0x70) {
case DW_EH_PE_absptr:
// do nothing
break;
case DW_EH_PE_pcrel:
result += (uintptr_t)(*data);
break;
case DW_EH_PE_textrel:
case DW_EH_PE_datarel:
case DW_EH_PE_funcrel:
case DW_EH_PE_aligned:
default:
// not supported
compilerrt_abort();
break;
}
// then apply indirection
if (encoding & DW_EH_PE_indirect) {
result = *((const uintptr_t *)result);
}
*data = p;
return result;
}
#if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \
!defined(__ARM_DWARF_EH__) && !defined(__SEH__)
#define USING_ARM_EHABI 1
_Unwind_Reason_Code __gnu_unwind_frame(struct _Unwind_Exception *,
struct _Unwind_Context *);
#endif
static inline _Unwind_Reason_Code
continueUnwind(struct _Unwind_Exception *exceptionObject,
struct _Unwind_Context *context) {
#if USING_ARM_EHABI
// On ARM EHABI the personality routine is responsible for actually
// unwinding a single stack frame before returning (ARM EHABI Sec. 6.1).
if (__gnu_unwind_frame(exceptionObject, context) != _URC_OK)
return _URC_FAILURE;
#endif
return _URC_CONTINUE_UNWIND;
}
// The C compiler makes references to __gcc_personality_v0 in
// the dwarf unwind information for translation units that use
// __attribute__((cleanup(xx))) on local variables.
// This personality routine is called by the system unwinder
// on each frame as the stack is unwound during a C++ exception
// throw through a C function compiled with -fexceptions.
#if __USING_SJLJ_EXCEPTIONS__
// the setjump-longjump based exceptions personality routine has a
// different name
COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_sj0(
int version, _Unwind_Action actions, uint64_t exceptionClass,
struct _Unwind_Exception *exceptionObject, struct _Unwind_Context *context)
#elif USING_ARM_EHABI
// The ARM EHABI personality routine has a different signature.
COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0(
_Unwind_State state, struct _Unwind_Exception *exceptionObject,
struct _Unwind_Context *context)
#elif defined(__SEH__)
static _Unwind_Reason_Code __gcc_personality_imp(
int version, _Unwind_Action actions, uint64_t exceptionClass,
struct _Unwind_Exception *exceptionObject, struct _Unwind_Context *context)
#else
COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0(
int version, _Unwind_Action actions, uint64_t exceptionClass,
struct _Unwind_Exception *exceptionObject, struct _Unwind_Context *context)
#endif
{
// Since C does not have catch clauses, there is nothing to do during
// phase 1 (the search phase).
#if USING_ARM_EHABI
// After resuming from a cleanup we should also continue on to the next
// frame straight away.
if ((state & _US_ACTION_MASK) != _US_UNWIND_FRAME_STARTING)
#else
if (actions & _UA_SEARCH_PHASE)
#endif
return continueUnwind(exceptionObject, context);
// There is nothing to do if there is no LSDA for this frame.
const uint8_t *lsda = (uint8_t *)_Unwind_GetLanguageSpecificData(context);
if (lsda == (uint8_t *)0)
return continueUnwind(exceptionObject, context);
uintptr_t pc = (uintptr_t)_Unwind_GetIP(context) - 1;
uintptr_t funcStart = (uintptr_t)_Unwind_GetRegionStart(context);
uintptr_t pcOffset = pc - funcStart;
// Parse LSDA header.
uint8_t lpStartEncoding = *lsda++;
if (lpStartEncoding != DW_EH_PE_omit) {
readEncodedPointer(&lsda, lpStartEncoding);
}
uint8_t ttypeEncoding = *lsda++;
if (ttypeEncoding != DW_EH_PE_omit) {
readULEB128(&lsda);
}
// Walk call-site table looking for range that includes current PC.
uint8_t callSiteEncoding = *lsda++;
size_t callSiteTableLength = readULEB128(&lsda);
const uint8_t *callSiteTableStart = lsda;
const uint8_t *callSiteTableEnd = callSiteTableStart + callSiteTableLength;
const uint8_t *p = callSiteTableStart;
while (p < callSiteTableEnd) {
uintptr_t start = readEncodedPointer(&p, callSiteEncoding);
size_t length = readEncodedPointer(&p, callSiteEncoding);
size_t landingPad = readEncodedPointer(&p, callSiteEncoding);
readULEB128(&p); // action value not used for C code
if (landingPad == 0)
continue; // no landing pad for this entry
if ((start <= pcOffset) && (pcOffset < (start + length))) {
// Found landing pad for the PC.
// Set Instruction Pointer to so we re-enter function
// at landing pad. The landing pad is created by the compiler
// to take two parameters in registers.
_Unwind_SetGR(context, __builtin_eh_return_data_regno(0),
(uintptr_t)exceptionObject);
_Unwind_SetGR(context, __builtin_eh_return_data_regno(1), 0);
_Unwind_SetIP(context, (funcStart + landingPad));
return _URC_INSTALL_CONTEXT;
}
}
// No landing pad found, continue unwinding.
return continueUnwind(exceptionObject, context);
}
#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
COMPILER_RT_ABI EXCEPTION_DISPOSITION
__gcc_personality_seh0(PEXCEPTION_RECORD ms_exc, void *this_frame,
PCONTEXT ms_orig_context, PDISPATCHER_CONTEXT ms_disp) {
return _GCC_specific_handler(ms_exc, this_frame, ms_orig_context, ms_disp,
__gcc_personality_imp);
}
#endif

View file

@ -1358,8 +1358,6 @@ o/$(MODE)/third_party/mbedtls/test/secp384r1_test.com.dbg: \
$(APE_NO_MODIFY_SELF)
@$(APELINK)
o/$(MODE)/third_party/mbedtls/test/test_suite_asn1parse.com.runs: private QUOTA = -M512m
# these need to be explictly defined because landlock make won't sandbox
# prerequisites with a trailing slash.
o/$(MODE)/third_party/mbedtls/test/data/.zip.o: \

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_ */

View file

@ -99,6 +99,9 @@ struct protoent *getprotoent (void);
struct protoent *getprotobyname (const char *);
struct protoent *getprotobynumber (int);
#define NI_MAXHOST 255
#define NI_MAXSERV 32
#if defined(_COSMO_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_POSIX_SOURCE) \
|| (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE+0 < 200809L) \
|| (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE+0 < 700)
@ -130,8 +133,6 @@ int getservbyname_r(const char *, const char *, struct servent *, char *, size_t
#define EAI_ALLDONE -103
#define EAI_INTR -104
#define EAI_IDN_ENCODE -105
#define NI_MAXHOST 255
#define NI_MAXSERV 32
#endif
COSMOPOLITAN_C_END_

View file

@ -1,26 +0,0 @@
# *NSYNC
*NSYNC is a library providing scalable synchronization primitives. The
following packages are provided:
- `THIRD_PARTY_NSYNC` has `nsync_mu` which doesn't depend on malloc().
- `THIRD_PARTY_NSYNC_MEM` has the rest of *NSYNC, e.g. `nsync_cv`.
The origin of this code is here:
git@github.com:google/nsync
ac5489682760393fe21bd2a8e038b528442412a7 (1.25.0)
Author: Mike Burrows <m3b@google.com>
Date: Wed Jun 1 16:47:52 2022 -0700
NSYNC uses the Apache 2.0 license. We made the following local changes:
- Write custom `nsync_malloc_()` so `malloc()` can use *NSYNC.
- Rewrite `futex()` wrapper to support old Linux kernels and OpenBSD.
- Normalize sources to Cosmopolitan style conventions; *NSYNC upstream
supports dozens of compilers and operating systems, at compile-time.
Since Cosmo solves portability at runtime instead, most of the build
config toil has been removed, in order to help the NSYNC source code
be more readable and hackable.

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

@ -0,0 +1,83 @@
#-*-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-unused-but-set-variable \
-Wno-class-memaccess \
-fno-strict-aliasing \
-Wno-frame-address \
-Wno-sign-compare
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)

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

@ -0,0 +1,20 @@
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
- Only enable hidden helper on GNU/Systemd
- Made __kmp_get_load_balance() portable at runtime
- Made __kmp_affinity_get_offline_cpus() portable at runtime
- Turned off quad floating point support (why does openmp have it?)
- Remove bloat for checking if multiple OpenMP libraries are linked

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

5597
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

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

@ -0,0 +1,170 @@
/*
* 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
#if IsModeDbg()
#define KMP_DEBUG 1
#endif
#define KMP_FTN_ENTRIES KMP_FTN_PLAIN
#define syscall {{openmp_shall_not_use_syscall}}
#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 1
#define OMPT_OPTIONAL LIBOMP_OMPT_OPTIONAL
#define LIBOMP_USE_ADAPTIVE_LOCKS 1
#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 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
#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 */

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