diff --git a/libc/calls/prctl.c b/libc/calls/prctl.c index bd31a8c75..456df4cee 100644 --- a/libc/calls/prctl.c +++ b/libc/calls/prctl.c @@ -53,15 +53,5 @@ int prctl(int operation, ...) { rc = enosys(); } -#if SYSDEBUG - if (operation == PR_CAPBSET_READ || operation == PR_CAPBSET_DROP) { - STRACE("prctl(%s, %s) → %d% m", DescribePrctlOperation(operation), - DescribeCapability(a), rc); - } else { - STRACE("prctl(%s, %p, %p, %p, %p) → %d% m", - DescribePrctlOperation(operation), a, b, c, d, rc); - } -#endif - return rc; } diff --git a/libc/intrin/describeflags.internal.h b/libc/intrin/describeflags.internal.h index 28d0a635a..8c7ee2686 100644 --- a/libc/intrin/describeflags.internal.h +++ b/libc/intrin/describeflags.internal.h @@ -13,7 +13,6 @@ const char *DescribeFlags(char *, size_t, const struct DescribeFlags *, size_t, const char *DescribeArchPrctlCode(char[12], int) libcesque; const char *DescribeCancelState(char[12], int, int *) libcesque; -const char *DescribeCapability(char[32], int) libcesque; const char *DescribeClockName(char[32], int) libcesque; const char *DescribeControlKeyState(char[64], uint32_t) libcesque; const char *DescribeDirfd(char[12], int) libcesque; @@ -47,7 +46,6 @@ const char *DescribeOpenFlags(char[128], int) libcesque; const char *DescribeOpenMode(char[15], int, int) libcesque; const char *DescribePersonalityFlags(char[128], int) libcesque; const char *DescribePollFlags(char[64], int) libcesque; -const char *DescribePrctlOperation(int) libcesque; const char *DescribeProtFlags(char[48], int) libcesque; const char *DescribePtrace(char[12], int) libcesque; const char *DescribePtraceEvent(char[32], int) libcesque; @@ -69,9 +67,7 @@ const char *DescribeVirtualKeyCode(char[32], uint32_t) libcesque; const char *DescribeWhence(char[12], int) libcesque; const char *DescribeWhichPrio(char[12], int) libcesque; -#define DescribeArchPrctlCode(x) DescribeArchPrctlCode(alloca(12), x) #define DescribeCancelState(x, y) DescribeCancelState(alloca(12), x, y) -#define DescribeCapability(x) DescribeCapability(alloca(32), x) #define DescribeClockName(x) DescribeClockName(alloca(32), x) #define DescribeControlKeyState(x) DescribeControlKeyState(alloca(64), x) #define DescribeDirfd(x) DescribeDirfd(alloca(12), x) diff --git a/libc/runtime/cxa_thread_atexit.c b/libc/runtime/cxa_thread_atexit.c index 9d8eaa3f1..cce24949f 100644 --- a/libc/runtime/cxa_thread_atexit.c +++ b/libc/runtime/cxa_thread_atexit.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/intrin/cxaatexit.internal.h" +#include "libc/intrin/strace.internal.h" #include "libc/intrin/weaken.h" #include "libc/mem/mem.h" #include "libc/nexgen32e/gc.internal.h" @@ -30,8 +31,6 @@ struct Dtor { struct Dtor *next; }; -static _Thread_local struct Dtor *__cxa_thread_atexit_list; - static void _pthread_unwind(struct CosmoTib *tib) { struct PosixThread *pt; struct _pthread_cleanup_buffer *cb; @@ -42,24 +41,24 @@ static void _pthread_unwind(struct CosmoTib *tib) { } } -static void __cxa_thread_unkey(struct CosmoTib *tib) { - void *val; - int i, j, gotsome; - pthread_key_dtor dtor; - for (j = 0; j < PTHREAD_DESTRUCTOR_ITERATIONS; ++j) { - for (gotsome = i = 0; i < PTHREAD_KEYS_MAX; ++i) { - if ((val = tib->tib_keys[i]) && - (dtor = atomic_load_explicit(_pthread_key_dtor + i, - memory_order_relaxed)) && - dtor != (pthread_key_dtor)-1) { - gotsome = 1; - tib->tib_keys[i] = 0; +static void _pthread_unkey(struct CosmoTib *tib) { + for (int j = 0; j < PTHREAD_DESTRUCTOR_ITERATIONS; ++j) { + bool gotsome = false; + for (int i = 0; i < PTHREAD_KEYS_MAX; ++i) { + void *val; + pthread_key_dtor dtor; + if ((dtor = atomic_load_explicit(&_pthread_key_dtor[i], + memory_order_acquire)) && + dtor != (pthread_key_dtor)-1 && + (val = atomic_exchange_explicit(&tib->tib_keys[i], 0, + memory_order_relaxed))) { + STRACE("_pthread_unkey(%t, %p)", dtor, val); + gotsome = true; dtor(val); } } - if (!gotsome) { + if (!gotsome) break; - } } } @@ -67,9 +66,8 @@ static void _pthread_ungarbage(struct CosmoTib *tib) { struct Garbages *g; while ((g = tib->tib_garbages)) { tib->tib_garbages = 0; - while (g->i--) { + while (g->i--) ((void (*)(intptr_t))g->p[g->i].fn)(g->p[g->i].arg); - } _weaken(free)(g->p); _weaken(free)(g); } @@ -82,10 +80,11 @@ void __cxa_thread_finalize(void) { _pthread_unwind(tib); if (tib->tib_nsync) _weaken(nsync_waiter_destroy)(tib->tib_nsync); - __cxa_thread_unkey(tib); + _pthread_unkey(tib); _pthread_ungarbage(tib); - while ((dtor = __cxa_thread_atexit_list)) { - __cxa_thread_atexit_list = dtor->next; + while ((dtor = tib->tib_atexit)) { + STRACE("__cxa_finalize(%t, %p)", dtor->fun, dtor->arg); + tib->tib_atexit = dtor->next; ((void (*)(void *))dtor->fun)(dtor->arg); _weaken(free)(dtor); } @@ -97,9 +96,11 @@ int __cxa_thread_atexit_impl(void *fun, void *arg, void *dso_symbol) { return -1; if (!(dtor = _weaken(malloc)(sizeof(struct Dtor)))) return -1; + struct CosmoTib *tib; + tib = __get_tls(); dtor->fun = fun; dtor->arg = arg; - dtor->next = __cxa_thread_atexit_list; - __cxa_thread_atexit_list = dtor; + dtor->next = tib->tib_atexit; + tib->tib_atexit = dtor; return 0; } diff --git a/libc/thread/pthread_cancel.c b/libc/thread/pthread_cancel.c index bc9dfd79e..14b0ce8b8 100644 --- a/libc/thread/pthread_cancel.c +++ b/libc/thread/pthread_cancel.c @@ -54,9 +54,8 @@ long _pthread_cancel_ack(void) { pthread_exit(PTHREAD_CANCELED); } pt->pt_flags |= PT_NOCANCEL; - if (IsOpenbsd()) { + if (IsOpenbsd()) pt->pt_flags |= PT_OPENBSD_KLUDGE; - } return ecanceled(); } @@ -351,6 +350,7 @@ static errno_t _pthread_cancel_everyone(void) { * @param thread may be 0 to cancel all threads except self * @return 0 on success, or errno on error * @raise ESRCH if system thread wasn't alive or we lost a race + * @cancelationpoint */ errno_t pthread_cancel(pthread_t thread) { struct PosixThread *arg; @@ -401,6 +401,7 @@ void pthread_testcancel(void) { * * @return 0 if not cancelled or cancelation is blocked or `ECANCELED` * in masked mode when the calling thread has been cancelled + * @cancelationpoint */ errno_t pthread_testcancel_np(void) { struct PosixThread *pt; diff --git a/libc/thread/pthread_create.c b/libc/thread/pthread_create.c index 4312c114d..9e01f26f6 100644 --- a/libc/thread/pthread_create.c +++ b/libc/thread/pthread_create.c @@ -117,6 +117,7 @@ static int PosixThread(void *arg, int tid) { } // set long jump handler so pthread_exit can bring control back here if (!setjmp(pt->pt_exiter)) { + sigdelset(&pt->pt_attr.__sigmask, SIGTHR); if (IsWindows()) { atomic_store_explicit(&__get_tls()->tib_sigmask, pt->pt_attr.__sigmask, memory_order_release); diff --git a/libc/thread/pthread_key_create.c b/libc/thread/pthread_key_create.c index 1f04da7a8..bc749a2be 100644 --- a/libc/thread/pthread_key_create.c +++ b/libc/thread/pthread_key_create.c @@ -48,9 +48,9 @@ int pthread_key_create(pthread_key_t *key, pthread_key_dtor dtor) { if (!dtor) dtor = (pthread_key_dtor)-1; for (i = 0; i < PTHREAD_KEYS_MAX; ++i) { - if (!(expect = atomic_load_explicit(_pthread_key_dtor + i, - memory_order_acquire)) && - atomic_compare_exchange_strong_explicit(_pthread_key_dtor + i, &expect, + if (!(expect = atomic_load_explicit(&_pthread_key_dtor[i], + memory_order_relaxed)) && + atomic_compare_exchange_strong_explicit(&_pthread_key_dtor[i], &expect, dtor, memory_order_release, memory_order_relaxed)) { *key = i; diff --git a/libc/thread/pthread_key_delete.c b/libc/thread/pthread_key_delete.c index a22239d13..b0b649c84 100644 --- a/libc/thread/pthread_key_delete.c +++ b/libc/thread/pthread_key_delete.c @@ -16,7 +16,6 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/assert.h" #include "libc/errno.h" #include "libc/intrin/atomic.h" #include "libc/thread/posixthread.internal.h" @@ -32,10 +31,12 @@ * * @param key was created by pthread_key_create() * @return 0 on success, or errno on error + * @raise EINVAL if `key` is invalid */ int pthread_key_delete(pthread_key_t k) { - unassert(0 <= k && k < PTHREAD_KEYS_MAX); - unassert(atomic_load_explicit(_pthread_key_dtor + k, memory_order_acquire)); - atomic_store_explicit(_pthread_key_dtor + k, 0, memory_order_release); + if (!(0 <= k && k < PTHREAD_KEYS_MAX)) + return EINVAL; // corrupt key identifier + if (!atomic_exchange_explicit(&_pthread_key_dtor[k], 0, memory_order_acq_rel)) + return EINVAL; // delete called twice return 0; } diff --git a/libc/thread/thread.h b/libc/thread/thread.h index a0eaf0167..7fd38f42c 100644 --- a/libc/thread/thread.h +++ b/libc/thread/thread.h @@ -1,7 +1,7 @@ #ifndef COSMOPOLITAN_LIBC_THREAD_THREAD_H_ #define COSMOPOLITAN_LIBC_THREAD_THREAD_H_ -#define PTHREAD_KEYS_MAX 48 +#define PTHREAD_KEYS_MAX 46 #define PTHREAD_STACK_MIN 65536 #define PTHREAD_DESTRUCTOR_ITERATIONS 4 diff --git a/libc/thread/tls.h b/libc/thread/tls.h index 788013afb..8880e1e8a 100644 --- a/libc/thread/tls.h +++ b/libc/thread/tls.h @@ -39,7 +39,8 @@ struct CosmoTib { uint32_t tib_sigstack_flags; _Atomic(int) tib_relock_maps; void *tib_nsync; - void *tib_keys[47]; + void *tib_atexit; + _Atomic(void *) tib_keys[46]; } __attribute__((__aligned__(64))); extern int __threaded; diff --git a/test/ctl/all_of_test.cc b/test/ctl/all_of_test.cc index 4bc090b67..bf8aa4bcd 100644 --- a/test/ctl/all_of_test.cc +++ b/test/ctl/all_of_test.cc @@ -20,9 +20,9 @@ #include "ctl/array.h" #include "libc/mem/leaks.h" -#include -#include -#define ctl std +// #include +// #include +// #define ctl std int main() diff --git a/libc/intrin/describeprctloperation.c b/test/libc/thread/pthread_getunique_np_test.c similarity index 75% rename from libc/intrin/describeprctloperation.c rename to test/libc/thread/pthread_getunique_np_test.c index fc0d3c085..f41c78975 100644 --- a/libc/intrin/describeprctloperation.c +++ b/test/libc/thread/pthread_getunique_np_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,24 +16,19 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/intrin/describeflags.internal.h" -#include "libc/sysv/consts/pr.h" +#include "libc/calls/calls.h" +#include "libc/testlib/testlib.h" +#include "libc/thread/thread.h" -const char *DescribePrctlOperation(int x) { - switch (x) { - case PR_GET_NAME: - return "PR_GET_NAME"; - case PR_SET_NO_NEW_PRIVS: - return "PR_SET_NO_NEW_PRIVS"; - case PR_SET_SECCOMP: - return "PR_SET_SECCOMP"; - case PR_GET_SECCOMP: - return "PR_GET_SECCOMP"; - case PR_CAPBSET_READ: - return "PR_CAPBSET_READ"; - case PR_CAPBSET_DROP: - return "PR_CAPBSET_DROP"; - default: - return "PRCTL_???"; - } +void *wut(void *arg) { + pthread_id_np_t tid; + pthread_getunique_np(pthread_self(), &tid); + ASSERT_EQ(gettid(), tid); + return 0; +} + +TEST(pthread_getunique_np, test) { + pthread_t id; + ASSERT_EQ(0, pthread_create(&id, 0, wut, (void *)1)); + ASSERT_EQ(0, pthread_join(id, 0)); }