diff --git a/examples/examples.mk b/examples/examples.mk index e5c68aca6..6ee3f8560 100644 --- a/examples/examples.mk +++ b/examples/examples.mk @@ -169,9 +169,14 @@ o/$(MODE)/usr/share/dict/words: \ ################################################################################ # binaries for execve_test.com -o/$(MODE)/examples/life-nomod.com.zip.o: ZIPOBJ_FLAGS += -B -o/$(MODE)/examples/life-classic.com.zip.o: ZIPOBJ_FLAGS += -B -o/$(MODE)/examples/pylife/pylife.com.zip.o: ZIPOBJ_FLAGS += -B +o/$(MODE)/examples/life-nomod.com.zip.o: o/$(MODE)/examples/life-nomod.com + @$(COMPILE) -AZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) -B $(OUTPUT_OPTION) $< + +o/$(MODE)/examples/life-classic.com.zip.o: o/$(MODE)/examples/life-classic.com + @$(COMPILE) -AZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) -B $(OUTPUT_OPTION) $< + +o/$(MODE)/examples/pylife/pylife.com.zip.o: o/$(MODE)/examples/pylife/pylife.com + @$(COMPILE) -AZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) -B $(OUTPUT_OPTION) $< o/$(MODE)/examples/life-classic.com.dbg: \ $(EXAMPLES_DEPS) \ diff --git a/libc/calls/struct/timespec.h b/libc/calls/struct/timespec.h index 1ac1f0aec..f5c407c4d 100644 --- a/libc/calls/struct/timespec.h +++ b/libc/calls/struct/timespec.h @@ -7,7 +7,7 @@ struct timespec { int64_t tv_nsec; /* nanoseconds */ }; -int futex(uint32_t *, int, int, const struct timespec *, uint32_t *); +int sys_futex(int *, int, int, const struct timespec *, int *); #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_TIMESPEC_H_ */ diff --git a/libc/fmt/vsnprintf.c b/libc/fmt/vsnprintf.c index 762684db8..9ad55b5a7 100644 --- a/libc/fmt/vsnprintf.c +++ b/libc/fmt/vsnprintf.c @@ -29,7 +29,9 @@ struct SprintfStr { }; static int vsnprintfputchar(const char *s, struct SprintfStr *t, size_t n) { - if (t->i + n <= t->n) { + if (n == 1 && t->i < t->n) { + t->p[t->i] = s[0]; + } else if (t->i + n <= t->n) { memcpy(t->p + t->i, s, n); } else if (t->i < t->n) { memcpy(t->p + t->i, s, t->n - t->i); diff --git a/libc/intrin/describefutexop.c b/libc/intrin/describefutexop.c new file mode 100644 index 000000000..5cf5be3af --- /dev/null +++ b/libc/intrin/describefutexop.c @@ -0,0 +1,37 @@ +/*-*- 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 2022 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/intrin/describeflags.internal.h" +#include "libc/macros.internal.h" +#include "libc/nt/enum/consolemodeflags.h" +#include "libc/sysv/consts/futex.h" + +const char *DescribeNtFutexOp(int x) { + const struct DescribeFlags kFutexOp[] = { + {FUTEX_WAIT_PRIVATE, "WAIT_PRIVATE"}, // + {FUTEX_WAKE_PRIVATE, "WAKE_PRIVATE"}, // + {FUTEX_REQUEUE_PRIVATE, "REQUEUE_PRIVATE"}, // + {FUTEX_PRIVATE_FLAG, "PRIVATE_FLAG"}, // + {FUTEX_REQUEUE, "REQUEUE"}, // + {FUTEX_WAIT, "WAIT"}, // + {FUTEX_WAKE, "WAKE"}, // + }; + _Alignas(char) static char futexop[32]; + return DescribeFlags(futexop, sizeof(futexop), kFutexOp, ARRAYLEN(kFutexOp), + "FUTEX_", x); +} diff --git a/libc/intrin/nopl.h b/libc/intrin/nopl.h index 269ad6799..600fd2b02 100644 --- a/libc/intrin/nopl.h +++ b/libc/intrin/nopl.h @@ -44,7 +44,8 @@ "nopl\t%a0" \ : /* no inputs */ \ : "X"(FUNC), "X"(IMAGE_BASE_VIRTUAL) \ - : "rax", "rdi", "rsi", "rdx", "rcx", "r8", "r9", "memory"); \ + : "rax", "rdi", "rsi", "rdx", "rcx", "r8", "r9", "r10", \ + "r11", "memory", "cc"); \ 0; \ }) @@ -60,7 +61,8 @@ "nopl\t%a1" \ : "+D"(__arg) \ : "X"(FUNC), "X"(IMAGE_BASE_VIRTUAL) \ - : "rax", "rsi", "rdx", "rcx", "r8", "r9", "memory"); \ + : "rax", "rsi", "rdx", "rcx", "r8", "r9", "r10", "r11", \ + "memory", "cc"); \ 0; \ }) diff --git a/libc/intrin/pthread_mutex_lock.c b/libc/intrin/pthread_mutex_lock.c index e678ac0a2..6b75a08c5 100644 --- a/libc/intrin/pthread_mutex_lock.c +++ b/libc/intrin/pthread_mutex_lock.c @@ -44,7 +44,8 @@ int pthread_mutex_lock(pthread_mutex_t *mutex) { } } atomic_fetch_add(&mutex->waits, +1); - if (!IsLinux() || futex((void *)&mutex->owner, FUTEX_WAIT, owner, 0, 0)) { + if (!IsLinux() || + sys_futex((void *)&mutex->owner, FUTEX_WAIT, owner, 0, 0)) { if (++tries & 7) { __builtin_ia32_pause(); } else { diff --git a/libc/intrin/pthread_mutex_unlock.c b/libc/intrin/pthread_mutex_unlock.c index 9aee64dc8..3f9d9262a 100644 --- a/libc/intrin/pthread_mutex_unlock.c +++ b/libc/intrin/pthread_mutex_unlock.c @@ -38,7 +38,7 @@ int pthread_mutex_unlock(pthread_mutex_t *mutex) { atomic_store_explicit(&mutex->owner, 0, memory_order_relaxed); if (IsLinux() && atomic_load_explicit(&mutex->waits, memory_order_acquire)) { - futex((void *)&mutex->owner, FUTEX_WAKE, 1, 0, 0); + sys_futex((void *)&mutex->owner, FUTEX_WAKE, 1, 0, 0); } } return 0; diff --git a/libc/stdio/getc.c b/libc/stdio/getc.c index 7775ac96f..906621ee6 100644 --- a/libc/stdio/getc.c +++ b/libc/stdio/getc.c @@ -24,5 +24,5 @@ * @threadsafe */ int(getc)(FILE *f) { - return getc(f); + return fgetc(f); } diff --git a/libc/sysv/calls/futex.s b/libc/sysv/calls/futex.s deleted file mode 100644 index 06de34ffe..000000000 --- a/libc/sysv/calls/futex.s +++ /dev/null @@ -1,2 +0,0 @@ -.include "o/libc/sysv/macros.internal.inc" -.scall futex,0xfff053fffffff0ca,globl diff --git a/libc/sysv/calls/sys_futex.s b/libc/sysv/calls/sys_futex.s new file mode 100644 index 000000000..50ac38801 --- /dev/null +++ b/libc/sysv/calls/sys_futex.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall sys_futex,0xfff053fffffff0ca,globl,hidden diff --git a/libc/sysv/syscalls.sh b/libc/sysv/syscalls.sh index ab51592b0..8d77dd21d 100755 --- a/libc/sysv/syscalls.sh +++ b/libc/sysv/syscalls.sh @@ -100,7 +100,7 @@ scall sys_kill 0x02507a025202503e globl hidden # kill(pid, sig, 1) b/c xnu scall sys_killpg 0xffffff092fffffff globl hidden scall sys_clone 0x11fffffffffff038 globl hidden scall sys_tkill 0x13e0771b121690c8 globl hidden # thr_kill() on freebsd; _lwp_kill() on netbsd; thrkill() on openbsd where arg3 should be 0; bsdthread_terminate() on XNU which only has 1 arg -scall futex 0xfff053fffffff0ca globl +scall sys_futex 0xfff053fffffff0ca globl hidden scall set_robust_list 0xfffffffffffff111 globl scall get_robust_list 0xfffffffffffff112 globl scall sys_uname 0xffffff0a4ffff03f globl hidden diff --git a/libc/testlib/ezbenchreport.c b/libc/testlib/ezbenchreport.c index 5e196020b..b0d2a28f4 100644 --- a/libc/testlib/ezbenchreport.c +++ b/libc/testlib/ezbenchreport.c @@ -18,7 +18,6 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/fmt/fmt.h" #include "libc/math.h" -#include "libc/runtime/gc.internal.h" #include "libc/runtime/runtime.h" #include "libc/stdio/stdio.h" #include "libc/testlib/testlib.h" diff --git a/libc/testlib/globals.c b/libc/testlib/globals.c index cfa349c22..c6563c30d 100644 --- a/libc/testlib/globals.c +++ b/libc/testlib/globals.c @@ -19,5 +19,5 @@ #include "libc/testlib/testlib.h" char g_fixturename[256]; -unsigned g_testlib_ran; -unsigned g_testlib_failed; +_Atomic(unsigned) g_testlib_ran; +_Atomic(unsigned) g_testlib_failed; diff --git a/libc/testlib/testlib.h b/libc/testlib/testlib.h index f0252c9dc..faf264432 100644 --- a/libc/testlib/testlib.h +++ b/libc/testlib/testlib.h @@ -2,7 +2,6 @@ #define COSMOPOLITAN_LIBC_TESTLIB_H_ #include "libc/bits/weaken.h" #include "libc/errno.h" -#include "libc/runtime/gc.internal.h" #include "libc/str/str.h" #include "libc/testlib/ugly.h" #if !(__ASSEMBLER__ + __LINKER__ + 0) @@ -318,8 +317,8 @@ extern char g_fixturename[256]; extern char g_testlib_olddir[PATH_MAX]; extern char g_testlib_tmpdir[PATH_MAX]; extern bool g_testlib_shoulddebugbreak; /* set by testmain */ -extern unsigned g_testlib_ran; /* set by wrappers */ -extern unsigned g_testlib_failed; /* set by wrappers */ +extern _Atomic(unsigned) g_testlib_ran; /* set by wrappers */ +extern _Atomic(unsigned) g_testlib_failed; /* set by wrappers */ extern const char *testlib_showerror_errno; /* set by macros */ extern const char *testlib_showerror_file; /* set by macros */ extern const char *testlib_showerror_func; /* set by macros */ diff --git a/libc/thread/join.c b/libc/thread/join.c index 99dded888..c07e98482 100644 --- a/libc/thread/join.c +++ b/libc/thread/join.c @@ -56,7 +56,7 @@ int cthread_join(cthread_t td, void **exitcode) { if (~atomic_fetch_add(&td->state, cthread_joining) & cthread_finished) { while ((x = atomic_load(&td->tid))) { // FUTEX_WAIT_PRIVATE makes it hang - cthread_memory_wait32((uint32_t *)&td->tid, x, 0); + cthread_memory_wait32(&td->tid, x, 0); } } if (exitcode) { diff --git a/libc/thread/thread.h b/libc/thread/thread.h index 9496de640..2fbd9a449 100644 --- a/libc/thread/thread.h +++ b/libc/thread/thread.h @@ -70,8 +70,8 @@ int cthread_sem_init(cthread_sem_t *, int); int cthread_sem_destroy(cthread_sem_t *); int cthread_sem_wait(cthread_sem_t *, int, const struct timespec *); int cthread_sem_signal(cthread_sem_t *); -int cthread_memory_wait32(uint32_t *, uint32_t, const struct timespec *); -int cthread_memory_wake32(uint32_t *, int); +int cthread_memory_wait32(int *, int, const struct timespec *); +int cthread_memory_wake32(int *, int); void cthread_zombies_add(cthread_t); void cthread_zombies_reap(void); diff --git a/libc/thread/wait.c b/libc/thread/wait.c index 1a81329d0..04b5335fa 100644 --- a/libc/thread/wait.c +++ b/libc/thread/wait.c @@ -24,12 +24,11 @@ #include "libc/thread/freebsd.internal.h" #include "libc/thread/thread.h" -int cthread_memory_wait32(uint32_t* addr, uint32_t val, - const struct timespec* timeout) { +int cthread_memory_wait32(int* addr, int val, const struct timespec* timeout) { size_t size; struct _umtx_time *put, ut; if (IsLinux() || IsOpenbsd()) { - return futex(addr, FUTEX_WAIT, val, timeout, 0); + return sys_futex(addr, FUTEX_WAIT, val, timeout, 0); #if 0 } else if (IsFreebsd()) { @@ -59,9 +58,9 @@ int cthread_memory_wait32(uint32_t* addr, uint32_t val, } } -int cthread_memory_wake32(uint32_t* addr, int n) { +int cthread_memory_wake32(int* addr, int n) { if (IsLinux() || IsOpenbsd()) { - return futex(addr, FUTEX_WAKE, n, 0, 0); + return sys_futex(addr, FUTEX_WAKE, n, 0, 0); #if 0 } else if (IsFreebsd()) { return _umtx_op(addr, UMTX_OP_MUTEX_WAKE, n, 0, 0); diff --git a/test/dsp/scale/scale_test.c b/test/dsp/scale/scale_test.c index 7394e7a3a..89f07b6c4 100644 --- a/test/dsp/scale/scale_test.c +++ b/test/dsp/scale/scale_test.c @@ -24,6 +24,7 @@ #include "libc/fmt/bing.internal.h" #include "libc/macros.internal.h" #include "libc/mem/mem.h" +#include "libc/runtime/gc.internal.h" #include "libc/stdio/stdio.h" #include "libc/str/str.h" #include "libc/testlib/ezbench.h" diff --git a/test/libc/calls/mkdir_test.c b/test/libc/calls/mkdir_test.c index 07aa908f2..d3e9e2406 100644 --- a/test/libc/calls/mkdir_test.c +++ b/test/libc/calls/mkdir_test.c @@ -22,6 +22,7 @@ #include "libc/fmt/fmt.h" #include "libc/log/check.h" #include "libc/mem/mem.h" +#include "libc/runtime/gc.internal.h" #include "libc/runtime/runtime.h" #include "libc/sysv/consts/o.h" #include "libc/testlib/testlib.h" diff --git a/test/libc/calls/open_test.c b/test/libc/calls/open_test.c index afec87b92..55c0fd41b 100644 --- a/test/libc/calls/open_test.c +++ b/test/libc/calls/open_test.c @@ -20,6 +20,7 @@ #include "libc/dce.h" #include "libc/errno.h" #include "libc/macros.internal.h" +#include "libc/runtime/gc.internal.h" #include "libc/sysv/consts/o.h" #include "libc/testlib/testlib.h" #include "libc/x/x.h" diff --git a/test/libc/calls/pipe_test.c b/test/libc/calls/pipe_test.c index 913f9d7b4..7b6b9a9cb 100644 --- a/test/libc/calls/pipe_test.c +++ b/test/libc/calls/pipe_test.c @@ -20,6 +20,7 @@ #include "libc/calls/struct/rlimit.h" #include "libc/dce.h" #include "libc/errno.h" +#include "libc/runtime/runtime.h" #include "libc/sysv/consts/rlimit.h" #include "libc/testlib/testlib.h" diff --git a/test/libc/calls/sched_getaffinity_test.c b/test/libc/calls/sched_getaffinity_test.c index 9edeb580b..65a010946 100644 --- a/test/libc/calls/sched_getaffinity_test.c +++ b/test/libc/calls/sched_getaffinity_test.c @@ -19,6 +19,7 @@ #include "libc/bits/popcnt.h" #include "libc/calls/calls.h" #include "libc/dce.h" +#include "libc/runtime/runtime.h" #include "libc/testlib/testlib.h" void SetUp(void) { diff --git a/test/libc/fmt/basename_test.c b/test/libc/fmt/basename_test.c index 60eb8ae42..847221077 100644 --- a/test/libc/fmt/basename_test.c +++ b/test/libc/fmt/basename_test.c @@ -19,6 +19,7 @@ #include "libc/bits/bits.h" #include "libc/fmt/conv.h" #include "libc/mem/mem.h" +#include "libc/runtime/gc.internal.h" #include "libc/testlib/testlib.h" #define BASENAME(x) basename(gc(strdup(x))) diff --git a/test/libc/fmt/zleb64_test.c b/test/libc/fmt/zleb64_test.c index 87b612563..d8cd220de 100644 --- a/test/libc/fmt/zleb64_test.c +++ b/test/libc/fmt/zleb64_test.c @@ -19,6 +19,7 @@ #include "libc/fmt/leb128.h" #include "libc/limits.h" #include "libc/mem/mem.h" +#include "libc/runtime/gc.internal.h" #include "libc/testlib/testlib.h" TEST(zleb64, testZero) { diff --git a/test/libc/intrin/asan_test.c b/test/libc/intrin/asan_test.c index 1caf76766..f1cbf0ea2 100644 --- a/test/libc/intrin/asan_test.c +++ b/test/libc/intrin/asan_test.c @@ -22,6 +22,7 @@ #include "libc/log/libfatal.internal.h" #include "libc/log/log.h" #include "libc/mem/mem.h" +#include "libc/runtime/gc.internal.h" #include "libc/runtime/runtime.h" #include "libc/stdio/stdio.h" #include "libc/str/str.h" diff --git a/test/libc/intrin/tls_test.c b/test/libc/intrin/tls_test.c index 48751d36b..ebfcb6df6 100644 --- a/test/libc/intrin/tls_test.c +++ b/test/libc/intrin/tls_test.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" #include "libc/errno.h" #include "libc/nexgen32e/gettls.h" #include "libc/nexgen32e/threaded.h" diff --git a/test/libc/log/test.mk b/test/libc/log/test.mk index 34d81864f..00e06a1f6 100644 --- a/test/libc/log/test.mk +++ b/test/libc/log/test.mk @@ -76,10 +76,13 @@ o/$(MODE)/test/libc/log/backtrace.com.dbg: \ $(APE_NO_MODIFY_SELF) @$(APELINK) -o/$(MODE)/test/libc/log/backtrace.com.zip.o \ -o/$(MODE)/test/libc/log/backtrace.com.dbg.zip.o: \ - ZIPOBJ_FLAGS += \ - -B +o/$(MODE)/test/libc/log/backtrace.com.zip.o: \ + o/$(MODE)/test/libc/log/backtrace.com + @$(COMPILE) -AZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) -B $(OUTPUT_OPTION) $< + +o/$(MODE)/test/libc/log/backtrace.com.dbg.zip.o: \ + o/$(MODE)/test/libc/log/backtrace.com.dbg + @$(COMPILE) -AZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) -B $(OUTPUT_OPTION) $< .PHONY: o/$(MODE)/test/libc/log o/$(MODE)/test/libc/log: \ diff --git a/test/libc/mem/arena_test.c b/test/libc/mem/arena_test.c index 3907067e0..a4a5f3725 100644 --- a/test/libc/mem/arena_test.c +++ b/test/libc/mem/arena_test.c @@ -19,6 +19,7 @@ #include "libc/log/libfatal.internal.h" #include "libc/mem/arena.h" #include "libc/mem/mem.h" +#include "libc/runtime/gc.internal.h" #include "libc/stdio/append.internal.h" #include "libc/str/str.h" #include "libc/testlib/ezbench.h" diff --git a/test/libc/mem/malloc_test.c b/test/libc/mem/malloc_test.c index 767467b28..835c7bae9 100644 --- a/test/libc/mem/malloc_test.c +++ b/test/libc/mem/malloc_test.c @@ -26,6 +26,7 @@ #include "libc/mem/mem.h" #include "libc/rand/rand.h" #include "libc/runtime/cxaatexit.internal.h" +#include "libc/runtime/gc.internal.h" #include "libc/runtime/memtrack.internal.h" #include "libc/runtime/runtime.h" #include "libc/stdio/stdio.h" diff --git a/test/libc/nexgen32e/memset_test.c b/test/libc/nexgen32e/memset_test.c index 86afded11..c4a0b2880 100644 --- a/test/libc/nexgen32e/memset_test.c +++ b/test/libc/nexgen32e/memset_test.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/mem/mem.h" #include "libc/nexgen32e/nexgen32e.h" +#include "libc/runtime/gc.internal.h" #include "libc/testlib/testlib.h" void *_memset(void *, int, size_t) asm("memset"); diff --git a/test/libc/nexgen32e/strcaseconv_test.c b/test/libc/nexgen32e/strcaseconv_test.c index 01e259e75..06dc6d5dc 100644 --- a/test/libc/nexgen32e/strcaseconv_test.c +++ b/test/libc/nexgen32e/strcaseconv_test.c @@ -19,6 +19,7 @@ #include "libc/mem/mem.h" #include "libc/nexgen32e/nexgen32e.h" #include "libc/rand/rand.h" +#include "libc/runtime/gc.internal.h" #include "libc/str/str.h" #include "libc/testlib/ezbench.h" #include "libc/testlib/testlib.h" diff --git a/test/libc/rand/devrand_test.c b/test/libc/rand/devrand_test.c index 2de7c3b6a..a416c5cb1 100644 --- a/test/libc/rand/devrand_test.c +++ b/test/libc/rand/devrand_test.c @@ -19,6 +19,7 @@ #include "libc/dce.h" #include "libc/mem/mem.h" #include "libc/rand/rand.h" +#include "libc/runtime/gc.internal.h" #include "libc/str/str.h" #include "libc/testlib/testlib.h" diff --git a/test/libc/rand/rand64_test.c b/test/libc/rand/rand64_test.c index 9f3dd3d6a..48dbc5d31 100644 --- a/test/libc/rand/rand64_test.c +++ b/test/libc/rand/rand64_test.c @@ -43,7 +43,7 @@ #define THREADS 8 #define ENTRIES 1024 -uint32_t ready; +int ready; volatile uint64_t A[THREADS * ENTRIES]; void OnChld(int sig) { @@ -109,7 +109,7 @@ TEST(rand64, testThreadSafety_doesntProduceIdenticalValues) { for (i = 0; i < THREADS; ++i) { while ((j = atomic_load((uint32_t *)(tls[i] + 0x38)))) { // FUTEX_WAIT_PRIVATE makes it hang - cthread_memory_wait32((uint32_t *)(tls[i] + 0x38), j, 0); + cthread_memory_wait32((int *)(tls[i] + 0x38), j, 0); } EXPECT_SYS(0, 0, munmap(stacks[i], GetStackSize())); free(tls[i]); diff --git a/test/libc/runtime/mprotect_test.c b/test/libc/runtime/mprotect_test.c index d9f64e1a4..7147144b7 100644 --- a/test/libc/runtime/mprotect_test.c +++ b/test/libc/runtime/mprotect_test.c @@ -24,6 +24,7 @@ #include "libc/intrin/kprintf.h" #include "libc/log/log.h" #include "libc/mem/mem.h" +#include "libc/runtime/gc.internal.h" #include "libc/runtime/runtime.h" #include "libc/stdio/stdio.h" #include "libc/sysv/consts/map.h" diff --git a/test/libc/sock/socketpair_test.c b/test/libc/sock/socketpair_test.c index 7b84c2294..0ccc5b294 100644 --- a/test/libc/sock/socketpair_test.c +++ b/test/libc/sock/socketpair_test.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/assert.h" +#include "libc/calls/calls.h" #include "libc/dce.h" #include "libc/sock/sock.h" #include "libc/sysv/consts/af.h" diff --git a/test/libc/stdio/dtoa_test.c b/test/libc/stdio/dtoa_test.c new file mode 100644 index 000000000..b9de01ca5 --- /dev/null +++ b/test/libc/stdio/dtoa_test.c @@ -0,0 +1,62 @@ +/*-*- 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 2022 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" +#include "libc/fmt/fmt.h" +#include "libc/intrin/spinlock.h" +#include "libc/math.h" +#include "libc/runtime/stack.h" +#include "libc/stdio/stdio.h" +#include "libc/sysv/consts/clone.h" +#include "libc/sysv/consts/map.h" +#include "libc/sysv/consts/prot.h" +#include "libc/testlib/testlib.h" +#include "libc/x/x.h" + +#define THREADS 16 + +char *stack[THREADS]; +char tls[THREADS][64]; + +int Worker(void *p) { + int i; + char str[64]; + for (i = 0; i < 256; ++i) { + bzero(str, sizeof(str)); + snprintf(str, sizeof(str), "%.15g", atan2(-1., -.5)); + ASSERT_STREQ("-2.0344439357957", str); + } + return 0; +} + +TEST(dtoa, test) { + int i; + for (i = 0; i < THREADS; ++i) { + clone(Worker, + (stack[i] = mmap(0, GetStackSize(), PROT_READ | PROT_WRITE, + MAP_STACK | MAP_ANONYMOUS, -1, 0)), + GetStackSize(), + CLONE_THREAD | CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | + CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | CLONE_SETTLS, + 0, 0, __initialize_tls(tls[i]), sizeof(tls[i]), + (int *)(tls[i] + 0x38)); + } + for (i = 0; i < THREADS; ++i) { + _spinlock((int *)(tls[i] + 0x38)); + } +} diff --git a/test/libc/stdio/dumphexc_test.c b/test/libc/stdio/dumphexc_test.c index 10f8d06e9..f7839e4fb 100644 --- a/test/libc/stdio/dumphexc_test.c +++ b/test/libc/stdio/dumphexc_test.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/mem/mem.h" +#include "libc/runtime/gc.internal.h" #include "libc/stdio/hex.internal.h" #include "libc/testlib/ezbench.h" #include "libc/testlib/hyperion.h" diff --git a/test/libc/stdio/popen_test.c b/test/libc/stdio/popen_test.c index c7d37b8ea..a14216a26 100644 --- a/test/libc/stdio/popen_test.c +++ b/test/libc/stdio/popen_test.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" #include "libc/log/check.h" #include "libc/stdio/stdio.h" #include "libc/testlib/testlib.h" diff --git a/test/libc/stdio/test.mk b/test/libc/stdio/test.mk index 8eb805252..272f0c0f4 100644 --- a/test/libc/stdio/test.mk +++ b/test/libc/stdio/test.mk @@ -35,6 +35,7 @@ TEST_LIBC_STDIO_DIRECTDEPS = \ LIBC_STR \ LIBC_STUBS \ LIBC_SYSV \ + LIBC_TINYMATH \ LIBC_TESTLIB \ LIBC_TIME \ LIBC_LOG \ diff --git a/test/libc/stdio/vappendf_test.c b/test/libc/stdio/vappendf_test.c index 8489e3e5e..660de610f 100644 --- a/test/libc/stdio/vappendf_test.c +++ b/test/libc/stdio/vappendf_test.c @@ -177,6 +177,7 @@ BENCH(vappendf, bench) { const char t[] = {0}; char *b = 0; EZBENCH2("appendf", donothing, appendf(&b, "hello")); + EZBENCH2("kappendf", donothing, kappendf(&b, "hello")); free(b), b = 0; EZBENCH2("appends", donothing, appends(&b, "hello")); free(b), b = 0; diff --git a/test/libc/str/longsort_test.c b/test/libc/str/longsort_test.c index 48174f17d..6487d6f2f 100644 --- a/test/libc/str/longsort_test.c +++ b/test/libc/str/longsort_test.c @@ -19,6 +19,7 @@ #include "libc/alg/alg.h" #include "libc/mem/mem.h" #include "libc/rand/rand.h" +#include "libc/runtime/gc.internal.h" #include "libc/runtime/runtime.h" #include "libc/str/str.h" #include "libc/testlib/ezbench.h" diff --git a/test/libc/str/pututf16_test.c b/test/libc/str/pututf16_test.c index 88322a130..8af2b8b8e 100644 --- a/test/libc/str/pututf16_test.c +++ b/test/libc/str/pututf16_test.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/bits/bits.h" #include "libc/mem/mem.h" +#include "libc/runtime/gc.internal.h" #include "libc/str/oldutf16.internal.h" #include "libc/str/str.h" #include "libc/testlib/testlib.h" diff --git a/test/libc/tinymath/hypot_test.c b/test/libc/tinymath/hypot_test.c index 672616616..b9090fbde 100644 --- a/test/libc/tinymath/hypot_test.c +++ b/test/libc/tinymath/hypot_test.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/math.h" +#include "libc/runtime/gc.internal.h" #include "libc/testlib/ezbench.h" #include "libc/testlib/testlib.h" #include "libc/x/x.h" diff --git a/test/libc/x/utf16to32_test.c b/test/libc/x/utf16to32_test.c index 3fd71c4dc..781cfacf7 100644 --- a/test/libc/x/utf16to32_test.c +++ b/test/libc/x/utf16to32_test.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/runtime/gc.internal.h" #include "libc/testlib/ezbench.h" #include "libc/testlib/hyperion.h" #include "libc/testlib/testlib.h" diff --git a/test/libc/x/utf8toutf16_test.c b/test/libc/x/utf8toutf16_test.c index d78391416..5c0ad707f 100644 --- a/test/libc/x/utf8toutf16_test.c +++ b/test/libc/x/utf8toutf16_test.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/mem/mem.h" +#include "libc/runtime/gc.internal.h" #include "libc/testlib/ezbench.h" #include "libc/testlib/hyperion.h" #include "libc/testlib/testlib.h" diff --git a/test/libc/x/xjoinpaths_test.c b/test/libc/x/xjoinpaths_test.c index c7a07ee7b..b1d05e539 100644 --- a/test/libc/x/xjoinpaths_test.c +++ b/test/libc/x/xjoinpaths_test.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/runtime/gc.internal.h" #include "libc/testlib/testlib.h" #include "libc/x/x.h" diff --git a/test/net/http/decodebase64_test.c b/test/net/http/decodebase64_test.c index b173629ba..16ed4cc77 100644 --- a/test/net/http/decodebase64_test.c +++ b/test/net/http/decodebase64_test.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/runtime/gc.internal.h" #include "libc/testlib/testlib.h" #include "net/http/escape.h" diff --git a/test/net/http/decodelatin1_test.c b/test/net/http/decodelatin1_test.c index dbd2a340b..53b222820 100644 --- a/test/net/http/decodelatin1_test.c +++ b/test/net/http/decodelatin1_test.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/errno.h" #include "libc/mem/mem.h" +#include "libc/runtime/gc.internal.h" #include "libc/testlib/ezbench.h" #include "libc/testlib/hyperion.h" #include "libc/testlib/testlib.h" diff --git a/test/net/http/parseurl_test.c b/test/net/http/parseurl_test.c index 34c09f5ae..c4767de27 100644 --- a/test/net/http/parseurl_test.c +++ b/test/net/http/parseurl_test.c @@ -19,6 +19,7 @@ #include "libc/limits.h" #include "libc/mem/mem.h" #include "libc/rand/rand.h" +#include "libc/runtime/gc.internal.h" #include "libc/testlib/ezbench.h" #include "libc/testlib/hyperion.h" #include "libc/testlib/testlib.h" diff --git a/test/tool/args/args_test.c b/test/tool/args/args_test.c index 5ff53051e..bed084b48 100644 --- a/test/tool/args/args_test.c +++ b/test/tool/args/args_test.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/mem/mem.h" +#include "libc/runtime/runtime.h" #include "libc/testlib/testlib.h" #include "tool/args/args.h" diff --git a/test/tool/build/lib/getargs_test.c b/test/tool/build/lib/getargs_test.c index d4102d520..c73eb8356 100644 --- a/test/tool/build/lib/getargs_test.c +++ b/test/tool/build/lib/getargs_test.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" #include "libc/runtime/runtime.h" #include "libc/str/str.h" #include "libc/sysv/consts/o.h" diff --git a/test/tool/build/lib/pty_test.c b/test/tool/build/lib/pty_test.c index 21fd838f3..048882cd8 100644 --- a/test/tool/build/lib/pty_test.c +++ b/test/tool/build/lib/pty_test.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/log/log.h" #include "libc/mem/mem.h" +#include "libc/runtime/gc.internal.h" #include "libc/stdio/stdio.h" #include "libc/str/str.h" #include "libc/testlib/ezbench.h" diff --git a/test/tool/plinko/test.mk b/test/tool/plinko/test.mk index f93b5a9e2..7fe9cfb11 100644 --- a/test/tool/plinko/test.mk +++ b/test/tool/plinko/test.mk @@ -80,10 +80,8 @@ o/$(MODE)/test/tool/plinko/%.com.dbg: \ o/$(MODE)/test/tool/plinko/plinko_test.com.runs: \ QUOTA = -M100g -o/$(MODE)/test/tool/plinko/algebra_test.lisp.zip.o \ -o/$(MODE)/test/tool/plinko/library_test.lisp.zip.o: \ - ZIPOBJ_FLAGS += \ - -B +o/$(MODE)/test/tool/plinko/algebra_test.lisp.zip.o: ZIPOBJ_FLAGS += -B +o/$(MODE)/test/tool/plinko/library_test.lisp.zip.o: ZIPOBJ_FLAGS += -B .PHONY: o/$(MODE)/test/tool/plinko o/$(MODE)/test/tool/plinko: \ diff --git a/third_party/gdtoa/gdtoa.internal.h b/third_party/gdtoa/gdtoa.internal.h index 146120c11..3d177c3d3 100644 --- a/third_party/gdtoa/gdtoa.internal.h +++ b/third_party/gdtoa/gdtoa.internal.h @@ -348,9 +348,8 @@ typedef struct ThInfo { #define Bcopy(x, y) \ memcpy(&x->sign, &y->sign, y->wds * sizeof(ULong) + 2 * sizeof(int)) -hidden extern char *__gdtoa_dtoa_result; -hidden extern const double __gdtoa_bigtens[]; hidden extern const double __gdtoa_tens[]; +hidden extern const double __gdtoa_bigtens[]; hidden extern const double __gdtoa_tinytens[]; hidden extern const unsigned char __gdtoa_hexdig[]; hidden extern const char *const __gdtoa_InfName[6]; diff --git a/third_party/gdtoa/lock.c b/third_party/gdtoa/lock.c new file mode 100644 index 000000000..9b5065aef --- /dev/null +++ b/third_party/gdtoa/lock.c @@ -0,0 +1,30 @@ +/*-*- 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 2022 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/intrin/pthread.h" +#include "third_party/gdtoa/lock.h" + +static pthread_mutex_t __gdtoa_lock_obj; + +int(__gdtoa_lock)(void) { + return pthread_mutex_lock(&__gdtoa_lock_obj); +} + +int(__gdtoa_unlock)(void) { + return pthread_mutex_unlock(&__gdtoa_lock_obj); +} diff --git a/third_party/gdtoa/lock.h b/third_party/gdtoa/lock.h new file mode 100644 index 000000000..a5637a3ee --- /dev/null +++ b/third_party/gdtoa/lock.h @@ -0,0 +1,21 @@ +#ifndef COSMOPOLITAN_THIRD_PARTY_GDTOA_LOCK_H_ +#define COSMOPOLITAN_THIRD_PARTY_GDTOA_LOCK_H_ +#include "libc/intrin/nopl.h" +#include "libc/nexgen32e/threaded.h" +#if !(__ASSEMBLER__ + __LINKER__ + 0) +COSMOPOLITAN_C_START_ + +int __gdtoa_lock(void); +int __gdtoa_unlock(void); + +#if defined(__GNUC__) && !defined(__llvm__) && !defined(__STRICT_ANSI__) +#define __gdtoa_lock() _NOPL0("__threadcalls", __gdtoa_lock) +#define __gdtoa_unlock() _NOPL0("__threadcalls", __gdtoa_unlock) +#else +#define __gdtoa_lock() (__threaded ? __gdtoa_lock() : 0) +#define __gdtoa_unlock() (__threaded ? __gdtoa_unlock() : 0) +#endif + +COSMOPOLITAN_C_END_ +#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ +#endif /* COSMOPOLITAN_THIRD_PARTY_GDTOA_LOCK_H_ */ diff --git a/third_party/gdtoa/misc.c b/third_party/gdtoa/misc.c index 7937dbbef..5a85567d3 100644 --- a/third_party/gdtoa/misc.c +++ b/third_party/gdtoa/misc.c @@ -33,6 +33,7 @@ #include "libc/macros.internal.h" #include "libc/runtime/runtime.h" #include "third_party/gdtoa/gdtoa.internal.h" +#include "third_party/gdtoa/lock.h" /* clang-format off */ static ThInfo TI0; @@ -46,68 +47,62 @@ __gdtoa_Brelease(Bigint *rv) } static void -Bclear(void) +__gdtoa_Bclear(void) { int i; + __gdtoa_lock(); for (i = 0; i < ARRAYLEN(TI0.Freelist); ++i) __gdtoa_Brelease(TI0.Freelist[i]); - bzero(&TI0.Freelist, sizeof(TI0.Freelist)); + __gdtoa_Brelease(TI0.P5s); + bzero(&TI0, sizeof(TI0)); + __gdtoa_unlock(); +} + +__attribute__((__constructor__)) static void +__gdtoa_Binit(void) +{ + atexit(__gdtoa_Bclear); + TI0.P5s = __gdtoa_i2b(625); + TI0.P5s->next = 0; } Bigint * __gdtoa_Balloc(int k) { -#if 0 int x; Bigint *rv; - x = 1 << k; - rv = (Bigint *)malloc(sizeof(Bigint) + (x-1)*sizeof(ULong)); - rv->k = k; - rv->maxwds = x; - rv->sign = 0; - rv->wds = 0; - return rv; -#else - int x; - Bigint *rv; - static char once; - if (!once) { - atexit(Bclear); - once = 1; - } + __gdtoa_lock(); if (k <= Kmax && (rv = TI0.Freelist[k]) != 0) { TI0.Freelist[k] = rv->next; } else { x = 1 << k; - rv = (Bigint *)malloc(sizeof(Bigint) + (x-1)*sizeof(ULong)); + rv = malloc(sizeof(Bigint) + (x-1)*sizeof(ULong)); rv->k = k; rv->maxwds = x; } rv->sign = 0; rv->wds = 0; + __gdtoa_unlock(); return rv; -#endif } void __gdtoa_Bfree(Bigint *v) { -#if 0 - free(v); -#else if (v) { if (v->k > Kmax) { - free((void*)v); + free(v); } else { + __gdtoa_lock(); v->next = TI0.Freelist[v->k]; TI0.Freelist[v->k] = v; + __gdtoa_unlock(); } } -#endif } -Bigint * -__gdtoa_multadd(Bigint *b, int m, int a) /* multiply by m and add a */ +Bigint * /* multiply by m and add a */ +__gdtoa_multadd(Bigint *b, int m, int a) { int i, wds; ULong *x; @@ -192,27 +187,18 @@ __gdtoa_mult(Bigint *a, Bigint *b) return c; } -static void -__gdtoa_pow5mult_destroy(void) { - __gdtoa_Brelease(TI0.P5s); - TI0.P5s = 0; -} - Bigint * __gdtoa_pow5mult(Bigint *b, int k) { - Bigint *b1, *p5, *p51; int i; + Bigint *b1, *p5, *p51; static const int p05[3] = { 5, 25, 125 }; if ((i = k & 3)) b = __gdtoa_multadd(b, p05[i-1], 0); if (!(k >>= 2)) return b; - if (!(p5 = TI0.P5s)) { - p5 = TI0.P5s = __gdtoa_i2b(625); - p5->next = 0; - atexit(__gdtoa_pow5mult_destroy); - } + __gdtoa_lock(); + p5 = TI0.P5s; for(;;) { if (k & 1) { b1 = __gdtoa_mult(b, p5); @@ -227,6 +213,7 @@ __gdtoa_pow5mult(Bigint *b, int k) } p5 = p51; } + __gdtoa_unlock(); return b; } diff --git a/third_party/python/python.mk b/third_party/python/python.mk index 5e5581fe2..5f75fec17 100644 --- a/third_party/python/python.mk +++ b/third_party/python/python.mk @@ -293,7 +293,7 @@ THIRD_PARTY_PYTHON_INCS = \ THIRD_PARTY_PYTHON_STAGE1_A_SRCS = \ third_party/python/Modules/_tracemalloc.c \ third_party/python/Modules/faulthandler.c \ - third_party/python/Objects/abstract.c \ + third_party/python/Objects/abstract.c \ third_party/python/Modules/fspath.c \ third_party/python/Modules/gcmodule.c \ third_party/python/Modules/getbuildinfo.c \ @@ -305,7 +305,7 @@ THIRD_PARTY_PYTHON_STAGE1_A_SRCS = \ third_party/python/Objects/bytes_methods.c \ third_party/python/Objects/bytesobject.c \ third_party/python/Objects/capsule.c \ - third_party/python/Objects/call.c \ + third_party/python/Objects/call.c \ third_party/python/Objects/cellobject.c \ third_party/python/Objects/classobject.c \ third_party/python/Objects/codeobject.c \ diff --git a/tool/build/runit.c b/tool/build/runit.c index 6c26d9d15..53b51587f 100644 --- a/tool/build/runit.c +++ b/tool/build/runit.c @@ -190,12 +190,15 @@ TryAgain: freeaddrinfo(ai); } -bool Send(int *pipes, int pipescount, const void *output, size_t outputsize) { - bool okall; - int rc, i, have; +bool Send(int tmpfd, const void *output, size_t outputsize) { + bool ok; + char *zbuf; + size_t zsize; + int rc, have; static bool once; static z_stream zs; - char *zbuf = gc(malloc(PIPE_BUF)); + zsize = 32768; + zbuf = gc(malloc(zsize)); if (!once) { CHECK_EQ(Z_OK, deflateInit2(&zs, 4, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY)); @@ -203,25 +206,24 @@ bool Send(int *pipes, int pipescount, const void *output, size_t outputsize) { } zs.next_in = output; zs.avail_in = outputsize; - okall = true; + ok = true; do { - zs.avail_out = PIPE_BUF; + zs.avail_out = zsize; zs.next_out = (unsigned char *)zbuf; rc = deflate(&zs, Z_SYNC_FLUSH); CHECK_NE(Z_STREAM_ERROR, rc); - have = PIPE_BUF - zs.avail_out; - for (i = 0; i < pipescount; ++i) { - rc = write(pipes[i * 2 + 1], zbuf, have); - if (rc != have) { - DEBUGF("write(%d, %d) → %d", pipes[i * 2 + 1], have, rc); - okall = false; - } + have = zsize - zs.avail_out; + rc = write(tmpfd, zbuf, have); + if (rc != have) { + DEBUGF("write(%d, %d) → %d", tmpfd, have, rc); + ok = false; + break; } } while (!zs.avail_out); - return okall; + return ok; } -bool SendRequest(int *pipes, int pipescount) { +bool SendRequest(int tmpfd) { int fd; char *p; size_t i; @@ -249,17 +251,14 @@ bool SendRequest(int *pipes, int pipescount) { q = mempcpy(q, name, namesize); assert(hdrsize == q - hdr); okall = true; - okall &= Send(pipes, pipescount, hdr, hdrsize); - okall &= Send(pipes, pipescount, p, progsize); + okall &= Send(tmpfd, hdr, hdrsize); + okall &= Send(tmpfd, p, progsize); CHECK_NE(-1, munmap(p, st.st_size)); CHECK_NE(-1, close(fd)); - for (i = 0; i < pipescount; ++i) { - okall &= !close(pipes[i * 2 + 1]); - } return okall; } -bool RelayRequest(void) { +void RelayRequest(void) { int i, rc, have, transferred; char *buf = gc(malloc(PIPE_BUF)); for (transferred = 0;;) { @@ -281,7 +280,6 @@ bool RelayRequest(void) { TlsDie("relay request failed to flush", rc); } close(13); - return true; } bool Recv(unsigned char *p, size_t n) { @@ -351,16 +349,17 @@ int RunOnHost(char *spec) { 1); if (!strchr(g_hostname, '.')) strcat(g_hostname, ".test."); DEBUGF("connecting to %s port %d", g_hostname, g_runitdport); - do { - for (;;) { - Connect(); - EzFd(g_sock); - if (!EzHandshake2()) break; - WARNF("warning: got connection reset in handshake"); - close(g_sock); + for (;;) { + Connect(); + EzFd(g_sock); + if (!(rc = EzHandshake2())) { + break; } - } while ((rc = RelayRequest()) == -1 || (rc = ReadResponse()) == -1); - return rc; + WARNF("got reset in handshake -0x%04x", rc); + close(g_sock); + } + RelayRequest(); + return ReadResponse(); } bool IsParallelBuild(void) { @@ -373,12 +372,20 @@ bool ShouldRunInParralel(void) { } int SpawnSubprocesses(int argc, char *argv[]) { + const char *tpath; sigset_t chldmask, savemask; + int i, rc, ws, pid, tmpfd, *pids, exitcode; struct sigaction ignore, saveint, savequit; - int i, rc, ws, pid, *pids, *pipes, exitcode; char *args[5] = {argv[0], argv[1], argv[2]}; - argc -= 3; - argv += 3; + + // create compressed network request ahead of time + CHECK_NE(-1, (tmpfd = open( + (tpath = gc(xasprintf( + "%s/runit.%d", firstnonnull(getenv("TMPDIR"), "/tmp"), + getpid()))), + O_WRONLY | O_CREAT | O_TRUNC, 0755))); + CHECK(SendRequest(tmpfd)); + CHECK_NE(-1, close(tmpfd)); // fork off 𝑛 subprocesses for each host on which we run binary. // what's important here is htop in tree mode will report like: @@ -389,8 +396,10 @@ int SpawnSubprocesses(int argc, char *argv[]) { // └─runit.com netbsd // // That way when one hangs, it's easy to know what o/s it is. + argc -= 3; + argv += 3; + exitcode = 0; pids = calloc(argc, sizeof(int)); - pipes = calloc(argc, sizeof(int) * 2); ignore.sa_flags = 0; ignore.sa_handler = SIG_IGN; sigemptyset(&ignore.sa_mask); @@ -401,26 +410,18 @@ int SpawnSubprocesses(int argc, char *argv[]) { sigprocmask(SIG_BLOCK, &chldmask, &savemask); for (i = 0; i < argc; ++i) { args[3] = argv[i]; - CHECK_NE(-1, pipe2(pipes + i * 2, O_CLOEXEC)); CHECK_NE(-1, (pids[i] = vfork())); if (!pids[i]) { - dup2(pipes[i * 2], 13); + dup2(open(tpath, O_RDONLY | O_CLOEXEC), 13); sigaction(SIGINT, &(struct sigaction){0}, 0); sigaction(SIGQUIT, &(struct sigaction){0}, 0); sigprocmask(SIG_SETMASK, &savemask, 0); execve(args[0], args, environ); // for htop _Exit(127); } - close(pipes[i * 2]); // close reader } - // the smart part is we only do the expensive deflate operation from - // the main process we assume file descriptor 13 is safely inherited - static z_stream zs; - sigaction(SIGPIPE, &ignore, 0); - exitcode = SendRequest(pipes, argc) ? 0 : 150; - - // now wait for the children to terminate + // wait for children to terminate for (;;) { if ((pid = wait(&ws)) == -1) { if (errno == EINTR) continue; @@ -443,10 +444,10 @@ int SpawnSubprocesses(int argc, char *argv[]) { break; } } + CHECK_NE(-1, unlink(tpath)); sigprocmask(SIG_SETMASK, &savemask, 0); sigaction(SIGQUIT, &savequit, 0); sigaction(SIGINT, &saveint, 0); - free(pipes); free(pids); return exitcode; } diff --git a/tool/build/runitd.c b/tool/build/runitd.c index 625376667..91e7aeed4 100644 --- a/tool/build/runitd.c +++ b/tool/build/runitd.c @@ -267,7 +267,7 @@ void SendOutputFragmentMessage(enum RunitCommand kind, unsigned char *buf, void Recv(void *output, size_t outputsize) { int rc; - ssize_t tx, chunk, received; + ssize_t tx, chunk, received, totalgot; static bool once; static int zstatus; static char buf[32768]; @@ -282,6 +282,7 @@ void Recv(void *output, size_t outputsize) { CHECK_EQ(Z_OK, inflateInit(&zs)); once = true; } + totalgot = 0; for (;;) { if (rbuf.len >= outputsize) { tx = MIN(outputsize, rbuf.len); @@ -312,6 +313,7 @@ void Recv(void *output, size_t outputsize) { close(g_clifd); TlsDie("read failed", received); } + totalgot += received; // decompress packet completely // into a dynamical size buffer zs.avail_in = received; @@ -331,12 +333,14 @@ void Recv(void *output, size_t outputsize) { CHECK_NE(Z_STREAM_ERROR, zstatus); switch (zstatus) { case Z_NEED_DICT: - zstatus = Z_DATA_ERROR; // make negative - // fallthrough + WARNF("tls recv Z_NEED_DICT %ld total %ld", received, totalgot); + exit(1); case Z_DATA_ERROR: + WARNF("tls recv Z_DATA_ERROR %ld total %ld", received, totalgot); + exit(1); case Z_MEM_ERROR: - close(g_clifd); - FATALF("tls recv zlib hard error %d", zstatus); + WARNF("tls recv Z_MEM_ERROR %ld total %ld", received, totalgot); + exit(1); case Z_BUF_ERROR: zstatus = Z_OK; // harmless? nothing for inflate to do break; // it probably just our wraparound eof diff --git a/tool/plinko/plinko.mk b/tool/plinko/plinko.mk index ab40018b8..00f01cc7a 100644 --- a/tool/plinko/plinko.mk +++ b/tool/plinko/plinko.mk @@ -63,7 +63,6 @@ $(TOOL_PLINKO_OBJS): \ $(BUILD_FILES) \ tool/plinko/plinko.mk -o/$(MODE)/tool/plinko/plinko.com.zip.o \ o/$(MODE)/tool/plinko/lib/library.lisp.zip.o \ o/$(MODE)/tool/plinko/lib/binarytrees.lisp.zip.o \ o/$(MODE)/tool/plinko/lib/algebra.lisp.zip.o \ @@ -72,6 +71,10 @@ o/$(MODE)/tool/plinko/lib/ok.lisp.zip.o: \ ZIPOBJ_FLAGS += \ -B +o/$(MODE)/tool/plinko/plinko.com.zip.o: \ + o/$(MODE)/tool/plinko/plinko.com + @$(COMPILE) -AZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) -B $(OUTPUT_OPTION) $< + .PHONY: o/$(MODE)/tool/plinko o/$(MODE)/tool/plinko: $(TOOL_PLINKO_BINS) $(TOOL_PLINKO_CHECKS)