diff --git a/build/config.mk b/build/config.mk index 4339931aa..091393c9f 100644 --- a/build/config.mk +++ b/build/config.mk @@ -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 diff --git a/libc/calls/getcontext.S b/libc/calls/getcontext.S index b1ab2850e..f1f8cc135 100644 --- a/libc/calls/getcontext.S +++ b/libc/calls/getcontext.S @@ -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() diff --git a/libc/calls/getcontext.inc b/libc/calls/getcontext.inc index 39a6d5ad6..2f08116cd 100644 --- a/libc/calls/getcontext.inc +++ b/libc/calls/getcontext.inc @@ -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 diff --git a/libc/calls/sigaction.c b/libc/calls/sigaction.c index 33b8f2acf..30f0025a7 100644 --- a/libc/calls/sigaction.c +++ b/libc/calls/sigaction.c @@ -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); diff --git a/libc/calls/struct/aarch64.internal.h b/libc/calls/struct/aarch64.internal.h index 71a7d11a2..a34650227 100644 --- a/libc/calls/struct/aarch64.internal.h +++ b/libc/calls/struct/aarch64.internal.h @@ -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; diff --git a/libc/calls/swapcontext.S b/libc/calls/swapcontext.S index 3cc9e81cd..0fbd1b9c8 100644 --- a/libc/calls/swapcontext.S +++ b/libc/calls/swapcontext.S @@ -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 diff --git a/libc/calls/tailcontext.S b/libc/calls/tailcontext.S index 945ecc840..c94dfc1a8 100644 --- a/libc/calls/tailcontext.S +++ b/libc/calls/tailcontext.S @@ -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)] diff --git a/libc/calls/ucontext.c b/libc/calls/ucontext.c index caae7faba..a5fc2be32 100644 --- a/libc/calls/ucontext.c +++ b/libc/calls/ucontext.c @@ -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); } diff --git a/libc/intrin/asan.c b/libc/intrin/asan.c index e38e5a27b..a7ca0c5ce 100644 --- a/libc/intrin/asan.c +++ b/libc/intrin/asan.c @@ -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__ */ diff --git a/libc/intrin/asan.internal.h b/libc/intrin/asan.internal.h index b76d5f44e..de1875d79 100644 --- a/libc/intrin/asan.internal.h +++ b/libc/intrin/asan.internal.h @@ -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_ */ diff --git a/libc/intrin/describeprctloperation.c b/libc/intrin/describeprctloperation.c index 27abc620c..67f724491 100644 --- a/libc/intrin/describeprctloperation.c +++ b/libc/intrin/describeprctloperation.c @@ -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: diff --git a/libc/nexgen32e/threaded.c b/libc/nexgen32e/threaded.c index 4230175e5..dc9921998 100644 --- a/libc/nexgen32e/threaded.c +++ b/libc/nexgen32e/threaded.c @@ -23,6 +23,11 @@ */ int __threaded; +/** + * Set to true if sigaction() has installed signal handlers. + */ +bool __interruptible; + #ifdef __x86_64__ bool __tls_enabled; #endif diff --git a/libc/runtime/enable_tls.c b/libc/runtime/enable_tls.c index 57b90e6e6..1569f1bc6 100644 --- a/libc/runtime/enable_tls.c +++ b/libc/runtime/enable_tls.c @@ -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 diff --git a/libc/runtime/runtime.h b/libc/runtime/runtime.h index e2b4ef27e..6294960c8 100644 --- a/libc/runtime/runtime.h +++ b/libc/runtime/runtime.h @@ -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; diff --git a/libc/stdckdint.h b/libc/stdckdint.h index de9f7c055..eacc77187 100644 --- a/libc/stdckdint.h +++ b/libc/stdckdint.h @@ -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::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_ */ diff --git a/libc/thread/makecontext.c b/libc/thread/makecontext.c index 14f9536f2..ddb285df6 100644 --- a/libc/thread/makecontext.c +++ b/libc/thread/makecontext.c @@ -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; } diff --git a/libc/thread/mktls.c b/libc/thread/mktls.c index 3b1eb03cb..e75c9811e 100644 --- a/libc/thread/mktls.c +++ b/libc/thread/mktls.c @@ -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 diff --git a/libc/thread/pthread_attr_setstack.c b/libc/thread/pthread_attr_setstack.c index 8a2650860..fb00491d7 100644 --- a/libc/thread/pthread_attr_setstack.c +++ b/libc/thread/pthread_attr_setstack.c @@ -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 diff --git a/libc/thread/pthread_cancel.c b/libc/thread/pthread_cancel.c index 3229ea382..0a0124fed 100644 --- a/libc/thread/pthread_cancel.c +++ b/libc/thread/pthread_cancel.c @@ -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; diff --git a/libc/thread/pthread_getname_np.c b/libc/thread/pthread_getname_np.c index 0bd568264..5aaaa225b 100644 --- a/libc/thread/pthread_getname_np.c +++ b/libc/thread/pthread_getname_np.c @@ -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; diff --git a/libc/thread/pthread_setname_np.c b/libc/thread/pthread_setname_np.c index 603d6c1d4..b7b30bb07 100644 --- a/libc/thread/pthread_setname_np.c +++ b/libc/thread/pthread_setname_np.c @@ -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) { diff --git a/libc/thread/spawn.c b/libc/thread/spawn.c index 5793f15d7..0b4f30387 100644 --- a/libc/thread/spawn.c +++ b/libc/thread/spawn.c @@ -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; diff --git a/libc/x/xspawn.h b/libc/x/xspawn.h index 22064fb6d..e2ad9f6e8 100644 --- a/libc/x/xspawn.h +++ b/libc/x/xspawn.h @@ -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) */ diff --git a/test/libc/calls/getcontext_test.c b/test/libc/calls/getcontext_test.c index 5db8e416d..82dccdefd 100644 --- a/test/libc/calls/getcontext_test.c +++ b/test/libc/calls/getcontext_test.c @@ -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"); } } diff --git a/test/libc/intrin/stdckdint_test.c b/test/libc/intrin/stdckdint_test.c deleted file mode 100644 index 045b62f93..000000000 --- a/test/libc/intrin/stdckdint_test.c +++ /dev/null @@ -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; -} diff --git a/test/libc/intrin/test.mk b/test/libc/intrin/test.mk index ff5e7e7fe..05d4cc7a8 100644 --- a/test/libc/intrin/test.mk +++ b/test/libc/intrin/test.mk @@ -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) \ diff --git a/test/libc/thread/makecontext_test.c b/test/libc/thread/makecontext_test.c index ba97c12be..206e121c6 100644 --- a/test/libc/thread/makecontext_test.c +++ b/test/libc/thread/makecontext_test.c @@ -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; diff --git a/test/libc/thread/pthread_create_test.c b/test/libc/thread/pthread_create_test.c index 4cc9e2ee2..b825d21d6 100644 --- a/test/libc/thread/pthread_create_test.c +++ b/test/libc/thread/pthread_create_test.c @@ -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)); diff --git a/test/libc/thread/pthread_setname_np_test.c b/test/libc/thread/pthread_setname_np_test.c index 16154b44d..d4744351a 100644 --- a/test/libc/thread/pthread_setname_np_test.c +++ b/test/libc/thread/pthread_setname_np_test.c @@ -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))); diff --git a/test/libc/thread/sem_open_test.c b/test/libc/thread/sem_open_test.c index e0308def6..34e9f75af 100644 --- a/test/libc/thread/sem_open_test.c +++ b/test/libc/thread/sem_open_test.c @@ -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)); } diff --git a/test/libc/thread/sem_timedwait_test.c b/test/libc/thread/sem_timedwait_test.c index b7de6beb2..53cb55952 100644 --- a/test/libc/thread/sem_timedwait_test.c +++ b/test/libc/thread/sem_timedwait_test.c @@ -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) { diff --git a/test/libc/thread/test.mk b/test/libc/thread/test.mk index 4b6994451..f9a6bc015 100644 --- a/test/libc/thread/test.mk +++ b/test/libc/thread/test.mk @@ -32,6 +32,7 @@ TEST_LIBC_THREAD_DIRECTDEPS = \ LIBC_STDIO \ LIBC_STR \ LIBC_SYSV \ + LIBC_SYSV_CALLS \ LIBC_TESTLIB \ LIBC_THREAD \ LIBC_TIME \ diff --git a/third_party/xxhash/xxh_x86dispatch.c b/third_party/xxhash/xxh_x86dispatch.c index cbcf112d6..55bdae09a 100644 --- a/third_party/xxhash/xxh_x86dispatch.c +++ b/third_party/xxhash/xxh_x86dispatch.c @@ -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__ */ diff --git a/third_party/xxhash/xxhash.h b/third_party/xxhash/xxhash.h index ddb2438e7..260523cd3 100644 --- a/third_party/xxhash/xxhash.h +++ b/third_party/xxhash/xxhash.h @@ -177,6 +177,7 @@ * @file xxhash.h * xxHash prototypes and implementation */ +#include "third_party/aarch64/arm_neon.internal.h" #if defined (__cplusplus) extern "C" { diff --git a/third_party/xxhash/xxhash.mk b/third_party/xxhash/xxhash.mk index 15f4c48dd..f4287e77d 100644 --- a/third_party/xxhash/xxhash.mk +++ b/third_party/xxhash/xxhash.mk @@ -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) diff --git a/third_party/zstd/lib/common/zstd_internal.h b/third_party/zstd/lib/common/zstd_internal.h index e3038ba71..27ff9fdce 100644 --- a/third_party/zstd/lib/common/zstd_internal.h +++ b/third_party/zstd/lib/common/zstd_internal.h @@ -39,6 +39,7 @@ #else # define ZSTD_TRACE 0 #endif +#include "third_party/aarch64/arm_neon.internal.h" #if defined (__cplusplus) extern "C" { diff --git a/third_party/zstd/zstd.mk b/third_party/zstd/zstd.mk index d2c1a089c..91a790845 100644 --- a/third_party/zstd/zstd.mk +++ b/third_party/zstd/zstd.mk @@ -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) diff --git a/tool/build/compile.c b/tool/build/compile.c index de85bbc60..d7e0706cf 100644 --- a/tool/build/compile.c +++ b/tool/build/compile.c @@ -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 */ diff --git a/tool/build/lib/getargs.c b/tool/build/lib/getargs.c index a4a17640c..49b3d0bf6 100644 --- a/tool/build/lib/getargs.c +++ b/tool/build/lib/getargs.c @@ -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); }