From cf1559c4487798211e3a98460cf1286b006b43e6 Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Sun, 28 Jul 2024 23:43:22 -0700 Subject: [PATCH] Remove __threaded variable --- libc/calls/calls.h | 1 + libc/calls/pledge.c | 3 +- libc/calls/sched_getscheduler.c | 1 - libc/calls/sched_setscheduler.c | 1 - libc/nexgen32e/threaded.c | 5 -- libc/proc/fork-nt.c | 4 -- libc/proc/proc.c | 1 - libc/runtime/clone.c | 4 -- libc/runtime/runtime.h | 1 - libc/thread/tls.h | 1 - test/libc/intrin/lock_test.c | 2 - test/libc/mem/malloc_test.c | 46 +++--------------- .../libc/mem/malloc_torture_test.c | 47 +++++++++++++++++-- test/libc/thread/pthread_atfork_test.c | 1 - third_party/dlmalloc/locks.inc | 4 -- 15 files changed, 51 insertions(+), 71 deletions(-) rename libc/intrin/enable_threads.c => test/libc/mem/malloc_torture_test.c (58%) diff --git a/libc/calls/calls.h b/libc/calls/calls.h index cd90cce73..fb4ddead1 100644 --- a/libc/calls/calls.h +++ b/libc/calls/calls.h @@ -129,6 +129,7 @@ int linkat(int, const char *, int, const char *, int) libcesque __read_only(2) _ int mincore(void *, size_t, unsigned char *) libcesque __read_only(1) __write_only(3); int mkdir(const char *, unsigned) libcesque __read_only(1); int mkdirat(int, const char *, unsigned) libcesque __read_only(2); +int mkfifo(const char *, unsigned); int mknod(const char *, unsigned, uint64_t) libcesque __read_only(1); int nice(int) libcesque; int open(const char *, int, ...) libcesque __read_only(1); diff --git a/libc/calls/pledge.c b/libc/calls/pledge.c index b5a6dbb63..88f1b236f 100644 --- a/libc/calls/pledge.c +++ b/libc/calls/pledge.c @@ -169,8 +169,7 @@ * turn APE binaries into static native binaries. * * - "prot_exec" allows mmap(PROT_EXEC) and mprotect(PROT_EXEC). This is - * needed to (1) code morph mutexes in __enable_threads(), and it's - * needed to (2) launch non-static or non-native executables, e.g. + * needed to launch non-static or non-native executables, e.g. * non-assimilated APE binaries, or dynamic-linked executables. * * - "unveil" allows unveil() to be called, as well as the underlying diff --git a/libc/calls/sched_getscheduler.c b/libc/calls/sched_getscheduler.c index d7a15554f..fafe9fdd3 100644 --- a/libc/calls/sched_getscheduler.c +++ b/libc/calls/sched_getscheduler.c @@ -31,7 +31,6 @@ * special; the kernel treats this as a thread id (noting that * `getpid() == gettid()` is always the case on Linux for the main * thread) and will only take effect for the specified tid. - * Therefore this function is POSIX-compliant iif `!__threaded`. * @return scheduler policy, or -1 w/ errno * @error ESRCH if `pid` not found * @error EPERM if not permitted diff --git a/libc/calls/sched_setscheduler.c b/libc/calls/sched_setscheduler.c index 576ecadfa..5f4839846 100644 --- a/libc/calls/sched_setscheduler.c +++ b/libc/calls/sched_setscheduler.c @@ -41,7 +41,6 @@ * special; the kernel treats this as a thread id (noting that * `getpid() == gettid()` is always the case on Linux for the main * thread) and will only take effect for the specified tid. - * Therefore this function is POSIX-compliant iif `!__threaded`. * * @param policy specifies the kernel's timesharing strategy. * diff --git a/libc/nexgen32e/threaded.c b/libc/nexgen32e/threaded.c index 5524c4667..1fad2aa80 100644 --- a/libc/nexgen32e/threaded.c +++ b/libc/nexgen32e/threaded.c @@ -18,11 +18,6 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/thread/tls.h" -/** - * Contains TID of main thread or 0 if threading isn't enabled. - */ -int __threaded; - #ifdef __x86_64__ char __tls_enabled; #endif diff --git a/libc/proc/fork-nt.c b/libc/proc/fork-nt.c index 4ca7b725a..19a22a16e 100644 --- a/libc/proc/fork-nt.c +++ b/libc/proc/fork-nt.c @@ -113,7 +113,6 @@ static dontinline textwindows ssize_t ForkIo2( ssize_t rc = ForkIo(h, buf, n, fn); if (ischild) { // prevent crashes - __threaded = false; __tls_enabled = false; __pid = __imp_GetCurrentProcessId(); __klog_handle = 0; @@ -268,7 +267,6 @@ textwindows void WinMainForked(void) { ReadOrDie(reader, __bss_start, __bss_end - __bss_start); kStartTsc = savetsc; __tls_enabled = false; - __threaded = false; // fixup memory manager __maps.maps = 0; @@ -464,8 +462,6 @@ textwindows int sys_fork_nt(uint32_t dwCreationFlags) { // the child's pending signals is initially empty atomic_store_explicit(&__sig.pending, 0, memory_order_relaxed); atomic_store_explicit(&tib->tib_sigpending, 0, memory_order_relaxed); - // re-enable threads - __enable_threads(); // re-apply code morphing for function tracing if (ftrace_stackdigs) { _weaken(__hook)(_weaken(ftrace_hook), _weaken(GetSymbolTable)()); diff --git a/libc/proc/proc.c b/libc/proc/proc.c index 324c08356..4814c1e43 100644 --- a/libc/proc/proc.c +++ b/libc/proc/proc.c @@ -236,7 +236,6 @@ static textwindows dontinstrument uint32_t __proc_worker(void *arg) { * Lazy initializes process tracker data structures and worker. */ static textwindows void __proc_setup(void) { - __enable_threads(); __proc.onbirth = CreateEvent(0, 0, 0, 0); // auto reset __proc.haszombies = CreateEvent(0, 1, 0, 0); // manual reset __proc.thread = CreateThread(0, 65536, __proc_worker, 0, diff --git a/libc/runtime/clone.c b/libc/runtime/clone.c index 1da1ffc03..a1918a1c7 100644 --- a/libc/runtime/clone.c +++ b/libc/runtime/clone.c @@ -746,10 +746,6 @@ errno_t clone(void *func, void *stk, size_t stksz, int flags, void *arg, void *ptid, void *tls, void *ctid) { int rc; - if (flags & CLONE_THREAD) { - __enable_threads(); - } - if (!func) { rc = EINVAL; } else if (IsLinux()) { diff --git a/libc/runtime/runtime.h b/libc/runtime/runtime.h index ea182a7a5..9b26bbbf1 100644 --- a/libc/runtime/runtime.h +++ b/libc/runtime/runtime.h @@ -113,7 +113,6 @@ void _weakfree(void *) libcesque; void *_mapanon(size_t) attributeallocsize((1)) mallocesque libcesque; void *_mapshared(size_t) attributeallocsize((1)) mallocesque libcesque; void CheckForFileLeaks(void) libcesque; -void __enable_threads(void) libcesque; void __oom_hook(size_t) libcesque; /* code morphing */ void __morph_begin(void) libcesque; diff --git a/libc/thread/tls.h b/libc/thread/tls.h index 362e7475b..df4e742d3 100644 --- a/libc/thread/tls.h +++ b/libc/thread/tls.h @@ -42,7 +42,6 @@ struct CosmoTib { _Atomic(void *) tib_keys[46]; } __attribute__((__aligned__(64))); -extern int __threaded; extern char __tls_morphed; extern unsigned __tls_index; diff --git a/test/libc/intrin/lock_test.c b/test/libc/intrin/lock_test.c index 491700d38..06782deed 100644 --- a/test/libc/intrin/lock_test.c +++ b/test/libc/intrin/lock_test.c @@ -189,8 +189,6 @@ int main(int argc, char *argv[]) { _Exit(1); } - __threaded = 1; - ASSERT_EQ(0, pthread_mutexattr_init(&attr)); ASSERT_EQ(0, pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL)); ASSERT_EQ(0, pthread_mutex_init(&mu, &attr)); diff --git a/test/libc/mem/malloc_test.c b/test/libc/mem/malloc_test.c index 18d2829ba..dd1908e68 100644 --- a/test/libc/mem/malloc_test.c +++ b/test/libc/mem/malloc_test.c @@ -179,47 +179,15 @@ void MallocFree(void) { free(p); } +void eat(void *p) { +} + +void (*pEat)(void *) = eat; + BENCH(bulk_free, bench) { + /* pEat(pthread_create); */ EZBENCH2("free() bulk", BulkFreeBenchSetup(), FreeBulk()); EZBENCH2("bulk_free()", BulkFreeBenchSetup(), bulk_free(bulk, ARRAYLEN(bulk))); - EZBENCH2("free(malloc(16)) ST", donothing, MallocFree()); - __enable_threads(); - EZBENCH2("free(malloc(16)) MT", donothing, MallocFree()); -} - -#define ITERATIONS 1000 -#define THREADS 10 -#define SIZE 1024 - -void *Worker(void *arg) { - for (int i = 0; i < ITERATIONS; ++i) { - char *p; - ASSERT_NE(NULL, (p = malloc(lemur64() % SIZE))); - ASSERT_NE(NULL, (p = realloc(p, max(lemur64() % SIZE, 1)))); - free(p); - } - return 0; -} - -TEST(malloc, torture) { - int i, n = THREADS; - pthread_t *t = gc(malloc(sizeof(pthread_t) * n)); - if (!n) - return; - printf("\nmalloc torture test w/ %d threads and %d iterations\n", n, - ITERATIONS); - SPAWN(fork); - struct timespec t1 = timespec_real(); - for (i = 0; i < n; ++i) { - ASSERT_EQ(0, pthread_create(t + i, 0, Worker, 0)); - } - for (i = 0; i < n; ++i) { - ASSERT_EQ(0, pthread_join(t[i], 0)); - } - struct timespec t2 = timespec_real(); - printf("consumed %g wall and %g cpu seconds\n", - timespec_tomicros(timespec_sub(t2, t1)) * 1e-6, - (double)clock() / CLOCKS_PER_SEC); - EXITS(0); + EZBENCH2("free(malloc(16))", donothing, MallocFree()); } diff --git a/libc/intrin/enable_threads.c b/test/libc/mem/malloc_torture_test.c similarity index 58% rename from libc/intrin/enable_threads.c rename to test/libc/mem/malloc_torture_test.c index 18c27364f..40ae54934 100644 --- a/libc/intrin/enable_threads.c +++ b/test/libc/mem/malloc_torture_test.c @@ -1,7 +1,7 @@ /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ │ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2022 Justine Alexandra Roberts Tunney │ +│ Copyright 2024 Justine Alexandra Roberts Tunney │ │ │ │ Permission to use, copy, modify, and/or distribute this software for │ │ any purpose with or without fee is hereby granted, provided that the │ @@ -16,9 +16,46 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/runtime/runtime.h" -#include "libc/thread/tls.h" +#include "libc/calls/struct/timespec.h" +#include "libc/intrin/safemacros.h" +#include "libc/mem/gc.h" +#include "libc/mem/mem.h" +#include "libc/stdio/rand.h" +#include "libc/stdio/stdio.h" +#include "libc/testlib/subprocess.h" +#include "libc/testlib/testlib.h" +#include "libc/thread/thread.h" -void __enable_threads(void) { - __threaded = 1; +#define ITERATIONS 1000 +#define THREADS 10 +#define SIZE 1024 + +void *Worker(void *arg) { + for (int i = 0; i < ITERATIONS; ++i) { + char *p; + ASSERT_NE(NULL, (p = malloc(lemur64() % SIZE))); + ASSERT_NE(NULL, (p = realloc(p, max(lemur64() % SIZE, 1)))); + free(p); + } + return 0; +} + +TEST(malloc, torture) { + int i, n = THREADS; + pthread_t *t = gc(malloc(sizeof(pthread_t) * n)); + if (!n) + return; + printf("\nmalloc torture test w/ %d threads and %d iterations\n", n, + ITERATIONS); + SPAWN(fork); + struct timespec t1 = timespec_real(); + for (i = 0; i < n; ++i) + ASSERT_EQ(0, pthread_create(t + i, 0, Worker, 0)); + for (i = 0; i < n; ++i) + ASSERT_EQ(0, pthread_join(t[i], 0)); + struct timespec t2 = timespec_real(); + printf("consumed %g wall and %g cpu seconds\n", + timespec_tomicros(timespec_sub(t2, t1)) * 1e-6, + (double)clock() / CLOCKS_PER_SEC); + EXITS(0); } diff --git a/test/libc/thread/pthread_atfork_test.c b/test/libc/thread/pthread_atfork_test.c index 00a19cec5..ba3c9b056 100644 --- a/test/libc/thread/pthread_atfork_test.c +++ b/test/libc/thread/pthread_atfork_test.c @@ -48,7 +48,6 @@ void *ForceThreadingMode(void *arg) { } TEST(pthread_atfork, test) { - __enable_threads(); SPAWN(fork); ASSERT_EQ(0, pthread_atfork(prepare1, parent1, child1)); ASSERT_EQ(0, pthread_atfork(prepare2, parent2, child2)); diff --git a/third_party/dlmalloc/locks.inc b/third_party/dlmalloc/locks.inc index 5e72eff95..bb2a149f8 100644 --- a/third_party/dlmalloc/locks.inc +++ b/third_party/dlmalloc/locks.inc @@ -39,7 +39,6 @@ static int malloc_wipe(MLOCK_T *lk) { } static int malloc_lock(MLOCK_T *lk) { - if (!__threaded) return 0; for (;;) { if (!atomic_exchange_explicit(lk, 1, memory_order_acquire)) break; @@ -51,7 +50,6 @@ static int malloc_lock(MLOCK_T *lk) { } static int malloc_unlock(MLOCK_T *lk) { - if (!__threaded) return 0; atomic_store_explicit(lk, 0, memory_order_release); return 0; } @@ -66,13 +64,11 @@ static int malloc_wipe(MLOCK_T *lk) { } static int malloc_lock(MLOCK_T *lk) { - if (!__threaded) return 0; nsync_mu_lock(lk); return 0; } static int malloc_unlock(MLOCK_T *lk) { - if (!__threaded) return 0; nsync_mu_unlock(lk); return 0; }