diff --git a/examples/thread.c b/examples/thread.c new file mode 100644 index 000000000..f019d7107 --- /dev/null +++ b/examples/thread.c @@ -0,0 +1,33 @@ +#if 0 +/*─────────────────────────────────────────────────────────────────╗ +│ To the extent possible under law, Justine Tunney has waived │ +│ all copyright and related or neighboring rights to this file, │ +│ as it is written in the following disclaimers: │ +│ • http://unlicense.org/ │ +│ • http://creativecommons.org/publicdomain/zero/1.0/ │ +╚─────────────────────────────────────────────────────────────────*/ +#endif +#include "libc/intrin/pthread.h" +#include "libc/stdio/stdio.h" + +/** + * @fileoverview Basic POSIX Threads Example. + * + * $ make -j8 o//examples/thread.com + * $ o//examples/thread.com + * hi there + * + */ + +void *worker(void *arg) { + fputs(arg, stdout); + return "there\n"; +} + +int main() { + void *result; + pthread_t id; + pthread_create(&id, 0, worker, "hi "); + pthread_join(id, &result); + fputs(result, stdout); +} diff --git a/libc/calls/state.internal.h b/libc/calls/state.internal.h index 0759ad91c..b5eacf1ba 100644 --- a/libc/calls/state.internal.h +++ b/libc/calls/state.internal.h @@ -1,6 +1,7 @@ #ifndef COSMOPOLITAN_LIBC_CALLS_STATE_INTERNAL_H_ #define COSMOPOLITAN_LIBC_CALLS_STATE_INTERNAL_H_ #include "libc/intrin/nopl.h" +#include "libc/intrin/pthread.h" #include "libc/nexgen32e/threaded.h" #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ @@ -9,6 +10,7 @@ hidden extern int __vforked; hidden extern bool __time_critical; hidden extern unsigned __sighandrvas[NSIG]; hidden extern unsigned __sighandflags[NSIG]; +hidden extern pthread_mutex_t __fds_lock_obj; hidden extern const struct NtSecurityAttributes kNtIsInheritable; void __fds_lock(void); diff --git a/libc/calls/symlinkat-nt.c b/libc/calls/symlinkat-nt.c index 4cf216cdd..dd36786bd 100644 --- a/libc/calls/symlinkat-nt.c +++ b/libc/calls/symlinkat-nt.c @@ -19,7 +19,7 @@ #include "libc/calls/calls.h" #include "libc/calls/syscall_support-nt.internal.h" #include "libc/errno.h" -#include "libc/intrin/once.h" +#include "libc/intrin/pthread.h" #include "libc/nt/enum/accessmask.h" #include "libc/nt/enum/fileflagandattributes.h" #include "libc/nt/enum/symboliclink.h" @@ -35,17 +35,20 @@ __msabi extern typeof(GetFileAttributes) *const __imp_GetFileAttributesW; -static bool AllowedToCreateSymlinks(void) { +static _Bool g_winlink_allowed; +static pthread_once_t g_winlink_once; + +static textwindows void InitializeWinlink(void) { int64_t tok; struct NtLuid id; struct NtTokenPrivileges tp; - if (!OpenProcessToken(GetCurrentProcess(), kNtTokenAllAccess, &tok)) return 0; - if (!LookupPrivilegeValue(0, u"SeCreateSymbolicLinkPrivilege", &id)) return 0; + if (!OpenProcessToken(GetCurrentProcess(), kNtTokenAllAccess, &tok)) return; + if (!LookupPrivilegeValue(0, u"SeCreateSymbolicLinkPrivilege", &id)) return; tp.PrivilegeCount = 1; tp.Privileges[0].Luid = id; tp.Privileges[0].Attributes = kNtSePrivilegeEnabled; - if (!AdjustTokenPrivileges(tok, 0, &tp, sizeof(tp), 0, 0)) return 0; - return GetLastError() != kNtErrorNotAllAssigned; + if (!AdjustTokenPrivileges(tok, 0, &tp, sizeof(tp), 0, 0)) return; + g_winlink_allowed = GetLastError() != kNtErrorNotAllAssigned; } textwindows int sys_symlinkat_nt(const char *target, int newdirfd, @@ -79,7 +82,8 @@ textwindows int sys_symlinkat_nt(const char *target, int newdirfd, // windows only lets administrators do this // even then we're required to ask for permission - if (!_once(AllowedToCreateSymlinks())) { + pthread_once(&g_winlink_once, InitializeWinlink); + if (!g_winlink_allowed) { return eperm(); } diff --git a/libc/integral/c.inc b/libc/integral/c.inc index c5aca2bc6..68bcd7090 100644 --- a/libc/integral/c.inc +++ b/libc/integral/c.inc @@ -84,7 +84,7 @@ #endif #ifndef __cplusplus -#define HAVE_STDBOOL_H +#define HAVE_STDBOOL_H 1 #if __STDC_VERSION__ + 0 >= 201112 typedef _Bool bool; #define true ((bool)+1) diff --git a/libc/intrin/asan.c b/libc/intrin/asan.c index 31064a01c..5fb061e14 100644 --- a/libc/intrin/asan.c +++ b/libc/intrin/asan.c @@ -29,7 +29,6 @@ #include "libc/intrin/lockcmpxchg.h" #include "libc/intrin/nomultics.internal.h" #include "libc/intrin/pthread.h" -#include "libc/intrin/spinlock.h" #include "libc/intrin/weaken.h" #include "libc/log/backtrace.internal.h" #include "libc/log/internal.h" diff --git a/libc/thread/self.c b/libc/intrin/fds_lock.c similarity index 88% rename from libc/thread/self.c rename to libc/intrin/fds_lock.c index a790a1ad7..b01bccb9e 100644 --- a/libc/thread/self.c +++ b/libc/intrin/fds_lock.c @@ -16,13 +16,13 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/nexgen32e/gettls.h" -#include "libc/nexgen32e/threaded.h" -#include "libc/thread/thread.h" +#include "libc/calls/state.internal.h" +#include "libc/intrin/pthread.h" -/** - * Returns thread descriptor of the current thread. - */ -cthread_t(cthread_self)(void) { - return (cthread_t)__get_tls(); +void(__fds_lock)(void) { + pthread_mutex_lock(&__fds_lock_obj); +} + +void(__fds_unlock)(void) { + pthread_mutex_unlock(&__fds_lock_obj); } diff --git a/libc/intrin/g_fds.c b/libc/intrin/g_fds.c index fb7908dbf..192476725 100644 --- a/libc/intrin/g_fds.c +++ b/libc/intrin/g_fds.c @@ -17,10 +17,9 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/internal.h" -#include "libc/calls/strace.internal.h" +#include "libc/calls/state.internal.h" #include "libc/intrin/pthread.h" #include "libc/intrin/pushpop.h" -#include "libc/intrin/spinlock.h" #include "libc/intrin/weaken.h" #include "libc/nt/runtime.h" #include "libc/sysv/consts/o.h" @@ -28,15 +27,7 @@ STATIC_YOINK("_init_g_fds"); struct Fds g_fds; -static pthread_mutex_t __fds_lock_obj; - -void(__fds_lock)(void) { - pthread_mutex_lock(&__fds_lock_obj); -} - -void(__fds_unlock)(void) { - pthread_mutex_unlock(&__fds_lock_obj); -} +pthread_mutex_t __fds_lock_obj; static textwindows dontinline void SetupWinStd(struct Fds *fds, int i, int x) { int64_t h; diff --git a/libc/intrin/getpid.c b/libc/intrin/getpid.c index a0d0c032d..5cd29b58b 100644 --- a/libc/intrin/getpid.c +++ b/libc/intrin/getpid.c @@ -25,7 +25,7 @@ * Returns process id. * * This function does not need to issue a system call. The PID is - * tracked by a global variable which is updated atfork(). The only + * tracked by a global variable which is updated at fork(). The only * exception is when the process is vfork()'d in which case a system * call shall be issued. * diff --git a/libc/intrin/kprintf.greg.c b/libc/intrin/kprintf.greg.c index 1ae95aecd..6d7bbf1ef 100644 --- a/libc/intrin/kprintf.greg.c +++ b/libc/intrin/kprintf.greg.c @@ -31,7 +31,6 @@ #include "libc/intrin/lockcmpxchg.h" #include "libc/intrin/nomultics.internal.h" #include "libc/intrin/safemacros.internal.h" -#include "libc/intrin/spinlock.h" #include "libc/intrin/weaken.h" #include "libc/limits.h" #include "libc/log/internal.h" diff --git a/libc/intrin/mmi.c b/libc/intrin/mmi.c index 8d6986001..f4268fc0a 100644 --- a/libc/intrin/mmi.c +++ b/libc/intrin/mmi.c @@ -16,18 +16,8 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/intrin/pthread.h" #include "libc/runtime/memtrack.internal.h" STATIC_YOINK("_init__mmi"); struct MemoryIntervals _mmi; -pthread_mutex_t __mmi_lock_obj; // recursive :'( - -void(__mmi_lock)(void) { - pthread_mutex_lock(&__mmi_lock_obj); -} - -void(__mmi_unlock)(void) { - pthread_mutex_unlock(&__mmi_lock_obj); -} diff --git a/libc/thread/wait.c b/libc/intrin/mmi_lock.c similarity index 72% rename from libc/thread/wait.c rename to libc/intrin/mmi_lock.c index d301b5a02..7dc44fd97 100644 --- a/libc/thread/wait.c +++ b/libc/intrin/mmi_lock.c @@ -1,7 +1,7 @@ /*-*- 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 2020 Justine Alexandra Roberts Tunney │ +│ 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 │ @@ -16,28 +16,15 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/calls/calls.h" -#include "libc/calls/struct/timespec.h" -#include "libc/dce.h" -#include "libc/errno.h" -#include "libc/intrin/atomic.h" -#include "libc/intrin/futex.internal.h" #include "libc/intrin/pthread.h" -#include "libc/thread/thread.h" +#include "libc/runtime/memtrack.internal.h" -int cthread_memory_wait32(int* addr, int val, const struct timespec* timeout) { - size_t size; - if (IsLinux() || IsOpenbsd()) { - return _futex_wait(addr, val, PTHREAD_PROCESS_SHARED, timeout); - } else { - return sched_yield(); - } +extern pthread_mutex_t __mmi_lock_obj; + +void(__mmi_lock)(void) { + pthread_mutex_lock(&__mmi_lock_obj); } -int cthread_memory_wake32(int* addr, int n) { - if (IsLinux() || IsOpenbsd()) { - return _futex_wake(addr, n, PTHREAD_PROCESS_SHARED); - } else { - return 0; - } +void(__mmi_unlock)(void) { + pthread_mutex_unlock(&__mmi_lock_obj); } diff --git a/libc/calls/atfork.c b/libc/intrin/mmi_lock_obj.c similarity index 63% rename from libc/calls/atfork.c rename to libc/intrin/mmi_lock_obj.c index f7ff0b47b..c34d116bc 100644 --- a/libc/calls/atfork.c +++ b/libc/intrin/mmi_lock_obj.c @@ -1,7 +1,7 @@ /*-*- 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 2020 Justine Alexandra Roberts Tunney │ +│ 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 │ @@ -16,47 +16,6 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/intrin/cmpxchg.h" -#include "libc/macros.internal.h" -#include "libc/runtime/runtime.h" -#include "libc/sysv/errfuns.h" +#include "libc/intrin/pthread.h" -static struct AtFork { - volatile size_t i; - struct AtForkCallback { - void (*fn)(void *); - void *arg; - } p[ATEXIT_MAX]; -} g_atfork; - -/** - * Registers function to be called by fork() in child. - * - * @return 0 on success, or -1 w/ errno - * @note vfork() won't invoke callbacks - * @asyncsignalsafe - */ -int atfork(void *fn, void *arg) { - size_t i; - for (;;) { - i = g_atfork.i; - if (i == ARRAYLEN(g_atfork.p)) return enomem(); - if (_cmpxchg(&g_atfork.i, i, i + 1)) { - g_atfork.p[i] = (struct AtForkCallback){.fn = fn, .arg = arg}; - return 0; - } - } -} - -/** - * Triggers callbacks registered by atfork(). - * - * @note only fork() should call this - * @asyncsignalsafe - */ -void __onfork(void) { - size_t i; - for (i = 0; i < g_atfork.i; ++i) { - g_atfork.p[i].fn(g_atfork.p[i].arg); - } -} +pthread_mutex_t __mmi_lock_obj; // recursive :'( diff --git a/libc/intrin/once.h b/libc/intrin/once.h deleted file mode 100644 index 4ce924ea5..000000000 --- a/libc/intrin/once.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_INTRIN_ONCE_H_ -#define COSMOPOLITAN_LIBC_INTRIN_ONCE_H_ -#include "libc/intrin/spinlock.h" - -/* TODO(jart): DELETE */ - -#define _once(x) \ - ({ \ - typeof(x) oncerc; \ - static bool once; \ - static typeof(oncerc) onceresult; \ - _Alignas(64) static char oncelock; \ - _spinlock(&oncelock); \ - if (once) { \ - oncerc = onceresult; \ - } else { \ - oncerc = onceresult = x; \ - } \ - _spunlock(&oncelock); \ - oncerc; \ - }) - -#endif /* COSMOPOLITAN_LIBC_INTRIN_ONCE_H_ */ diff --git a/libc/intrin/pthread.h b/libc/intrin/pthread.h index 2f466f2ed..8e74f763f 100644 --- a/libc/intrin/pthread.h +++ b/libc/intrin/pthread.h @@ -1,8 +1,6 @@ #ifndef COSMOPOLITAN_LIBC_RUNTIME_PTHREAD_H_ #define COSMOPOLITAN_LIBC_RUNTIME_PTHREAD_H_ -#define PTHREAD_ONCE_INIT 0 - #define PTHREAD_KEYS_MAX 64 #define PTHREAD_STACK_MIN FRAMESIZE #define PTHREAD_DESTRUCTOR_ITERATIONS 4 @@ -27,6 +25,7 @@ COSMOPOLITAN_C_START_ /* clang-format off */ +#define PTHREAD_ONCE_INIT {0} #define PTHREAD_COND_INITIALIZER {PTHREAD_PROCESS_DEFAULT} #define PTHREAD_BARRIER_INITIALIZER {PTHREAD_PROCESS_DEFAULT} #define PTHREAD_RWLOCK_INITIALIZER {PTHREAD_PROCESS_DEFAULT} @@ -34,16 +33,22 @@ COSMOPOLITAN_C_START_ PTHREAD_PROCESS_DEFAULT} /* clang-format on */ -typedef void *pthread_t; +typedef uintptr_t pthread_t; typedef int pthread_id_np_t; typedef char pthread_condattr_t; typedef char pthread_rwlockattr_t; typedef char pthread_barrierattr_t; typedef unsigned pthread_key_t; -typedef _Atomic(char) pthread_once_t; -typedef _Atomic(char) pthread_spinlock_t; typedef void (*pthread_key_dtor)(void *); +typedef struct pthread_once_s { + _Atomic(char) lock; +} pthread_once_t; + +typedef struct pthread_spinlock_s { + _Atomic(char) lock; +} pthread_spinlock_t; + typedef struct pthread_mutex_s { char type; char pshared; @@ -167,45 +172,26 @@ int pthread_barrier_destroy(pthread_barrier_t *); int pthread_barrier_init(pthread_barrier_t *, const pthread_barrierattr_t *, unsigned); -#define pthread_spin_init(pSpin, multiprocess) (*(pSpin) = 0) -#define pthread_spin_destroy(pSpin) (*(pSpin) = 0) +#define pthread_spin_init(pSpin, multiprocess) ((pSpin)->lock = 0, 0) +#define pthread_spin_destroy(pSpin) ((pSpin)->lock = -1, 0) #if (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 407 extern const errno_t EBUSY; -#define pthread_spin_unlock(pSpin) \ - (__atomic_store_n(pSpin, 0, __ATOMIC_RELAXED), 0) -#define pthread_spin_trylock(pSpin) \ - (__atomic_test_and_set(pSpin, __ATOMIC_SEQ_CST) ? EBUSY : 0) -#ifdef TINY -#define pthread_spin_lock(pSpin) _pthread_spin_lock_tiny(pSpin) -#else -#define pthread_spin_lock(pSpin) _pthread_spin_lock_cooperative(pSpin) -#endif -#define _pthread_spin_lock_tiny(pSpin) \ - ({ \ - while (__atomic_test_and_set(pSpin, __ATOMIC_SEQ_CST)) { \ - __builtin_ia32_pause(); \ - } \ - 0; \ +#define pthread_spin_lock(pSpin) \ + ({ \ + pthread_spinlock_t *_s = pSpin; \ + while (__atomic_test_and_set(&_s->lock, __ATOMIC_SEQ_CST)) donothing; \ + 0; \ }) -#define _pthread_spin_lock_cooperative(pSpin) \ - ({ \ - char __x; \ - volatile int __i; \ - unsigned __tries = 0; \ - pthread_spinlock_t *__lock = pSpin; \ - for (;;) { \ - __atomic_load(__lock, &__x, __ATOMIC_RELAXED); \ - if (!__x && !__atomic_test_and_set(__lock, __ATOMIC_SEQ_CST)) { \ - break; \ - } else if (__tries < 7) { \ - for (__i = 0; __i != 1 << __tries; __i++) { \ - } \ - __tries++; \ - } else { \ - pthread_yield(); \ - } \ - } \ - 0; \ +#define pthread_spin_unlock(pSpin) \ + ({ \ + pthread_spinlock_t *_s = pSpin; \ + __atomic_store_n(&_s->lock, 0, __ATOMIC_RELAXED); \ + 0; \ + }) +#define pthread_spin_trylock(pSpin) \ + ({ \ + pthread_spinlock_t *_s = pSpin; \ + __atomic_test_and_set(&_s->lock, __ATOMIC_SEQ_CST) ? EBUSY : 0; \ }) #endif /* GCC 4.7+ */ diff --git a/libc/intrin/pthread_mutex_lock.c b/libc/intrin/pthread_mutex_lock.c index 77ee171ae..24f2de035 100644 --- a/libc/intrin/pthread_mutex_lock.c +++ b/libc/intrin/pthread_mutex_lock.c @@ -24,7 +24,6 @@ #include "libc/intrin/atomic.h" #include "libc/intrin/futex.internal.h" #include "libc/intrin/pthread.h" -#include "libc/intrin/spinlock.h" #include "libc/linux/futex.h" #include "libc/nexgen32e/threaded.h" #include "libc/sysv/consts/futex.h" @@ -85,20 +84,6 @@ static int pthread_mutex_lock_spin(pthread_mutex_t *mutex, int expect, * // do work... * pthread_mutex_unlock(&lock); * - * Microbenchmarks for single-threaded lock + unlock: - * - * pthread_spinlock_t : 12c ( 4ns) - * PTHREAD_MUTEX_NORMAL : 37c ( 12ns) - * PTHREAD_MUTEX_RECURSIVE : 22c ( 7ns) - * PTHREAD_MUTEX_ERRORCHECK : 27c ( 9ns) - * - * Microbenchmarks for multi-threaded lock + unlock: - * - * pthread_spinlock_t : 2,396c (774ns) - * PTHREAD_MUTEX_NORMAL : 535c (173ns) - * PTHREAD_MUTEX_RECURSIVE : 1,045c (338ns) - * PTHREAD_MUTEX_ERRORCHECK : 917c (296ns) - * * @return 0 on success, or error number on failure * @see pthread_spin_lock() */ diff --git a/libc/intrin/pthread_once.c b/libc/intrin/pthread_once.c index d7881043d..1d13fd863 100644 --- a/libc/intrin/pthread_once.c +++ b/libc/intrin/pthread_once.c @@ -45,20 +45,21 @@ */ int pthread_once(pthread_once_t *once, void init(void)) { char old; - switch ((old = atomic_load_explicit(once, memory_order_relaxed))) { + switch ((old = atomic_load_explicit(&once->lock, memory_order_relaxed))) { case INIT: - if (atomic_compare_exchange_strong_explicit(once, &old, CALLING, + if (atomic_compare_exchange_strong_explicit(&once->lock, &old, CALLING, memory_order_acquire, memory_order_relaxed)) { init(); - atomic_store(once, FINISHED); + atomic_store(&once->lock, FINISHED); break; } // fallthrough case CALLING: do { pthread_yield(); - } while (atomic_load_explicit(once, memory_order_relaxed) == CALLING); + } while (atomic_load_explicit(&once->lock, memory_order_relaxed) == + CALLING); break; case FINISHED: break; diff --git a/libc/intrin/pthread_spin_lock.c b/libc/intrin/pthread_spin_lock.c index 009aefe52..dca24fb7b 100644 --- a/libc/intrin/pthread_spin_lock.c +++ b/libc/intrin/pthread_spin_lock.c @@ -21,11 +21,6 @@ /** * Acquires spin lock. * - * spin l: 181,570c 58,646ns - * mutex normal l: 297,965c 96,241ns - * mutex recursive l: 1,112,166c 359,223ns - * mutex errorcheck l: 1,449,723c 468,252ns - * * If the lock is already held, this function will wait for it to become * available. No genuine error conditions are currently defined. This is * similar to pthread_mutex_lock() except spin locks are much simpler so @@ -45,7 +40,7 @@ * * Cosmopolitan permits succinct notation for spin locks: * - * pthread_spinlock_t lock = 0; + * pthread_spinlock_t lock = {0}; * pthread_spin_lock(&lock); * // do work... * pthread_spin_unlock(&lock); diff --git a/libc/intrin/rand64.c b/libc/intrin/rand64.c index c020c14c5..6b915c2a1 100644 --- a/libc/intrin/rand64.c +++ b/libc/intrin/rand64.c @@ -18,7 +18,6 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/_getauxval.internal.h" #include "libc/intrin/pthread.h" -#include "libc/intrin/spinlock.h" #include "libc/nexgen32e/rdtsc.h" #include "libc/nexgen32e/threaded.h" #include "libc/runtime/internal.h" diff --git a/libc/intrin/releasefd.c b/libc/intrin/releasefd.c index 6b4b7e03b..505fd9eb5 100644 --- a/libc/intrin/releasefd.c +++ b/libc/intrin/releasefd.c @@ -18,7 +18,6 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/internal.h" #include "libc/calls/state.internal.h" -#include "libc/intrin/spinlock.h" #include "libc/macros.internal.h" void __releasefd(int fd) { diff --git a/libc/intrin/spinlock.h b/libc/intrin/spinlock.h deleted file mode 100644 index e2f0cd67a..000000000 --- a/libc/intrin/spinlock.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_INTRIN_SPINLOCK_H_ -#define COSMOPOLITAN_LIBC_INTRIN_SPINLOCK_H_ -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -/* TODO(jart): DELETE */ - -#ifdef TINY -#define _spinlock(lock) _spinlock_tiny(lock) -#else -#define _spinlock(lock) _spinlock_cooperative(lock) -#endif - -#define _spunlock(lock) (__atomic_store_n(lock, 0, __ATOMIC_RELAXED), 0) - -#define _seizelock(lock, value) \ - ({ \ - autotype(lock) __lock = (lock); \ - typeof(*__lock) __x = (value); \ - __atomic_store(__lock, &__x, __ATOMIC_RELEASE); \ - }) - -#define _spinlock_tiny(lock) \ - ({ \ - while (_trylock(lock)) { \ - __builtin_ia32_pause(); \ - } \ - 0; \ - }) - -#define _spinlock_cooperative(lock) \ - ({ \ - char __x; \ - volatile int __i; \ - unsigned __tries = 0; \ - char *__lock = (lock); \ - for (;;) { \ - __atomic_load(__lock, &__x, __ATOMIC_RELAXED); \ - if (!__x && !_trylock(__lock)) { \ - break; \ - } else if (__tries < 7) { \ - for (__i = 0; __i != 1 << __tries; __i++) { \ - } \ - __tries++; \ - } else { \ - _spinlock_yield(); \ - } \ - } \ - 0; \ - }) - -#define _trylock(lock) __atomic_test_and_set(lock, __ATOMIC_SEQ_CST) - -int _spinlock_yield(void); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_LIBC_INTRIN_SPINLOCK_H_ */ diff --git a/libc/log/vflogf.c b/libc/log/vflogf.c index 39aba9c8d..c8941e48b 100644 --- a/libc/log/vflogf.c +++ b/libc/log/vflogf.c @@ -16,8 +16,6 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/intrin/bits.h" -#include "libc/intrin/safemacros.internal.h" #include "libc/calls/calls.h" #include "libc/calls/dprintf.h" #include "libc/calls/strace.internal.h" @@ -27,7 +25,8 @@ #include "libc/errno.h" #include "libc/fmt/conv.h" #include "libc/fmt/fmt.h" -#include "libc/intrin/spinlock.h" +#include "libc/intrin/bits.h" +#include "libc/intrin/safemacros.internal.h" #include "libc/log/internal.h" #include "libc/log/log.h" #include "libc/math.h" diff --git a/libc/mem/gc.c b/libc/mem/gc.c index 0280884c9..3e0dfde84 100644 --- a/libc/mem/gc.c +++ b/libc/mem/gc.c @@ -17,7 +17,6 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/assert.h" -#include "libc/intrin/kprintf.h" #include "libc/intrin/likely.h" #include "libc/mem/mem.h" #include "libc/nexgen32e/gc.internal.h" @@ -72,10 +71,7 @@ static void DeferFunction(struct StackFrame *frame, void *fn, void *arg) { if (!(g = malloc(sizeof(struct Garbages)))) notpossible; g->i = 0; g->n = 4; - if (!(g->p = malloc(g->n * sizeof(struct Garbage)))) { - kprintf("malloc failed\n"); - notpossible; - } + if (!(g->p = malloc(g->n * sizeof(struct Garbage)))) notpossible; tls->garbages = g; } else if (UNLIKELY(g->i == g->n)) { p2 = g->p; diff --git a/libc/runtime/clone.c b/libc/runtime/clone.c index d3123700f..cce8f608d 100644 --- a/libc/runtime/clone.c +++ b/libc/runtime/clone.c @@ -23,7 +23,7 @@ #include "libc/dce.h" #include "libc/errno.h" #include "libc/intrin/asan.internal.h" -#include "libc/intrin/spinlock.h" +#include "libc/intrin/pthread.h" #include "libc/limits.h" #include "libc/macros.internal.h" #include "libc/nexgen32e/gettls.h" @@ -63,7 +63,7 @@ struct CloneArgs { uint32_t utid; int64_t tid64; }; - char lock; + pthread_spinlock_t lock; int *ptid; int *ctid; int *ztid; @@ -163,7 +163,7 @@ XnuThreadMain(void *pthread, // rdi wt->tid = tid; *wt->ptid = tid; *wt->ctid = tid; - _spunlock(&wt->lock); + pthread_spin_unlock(&wt->lock); if (wt->tls) { // XNU uses the same 0x30 offset as the WIN32 TIB x64. They told the @@ -216,11 +216,11 @@ static int CloneXnu(int (*fn)(void *), char *stk, size_t stksz, int flags, wt->ctid = flags & CLONE_CHILD_SETTID ? ctid : &wt->tid; wt->ztid = flags & CLONE_CHILD_CLEARTID ? ctid : &wt->tid; wt->tls = flags & CLONE_SETTLS ? tls : 0; - wt->lock = 1; + wt->lock.lock = 1; if ((rc = bsdthread_create(fn, arg, wt, 0, PTHREAD_START_CUSTOM_XNU)) != -1) { - _spinlock(&wt->lock); + pthread_spin_lock(&wt->lock); rc = wt->tid; - _spunlock(&wt->lock); + pthread_spin_unlock(&wt->lock); } return rc; } diff --git a/libc/runtime/fork.c b/libc/runtime/fork.c index 4bab187ac..e717e421e 100644 --- a/libc/runtime/fork.c +++ b/libc/runtime/fork.c @@ -16,18 +16,17 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/intrin/bits.h" -#include "libc/intrin/weaken.h" #include "libc/calls/calls.h" #include "libc/calls/strace.internal.h" +#include "libc/calls/struct/sigset.h" #include "libc/calls/syscall-nt.internal.h" #include "libc/calls/syscall-sysv.internal.h" -#include "libc/calls/syscall_support-sysv.internal.h" #include "libc/dce.h" #include "libc/nexgen32e/gettls.h" #include "libc/nexgen32e/threaded.h" #include "libc/nt/process.h" #include "libc/runtime/internal.h" +#include "libc/sysv/consts/sig.h" /** * Creates new process. @@ -37,14 +36,17 @@ */ int fork(void) { axdx_t ad; + sigset_t old, all; int ax, dx, parent; + sigfillset(&all); + sigprocmask(SIG_BLOCK, &all, &old); if (!IsWindows()) { ad = sys_fork(); ax = ad.ax; dx = ad.dx; if (IsXnu() && ax != -1) { - /* eax always returned with childs pid */ - /* edx is 0 for parent and 1 for child */ + // eax always returned with childs pid + // edx is 0 for parent and 1 for child ax &= dx - 1; } } else { @@ -62,11 +64,10 @@ int fork(void) { *(int *)(__get_tls() + 0x38) = IsLinux() ? dx : sys_gettid(); } STRACE("fork() → 0 (child of %d)", parent); - if (weaken(__onfork)) { - weaken(__onfork)(); - } + sigprocmask(SIG_SETMASK, &old, 0); } else { STRACE("fork() → %d% m", ax); + sigprocmask(SIG_SETMASK, &old, 0); } return ax; } diff --git a/libc/runtime/getsymboltable.c b/libc/runtime/getsymboltable.c index 169ba510a..742504416 100644 --- a/libc/runtime/getsymboltable.c +++ b/libc/runtime/getsymboltable.c @@ -17,11 +17,11 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/assert.h" -#include "libc/intrin/bits.h" -#include "libc/intrin/weaken.h" #include "libc/calls/strace.internal.h" +#include "libc/intrin/bits.h" #include "libc/intrin/promises.internal.h" -#include "libc/intrin/spinlock.h" +#include "libc/intrin/pthread.h" +#include "libc/intrin/weaken.h" #include "libc/macros.internal.h" #include "libc/runtime/internal.h" #include "libc/runtime/runtime.h" @@ -32,7 +32,7 @@ #include "libc/zipos/zipos.internal.h" #include "third_party/zlib/puff.h" -static int g_lock; +static pthread_spinlock_t g_lock; hidden struct SymbolTable *__symtab; // for kprintf /** @@ -125,7 +125,7 @@ static struct SymbolTable *GetSymbolTableFromElf(void) { */ struct SymbolTable *GetSymbolTable(void) { struct Zipos *z; - if (_trylock(&g_lock)) return 0; + if (pthread_spin_trylock(&g_lock)) return 0; if (!__symtab && !__isworker) { if (weaken(__zipos_get) && (z = weaken(__zipos_get)())) { if ((__symtab = GetSymbolTableFromZip(z))) { @@ -139,7 +139,7 @@ struct SymbolTable *GetSymbolTable(void) { __symtab = GetSymbolTableFromElf(); } } - _spunlock(&g_lock); + pthread_spin_unlock(&g_lock); return __symtab; } diff --git a/libc/runtime/mmap.c b/libc/runtime/mmap.c index 97b00ec93..4bdfeaaf9 100644 --- a/libc/runtime/mmap.c +++ b/libc/runtime/mmap.c @@ -30,7 +30,6 @@ #include "libc/intrin/likely.h" #include "libc/intrin/pthread.h" #include "libc/intrin/safemacros.internal.h" -#include "libc/intrin/spinlock.h" #include "libc/intrin/weaken.h" #include "libc/limits.h" #include "libc/log/backtrace.internal.h" diff --git a/libc/runtime/mprotect-nt.greg.c b/libc/runtime/mprotect-nt.greg.c index 1ee9f1578..9cf587384 100644 --- a/libc/runtime/mprotect-nt.greg.c +++ b/libc/runtime/mprotect-nt.greg.c @@ -16,7 +16,6 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/intrin/spinlock.h" #include "libc/nt/memory.h" #include "libc/runtime/directmap.internal.h" #include "libc/runtime/internal.h" diff --git a/libc/runtime/msync-nt.c b/libc/runtime/msync-nt.c index 3dc2d0ff0..519764531 100644 --- a/libc/runtime/msync-nt.c +++ b/libc/runtime/msync-nt.c @@ -16,7 +16,6 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/intrin/spinlock.h" #include "libc/macros.internal.h" #include "libc/nt/files.h" #include "libc/nt/memory.h" diff --git a/libc/runtime/munmap.c b/libc/runtime/munmap.c index a42b300e6..7e09080bc 100644 --- a/libc/runtime/munmap.c +++ b/libc/runtime/munmap.c @@ -24,7 +24,6 @@ #include "libc/errno.h" #include "libc/intrin/asan.internal.h" #include "libc/intrin/likely.h" -#include "libc/intrin/spinlock.h" #include "libc/intrin/weaken.h" #include "libc/log/backtrace.internal.h" #include "libc/log/libfatal.internal.h" diff --git a/libc/runtime/printmaps.c b/libc/runtime/printmaps.c index 5eaaaef7d..122c97c5e 100644 --- a/libc/runtime/printmaps.c +++ b/libc/runtime/printmaps.c @@ -16,7 +16,6 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/intrin/spinlock.h" #include "libc/runtime/memtrack.internal.h" #include "libc/runtime/runtime.h" diff --git a/libc/sock/accept-nt.c b/libc/sock/accept-nt.c index d1c805a5f..81a398cac 100644 --- a/libc/sock/accept-nt.c +++ b/libc/sock/accept-nt.c @@ -19,7 +19,6 @@ #include "libc/calls/internal.h" #include "libc/calls/sig.internal.h" #include "libc/calls/state.internal.h" -#include "libc/intrin/spinlock.h" #include "libc/mem/mem.h" #include "libc/nt/winsock.h" #include "libc/sock/internal.h" diff --git a/libc/sock/epoll.c b/libc/sock/epoll.c index 8168446d8..a7e99521e 100644 --- a/libc/sock/epoll.c +++ b/libc/sock/epoll.c @@ -38,7 +38,6 @@ #include "libc/calls/syscall_support-sysv.internal.h" #include "libc/dce.h" #include "libc/errno.h" -#include "libc/intrin/spinlock.h" #include "libc/limits.h" #include "libc/macros.internal.h" #include "libc/mem/mem.h" diff --git a/libc/sock/getsockname-nt.c b/libc/sock/getsockname-nt.c index e8e1cb6e4..569b377bc 100644 --- a/libc/sock/getsockname-nt.c +++ b/libc/sock/getsockname-nt.c @@ -17,12 +17,10 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/assert.h" -#include "libc/dce.h" +#include "libc/calls/struct/fd.internal.h" #include "libc/nt/winsock.h" #include "libc/sock/internal.h" #include "libc/sock/syscall_fd.internal.h" -#include "libc/sock/yoink.inc" -#include "libc/sysv/errfuns.h" textwindows int sys_getsockname_nt(struct Fd *fd, void *out_addr, uint32_t *out_addrsize) { diff --git a/libc/sock/kntwsadata.c b/libc/sock/kntwsadata.c index 43703e91d..05d974b0b 100644 --- a/libc/sock/kntwsadata.c +++ b/libc/sock/kntwsadata.c @@ -16,11 +16,10 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/intrin/weaken.h" #include "libc/calls/calls.h" #include "libc/calls/strace.internal.h" #include "libc/dce.h" -#include "libc/intrin/spinlock.h" +#include "libc/intrin/weaken.h" #include "libc/mem/mem.h" #include "libc/nt/runtime.h" #include "libc/nt/winsock.h" diff --git a/libc/sock/socket-nt.c b/libc/sock/socket-nt.c index 10c06eebc..335e62d6b 100644 --- a/libc/sock/socket-nt.c +++ b/libc/sock/socket-nt.c @@ -18,7 +18,6 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/internal.h" #include "libc/calls/state.internal.h" -#include "libc/intrin/spinlock.h" #include "libc/mem/mem.h" #include "libc/nt/enum/fileflagandattributes.h" #include "libc/nt/iphlpapi.h" diff --git a/libc/sock/socketpair-nt.c b/libc/sock/socketpair-nt.c index 153d09e46..e4ad00122 100644 --- a/libc/sock/socketpair-nt.c +++ b/libc/sock/socketpair-nt.c @@ -19,7 +19,6 @@ #include "libc/calls/internal.h" #include "libc/calls/state.internal.h" #include "libc/calls/syscall_support-nt.internal.h" -#include "libc/intrin/spinlock.h" #include "libc/nt/createfile.h" #include "libc/nt/enum/accessmask.h" #include "libc/nt/enum/creationdisposition.h" diff --git a/libc/stdio/fflush_unlocked.c b/libc/stdio/fflush_unlocked.c index b5beec78d..0746536be 100644 --- a/libc/stdio/fflush_unlocked.c +++ b/libc/stdio/fflush_unlocked.c @@ -21,7 +21,6 @@ #include "libc/intrin/bits.h" #include "libc/intrin/pthread.h" #include "libc/intrin/pushpop.h" -#include "libc/intrin/spinlock.h" #include "libc/macros.internal.h" #include "libc/mem/arraylist.internal.h" #include "libc/mem/mem.h" diff --git a/libc/stdio/flushlbf.c b/libc/stdio/flushlbf.c index 2df178c2a..69bd5e4c9 100644 --- a/libc/stdio/flushlbf.c +++ b/libc/stdio/flushlbf.c @@ -18,7 +18,6 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/intrin/pthread.h" -#include "libc/intrin/spinlock.h" #include "libc/stdio/fflush.internal.h" #include "libc/stdio/lock.h" #include "libc/stdio/stdio.h" diff --git a/libc/str/unicode.h b/libc/str/unicode.h index 07bb280ff..85e5c6c6f 100644 --- a/libc/str/unicode.h +++ b/libc/str/unicode.h @@ -32,7 +32,7 @@ struct lconv { int wcwidth(wchar_t) pureconst; int wcswidth(const wchar_t *, size_t) strlenesque; -int wcsnwidth(const wchar_t *, size_t, size_t) strlenesque; +int wcsnwidth(const wchar_t *, size_t, int) strlenesque; struct lconv *localeconv(void); COSMOPOLITAN_C_END_ diff --git a/libc/str/wcsnwidth.c b/libc/str/wcsnwidth.c index 0fd76a322..6ba9d935b 100644 --- a/libc/str/wcsnwidth.c +++ b/libc/str/wcsnwidth.c @@ -21,7 +21,7 @@ /** * Returns monospace display width of wide character string. */ -int wcsnwidth(const wchar_t *pwcs, size_t n, size_t o) { +int wcsnwidth(const wchar_t *pwcs, size_t n, int o) { int w, width = 0; for (; *pwcs && n-- > 0; pwcs++) { if ((w = wcwidth(*pwcs)) < 0) { diff --git a/libc/testlib/testrunner.c b/libc/testlib/testrunner.c index d1a16a99b..818577c54 100644 --- a/libc/testlib/testrunner.c +++ b/libc/testlib/testrunner.c @@ -29,7 +29,7 @@ #include "libc/fmt/itoa.h" #include "libc/intrin/atomic.h" #include "libc/intrin/kprintf.h" -#include "libc/intrin/spinlock.h" +#include "libc/intrin/pthread.h" #include "libc/intrin/weaken.h" #include "libc/log/check.h" #include "libc/log/internal.h" @@ -52,7 +52,7 @@ static int x; char g_testlib_olddir[PATH_MAX]; char g_testlib_tmpdir[PATH_MAX]; struct sigaction wanthandlers[31]; -static char testlib_error_lock; +static pthread_spinlock_t testlib_error_lock; void testlib_finish(void) { if (g_testlib_failed) { @@ -64,7 +64,7 @@ void testlib_finish(void) { void testlib_error_enter(const char *file, const char *func) { atomic_fetch_sub_explicit(&__ftrace, 1, memory_order_relaxed); atomic_fetch_sub_explicit(&__strace, 1, memory_order_relaxed); - if (!__vforked) _spinlock(&testlib_error_lock); + if (!__vforked) pthread_spin_lock(&testlib_error_lock); if (!IsWindows()) sys_getpid(); /* make strace easier to read */ if (!IsWindows()) sys_getpid(); if (g_testlib_shoulddebugbreak) { @@ -77,7 +77,7 @@ void testlib_error_enter(const char *file, const char *func) { void testlib_error_leave(void) { atomic_fetch_add_explicit(&__ftrace, 1, memory_order_relaxed); atomic_fetch_add_explicit(&__strace, 1, memory_order_relaxed); - _spunlock(&testlib_error_lock); + pthread_spin_unlock(&testlib_error_lock); } wontreturn void testlib_abort(void) { diff --git a/libc/thread/attr.c b/libc/thread/attr.c deleted file mode 100644 index 66c261962..000000000 --- a/libc/thread/attr.c +++ /dev/null @@ -1,69 +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 2020 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/errno.h" -#include "libc/runtime/stack.h" -#include "libc/thread/thread.h" - -#define MIN_STACKSIZE (8 * PAGESIZE) // includes guard, rounds up to FRAMESIZE -#define MIN_GUARDSIZE PAGESIZE - -// CTOR/DTOR -int cthread_attr_init(cthread_attr_t* attr) { - attr->stacksize = GetStackSize(); - attr->guardsize = PAGESIZE; - attr->mode = CTHREAD_CREATE_JOINABLE; - return 0; -} -int cthread_attr_destroy(cthread_attr_t* attr) { - (void)attr; - return 0; -} - -// stacksize -int cthread_attr_setstacksize(cthread_attr_t* attr, size_t size) { - if (size & (PAGESIZE - 1)) return EINVAL; - if (size < MIN_STACKSIZE) return EINVAL; - attr->stacksize = size; - return 0; -} -size_t cthread_attr_getstacksize(const cthread_attr_t* attr) { - return attr->stacksize; -} - -// guardsize -int cthread_attr_setguardsize(cthread_attr_t* attr, size_t size) { - if (size & (PAGESIZE - 1)) return EINVAL; - if (size < MIN_GUARDSIZE) return EINVAL; - attr->guardsize = size; - return 0; -} -size_t cthread_attr_getguardsize(const cthread_attr_t* attr) { - return attr->guardsize; -} - -// detachstate -int cthread_attr_setdetachstate(cthread_attr_t* attr, int mode) { - if (mode & ~(CTHREAD_CREATE_JOINABLE | CTHREAD_CREATE_DETACHED)) - return EINVAL; - attr->mode = mode; - return 0; -} -int cthread_attr_getdetachstate(const cthread_attr_t* attr) { - return attr->mode; -} diff --git a/libc/thread/pthread_create.c b/libc/thread/pthread_create.c index cf138051d..b384ef6a5 100644 --- a/libc/thread/pthread_create.c +++ b/libc/thread/pthread_create.c @@ -53,7 +53,7 @@ static int PosixThread(void *arg, int tid) { struct PosixThread *pt = arg; enum PosixThreadStatus status; if (!setjmp(pt->exiter)) { - ((cthread_t)__get_tls())->pthread = pt; + ((cthread_t)__get_tls())->pthread = (pthread_t)pt; pt->rc = pt->start_routine(pt->arg); } if (weaken(_pthread_key_destruct)) { @@ -72,7 +72,20 @@ static int PosixThread(void *arg, int tid) { } /** - * Creates thread. + * Creates thread, e.g. + * + * void *worker(void *arg) { + * fputs(arg, stdout); + * return "there\n"; + * } + * + * int main() { + * void *result; + * pthread_t id; + * pthread_create(&id, 0, worker, "hi "); + * pthread_join(id, &result); + * fputs(result, stdout); + * } * * Here's the OSI model of threads in Cosmopolitan: * @@ -216,7 +229,7 @@ int pthread_create(pthread_t *thread, const pthread_attr_t *attr, } if (thread) { - *thread = pt; + *thread = (pthread_t)pt; } return 0; } diff --git a/libc/thread/pthread_detach.c b/libc/thread/pthread_detach.c index 88c32f603..c3aa460dd 100644 --- a/libc/thread/pthread_detach.c +++ b/libc/thread/pthread_detach.c @@ -30,7 +30,7 @@ */ int pthread_detach(pthread_t thread) { enum PosixThreadStatus status; - struct PosixThread *pt = thread; + struct PosixThread *pt = (struct PosixThread *)thread; for (;;) { status = atomic_load_explicit(&pt->status, memory_order_relaxed); if (status == kPosixThreadDetached || status == kPosixThreadZombie) { diff --git a/libc/thread/pthread_equal.c b/libc/thread/pthread_equal.c index 85b60dfb5..1fb1ae0ce 100644 --- a/libc/thread/pthread_equal.c +++ b/libc/thread/pthread_equal.c @@ -25,7 +25,7 @@ * @return nonzero if equal, otherwise zero */ int pthread_equal(pthread_t t1, pthread_t t2) { - struct PosixThread *a = t1; - struct PosixThread *b = t2; + struct PosixThread *a = (struct PosixThread *)t1; + struct PosixThread *b = (struct PosixThread *)t2; return a->spawn.ptid == b->spawn.ptid; } diff --git a/libc/thread/pthread_exit.c b/libc/thread/pthread_exit.c index c6cb898ad..842dc7e7f 100644 --- a/libc/thread/pthread_exit.c +++ b/libc/thread/pthread_exit.c @@ -37,7 +37,7 @@ */ wontreturn void pthread_exit(void *rc) { struct PosixThread *pt; - if ((pt = ((cthread_t)__get_tls())->pthread)) { + if ((pt = (struct PosixThread *)((cthread_t)__get_tls())->pthread)) { pt->rc = rc; _gclongjmp(pt->exiter, 1); } else { diff --git a/libc/thread/pthread_getattr_np.c b/libc/thread/pthread_getattr_np.c index a3b66ea20..878d7ecd9 100644 --- a/libc/thread/pthread_getattr_np.c +++ b/libc/thread/pthread_getattr_np.c @@ -22,7 +22,7 @@ #include "libc/thread/thread.h" int pthread_getattr_np(pthread_t thread, pthread_attr_t *attr) { - struct PosixThread *pt = thread; + struct PosixThread *pt = (struct PosixThread *)thread; memcpy(attr, &pt->attr, sizeof(pt->attr)); return 0; } diff --git a/libc/thread/pthread_getunique_np.c b/libc/thread/pthread_getunique_np.c index f4aea3f1a..a7e046508 100644 --- a/libc/thread/pthread_getunique_np.c +++ b/libc/thread/pthread_getunique_np.c @@ -23,6 +23,6 @@ * Returns thread id of POSIX thread. */ int64_t pthread_getunique_np(pthread_t thread) { - struct PosixThread *pt = thread; + struct PosixThread *pt = (struct PosixThread *)thread; return pt->spawn.ptid; } diff --git a/libc/thread/pthread_join.c b/libc/thread/pthread_join.c index 2ad2a2729..8ae82d909 100644 --- a/libc/thread/pthread_join.c +++ b/libc/thread/pthread_join.c @@ -31,7 +31,7 @@ * @raise EDEADLK if thread is detached */ int pthread_join(pthread_t thread, void **value_ptr) { - struct PosixThread *pt = thread; + struct PosixThread *pt = (struct PosixThread *)thread; if (pt->status == kPosixThreadDetached || // pt->status == kPosixThreadZombie) { assert(!"badjoin"); diff --git a/libc/thread/sem.c b/libc/thread/sem.c deleted file mode 100644 index dfbb50169..000000000 --- a/libc/thread/sem.c +++ /dev/null @@ -1,133 +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 2020 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/atomic.h" -#include "libc/calls/calls.h" -#include "libc/thread/thread.h" - -#define CTHREAD_THREAD_VAL_BITS 32 - -static void Pause(int attempt) { - if (attempt < 16) { - for (int i = 0; i < (1 << attempt); ++i) { - __builtin_ia32_pause(); - } - } else { - sched_yield(); - } -} - -/** - * Initializes semaphore. - */ -int cthread_sem_init(cthread_sem_t* sem, int count) { - sem->linux.count = count; - return 0; -} - -/** - * Destroys semaphore. - */ -int cthread_sem_destroy(cthread_sem_t* sem) { - (void)sem; - return 0; -} - -/** - * Notifies a thread waiting on semaphore. - */ -int cthread_sem_signal(cthread_sem_t* sem) { - uint64_t count; - count = atomic_fetch_add(&sem->linux.count, 1); - if ((count >> CTHREAD_THREAD_VAL_BITS)) { - // WARNING: an offset of 4 bytes would be required on little-endian archs - void* wait_address = &sem->linux.count; - cthread_memory_wake32(wait_address, 1); - } - return 0; -} - -/** - * Waits on semaphore with kernel assistance. - */ -int cthread_sem_wait_futex(cthread_sem_t* sem, const struct timespec* timeout) { - uint64_t count; - - // record current thread as waiter - count = atomic_fetch_add(&sem->linux.count, - (uint64_t)1 << CTHREAD_THREAD_VAL_BITS); - - for (;;) { - // try to acquire the semaphore, as well as remove itself from waiters - while ((uint32_t)count > 0) { - // without spin, we could miss a futex wake - if (atomic_compare_exchange_weak( - &sem->linux.count, &count, - count - 1 - ((uint64_t)1 << CTHREAD_THREAD_VAL_BITS))) { - return 0; - } - } - - // WARNING: an offset of 4 bytes would be required on little-endian archs - void* wait_address = &sem->linux.count; - cthread_memory_wait32(wait_address, count, timeout); - count = atomic_load(&sem->linux.count); - } - - return 0; -} - -/** - * Waits on semaphore without kernel assistance. - */ -int cthread_sem_wait_spin(cthread_sem_t* sem, uint64_t count, int spin, - const struct timespec* timeout) { - // spin on pause - for (int attempt = 0; attempt < spin; ++attempt) { - // if ((count >> CTHREAD_THREAD_VAL_BITS) != 0) break; - while ((uint32_t)count > 0) { - // spin is useful if multiple waiters can acquire the semaphore at the - // same time - if (atomic_compare_exchange_weak(&sem->linux.count, &count, count - 1)) { - return 0; - } - } - Pause(attempt); - } - - return cthread_sem_wait_futex(sem, timeout); -} - -/** - * Waits on semaphore. - */ -int cthread_sem_wait(cthread_sem_t* sem, int spin, - const struct timespec* timeout) { - uint64_t count = atomic_load(&sem->linux.count); - - // uncontended - while ((uint32_t)count > 0) { - // spin is useful if multiple waiters can acquire the semaphore at the same - // time - if (atomic_compare_exchange_weak(&sem->linux.count, &count, count - 1)) { - return 0; - } - } - - return cthread_sem_wait_spin(sem, count, spin, timeout); -} diff --git a/libc/thread/thread.h b/libc/thread/thread.h index c9bfb5e6a..0bde1fa03 100644 --- a/libc/thread/thread.h +++ b/libc/thread/thread.h @@ -1,23 +1,11 @@ #ifndef COSMOPOLITAN_LIBC_THREAD_THREAD_H_ #define COSMOPOLITAN_LIBC_THREAD_THREAD_H_ -#include "libc/calls/struct/timespec.h" #include "libc/intrin/pthread.h" #include "libc/runtime/runtime.h" #include "libc/str/locale.h" - -#define CTHREAD_CREATE_DETACHED 1 -#define CTHREAD_CREATE_JOINABLE 0 - #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ -enum cthread_state { - cthread_started = 0, - cthread_joining = 1, - cthread_finished = 2, - cthread_detached = 4, -}; - struct FtraceTls { /* 16 */ bool once; /* 0 */ bool noreentry; /* 1 */ @@ -38,32 +26,6 @@ struct cthread_descriptor_t { typedef struct cthread_descriptor_t *cthread_t; -typedef union cthread_sem_t { - struct { - uint64_t count; - } linux; -} cthread_sem_t; - -typedef struct cthread_attr_t { - size_t stacksize, guardsize; - int mode; -} cthread_attr_t; - -cthread_t cthread_self(void); -int cthread_attr_init(cthread_attr_t *); -int cthread_attr_destroy(cthread_attr_t *); -int cthread_attr_setstacksize(cthread_attr_t *, size_t); -size_t thread_attr_getstacksize(const cthread_attr_t *); -int cthread_attr_setguardsize(cthread_attr_t *, size_t); -size_t cthread_attr_getguardsize(const cthread_attr_t *); -int cthread_attr_setdetachstate(cthread_attr_t *, int); -int cthread_attr_getdetachstate(const cthread_attr_t *); -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(int *, int, const struct timespec *); -int cthread_memory_wake32(int *, int); void cthread_ungarbage(void); COSMOPOLITAN_C_END_ diff --git a/libc/time/localtime.c b/libc/time/localtime.c index 35fe035c2..407c10c5f 100644 --- a/libc/time/localtime.c +++ b/libc/time/localtime.c @@ -6,7 +6,6 @@ #include "libc/intrin/bits.h" #include "libc/intrin/nopl.h" #include "libc/intrin/pthread.h" -#include "libc/intrin/spinlock.h" #include "libc/mem/mem.h" #include "libc/nexgen32e/threaded.h" #include "libc/runtime/gc.h" diff --git a/libc/zipos/open.c b/libc/zipos/open.c index 3a879cea8..ad6ad9918 100644 --- a/libc/zipos/open.c +++ b/libc/zipos/open.c @@ -28,7 +28,6 @@ #include "libc/intrin/atomic.h" #include "libc/intrin/cmpxchg.h" #include "libc/intrin/lockcmpxchg.h" -#include "libc/intrin/spinlock.h" #include "libc/nexgen32e/crc32.h" #include "libc/runtime/directmap.internal.h" #include "libc/runtime/internal.h" diff --git a/test/libc/calls/reservefd_test.c b/test/libc/calls/reservefd_test.c index 4e3062b03..a513cb243 100644 --- a/test/libc/calls/reservefd_test.c +++ b/test/libc/calls/reservefd_test.c @@ -23,7 +23,6 @@ #include "libc/calls/struct/rlimit.h" #include "libc/calls/struct/sigaction.h" #include "libc/errno.h" -#include "libc/intrin/spinlock.h" #include "libc/intrin/wait0.internal.h" #include "libc/macros.internal.h" #include "libc/nexgen32e/threaded.h" diff --git a/test/libc/intrin/pthread_mutex_lock2_test.c b/test/libc/intrin/pthread_mutex_lock2_test.c index 85663299c..f486e7cab 100644 --- a/test/libc/intrin/pthread_mutex_lock2_test.c +++ b/test/libc/intrin/pthread_mutex_lock2_test.c @@ -109,7 +109,7 @@ void BenchLockUnlock(pthread_mutex_t *m) { BENCH(pthread_mutex_lock, bench_uncontended) { { - pthread_spinlock_t s = 0; + pthread_spinlock_t s = {0}; EZBENCH2("spin 1x", donothing, BenchSpinUnspin(&s)); } { @@ -161,7 +161,7 @@ int MutexContentionWorker(void *arg, int tid) { BENCH(pthread_mutex_lock, bench_contended) { struct spawn t; { - pthread_spinlock_t s = 0; + pthread_spinlock_t s = {0}; struct SpinContentionArgs a = {&s}; _spawn(SpinContentionWorker, &a, &t); while (!a.ready) sched_yield(); diff --git a/test/libc/intrin/pthread_mutex_lock_test.c b/test/libc/intrin/pthread_mutex_lock_test.c index 79d78484d..97e4f515a 100644 --- a/test/libc/intrin/pthread_mutex_lock_test.c +++ b/test/libc/intrin/pthread_mutex_lock_test.c @@ -23,7 +23,6 @@ #include "libc/errno.h" #include "libc/intrin/futex.internal.h" #include "libc/intrin/pthread.h" -#include "libc/intrin/spinlock.h" #include "libc/intrin/wait0.internal.h" #include "libc/log/check.h" #include "libc/macros.internal.h" diff --git a/test/libc/intrin/rand64_test.c b/test/libc/intrin/rand64_test.c index 0022a3e0f..4251d7a43 100644 --- a/test/libc/intrin/rand64_test.c +++ b/test/libc/intrin/rand64_test.c @@ -22,7 +22,6 @@ #include "libc/dce.h" #include "libc/errno.h" #include "libc/intrin/atomic.h" -#include "libc/intrin/spinlock.h" #include "libc/limits.h" #include "libc/macros.internal.h" #include "libc/mem/mem.h" diff --git a/test/libc/runtime/clone_test.c b/test/libc/runtime/clone_test.c index fead305fe..a6d9c2cce 100644 --- a/test/libc/runtime/clone_test.c +++ b/test/libc/runtime/clone_test.c @@ -21,7 +21,6 @@ #include "libc/dce.h" #include "libc/errno.h" #include "libc/intrin/futex.internal.h" -#include "libc/intrin/spinlock.h" #include "libc/intrin/wait0.internal.h" #include "libc/log/backtrace.internal.h" #include "libc/macros.internal.h" diff --git a/test/libc/runtime/fork_test.c b/test/libc/runtime/fork_test.c index 45f2d8fd7..c06a6e60a 100644 --- a/test/libc/runtime/fork_test.c +++ b/test/libc/runtime/fork_test.c @@ -18,9 +18,12 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/struct/sigaction.h" +#include "libc/calls/struct/timespec.h" #include "libc/dce.h" +#include "libc/intrin/kprintf.h" #include "libc/log/check.h" #include "libc/macros.internal.h" +#include "libc/nexgen32e/rdtsc.h" #include "libc/runtime/runtime.h" #include "libc/sysv/consts/map.h" #include "libc/sysv/consts/msync.h" @@ -29,10 +32,6 @@ #include "libc/testlib/ezbench.h" #include "libc/testlib/testlib.h" -void SetUpOnce(void) { - ASSERT_SYS(0, 0, pledge("stdio proc", 0)); -} - TEST(fork, testPipes) { int a, b; int ws, pid; @@ -142,5 +141,5 @@ void ForkInSerial(void) { } BENCH(fork, bench) { - EZBENCH2("fork", donothing, ForkInSerial()); + EZBENCH2("fork a", donothing, ForkInSerial()); } diff --git a/test/libc/stdio/dtoa_test.c b/test/libc/stdio/dtoa_test.c index 8d63a4997..7b2cc638f 100644 --- a/test/libc/stdio/dtoa_test.c +++ b/test/libc/stdio/dtoa_test.c @@ -20,7 +20,6 @@ #include "libc/calls/struct/sched_param.h" #include "libc/dce.h" #include "libc/fmt/fmt.h" -#include "libc/intrin/spinlock.h" #include "libc/intrin/wait0.internal.h" #include "libc/macros.internal.h" #include "libc/math.h" diff --git a/tool/build/mkdeps.c b/tool/build/mkdeps.c index 66a8704f9..e2876b925 100644 --- a/tool/build/mkdeps.c +++ b/tool/build/mkdeps.c @@ -16,27 +16,25 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/mem/alg.h" -#include "libc/mem/arraylist.internal.h" -#include "libc/mem/arraylist2.internal.h" -#include "libc/mem/bisectcarleft.internal.h" #include "libc/assert.h" -#include "libc/intrin/bits.h" -#include "libc/intrin/safemacros.internal.h" #include "libc/calls/calls.h" #include "libc/calls/struct/stat.h" -#include "libc/calls/sysparam.h" #include "libc/dce.h" #include "libc/errno.h" #include "libc/fmt/fmt.h" +#include "libc/intrin/bits.h" #include "libc/intrin/kprintf.h" #include "libc/intrin/pthread.h" -#include "libc/intrin/spinlock.h" +#include "libc/intrin/safemacros.internal.h" #include "libc/intrin/wait0.internal.h" #include "libc/log/check.h" #include "libc/log/log.h" #include "libc/macros.internal.h" +#include "libc/mem/alg.h" #include "libc/mem/alloca.h" +#include "libc/mem/arraylist.internal.h" +#include "libc/mem/arraylist2.internal.h" +#include "libc/mem/bisectcarleft.internal.h" #include "libc/mem/mem.h" #include "libc/nexgen32e/crc32.h" #include "libc/nexgen32e/threaded.h" diff --git a/tool/net/redbean.c b/tool/net/redbean.c index f9b2d5817..4d4fb6022 100644 --- a/tool/net/redbean.c +++ b/tool/net/redbean.c @@ -36,8 +36,8 @@ #include "libc/intrin/atomic.h" #include "libc/intrin/likely.h" #include "libc/intrin/nomultics.internal.h" +#include "libc/intrin/pthread.h" #include "libc/intrin/safemacros.internal.h" -#include "libc/intrin/spinlock.h" #include "libc/log/check.h" #include "libc/log/log.h" #include "libc/macros.internal.h" @@ -343,7 +343,7 @@ static struct Shared { #include "tool/net/counters.inc" #undef C } c; - _Alignas(64) char montermlock; + pthread_spinlock_t montermlock; } * shared; static const char kCounterNames[] = @@ -6257,7 +6257,7 @@ static int MemoryMonitor(void *arg, int tid) { sigaddset(&ss, SIGUSR2); sigprocmask(SIG_BLOCK, &ss, 0); - _spinlock(&shared->montermlock); + pthread_spin_lock(&shared->montermlock); if (!id) { if ((tty = open(monitortty, O_RDWR | O_NOCTTY)) != -1) { ioctl(tty, TCGETS, &oldterm); @@ -6273,7 +6273,7 @@ static int MemoryMonitor(void *arg, int tid) { WRITE(tty, "\e[?25l", 6); } } - _spunlock(&shared->montermlock); + pthread_spin_unlock(&shared->montermlock); if (tty != -1) { for (gen = 0, mi = 0, b = 0; !terminatemonitor;) { @@ -6355,11 +6355,11 @@ static int MemoryMonitor(void *arg, int tid) { " GEN=%ld\e[J", id, getpid(), ws.ws_col, ws.ws_row, workers, gen); - _spinlock(&shared->montermlock); + pthread_spin_lock(&shared->montermlock); WRITE(tty, b, appendz(b).i); appendr(&b, 0); usleep(MONITOR_MICROS); - _spunlock(&shared->montermlock); + pthread_spin_unlock(&shared->montermlock); } else { // running out of memory temporarily is a real possibility here // the right thing to do, is stand aside and let lua try to fix