Hunt down more bugs

After going through the MODE=dbg and MODE=zero build modes, a bunch of
little issues were identified, which have been addressed. Fixing those
issues created even more troubles for the project, because it improved
our ability to detect latent problems which are getting fixed so fast.
This commit is contained in:
Justine Tunney 2023-07-03 17:35:11 -07:00
parent 73c0faa1b5
commit 97b7116953
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
39 changed files with 557 additions and 754 deletions

View file

@ -136,6 +136,7 @@ endif
ifeq ($(MODE), asan)
ENABLE_FTRACE = 1
CONFIG_OFLAGS ?= -g
CONFIG_CPPFLAGS += -D__SANITIZE_ADDRESS__
CONFIG_CCFLAGS += $(BACKTRACES) -O2 -DSYSDEBUG
CONFIG_COPTS += -fsanitize=address
TARGET_ARCH ?= -msse3
@ -155,7 +156,7 @@ endif
ifeq ($(MODE), dbg)
ENABLE_FTRACE = 1
CONFIG_OFLAGS ?= -g
CONFIG_CPPFLAGS += -DMODE_DBG
CONFIG_CPPFLAGS += -DMODE_DBG -D__SANITIZE_ADDRESS__
CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG -O0 -fno-inline
CONFIG_COPTS += -fsanitize=address -fsanitize=undefined
TARGET_ARCH ?= -msse3

View file

@ -20,6 +20,12 @@
// Gets machine state.
//
// This function goes 14x slower if sigaction() has ever been used to
// install a signal handling function. If you don't care about signal
// safety and just want fast fibers, then you may override the global
// variable `__interruptible` to disable the sigprocmask() calls, for
// pure userspace context switching.
//
// @return 0 on success, or -1 w/ errno
// @see makecontext()
// @see swapcontext()

View file

@ -63,7 +63,10 @@
#elif defined(__aarch64__)
#define REGS(i) 184+i*8
stp xzr,x1,[x0,REGS(0)] // x0 = 0
// x14 and x15 are clobbered
// all other registers are preserved
stp xzr,x1,[x0,REGS(0)] // context.x0 = 0
stp x2,x3,[x0,REGS(2)]
stp x4,x5,[x0,REGS(4)]
stp x6,x7,[x0,REGS(6)]
@ -84,6 +87,44 @@
str xzr,[x0,448] // pstate = 0
str xzr,[x0,456] // no vectors yet
/*void getfpsimd(ucontext_t *uc) {
struct fpsimd_context *fp;
fp = (struct fpsimd_context *)uc->uc_mcontext.__reserved;
fp[0].head.magic = FPSIMD_MAGIC;
fp[0].head.size = sizeof(*fp);
fp[1].head.magic = 0;
fp[1].head.size = 0;
asm("mrs\t%0,fpsr" : "=r"(fp->fpsr));
asm("mrs\t%0,fpcr" : "=r"(fp->fpcr));
asm("stp\tq0,q1,%0" : "=m"(fp->vregs[0]));
asm("stp\tq2,q3,%0" : "=m"(fp->vregs[2]));
asm("stp\tq4,q5,%0" : "=m"(fp->vregs[4]));
asm("stp\tq6,q7,%0" : "=m"(fp->vregs[6]));
asm("stp\tq8,q9,%0" : "=m"(fp->vregs[8]));
asm("stp\tq10,q11,%0" : "=m"(fp->vregs[10]));
asm("stp\tq12,q13,%0" : "=m"(fp->vregs[12]));
asm("stp\tq14,q15,%0" : "=m"(fp->vregs[14]));
}*/
add x15,x0,464
mov x14,0x8001
movk x14,0x4650,lsl 16
str xzr,[x0,992]
movk x14,0x210,lsl 32
str x14,[x0,464]
mrs x14,fpsr
str w14,[x15,8]
mrs x14,fpcr
str w14,[x15,12]
stp q0,q1,[x15,16]
stp q2,q3,[x15,48]
stp q4,q5,[x15,80]
stp q6,q7,[x15,112]
stp q8,q9,[x15,144]
stp q10,q11,[x15,176]
stp q12,q13,[x15,208]
stp q14,q15,[x15,240]
#else
#error "unsupported architecture"
#endif

View file

@ -467,6 +467,13 @@ static int __sigaction(int sig, const struct sigaction *act,
* spawned your process, happened to call `setrlimit()`. Doing this is
* a wonderful idea.
*
* Using signals might make your C runtime slower. Upon successfully
* installing its first signal handling function, sigaction() will set
* the global variable `__interruptible` to true, to let everything else
* know that signals are in play. That way code which would otherwise be
* frequently calling sigprocmask() out of an abundance of caution, will
* no longer need to pay its outrageous cost.
*
* @return 0 on success or -1 w/ errno
* @see xsigaction() for a much better api
* @asyncsignalsafe
@ -478,6 +485,13 @@ int sigaction(int sig, const struct sigaction *act, struct sigaction *oldact) {
rc = einval();
} else {
rc = __sigaction(sig, act, oldact);
if (!rc && act && (uintptr_t)act->sa_handler >= kSigactionMinRva) {
static bool once;
if (!once) {
__interruptible = true;
once = true;
}
}
}
STRACE("sigaction(%G, %s, [%s]) → %d% m", sig, DescribeSigaction(0, act),
DescribeSigaction(rc, oldact), rc);

View file

@ -1,13 +1,14 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_AARCH64_H_
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_AARCH64_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define FPSIMD_MAGIC 0x46508001
#define ESR_MAGIC 0x45535201
#define EXTRA_MAGIC 0x45585401
#define SVE_MAGIC 0x53564501
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct _aarch64_ctx {
uint32_t magic;
uint32_t size;

View file

@ -27,6 +27,12 @@
//
// swapcontext(x, y);
//
// This function goes 14x slower if sigaction() has ever been used to
// install a signal handling function. If you don't care about signal
// safety and just want fast fibers, then you may override the global
// variable `__interruptible` to disable the sigprocmask() calls, for
// pure userspace context switching.
//
// @return 0 on success, or -1 w/ errno
// @returnstwice
// @threadsafe

View file

@ -64,6 +64,47 @@ __tailcontext:
#elif defined(__aarch64__)
#define REGS(i) 184+i*8
/*void setfpsimd(const ucontext_t *uc) {
struct fpsimd_context *fp;
fp = (struct fpsimd_context *)uc->uc_mcontext.__reserved;
if (fp[0].head.magic == FPSIMD_MAGIC) {
asm("msr\tfpsr,%0" ::"r"(fp->fpsr));
asm("msr\tfpcr,%0" ::"r"(fp->fpcr));
asm("ldp\tq0,q1,%0" ::"m"(fp->vregs[0]));
asm("ldp\tq2,q3,%0" ::"m"(fp->vregs[2]));
asm("ldp\tq4,q5,%0" ::"m"(fp->vregs[4]));
asm("ldp\tq6,q7,%0" ::"m"(fp->vregs[6]));
asm("ldp\tq8,q9,%0" ::"m"(fp->vregs[8]));
asm("ldp\tq10,q11,%0" ::"m"(fp->vregs[10]));
asm("ldp\tq12,q13,%0" ::"m"(fp->vregs[12]));
asm("ldp\tq14,q15,%0" ::"m"(fp->vregs[14]));
}
}*/
ldr w14,[x0,464]
add x15,x0,464
mov w13,0x8001
movk w13,0x4650,lsl 16
cmp w14,w13
bne 1f
ldr w13,[x15,8]
msr fpsr,x13
ldr w13,[x15,12]
msr fpcr,x13
ldp q0,q1,[x15,16]
ldp q2,q3,[x15,48]
ldp q4,q5,[x15,80]
ldp q6,q7,[x15,112]
ldp q8,q9,[x15,144]
ldp q10,q11,[x15,176]
ldp q12,q13,[x15,208]
ldp q14,q15,[x15,240]
1:
// x16 is clobbered
// x18 belongs to apple
// all other registers are restored
ldp x1,x16,[x0,REGS(31)] // sp, pc
mov sp,x1
ldr x30,[x0,REGS(30)]
@ -72,7 +113,7 @@ __tailcontext:
ldp x24,x25,[x0,REGS(24)]
ldp x22,x23,[x0,REGS(22)]
ldp x20,x21,[x0,REGS(20)]
ldp x18,x19,[x0,REGS(18)]
ldr x19,[x0,REGS(19)]
ldr x17,[x0,REGS(17)]
ldp x14,x15,[x0,REGS(14)]
ldp x12,x13,[x0,REGS(12)]

View file

@ -18,13 +18,27 @@
*/
#include "libc/calls/ucontext.h"
#include "libc/calls/struct/sigset.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/sig.h"
int __tailcontext(const ucontext_t *);
static int __contextmask(const sigset_t *opt_set, sigset_t *opt_out_oldset) {
if (!__interruptible) return 0;
// signal handling functions might exist
// now context switching needs to go 14x slower
return sigprocmask(SIG_SETMASK, opt_set, opt_out_oldset);
}
/**
* Sets machine context.
*
* This function goes 14x slower if sigaction() has ever been used to
* install a signal handling function. If you don't care about signal
* safety and just want fast fibers, then you may override the global
* variable `__interruptible` to disable the sigprocmask() calls, for
* pure userspace context switching.
*
* @return -1 on error w/ errno, otherwise won't return unless sent back
* @see swapcontext()
* @see makecontext()
@ -32,14 +46,14 @@ int __tailcontext(const ucontext_t *);
* @threadsafe
*/
int setcontext(const ucontext_t *uc) {
if (sigprocmask(SIG_SETMASK, &uc->uc_sigmask, 0)) return -1;
if (__contextmask(&uc->uc_sigmask, 0)) return -1;
return __tailcontext(uc);
}
int __getcontextsig(ucontext_t *uc) {
return sigprocmask(SIG_SETMASK, 0, &uc->uc_sigmask);
return __contextmask(0, &uc->uc_sigmask);
}
int __swapcontextsig(ucontext_t *x, const ucontext_t *y) {
return sigprocmask(SIG_SETMASK, &y->uc_sigmask, &x->uc_sigmask);
return __contextmask(&y->uc_sigmask, &x->uc_sigmask);
}

View file

@ -103,6 +103,8 @@ STATIC_YOINK("_init_asan");
#define RBP __builtin_frame_address(0)
#define ASAN_LOG(...) (void)0 // kprintf(__VA_ARGS__)
#define HOOK(HOOK, IMPL) \
do { \
if (_weaken(HOOK)) { \
@ -210,7 +212,7 @@ static char *__asan_stpcpy(char *d, const char *s) {
}
}
static void __asan_memset(void *p, char c, size_t n) {
void __asan_memset(void *p, char c, size_t n) {
char *b;
size_t i;
uint64_t x;
@ -328,7 +330,7 @@ static void *__asan_mempcpy(void *dst, const void *src, size_t n) {
}
}
static void *__asan_memcpy(void *dst, const void *src, size_t n) {
void *__asan_memcpy(void *dst, const void *src, size_t n) {
__asan_mempcpy(dst, src, n);
return dst;
}
@ -1263,21 +1265,6 @@ int __asan_malloc_trim(size_t pad) {
return _weaken(dlmalloc_trim) ? _weaken(dlmalloc_trim)(pad) : 0;
}
void *__asan_stack_malloc(size_t size, int classid) {
struct AsanTrace bt;
__asan_trace(&bt, RBP);
return __asan_allocate(16, size, &bt, kAsanStackUnderrun, kAsanStackOverrun,
0xf9);
}
void __asan_stack_free(char *p, size_t size, int classid) {
__asan_deallocate(p, kAsanStackFree);
}
void __asan_handle_no_return(void) {
__asan_unpoison((void *)GetStackAddr(), GetStackSize());
}
void __asan_register_globals(struct AsanGlobal g[], int n) {
int i;
__asan_poison(g, sizeof(*g) * n, kAsanProtected);
@ -1320,35 +1307,65 @@ void __asan_report_store(uint8_t *addr, int size) {
__asan_unreachable();
}
void *__asan_stack_malloc(size_t size, int classid) {
struct AsanTrace bt;
ASAN_LOG("__asan_stack_malloc(%zu, %d)\n", size, classid);
__asan_trace(&bt, RBP);
return __asan_allocate(16, size, &bt, kAsanStackUnderrun, kAsanStackOverrun,
0xf9);
}
void __asan_stack_free(char *p, size_t size, int classid) {
ASAN_LOG("__asan_stack_free(%p, %zu, %d)\n", p, size, classid);
__asan_deallocate(p, kAsanStackFree);
}
void __asan_handle_no_return(void) {
// this check is stupid and has far-reaching toilsome ramifications
}
void __asan_poison_stack_memory(char *addr, size_t size) {
ASAN_LOG("__asan_poison_stack_memory(%p, %zu)\n", addr, size);
__asan_poison(addr, size, kAsanStackFree);
}
void __asan_unpoison_stack_memory(char *addr, size_t size) {
ASAN_LOG("__asan_unpoison_stack_memory(%p, %zu)\n", addr, size);
__asan_unpoison(addr, size);
}
void __asan_alloca_poison(char *addr, uintptr_t size) {
__asan_poison(addr - 32, 32, kAsanAllocaUnderrun);
__asan_poison(addr + size, 32, kAsanAllocaOverrun);
ASAN_LOG("__asan_alloca_poison(%p, %zu)\n", addr, size);
size_t rounded_up_size = ROUNDUP(size, 8);
size_t padding_size = ROUNDUP(size, 32) - rounded_up_size;
size_t rounded_down_size = ROUNDDOWN(size, 8);
char *left_redzone = addr - 32;
void *right_redzone = addr + rounded_up_size;
__asan_unpoison(addr + rounded_down_size, size - rounded_down_size);
__asan_poison(left_redzone, 32, kAsanAllocaUnderrun);
__asan_poison(right_redzone, padding_size + 32, kAsanAllocaOverrun);
}
void __asan_allocas_unpoison(uintptr_t x, uintptr_t y) {
ASAN_LOG("__asan_allocas_unpoison(%p, %p)\n", x, y);
if (!x || x > y) return;
__asan_memset((void *)((x >> 3) + 0x7fff8000), 0, (y - x) / 8);
__asan_unpoison((char *)x, y - x);
}
void *__asan_addr_is_in_fake_stack(void *fakestack, void *addr, void **beg,
void **end) {
ASAN_LOG("__asan_addr_is_in_fake_stack(%p)\n", addr);
return 0;
}
void *__asan_get_current_fake_stack(void) {
ASAN_LOG("__asan_get_current_fake_stack()\n");
return 0;
}
void __sanitizer_annotate_contiguous_container(char *beg, char *end,
char *old_mid, char *new_mid) {
ASAN_LOG("__sanitizer_annotate_contiguous_container()\n");
// the c++ stl uses this
// TODO(jart): make me faster
__asan_unpoison(beg, new_mid - beg);
@ -1356,9 +1373,11 @@ void __sanitizer_annotate_contiguous_container(char *beg, char *end,
}
void __asan_before_dynamic_init(const char *module_name) {
ASAN_LOG("__asan_before_dynamic_init()\n");
}
void __asan_after_dynamic_init(void) {
ASAN_LOG("__asan_after_dynamic_init()\n");
}
void __asan_install_malloc_hooks(void) {
@ -1506,4 +1525,7 @@ void __asan_init(int argc, char **argv, char **envp, intptr_t *auxv) {
STRACE("cosmopolitan memory safety module initialized");
}
__weak_reference(__asan_poison, __asan_poison_memory_region);
__weak_reference(__asan_unpoison, __asan_unpoison_memory_region);
#endif /* __x86_64__ */

View file

@ -39,6 +39,9 @@ void *__asan_memalign(size_t, size_t);
size_t __asan_get_heap_size(const void *);
void *__asan_realloc_in_place(void *, size_t);
void __asan_memset(void *, char, size_t);
void *__asan_memcpy(void *, const void *, size_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_INTRIN_ASAN_H_ */

View file

@ -21,6 +21,8 @@
const char *DescribePrctlOperation(int x) {
switch (x) {
case PR_GET_NAME:
return "PR_GET_NAME";
case PR_SET_NO_NEW_PRIVS:
return "PR_SET_NO_NEW_PRIVS";
case PR_SET_SECCOMP:

View file

@ -23,6 +23,11 @@
*/
int __threaded;
/**
* Set to true if sigaction() has installed signal handlers.
*/
bool __interruptible;
#ifdef __x86_64__
bool __tls_enabled;
#endif

View file

@ -19,6 +19,7 @@
#include "ape/sections.internal.h"
#include "libc/assert.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/asancodes.h"
@ -209,7 +210,11 @@ textstartup void __enable_tls(void) {
// copy in initialized data section
if (I(_tdata_size)) {
memcpy(tls, _tdata_start, I(_tdata_size));
if (IsAsan()) {
__asan_memcpy(tls, _tdata_start, I(_tdata_size));
} else {
memcpy(tls, _tdata_start, I(_tdata_size));
}
}
// ask the operating system to change the x86 segment register

View file

@ -72,6 +72,7 @@ extern int __argc;
extern char **__argv;
extern char **__envp;
extern unsigned long *__auxv;
extern bool __interruptible;
extern intptr_t __oldstack;
extern uint64_t __nosync;
extern int __strace;

View file

@ -3,171 +3,8 @@
#define __STDC_VERSION_STDCKDINT_H__ 202311L
#if !defined(MODE_DBG) && \
((defined(__GNUC__) && __GNUC__ >= 5 && !defined(__ICC)) || \
(defined(__has_builtin) && (__has_builtin(__builtin_add_overflow) && \
__has_builtin(__builtin_sub_overflow) && \
__has_builtin(__builtin_mul_overflow))))
#define ckd_add(res, x, y) __builtin_add_overflow((x), (y), (res))
#define ckd_sub(res, x, y) __builtin_sub_overflow((x), (y), (res))
#define ckd_mul(res, x, y) __builtin_mul_overflow((x), (y), (res))
#else
#define ckd_add(res, x, y) __ckd_arithmetic(add, res, x, y)
#define ckd_sub(res, x, y) __ckd_arithmetic(sub, res, x, y)
#define ckd_mul(res, x, y) __ckd_arithmetic(mul, res, x, y)
/*
* implementation details
*/
#if defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 8 && \
((defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 406) || \
defined(__llvm__)) && \
!defined(__STRICT_ANSI__)
#define __ckd_dword __int128
#else
#define __ckd_dword long long
#endif
#if defined(__cplusplus) && __cplusplus >= 201103L
#include "third_party/libcxx/type_traits"
#define __ckd_is_unsigned(res) std::is_unsigned<decltype(*(res))>::value
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
#define __ckd_is_unsigned(res) \
_Generic(*(res), unsigned : 1, unsigned long : 1, unsigned long long : 1, \
unsigned __ckd_dword : 1, default : 0)
#else
#define __ckd_is_unsigned(res) ((__typeof(*(res)))-1 >= 0)
#endif
#define __ckd_arithmetic(op, res, x, y) \
(__ckd_is_unsigned(res) \
? (sizeof(*(res)) == sizeof(int) \
? __ckd_##op##u((unsigned *)(res), (x), (y)) \
: sizeof(*(res)) == sizeof(long) \
? __ckd_##op##ul((unsigned long *)(res), (x), (y)) \
: sizeof(*(res)) == sizeof(__ckd_dword) \
? __ckd_##op##ull((unsigned __ckd_dword *)(res), (x), (y)) \
: __ckd_trap()) \
: (sizeof(*(res)) == sizeof(int) \
? __ckd_##op((signed int *)(res), (x), (y)) \
: sizeof(*(res)) == sizeof(long) \
? __ckd_##op##l((long *)(res), (x), (y)) \
: sizeof(*(res)) == sizeof(__ckd_dword) \
? __ckd_##op##ll((__ckd_dword *)(res), (x), (y)) \
: __ckd_trap()))
__funline int __ckd_trap(void) {
return *(volatile int *)0 = 0;
}
/*
* unsigned checked arithmetic
*/
__funline int __ckd_addu(unsigned *__z, unsigned __x, unsigned __y) {
*__z = __x + __y;
return *__z < __x;
}
__funline int __ckd_addul(unsigned long *__z, unsigned long __x,
unsigned long __y) {
*__z = __x + __y;
return *__z < __x;
}
__funline int __ckd_addull(unsigned __ckd_dword *__z, unsigned __ckd_dword __x,
unsigned __ckd_dword __y) {
*__z = __x + __y;
return *__z < __x;
}
__funline int __ckd_subu(unsigned *__z, unsigned __x, unsigned __y) {
*__z = __x - __y;
return __x < __y;
}
__funline int __ckd_subul(unsigned long *__z, unsigned long __x,
unsigned long __y) {
*__z = __x - __y;
return __x < __y;
}
__funline int __ckd_subull(unsigned __ckd_dword *__z, unsigned __ckd_dword __x,
unsigned __ckd_dword __y) {
*__z = __x - __y;
return __x < __y;
}
__funline int __ckd_mulu(unsigned *__z, unsigned __x, unsigned __y) {
*__z = __x * __y;
return __x && *__z / __x != __y;
}
__funline int __ckd_mulul(unsigned long *__z, unsigned long __x,
unsigned long __y) {
*__z = __x * __y;
return __x && *__z / __x != __y;
}
__funline int __ckd_mulull(unsigned __ckd_dword *__z, unsigned __ckd_dword __x,
unsigned __ckd_dword __y) {
*__z = __x * __y;
return __x && *__z / __x != __y;
}
/*
* signed checked arithmetic
*/
int __mulosi4(int, int, int *);
long __mulodi4(long, long, int *);
__ckd_dword __muloti4(__ckd_dword, __ckd_dword, int *);
__funline int __ckd_add(int *__z, int __x, int __y) {
unsigned int __a, __b, __c;
*__z = __c = (__a = __x) + (__b = __y);
return ((__c ^ __a) & (__c ^ __b)) >> (sizeof(int) * CHAR_BIT - 1);
}
__funline int __ckd_addl(long *__z, long __x, long __y) {
unsigned long __a, __b, __c;
*__z = __c = (__a = __x) + (__b = __y);
return ((__c ^ __a) & (__c ^ __b)) >> (sizeof(long) * CHAR_BIT - 1);
}
__funline int __ckd_addll(__ckd_dword *__z, __ckd_dword __x, __ckd_dword __y) {
unsigned __ckd_dword __a, __b, __c;
*__z = __c = (__a = __x) + (__b = __y);
return ((__c ^ __a) & (__c ^ __b)) >> (sizeof(__ckd_dword) * CHAR_BIT - 1);
}
__funline int __ckd_sub(int *__z, int __x, int __y) {
unsigned int __a, __b, __c;
*__z = __c = (__a = __x) - (__b = __y);
return ((__a ^ __b) & (__c ^ __a)) >> (sizeof(int) * CHAR_BIT - 1);
}
__funline int __ckd_subl(long *__z, long __x, long __y) {
unsigned long __a, __b, __c;
*__z = __c = (__a = __x) - (__b = __y);
return ((__a ^ __b) & (__c ^ __a)) >> (sizeof(long) * CHAR_BIT - 1);
}
__funline int __ckd_subll(__ckd_dword *__z, __ckd_dword __x, __ckd_dword __y) {
unsigned __ckd_dword __a, __b, __c;
*__z = __c = (__a = __x) - (__b = __y);
return ((__a ^ __b) & (__c ^ __a)) >> (sizeof(__ckd_dword) * CHAR_BIT - 1);
}
__funline int __ckd_mul(int *__z, int __x, int __y) {
int __o;
*__z = __mulosi4(__x, __y, &__o);
return __o;
}
__funline int __ckd_mull(long *__z, long __x, long __y) {
int __o;
*__z = __mulodi4(__x, __y, &__o);
return __o;
}
__funline int __ckd_mulll(__ckd_dword *__z, __ckd_dword __x, __ckd_dword __y) {
int __o;
*__z = __muloti4(__x, __y, &__o);
return __o;
}
#endif
#endif /* COSMOPOLITAN_LIBC_STDCKDINT_H_ */

View file

@ -19,6 +19,7 @@
#include "libc/assert.h"
#include "libc/calls/struct/ucontext.internal.h"
#include "libc/calls/ucontext.h"
#include "libc/dce.h"
#include "libc/nexgen32e/nexgen32e.h"
#include "libc/nexgen32e/stackframe.h"
#include "libc/runtime/runtime.h"
@ -26,18 +27,18 @@
#include "libc/str/str.h"
#include "libc/thread/thread.h"
typedef double vect __attribute__((__vector_size__(16), __aligned__(16)));
struct Gadget {
void (*func)();
int args[6];
long longs[6];
vect vects[6];
};
static void runcontext(struct Gadget *call, ucontext_t *link) {
call->func(call->args[0], //
call->args[1], //
call->args[2], //
call->args[3], //
call->args[4], //
call->args[5]);
call->func(call->longs[0], call->longs[1], call->longs[2], call->longs[3],
call->longs[4], call->longs[5], call->vects[0], call->vects[1],
call->vects[2], call->vects[3], call->vects[4], call->vects[5]);
if (link) {
setcontext(link);
abort();
@ -61,46 +62,71 @@ static void runcontext(struct Gadget *call, ucontext_t *link) {
*
* exit(42);
*
* @param uc stores processor state; the caller must:
* 1. initialize it using getcontext()
* 2. assign new value to `uc->uc_stack.ss_sp`
* 3. use `uc->uc_link` to define successor context
* The safest way to allocate stack memory is to use NewCosmoStack() and
* GetStackSize(), which will mmap() a fresh region of memory per a link
* time configuration, mprotect() some guard pages at the bottom, poison
* them if ASAN is in play, and then tell the OS that it's stack memory.
* If that's overkill for your use case, then you could potentially pass
* stacks as small as 1024 bytes; however they need to come from a stack
* allocation Cosmo granted to your main process and threads. It needn't
* be aligned, since this function takes care of that automatically. The
* address selected shall be `uc_stack.ss_ip + uc_stack.ss_size` and all
* the action happens beneath that address.
*
* On AMD64 and ARM64 you may pass up to six `long` integer args, and up
* to six vectors (e.g. double, floats, __m128i, uint8x16_t). Thou shall
* not call code created by Microsoft compilers, even though this should
* work perfectly fine on Windows, as it is written in the System V ABI,
* which specifies your parameters are always being passed in registers.
*
* @param uc stores processor state; the caller must have:
* 1. initialized it using `getcontext(uc)`
* 2. allocated new values for `uc->uc_stack`
* 3. specified a successor context in `uc->uc_link`
* @param func is the function to call when `uc` is activated;
* when `func` returns control passes to the linked context
* when `func` returns, control is passed to `uc->uc_link`,
* which if null will result in pthread_exit() being called
* @param argc is number of `int` arguments for `func` (max 6)
* @param argc is effectively ignored (see notes above)
* @see setcontext(), getcontext(), swapcontext()
* @threadsafe
*/
void makecontext(ucontext_t *uc, void func(), int argc, ...) {
int i;
va_list va;
uintptr_t sp;
long sp, sb;
struct Gadget *call;
struct StackFrame *sf;
assert(argc <= 6u);
// allocate call
sp = (uintptr_t)uc->uc_stack.ss_sp;
sp = sb = (long)uc->uc_stack.ss_sp;
sp += uc->uc_stack.ss_size;
sp -= 16; // openbsd:stackbound
sp -= sizeof(*call);
sp &= -alignof(*call);
call = (struct Gadget *)sp;
// get arguments
va_start(va, argc);
call->func = func;
for (i = 0; i < argc; ++i) {
call->args[i] = va_arg(va, int);
}
va_start(va, argc);
call->longs[0] = va_arg(va, long);
call->longs[1] = va_arg(va, long);
call->longs[2] = va_arg(va, long);
call->longs[3] = va_arg(va, long);
call->longs[4] = va_arg(va, long);
call->longs[5] = va_arg(va, long);
call->vects[0] = va_arg(va, vect);
call->vects[1] = va_arg(va, vect);
call->vects[2] = va_arg(va, vect);
call->vects[3] = va_arg(va, vect);
call->vects[4] = va_arg(va, vect);
call->vects[5] = va_arg(va, vect);
va_end(va);
// construct fake function call on new stack
// constructs fake function call on new stack
//
// the location where getcontext() was called shall be the previous
// entry in the backtrace when runcontext was called, e.g.
//
// 1000800bf160 423024 systemfive_linux+31
// 1000800fff90 405299 abort+58
// 1000800fff90 405299 func+58
// 1000800fffb0 40d98c runcontext+42
// 1000800fffd0 40b308 makecontext_backtrace+20
// 7fff22a7ff50 40c2d5 testlib_runtestcases+218
@ -110,12 +136,12 @@ void makecontext(ucontext_t *uc, void func(), int argc, ...) {
// 7fff22a7fff0 4034e2 _start+137
//
// is about what it should look like.
sp &= -(sizeof(uintptr_t) * 2);
sp &= -(sizeof(long) * 2);
#ifdef __x86__
*(uintptr_t *)(sp -= sizeof(uintptr_t)) = uc->uc_mcontext.PC;
*(long *)(sp -= sizeof(long)) = uc->uc_mcontext.PC;
#elif defined(__aarch64__)
*(uintptr_t *)(sp -= sizeof(uintptr_t)) = uc->uc_mcontext.regs[30];
*(uintptr_t *)(sp -= sizeof(uintptr_t)) = uc->uc_mcontext.regs[29];
*(long *)(sp -= sizeof(long)) = uc->uc_mcontext.regs[30];
*(long *)(sp -= sizeof(long)) = uc->uc_mcontext.regs[29];
uc->uc_mcontext.BP = uc->uc_mcontext.SP;
#else
#error "unsupported architecture"
@ -123,7 +149,7 @@ void makecontext(ucontext_t *uc, void func(), int argc, ...) {
// program context
uc->uc_mcontext.SP = sp;
uc->uc_mcontext.PC = (uintptr_t)runcontext;
uc->uc_mcontext.ARG0 = (uintptr_t)call;
uc->uc_mcontext.ARG1 = (uintptr_t)uc->uc_link;
uc->uc_mcontext.PC = (long)runcontext;
uc->uc_mcontext.ARG0 = (long)call;
uc->uc_mcontext.ARG1 = (long)uc->uc_link;
}

View file

@ -31,13 +31,11 @@
#define I(x) ((uintptr_t)x)
void Bzero(void *, size_t) asm("bzero"); // gcc bug
static char *_mktls_finish(struct CosmoTib **out_tib, char *mem,
struct CosmoTib *tib) {
struct CosmoTib *old;
old = __get_tls();
Bzero(tib, sizeof(*tib));
bzero(tib, sizeof(*tib));
tib->tib_self = tib;
tib->tib_self2 = tib;
tib->tib_ftrace = old->tib_ftrace;
@ -51,29 +49,37 @@ static char *_mktls_finish(struct CosmoTib **out_tib, char *mem,
}
static char *_mktls_below(struct CosmoTib **out_tib) {
char *tls;
struct CosmoTib *neu;
size_t siz;
char *mem, *tls;
struct CosmoTib *tib;
// allocate memory for tdata, tbss, and tib
tls = memalign(TLS_ALIGNMENT, I(_tls_size) + sizeof(struct CosmoTib));
if (!tls) return 0;
siz = ROUNDUP(I(_tls_size) + sizeof(*tib), _Alignof(struct CosmoTib));
siz = ROUNDUP(siz, _Alignof(struct CosmoTib));
mem = memalign(_Alignof(struct CosmoTib), siz);
// poison memory between tdata and tbss
if (IsAsan()) {
__asan_poison(tls + I(_tdata_size), I(_tbss_offset) - I(_tdata_size),
// poison the space between .tdata and .tbss
__asan_poison(mem + I(_tdata_size), I(_tbss_offset) - I(_tdata_size),
kAsanProtected);
}
// initialize .tdata
tib = (struct CosmoTib *)(mem + siz - sizeof(*tib));
tls = mem + siz - sizeof(*tib) - I(_tls_size);
// copy in initialized data section
if (I(_tdata_size)) {
memmove(tls, _tdata_start, I(_tdata_size));
if (IsAsan()) {
__asan_memcpy(tls, _tdata_start, I(_tdata_size));
} else {
memcpy(tls, _tdata_start, I(_tdata_size));
}
}
// clear .tbss
Bzero(tls + I(_tbss_offset), I(_tbss_size));
bzero(tls + I(_tbss_offset), I(_tbss_size));
// set up thread information block
return _mktls_finish(out_tib, tls, (struct CosmoTib *)(tls + I(_tls_size)));
return _mktls_finish(out_tib, mem, tib);
}
static char *_mktls_above(struct CosmoTib **out_tib) {
@ -103,12 +109,16 @@ static char *_mktls_above(struct CosmoTib **out_tib) {
// initialize .tdata
if (I(_tdata_size)) {
memmove(tls, _tdata_start, I(_tdata_size));
if (IsAsan()) {
__asan_memcpy(tls, _tdata_start, I(_tdata_size));
} else {
memmove(tls, _tdata_start, I(_tdata_size));
}
}
// clear .tbss
if (I(_tbss_size)) {
Bzero(tls + I(_tbss_offset), I(_tbss_size));
bzero(tls + I(_tbss_offset), I(_tbss_size));
}
// set up thread information block

View file

@ -55,6 +55,9 @@
* allocations, things like page size alignment, shall be handled
* automatically for compatibility with existing codebases.
*
* The same stack shouldn't be used for two separate threads. Use
* fresh stacks for each thread so that ASAN can be much happier.
*
* @param stackaddr is address of stack allocated by caller, and
* may be NULL in which case default behavior is restored
* @param stacksize is size of caller allocated stack

View file

@ -209,7 +209,7 @@ static void ListenForSigThr(void) {
* void *p = _gc(malloc(123));
* read(0, p, 123);
*
* It's possible to put a thread in asynchronous cancellation mode using
* It's possible to put a thread in asynchronous cancellation mode with
*
* pthread_setcancelstate(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
* for (;;) donothing;

View file

@ -75,15 +75,22 @@ static errno_t pthread_getname_impl(pthread_t thread, char *name, size_t size) {
}
return 0;
} else if (IsNetbsd()) {
} else if (IsNetbsd() || IsOpenbsd()) {
int ax;
char cf;
int ax, dx;
long dx, si;
if (IsNetbsd()) {
ax = 324; // _lwp_getname
} else {
ax = 142; // sys_getthrname
}
// NetBSD doesn't document the subtleties of its nul-terminator
// behavior, so like Linux we shall take the paranoid approach.
dx = size - 1;
si = (long)name;
asm volatile(CFLAG_ASM("syscall")
: CFLAG_CONSTRAINT(cf), "=a"(ax), "=d"(dx)
: "1"(324 /* _lwp_getname */), "D"(tid), "S"(name),
"d"(size - 1)
: CFLAG_CONSTRAINT(cf), "+a"(ax), "+D"(tid), "+S"(si), "+d"(dx)
: /* no outputs */
: "rcx", "r8", "r9", "r10", "r11", "memory");
if (!cf) {
// if size + our nul + kernel's nul is the buffer size, then we
@ -116,7 +123,7 @@ static errno_t pthread_getname_impl(pthread_t thread, char *name, size_t size) {
* @return 0 on success, or errno on error
* @raise ERANGE if `size` wasn't large enough, in which case your
* result will still be returned truncated if possible
* @raise ENOSYS on MacOS, Windows, FreeBSD, and OpenBSD
* @raise ENOSYS on MacOS, Windows, and FreeBSD
*/
errno_t pthread_getname_np(pthread_t thread, char *name, size_t size) {
errno_t rc;

View file

@ -23,7 +23,6 @@
#include "libc/errno.h"
#include "libc/fmt/itoa.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/asmflag.h"
#include "libc/intrin/atomic.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/at.h"
@ -72,23 +71,20 @@ static errno_t pthread_setname_impl(pthread_t thread, const char *name) {
}
return 0;
} else if (IsFreebsd()) {
char cf;
int ax, dx;
asm volatile(CFLAG_ASM("syscall")
: CFLAG_CONSTRAINT(cf), "=a"(ax), "=d"(dx)
: "1"(323 /* thr_set_name */), "D"(tid), "S"(name)
: "rcx", "r8", "r9", "r10", "r11", "memory");
return !cf ? 0 : ax;
} else if (IsNetbsd()) {
char cf;
int ax, dx;
asm volatile(CFLAG_ASM("syscall")
: CFLAG_CONSTRAINT(cf), "=a"(ax), "=d"(dx)
: "1"(323 /* _lwp_setname */), "D"(tid), "S"(name)
: "rcx", "r8", "r9", "r10", "r11", "memory");
return !cf ? 0 : ax;
} else if (IsFreebsd() || IsNetbsd() || IsOpenbsd()) {
int ax;
if (IsFreebsd()) {
ax = 464; // thr_set_name
} else if (IsNetbsd()) {
ax = 323; // _lwp_setname
} else {
ax = 143; // sys_setthrname
}
asm volatile("syscall"
: "+a"(ax), "+D"(tid), "+S"(name)
: /* no inputs */
: "rcx", "rdx", "r8", "r9", "r10", "r11", "memory");
return ax;
} else {
return ENOSYS;
@ -115,7 +111,7 @@ static errno_t pthread_setname_impl(pthread_t thread, const char *name) {
* @return 0 on success, or errno on error
* @raise ERANGE if length of `name` exceeded system limit, in which
* case the name may have still been set with os using truncation
* @raise ENOSYS on MacOS, Windows, and OpenBSD
* @raise ENOSYS on MacOS, and Windows
* @see pthread_getname_np()
*/
errno_t pthread_setname_np(pthread_t thread, const char *name) {

View file

@ -50,6 +50,8 @@
* Your spawn library abstracts clone() which also works on all
* platforms; however our implementation of clone() is significantly
* complicated so we strongly recommend always favoring this API.
*
* @deprecated
*/
#define _TLSZ ((intptr_t)_tls_size)
@ -92,6 +94,7 @@ static int Spawner(void *arg, int tid) {
* except when it isn't specified, in which case, the thread is kind
* of detached and will (currently) just leak the stack / tls memory
* @return 0 on success, or -1 w/ errno
* @deprecated
*/
int _spawn(int fun(void *, int), void *arg, struct spawn *opt_out_thread) {
errno_t rc;
@ -144,6 +147,8 @@ int _spawn(int fun(void *, int), void *arg, struct spawn *opt_out_thread) {
* Waits for thread created by _spawn() to terminate.
*
* This will free your thread's stack and tls memory too.
*
* @deprecated
*/
int _join(struct spawn *th) {
int rc;

View file

@ -5,7 +5,7 @@
COSMOPOLITAN_C_START_
int xspawn(struct rusage *);
int xvspawn(void (*)(void *), void *, struct rusage *);
int xvspawn(void (*)(void *), void *, struct rusage *) returnstwice;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -54,6 +54,7 @@ TEST(getcontext, test) {
TEST(getcontext, canReadAndWriteSignalMask) {
sigset_t ss, old;
volatile int n = 0;
EXPECT_TRUE(__interruptible);
sigemptyset(&ss);
sigaddset(&ss, SIGUSR1);
sigprocmask(SIG_SETMASK, &ss, &old);
@ -81,7 +82,10 @@ void SetGetContext(void) {
}
BENCH(getcontext, bench) {
EZBENCH2("get/setcontext", donothing, SetGetContext());
__interruptible = false;
EZBENCH2("getsetcontext nosig", donothing, SetGetContext());
__interruptible = true;
EZBENCH2("getsetcontext", donothing, SetGetContext());
}
BENCH(swapcontext, bench) {
@ -95,7 +99,11 @@ BENCH(swapcontext, bench) {
}
} else {
ready = true;
EZBENCH2("x2 swapcontext", donothing, swapcontext(&loop, &main));
__interruptible = false;
EZBENCH2("swapcontextx2 nosig", donothing, swapcontext(&loop, &main));
// kprintf("dollar\n");
__interruptible = true;
EZBENCH2("swapcontextx2", donothing, swapcontext(&loop, &main));
// kprintf("dollar\n");
}
}

View file

@ -1,401 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 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/stdckdint.h"
#include "libc/macros.internal.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#define FAIL ++failed < 100
#define uintmax_t uint128_t
#define T int
#define TBIT (sizeof(T) * CHAR_BIT - 1)
#define TMIN (((T) ~(T)0) > 1 ? (T)0 : (T)((uintmax_t)1 << TBIT))
#define TMAX (((T) ~(T)0) > 1 ? (T) ~(T)0 : (T)(((uintmax_t)1 << TBIT) - 1))
T Vint[] = {5, 4, 2, 77, 4, 7,
0, 1, 2, 3, 4, -1,
-2, -3, -4, TMIN, TMIN + 1, TMIN + 2,
TMIN + 3, TMIN + 5, TMIN + 7, TMAX, TMAX - 1, TMAX - 2,
TMAX - 77, TMAX - 3, TMAX - 5, TMAX - 7, TMAX - 50, TMIN / 2,
TMAX / 2, TMAX / 2 - 3};
#undef TMAX
#undef TMIN
#undef TBIT
#undef T
#define T long
#define TBIT (sizeof(T) * CHAR_BIT - 1)
#define TMIN (((T) ~(T)0) > 1 ? (T)0 : (T)((uintmax_t)1 << TBIT))
#define TMAX (((T) ~(T)0) > 1 ? (T) ~(T)0 : (T)(((uintmax_t)1 << TBIT) - 1))
T Vlong[] = {5, 4, 2, 77, 4, 7,
0, 1, 2, 3, 4, -1,
-2, -3, -4, TMIN, TMIN + 1, TMIN + 2,
TMIN + 3, TMIN + 5, TMIN + 7, TMAX, TMAX - 1, TMAX - 2,
TMAX - 77, TMAX - 3, TMAX - 5, TMAX - 7, TMAX - 50, TMIN / 2,
TMAX / 2, TMAX / 2 - 3};
#undef TMAX
#undef TMIN
#undef TBIT
#undef T
#define T __int128
#define TBIT (sizeof(T) * CHAR_BIT - 1)
#define TMIN (((T) ~(T)0) > 1 ? (T)0 : (T)((uintmax_t)1 << TBIT))
#define TMAX (((T) ~(T)0) > 1 ? (T) ~(T)0 : (T)(((uintmax_t)1 << TBIT) - 1))
T Vint128[] = {5, 4, 2, 77, 4, 7,
0, 1, 2, 3, 4, -1,
-2, -3, -4, TMIN, TMIN + 1, TMIN + 2,
TMIN + 3, TMIN + 5, TMIN + 7, TMAX, TMAX - 1, TMAX - 2,
TMAX - 77, TMAX - 3, TMAX - 5, TMAX - 7, TMAX - 50, TMIN / 2,
TMAX / 2, TMAX / 2 - 3};
#undef TMAX
#undef TMIN
#undef TBIT
#undef T
int failed;
void test_ckd_add(void) {
for (int i = 0; i < ARRAYLEN(Vint); ++i) {
int x = Vint[i];
for (int j = 0; j < ARRAYLEN(Vint); ++j) {
int z1, z2, o1, o2, y = Vint[i];
o1 = ckd_add(&z1, x, y);
o2 = __builtin_add_overflow(x, y, &z2);
if (z1 != z2 && FAIL) {
fprintf(stderr, "add %d + %d = %d vs. %d\n", x, y, z1, z2);
}
if (o1 != o2 && FAIL) {
fprintf(stderr, "add %d + %d overflow disagreement\n", x, y);
}
}
}
}
void test_ckd_sub(void) {
for (int i = 0; i < ARRAYLEN(Vint); ++i) {
int x = Vint[i];
for (int j = 0; j < ARRAYLEN(Vint); ++j) {
int z1, z2, o1, o2, y = Vint[i];
o1 = ckd_sub(&z1, x, y);
o2 = __builtin_sub_overflow(x, y, &z2);
if (z1 != z2 && FAIL) {
fprintf(stderr, "sub %d - %d = %d vs. %d\n", x, y, z1, z2);
}
if (o1 != o2 && FAIL) {
fprintf(stderr, "sub %d - %d overflow disagreement\n", x, y);
}
}
}
}
void test_ckd_mul(void) {
for (int i = 0; i < ARRAYLEN(Vint); ++i) {
int x = Vint[i];
for (int j = 0; j < ARRAYLEN(Vint); ++j) {
int z1, z2, o1, o2, y = Vint[i];
o1 = ckd_mul(&z1, x, y);
o2 = __builtin_mul_overflow(x, y, &z2);
if (z1 != z2 && FAIL) {
fprintf(stderr, "mul %d * %d = %d vs. %d\n", x, y, z1, z2);
}
if (o1 != o2 && FAIL) {
fprintf(stderr, "mul %d * %d overflow disagreement\n", x, y);
}
}
}
}
void test_ckd_add_long(void) {
for (long i = 0; i < ARRAYLEN(Vlong); ++i) {
long x = Vlong[i];
for (long j = 0; j < ARRAYLEN(Vlong); ++j) {
long z1, z2, o1, o2, y = Vlong[i];
o1 = ckd_add(&z1, x, y);
o2 = __builtin_add_overflow(x, y, &z2);
if (z1 != z2 && FAIL) {
fprintf(stderr, "add %ld + %ld = %ld vs. %ld\n", x, y, z1, z2);
}
if (o1 != o2 && FAIL) {
fprintf(stderr, "add %ld + %ld overflow disagreement\n", x, y);
}
}
}
}
void test_ckd_sub_long(void) {
for (long i = 0; i < ARRAYLEN(Vlong); ++i) {
long x = Vlong[i];
for (long j = 0; j < ARRAYLEN(Vlong); ++j) {
long z1, z2, o1, o2, y = Vlong[i];
o1 = ckd_sub(&z1, x, y);
o2 = __builtin_sub_overflow(x, y, &z2);
if (z1 != z2 && FAIL) {
fprintf(stderr, "sub %ld - %ld = %ld vs. %ld\n", x, y, z1, z2);
}
if (o1 != o2 && FAIL) {
fprintf(stderr, "sub %ld - %ld overflow disagreement\n", x, y);
}
}
}
}
void test_ckd_mul_long(void) {
for (long i = 0; i < ARRAYLEN(Vlong); ++i) {
long x = Vlong[i];
for (long j = 0; j < ARRAYLEN(Vlong); ++j) {
long z1, z2, o1, o2, y = Vlong[i];
o1 = ckd_mul(&z1, x, y);
o2 = __builtin_mul_overflow(x, y, &z2);
if (z1 != z2 && FAIL) {
fprintf(stderr, "mul %ld * %ld = %ld vs. %ld\n", x, y, z1, z2);
}
if (o1 != o2 && FAIL) {
fprintf(stderr, "mul %ld * %ld overflow disagreement\n", x, y);
}
}
}
}
void test_ckd_add_int128(void) {
for (int128_t i = 0; i < ARRAYLEN(Vint128); ++i) {
int128_t x = Vint128[i];
for (int128_t j = 0; j < ARRAYLEN(Vint128); ++j) {
int128_t z1, z2, o1, o2, y = Vint128[i];
o1 = ckd_add(&z1, x, y);
o2 = __builtin_add_overflow(x, y, &z2);
if (z1 != z2 && FAIL) {
fprintf(stderr, "add %jjd * %jjd = %jjd vs. %jjd\n", x, y, z1, z2);
}
if (o1 != o2 && FAIL) {
fprintf(stderr, "add %jjd * %jjd overflow disagreement\n", x, y);
}
}
}
}
void test_ckd_sub_int128(void) {
for (int128_t i = 0; i < ARRAYLEN(Vint128); ++i) {
int128_t x = Vint128[i];
for (int128_t j = 0; j < ARRAYLEN(Vint128); ++j) {
int128_t z1, z2, o1, o2, y = Vint128[i];
o1 = ckd_sub(&z1, x, y);
o2 = __builtin_sub_overflow(x, y, &z2);
if (z1 != z2 && FAIL) {
fprintf(stderr, "sub %jjd * %jjd = %jjd vs. %jjd\n", x, y, z1, z2);
}
if (o1 != o2 && FAIL) {
fprintf(stderr, "sub %jjd * %jjd overflow disagreement\n", x, y);
}
}
}
}
void test_ckd_mul_int128(void) {
for (int128_t i = 0; i < ARRAYLEN(Vint128); ++i) {
int128_t x = Vint128[i];
for (int128_t j = 0; j < ARRAYLEN(Vint128); ++j) {
int128_t z1, z2, o1, o2, y = Vint128[i];
o1 = ckd_mul(&z1, x, y);
o2 = __builtin_mul_overflow(x, y, &z2);
if (z1 != z2 && FAIL) {
fprintf(stderr, "mul %jjd * %jjd = %jjd vs. %jjd\n", x, y, z1, z2);
}
if (o1 != o2 && FAIL) {
fprintf(stderr, "mul %jjd * %jjd overflow disagreement\n", x, y);
}
}
}
}
void test_ckd_addu(void) {
for (int i = 0; i < ARRAYLEN(Vint); ++i) {
unsigned int x = Vint[i];
for (int j = 0; j < ARRAYLEN(Vint); ++j) {
unsigned int z1, z2, o1, o2, y = Vint[i];
o1 = ckd_add(&z1, x, y);
o2 = __builtin_add_overflow(x, y, &z2);
if (z1 != z2 && FAIL) {
fprintf(stderr, "unsigned add %u + %u = %u vs. %u\n", x, y, z1, z2);
}
if (o1 != o2 && FAIL) {
fprintf(stderr, "unsigned add %u + %u overflow disagreement\n", x, y);
}
}
}
}
void test_ckd_subu(void) {
for (int i = 0; i < ARRAYLEN(Vint); ++i) {
unsigned int x = Vint[i];
for (int j = 0; j < ARRAYLEN(Vint); ++j) {
unsigned int z1, z2, o1, o2, y = Vint[i];
o1 = ckd_sub(&z1, x, y);
o2 = __builtin_sub_overflow(x, y, &z2);
if (z1 != z2 && FAIL) {
fprintf(stderr, "unsigned sub %u - %u = %u vs. %u\n", x, y, z1, z2);
}
if (o1 != o2 && FAIL) {
fprintf(stderr, "unsigned sub %u - %u overflow disagreement\n", x, y);
}
}
}
}
void test_ckd_mulu(void) {
for (int i = 0; i < ARRAYLEN(Vint); ++i) {
unsigned int x = Vint[i];
for (int j = 0; j < ARRAYLEN(Vint); ++j) {
unsigned int z1, z2, o1, o2, y = Vint[i];
o1 = ckd_mul(&z1, x, y);
o2 = __builtin_mul_overflow(x, y, &z2);
if (z1 != z2 && FAIL) {
fprintf(stderr, "unsigned mul %u * %u = %u vs. %u\n", x, y, z1, z2);
}
if (o1 != o2 && FAIL) {
fprintf(stderr, "unsigned mul %u * %u overflow disagreement\n", x, y);
}
}
}
}
void test_ckd_addul(void) {
for (int i = 0; i < ARRAYLEN(Vlong); ++i) {
unsigned long x = Vlong[i];
for (int j = 0; j < ARRAYLEN(Vlong); ++j) {
unsigned long z1, z2, o1, o2, y = Vlong[i];
o1 = ckd_add(&z1, x, y);
o2 = __builtin_add_overflow(x, y, &z2);
if (z1 != z2 && FAIL) {
fprintf(stderr, "ulong add %lu + %lu = %lu vs. %lu\n", x, y, z1, z2);
}
if (o1 != o2 && FAIL) {
fprintf(stderr, "ulong add %lu + %lu overflow disagreement\n", x, y);
}
}
}
}
void test_ckd_subul(void) {
for (int i = 0; i < ARRAYLEN(Vlong); ++i) {
unsigned long x = Vlong[i];
for (int j = 0; j < ARRAYLEN(Vlong); ++j) {
unsigned long z1, z2, o1, o2, y = Vlong[i];
o1 = ckd_sub(&z1, x, y);
o2 = __builtin_sub_overflow(x, y, &z2);
if (z1 != z2 && FAIL) {
fprintf(stderr, "ulong sub %lu - %lu = %lu vs. %lu\n", x, y, z1, z2);
}
if (o1 != o2 && FAIL) {
fprintf(stderr, "ulong sub %lu - %lu overflow disagreement\n", x, y);
}
}
}
}
void test_ckd_mulul(void) {
for (int i = 0; i < ARRAYLEN(Vlong); ++i) {
unsigned long x = Vlong[i];
for (int j = 0; j < ARRAYLEN(Vlong); ++j) {
unsigned long z1, z2, o1, o2, y = Vlong[i];
o1 = ckd_mul(&z1, x, y);
o2 = __builtin_mul_overflow(x, y, &z2);
if (z1 != z2 && FAIL) {
fprintf(stderr, "ulong mul %lu * %lu = %lu vs. %lu\n", x, y, z1, z2);
}
if (o1 != o2 && FAIL) {
fprintf(stderr, "ulong mul %lu * %lu overflow disagreement\n", x, y);
}
}
}
}
void test_ckd_addull(void) {
for (int i = 0; i < ARRAYLEN(Vint128); ++i) {
uint128_t x = Vint128[i];
for (int j = 0; j < ARRAYLEN(Vint128); ++j) {
uint128_t z1, z2, o1, o2, y = Vint128[i];
o1 = ckd_add(&z1, x, y);
o2 = __builtin_add_overflow(x, y, &z2);
if (z1 != z2 && FAIL) {
fprintf(stderr, "u128 add %jju + %jju = %jju vs. %jju\n", x, y, z1, z2);
}
if (o1 != o2 && FAIL) {
fprintf(stderr, "u128 add %jju + %jju overflow disagreement\n", x, y);
}
}
}
}
void test_ckd_subull(void) {
for (int i = 0; i < ARRAYLEN(Vint128); ++i) {
uint128_t x = Vint128[i];
for (int j = 0; j < ARRAYLEN(Vint128); ++j) {
uint128_t z1, z2, o1, o2, y = Vint128[i];
o1 = ckd_sub(&z1, x, y);
o2 = __builtin_sub_overflow(x, y, &z2);
if (z1 != z2 && FAIL) {
fprintf(stderr, "u128 sub %jju - %jju = %jju vs. %jju\n", x, y, z1, z2);
}
if (o1 != o2 && FAIL) {
fprintf(stderr, "u128 sub %jju - %jju overflow disagreement\n", x, y);
}
}
}
}
void test_ckd_mulull(void) {
for (int i = 0; i < ARRAYLEN(Vint128); ++i) {
uint128_t x = Vint128[i];
for (int j = 0; j < ARRAYLEN(Vint128); ++j) {
uint128_t z1, z2, o1, o2, y = Vint128[i];
o1 = ckd_mul(&z1, x, y);
o2 = __builtin_mul_overflow(x, y, &z2);
if (z1 != z2 && FAIL) {
fprintf(stderr, "u128 mul %jju * %jju = %jju vs. %jju\n", x, y, z1, z2);
}
if (o1 != o2 && FAIL) {
fprintf(stderr, "u128 mul %jju * %jju overflow disagreement\n", x, y);
}
}
}
}
int main(int argc, char *argv[]) {
test_ckd_add();
test_ckd_sub();
test_ckd_mul();
test_ckd_add_long();
test_ckd_sub_long();
test_ckd_mul_long();
test_ckd_add_int128();
test_ckd_sub_int128();
test_ckd_mul_int128();
test_ckd_addu();
test_ckd_subu();
test_ckd_mulu();
test_ckd_addul();
test_ckd_subul();
test_ckd_mulul();
test_ckd_addull();
test_ckd_subull();
test_ckd_mulull();
return failed ? 1 : 0;
}

View file

@ -58,14 +58,6 @@ o/$(MODE)/test/libc/intrin/%.com.dbg: \
$(APE_NO_MODIFY_SELF)
@$(APELINK)
o/$(MODE)/test/libc/intrin/stdckdint_test.com.dbg: \
$(TEST_LIBC_INTRIN_DEPS) \
o/$(MODE)/test/libc/intrin/stdckdint_test.o \
o/$(MODE)/test/libc/intrin/intrin.pkg \
$(CRT) \
$(APE_NO_MODIFY_SELF)
@$(APELINK)
# Test what happens when *NSYNC isn't linked.
o/$(MODE)/test/libc/intrin/lock_test.com.dbg: \
$(TEST_LIBC_INTRIN_DEPS) \

View file

@ -31,14 +31,46 @@
#include "libc/x/x.h"
#include "third_party/libcxx/math.h"
ucontext_t uc;
bool gotsome;
ucontext_t uc, goback;
char testlib_enable_tmp_setup_teardown;
void itsatrap(int x, int y) {
void check_args(long x0, long x1, long x2, long x3, long x4, long x5, double f0,
double f1, double f2, double f3, double f4, double f5) {
EXPECT_EQ(LONG_MIN + 100, x0);
EXPECT_EQ(LONG_MIN + 101, x1);
EXPECT_EQ(LONG_MIN + 102, x2);
EXPECT_EQ(LONG_MIN + 103, x3);
EXPECT_EQ(LONG_MIN + 104, x4);
EXPECT_EQ(LONG_MIN + 105, x5);
EXPECT_TRUE(20. == f0);
EXPECT_TRUE(21. == f1);
EXPECT_TRUE(22. == f2);
EXPECT_TRUE(23. == f3);
EXPECT_TRUE(24. == f4);
EXPECT_TRUE(25. == f5);
gotsome = true;
}
TEST(makecontext, args) {
char stack[1024];
__interruptible = false;
getcontext(&uc);
uc.uc_link = &goback;
uc.uc_stack.ss_sp = stack;
uc.uc_stack.ss_size = sizeof(stack);
makecontext(&uc, check_args, 12, 20., 21., 22., LONG_MIN + 100,
LONG_MIN + 101, LONG_MIN + 102, LONG_MIN + 103, LONG_MIN + 104,
LONG_MIN + 105, 23., 24., 25.);
swapcontext(&goback, &uc);
EXPECT_TRUE(gotsome);
}
noasan noubsan void itsatrap(int x, int y) {
*(int *)(intptr_t)x = scalbn(x, y);
}
TEST(makecontext, test) {
TEST(makecontext, crash) {
SPAWN(fork);
getcontext(&uc);
uc.uc_link = 0;

View file

@ -156,7 +156,8 @@ TEST(pthread_create, testCustomStack_withReallySmallSize) {
ASSERT_EQ(0, pthread_create(&id, &attr, Increment, 0));
ASSERT_EQ(0, pthread_attr_destroy(&attr));
ASSERT_EQ(0, pthread_join(id, 0));
// we still own the stack memory
free(stk);
stk = malloc(siz);
ASSERT_EQ(0, pthread_attr_init(&attr));
ASSERT_EQ(0, pthread_attr_setstack(&attr, stk, siz));
ASSERT_EQ(0, pthread_create(&id, &attr, Increment, 0));

View file

@ -17,11 +17,41 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/atomic.h"
#include "libc/calls/calls.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/calls/syscall_support-sysv.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/atomic.h"
#include "libc/intrin/kprintf.h"
#include "libc/runtime/runtime.h"
#include "libc/testlib/testlib.h"
#include "libc/thread/thread.h"
void SetUpOnce(void) {
if (IsXnu()) {
tinyprint(2, program_invocation_short_name,
": no custom thread names on apple\n", NULL);
exit(0);
}
if (IsWindows()) {
tinyprint(2, program_invocation_short_name,
": no custom thread names on windows\n", NULL);
exit(0);
}
if (IsLinux() || IsOpenbsd()) {
char buf[512];
if (pthread_getname_np(pthread_self(), buf, sizeof(buf)) == ENOSYS) {
tinyprint(2, program_invocation_short_name,
": kernel too old for thread name support\n", NULL);
exit(0);
}
}
}
static void *SetName(void *arg) {
ASSERT_EQ(0, pthread_setname_np(pthread_self(), "justine"));
return 0;
@ -29,7 +59,6 @@ static void *SetName(void *arg) {
TEST(pthread_setname_np, SetName_SystemCallSucceeds) {
pthread_t id;
if (!IsLinux() || !IsNetbsd() || !IsFreebsd()) return;
ASSERT_EQ(0, pthread_create(&id, 0, SetName, 0));
ASSERT_EQ(0, pthread_join(id, 0));
}
@ -44,25 +73,14 @@ static void *SetGetNameOfSelf(void *arg) {
TEST(pthread_setname_np, SetGetNameOfSelf) {
pthread_t id;
if (!IsLinux() || !IsNetbsd()) return;
if (IsFreebsd()) {
// no get thread name no freebsd (why??)
return;
}
ASSERT_EQ(0, pthread_create(&id, 0, SetGetNameOfSelf, 0));
ASSERT_EQ(0, pthread_join(id, 0));
}
static void *GetDefaultName(void *arg) {
char me[16];
ASSERT_EQ(0, pthread_getname_np(pthread_self(), me, sizeof(me)));
EXPECT_STREQ("", me);
return 0;
}
TEST(pthread_setname_np, GetDefaultName_IsEmptyString) {
pthread_t id;
if (!IsLinux() || !IsNetbsd()) return;
ASSERT_EQ(0, pthread_create(&id, 0, GetDefaultName, 0));
ASSERT_EQ(0, pthread_join(id, 0));
}
atomic_char sync1, sync2;
static void *GetNameOfOtherThreadWorker(void *arg) {
@ -75,10 +93,15 @@ static void *GetNameOfOtherThreadWorker(void *arg) {
TEST(pthread_setname_np, GetNameOfOtherThread) {
char me[16];
pthread_t id;
if (!IsLinux() || !IsNetbsd()) return;
if (IsFreebsd()) {
// no get thread name no freebsd (why??)
return;
}
ASSERT_EQ(0, pthread_create(&id, 0, GetNameOfOtherThreadWorker, 0));
while (!atomic_load(&sync1)) pthread_yield();
ASSERT_EQ(0, pthread_getname_np(id, me, sizeof(me)));
errno_t e = pthread_getname_np(id, me, sizeof(me));
if (IsLinux() && e == ENOENT) return; // bah old kernel
ASSERT_EQ(0, e);
EXPECT_STREQ("justine", me);
ASSERT_EQ(0, pthread_setname_np(id, "tunney"));
ASSERT_EQ(0, pthread_getname_np(id, me, sizeof(me)));

View file

@ -108,7 +108,7 @@ TEST(sem_close, withUnnamedSemaphore_isUndefinedBehavior) {
SPAWN(fork);
IgnoreStderr();
sem_close(&sem);
EXITS(128 + SIGILL); // see __assert_fail
EXITS(128 + SIGABRT); // see __assert_fail
ASSERT_SYS(0, 0, sem_destroy(&sem));
}
@ -119,7 +119,7 @@ TEST(sem_destroy, withNamedSemaphore_isUndefinedBehavior) {
SPAWN(fork);
IgnoreStderr();
sem_destroy(sem);
EXITS(128 + SIGILL); // see __assert_fail
EXITS(128 + SIGABRT); // see __assert_fail
ASSERT_SYS(0, 0, sem_unlink("/boop"));
ASSERT_SYS(0, 0, sem_close(sem));
}

View file

@ -51,7 +51,7 @@ TEST(sem_post, afterDestroyed_isUndefinedBehavior) {
ASSERT_SYS(0, 0, sem_destroy(&sem));
IgnoreStderr();
sem_post(&sem);
EXITS(128 + SIGILL); // see __assert_fail
EXITS(128 + SIGABRT); // see __assert_fail
}
TEST(sem_trywait, afterDestroyed_isUndefinedBehavior) {
@ -63,7 +63,7 @@ TEST(sem_trywait, afterDestroyed_isUndefinedBehavior) {
ASSERT_SYS(0, 0, sem_destroy(&sem));
IgnoreStderr();
sem_trywait(&sem);
EXITS(128 + SIGILL); // see __assert_fail
EXITS(128 + SIGABRT); // see __assert_fail
}
TEST(sem_wait, afterDestroyed_isUndefinedBehavior) {
@ -75,7 +75,7 @@ TEST(sem_wait, afterDestroyed_isUndefinedBehavior) {
ASSERT_SYS(0, 0, sem_destroy(&sem));
IgnoreStderr();
sem_wait(&sem);
EXITS(128 + SIGILL); // see __assert_fail
EXITS(128 + SIGABRT); // see __assert_fail
}
TEST(sem_timedwait, afterDestroyed_isUndefinedBehavior) {
@ -87,7 +87,7 @@ TEST(sem_timedwait, afterDestroyed_isUndefinedBehavior) {
ASSERT_SYS(0, 0, sem_destroy(&sem));
IgnoreStderr();
sem_timedwait(&sem, 0);
EXITS(128 + SIGILL); // see __assert_fail
EXITS(128 + SIGABRT); // see __assert_fail
}
void *Worker(void *arg) {

View file

@ -32,6 +32,7 @@ TEST_LIBC_THREAD_DIRECTDEPS = \
LIBC_STDIO \
LIBC_STR \
LIBC_SYSV \
LIBC_SYSV_CALLS \
LIBC_TESTLIB \
LIBC_THREAD \
LIBC_TIME \

View file

@ -1,4 +1,6 @@
// clang-format off
#ifdef __x86_64__
/*
* xxHash - Extremely Fast Hash algorithm
* Copyright (C) 2020-2021 Yann Collet
@ -806,3 +808,5 @@ XXH3_128bits_update_dispatch(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE cons
}
#endif
/*! @} */
#endif /* __x86_64__ */

View file

@ -177,6 +177,7 @@
* @file xxhash.h
* xxHash prototypes and implementation
*/
#include "third_party/aarch64/arm_neon.internal.h"
#if defined (__cplusplus)
extern "C" {

View file

@ -12,36 +12,36 @@ THIRD_PARTY_XXHASH_SRCS = $(filter %.c,$(THIRD_PARTY_XXHASH_FILES))
THIRD_PARTY_XXHASH_OBJS = $(THIRD_PARTY_XXHASH_SRCS:%.c=o/$(MODE)/%.o)
THIRD_PARTY_XXHASH_A_DIRECTDEPS = \
LIBC_CALLS \
LIBC_FMT \
LIBC_INTRIN \
LIBC_MEM \
LIBC_RUNTIME \
LIBC_STDIO \
LIBC_STR \
LIBC_SYSV \
LIBC_CALLS \
LIBC_FMT \
LIBC_INTRIN \
LIBC_MEM \
LIBC_RUNTIME \
LIBC_STDIO \
LIBC_STR \
LIBC_SYSV \
LIBC_TIME
THIRD_PARTY_XXHASH_A_DEPS := \
THIRD_PARTY_XXHASH_A_DEPS := \
$(call uniq,$(foreach x,$(THIRD_PARTY_XXHASH_A_DIRECTDEPS),$($(x))))
THIRD_PARTY_XXHASH_CHECKS = \
$(THIRD_PARTY_XXHASH_A).pkg \
THIRD_PARTY_XXHASH_CHECKS = \
$(THIRD_PARTY_XXHASH_A).pkg \
$(THIRD_PARTY_XXHASH_HDRS:%=o/$(MODE)/%.ok)
$(THIRD_PARTY_XXHASH_A): \
third_party/xxhash/ \
$(THIRD_PARTY_XXHASH_A).pkg \
third_party/xxhash/ \
$(THIRD_PARTY_XXHASH_A).pkg \
$(THIRD_PARTY_XXHASH_OBJS)
$(THIRD_PARTY_XXHASH_A).pkg: \
$(THIRD_PARTY_XXHASH_OBJS) \
$(THIRD_PARTY_XXHASH_A).pkg: \
$(THIRD_PARTY_XXHASH_OBJS) \
$(foreach x,$(THIRD_PARTY_XXHASH_A_DIRECTDEPS),$($(x)_A).pkg)
o/$(MODE)/third_party/xxhash/xxhsum.com.dbg: \
$(THIRD_PARTY_XXHASH) \
o/$(MODE)/third_party/xxhash/cli/xxhsum.o \
$(CRT) \
$(THIRD_PARTY_XXHASH) \
o/$(MODE)/third_party/xxhash/cli/xxhsum.o \
$(CRT) \
$(APE_NO_MODIFY_SELF)
@$(APELINK)
@ -50,6 +50,6 @@ THIRD_PARTY_XXHASH_COMS = o/$(MODE)/third_party/xxhash/xxhsum.com
THIRD_PARTY_XXHASH_LIBS = $(THIRD_PARTY_XXHASH_A)
.PHONY: o/$(MODE)/third_party/xxhash
o/$(MODE)/third_party/xxhash: \
o/$(MODE)/third_party/xxhash: \
$(THIRD_PARTY_XXHASH_BINS) \
$(THIRD_PARTY_XXHASH_CHECKS)

View file

@ -39,6 +39,7 @@
#else
# define ZSTD_TRACE 0
#endif
#include "third_party/aarch64/arm_neon.internal.h"
#if defined (__cplusplus)
extern "C" {

View file

@ -6,58 +6,153 @@ PKGS += THIRD_PARTY_ZSTD
THIRD_PARTY_ZSTD_ARTIFACTS += THIRD_PARTY_ZSTD_A
THIRD_PARTY_ZSTD = $(THIRD_PARTY_ZSTD_A_DEPS) $(THIRD_PARTY_ZSTD_A)
THIRD_PARTY_ZSTD_A = o/$(MODE)/third_party/zstd/zstd.a
THIRD_PARTY_ZSTD_A_FILES := $(shell find ./third_party/zstd/lib -type f) $(wildcard third_party/zstd/programs/*)
THIRD_PARTY_ZSTD_A_HDRS = $(filter %.h,$(THIRD_PARTY_ZSTD_A_FILES))
THIRD_PARTY_ZSTD_A_SRCS = $(filter %.c,$(THIRD_PARTY_ZSTD_A_FILES))
THIRD_PARTY_ZSTD_A_INCS = $(filter %.inc,$(THIRD_PARTY_ZSTD_A_FILES))
THIRD_PARTY_ZSTD_A_OBJS = $(THIRD_PARTY_ZSTD_A_SRCS:%.c=o/$(MODE)/%.o)
THIRD_PARTY_ZSTD_A_CHECKS = \
$(THIRD_PARTY_ZSTD_A).pkg \
THIRD_PARTY_ZSTD_A_FILES := \
third_party/zstd/lib/common/allocations.h \
third_party/zstd/lib/common/bits.h \
third_party/zstd/lib/common/bitstream.h \
third_party/zstd/lib/common/compiler.h \
third_party/zstd/lib/common/cpu.h \
third_party/zstd/lib/common/debug.c \
third_party/zstd/lib/common/debug.h \
third_party/zstd/lib/common/entropy_common.c \
third_party/zstd/lib/common/error_private.c \
third_party/zstd/lib/common/error_private.h \
third_party/zstd/lib/common/fse.h \
third_party/zstd/lib/common/fse_decompress.c \
third_party/zstd/lib/common/huf.h \
third_party/zstd/lib/common/mem.h \
third_party/zstd/lib/common/pool.c \
third_party/zstd/lib/common/pool.h \
third_party/zstd/lib/common/portability_macros.h \
third_party/zstd/lib/common/threading.c \
third_party/zstd/lib/common/threading.h \
third_party/zstd/lib/common/xxhash.c \
third_party/zstd/lib/common/xxhash.h \
third_party/zstd/lib/common/zstd_common.c \
third_party/zstd/lib/common/zstd_deps.h \
third_party/zstd/lib/common/zstd_internal.h \
third_party/zstd/lib/common/zstd_trace.h \
third_party/zstd/lib/compress/clevels.h \
third_party/zstd/lib/compress/fse_compress.c \
third_party/zstd/lib/compress/hist.c \
third_party/zstd/lib/compress/hist.h \
third_party/zstd/lib/compress/huf_compress.c \
third_party/zstd/lib/compress/zstd_compress.c \
third_party/zstd/lib/compress/zstd_compress_internal.h \
third_party/zstd/lib/compress/zstd_compress_literals.c \
third_party/zstd/lib/compress/zstd_compress_literals.h \
third_party/zstd/lib/compress/zstd_compress_sequences.c \
third_party/zstd/lib/compress/zstd_compress_sequences.h \
third_party/zstd/lib/compress/zstd_compress_superblock.c \
third_party/zstd/lib/compress/zstd_compress_superblock.h \
third_party/zstd/lib/compress/zstd_cwksp.h \
third_party/zstd/lib/compress/zstd_double_fast.c \
third_party/zstd/lib/compress/zstd_double_fast.h \
third_party/zstd/lib/compress/zstd_fast.c \
third_party/zstd/lib/compress/zstd_fast.h \
third_party/zstd/lib/compress/zstd_lazy.c \
third_party/zstd/lib/compress/zstd_lazy.h \
third_party/zstd/lib/compress/zstd_ldm.c \
third_party/zstd/lib/compress/zstd_ldm.h \
third_party/zstd/lib/compress/zstd_ldm_geartab.h \
third_party/zstd/lib/compress/zstd_opt.c \
third_party/zstd/lib/compress/zstd_opt.h \
third_party/zstd/lib/compress/zstdmt_compress.c \
third_party/zstd/lib/compress/zstdmt_compress.h \
third_party/zstd/lib/decompress/huf_decompress.c \
third_party/zstd/lib/decompress/huf_decompress_amd64.S \
third_party/zstd/lib/decompress/zstd_ddict.c \
third_party/zstd/lib/decompress/zstd_ddict.h \
third_party/zstd/lib/decompress/zstd_decompress.c \
third_party/zstd/lib/decompress/zstd_decompress_block.c \
third_party/zstd/lib/decompress/zstd_decompress_block.h \
third_party/zstd/lib/decompress/zstd_decompress_internal.h \
third_party/zstd/lib/deprecated/zbuff.h \
third_party/zstd/lib/deprecated/zbuff_common.c \
third_party/zstd/lib/deprecated/zbuff_compress.c \
third_party/zstd/lib/deprecated/zbuff_decompress.c \
third_party/zstd/lib/dictBuilder/cover.c \
third_party/zstd/lib/dictBuilder/cover.h \
third_party/zstd/lib/dictBuilder/divsufsort.c \
third_party/zstd/lib/dictBuilder/divsufsort.h \
third_party/zstd/lib/dictBuilder/fastcover.c \
third_party/zstd/lib/dictBuilder/zdict.c \
third_party/zstd/programs/benchfn.c \
third_party/zstd/programs/benchfn.h \
third_party/zstd/programs/benchzstd.c \
third_party/zstd/programs/benchzstd.h \
third_party/zstd/programs/datagen.c \
third_party/zstd/programs/datagen.h \
third_party/zstd/programs/dibio.c \
third_party/zstd/programs/dibio.h \
third_party/zstd/programs/fileio.c \
third_party/zstd/programs/fileio.h \
third_party/zstd/programs/fileio_asyncio.c \
third_party/zstd/programs/fileio_asyncio.h \
third_party/zstd/programs/fileio_common.h \
third_party/zstd/programs/fileio_types.h \
third_party/zstd/programs/platform.h \
third_party/zstd/programs/timefn.c \
third_party/zstd/programs/timefn.h \
third_party/zstd/programs/util.c \
third_party/zstd/programs/util.h \
third_party/zstd/programs/zstdcli.c \
third_party/zstd/programs/zstdcli_trace.c \
third_party/zstd/programs/zstdcli_trace.h
THIRD_PARTY_ZSTD_A_CHECKS = \
$(THIRD_PARTY_ZSTD_A).pkg \
$(THIRD_PARTY_ZSTD_A_HDRS:%=o/$(MODE)/%.ok)
THIRD_PARTY_ZSTD_A_DIRECTDEPS = \
LIBC_INTRIN \
LIBC_NEXGEN32E \
LIBC_STR \
LIBC_MEM \
LIBC_STDIO \
LIBC_TIME \
LIBC_CALLS \
LIBC_RUNTIME \
THIRD_PARTY_ZSTD_A_DIRECTDEPS = \
LIBC_INTRIN \
LIBC_NEXGEN32E \
LIBC_STR \
LIBC_MEM \
LIBC_STDIO \
LIBC_TIME \
LIBC_CALLS \
LIBC_RUNTIME \
LIBC_FMT \
LIBC_LOG \
LIBC_SYSV
THIRD_PARTY_ZSTD_A_DEPS := \
THIRD_PARTY_ZSTD_A_DEPS := \
$(call uniq,$(foreach x,$(THIRD_PARTY_ZSTD_A_DIRECTDEPS),$($(x))))
$(THIRD_PARTY_ZSTD_A): \
third_party/zstd/ \
$(THIRD_PARTY_ZSTD_A).pkg \
$(THIRD_PARTY_ZSTD_A): \
third_party/zstd/ \
$(THIRD_PARTY_ZSTD_A).pkg \
$(THIRD_PARTY_ZSTD_A_OBJS)
$(THIRD_PARTY_ZSTD_A).pkg: \
$(THIRD_PARTY_ZSTD_A_OBJS) \
$(THIRD_PARTY_ZSTD_A).pkg: \
$(THIRD_PARTY_ZSTD_A_OBJS) \
$(foreach x,$(THIRD_PARTY_ZSTD_A_DIRECTDEPS),$($(x)_A).pkg)
$(THIRD_PARTY_ZSTD_A_CHECKS): private \
CFLAGS += \
-Wframe-larger-than=262144 \
$(THIRD_PARTY_ZSTD_A_CHECKS): private \
CFLAGS += \
-Wframe-larger-than=262144 \
-Wno-comment
$(THIRD_PARTY_ZSTD_A_OBJS): private \
CFLAGS += \
-Wframe-larger-than=262144 \
$(THIRD_PARTY_ZSTD_A_OBJS): private \
CFLAGS += \
-Wframe-larger-than=262144 \
-Wno-comment
o/$(MODE)/third_party/zstd/zstd.com.dbg: \
$(THIRD_PARTY_ZSTD) \
o/$(MODE)/third_party/zstd/programs/zstdcli.o \
$(CRT) \
$(THIRD_PARTY_ZSTD) \
o/$(MODE)/third_party/zstd/programs/zstdcli.o \
$(CRT) \
$(APE_NO_MODIFY_SELF)
@$(APELINK)
o/$(MODE)/third_party/zstd/lib/compress/zstd_lazy.o: \
QUOTA += -C64
THIRD_PARTY_ZSTD_BINS = $(THIRD_PARTY_ZSTD_COMS) $(THIRD_PARTY_ZSTD_COMS:%=%.dbg)
THIRD_PARTY_ZSTD_COMS = o/$(MODE)/third_party/zstd/zstd.com
@ -68,6 +163,6 @@ THIRD_PARTY_ZSTD_OBJS = $(foreach x,$(THIRD_PARTY_ZSTD_ARTIFACTS),$($(x)_OBJS))
$(THIRD_PARTY_ZSTD_OBJS): $(BUILD_FILES) third_party/zstd/zstd.mk
.PHONY: o/$(MODE)/third_party/zstd
o/$(MODE)/third_party/zstd: \
o/$(MODE)/third_party/zstd: \
$(THIRD_PARTY_ZSTD_BINS) \
$(THIRD_PARTY_ZSTD_CHECKS)

View file

@ -834,7 +834,7 @@ int main(int argc, char *argv[]) {
*/
verbose = 4;
timeout = 90; /* secs */
cpuquota = 16; /* secs */
cpuquota = 32; /* secs */
proquota = 2048; /* procs */
fszquota = 256 * 1000 * 1000; /* bytes */
memquota = 512 * 1024 * 1024; /* bytes */

View file

@ -177,7 +177,7 @@ const char *getargs_next(struct GetArgs *ga) {
getargs_fail(ga->path, "mmap");
}
ga->map = p;
ga->mapsize = ROUNDUP(size, 4096);
ga->mapsize = size;
}
close(fd);
}