mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-23 05:42:29 +00:00
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:
parent
73c0faa1b5
commit
97b7116953
39 changed files with 557 additions and 754 deletions
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -23,6 +23,11 @@
|
|||
*/
|
||||
int __threaded;
|
||||
|
||||
/**
|
||||
* Set to true if sigaction() has installed signal handlers.
|
||||
*/
|
||||
bool __interruptible;
|
||||
|
||||
#ifdef __x86_64__
|
||||
bool __tls_enabled;
|
||||
#endif
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
163
libc/stdckdint.h
163
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<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_ */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) */
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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) \
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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)));
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -32,6 +32,7 @@ TEST_LIBC_THREAD_DIRECTDEPS = \
|
|||
LIBC_STDIO \
|
||||
LIBC_STR \
|
||||
LIBC_SYSV \
|
||||
LIBC_SYSV_CALLS \
|
||||
LIBC_TESTLIB \
|
||||
LIBC_THREAD \
|
||||
LIBC_TIME \
|
||||
|
|
4
third_party/xxhash/xxh_x86dispatch.c
vendored
4
third_party/xxhash/xxh_x86dispatch.c
vendored
|
@ -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__ */
|
||||
|
|
1
third_party/xxhash/xxhash.h
vendored
1
third_party/xxhash/xxhash.h
vendored
|
@ -177,6 +177,7 @@
|
|||
* @file xxhash.h
|
||||
* xxHash prototypes and implementation
|
||||
*/
|
||||
#include "third_party/aarch64/arm_neon.internal.h"
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
|
|
38
third_party/xxhash/xxhash.mk
vendored
38
third_party/xxhash/xxhash.mk
vendored
|
@ -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)
|
||||
|
|
1
third_party/zstd/lib/common/zstd_internal.h
vendored
1
third_party/zstd/lib/common/zstd_internal.h
vendored
|
@ -39,6 +39,7 @@
|
|||
#else
|
||||
# define ZSTD_TRACE 0
|
||||
#endif
|
||||
#include "third_party/aarch64/arm_neon.internal.h"
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
|
|
151
third_party/zstd/zstd.mk
vendored
151
third_party/zstd/zstd.mk
vendored
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue