From 50d7d2d02edd45dc9fe2ae7802b815f447631788 Mon Sep 17 00:00:00 2001 From: R Date: Wed, 25 Sep 2024 17:57:58 +0100 Subject: [PATCH 01/13] Add dummy implementation of pthread_attr for single-threaded model --- Makefile | 31 +++++++++++++------- expected/wasm32-wasip1/defined-symbols.txt | 24 +++++++++++++++ expected/wasm32-wasip1/predefined-macros.txt | 3 ++ expected/wasm32-wasip2/defined-symbols.txt | 24 +++++++++++++++ expected/wasm32-wasip2/predefined-macros.txt | 3 ++ libc-top-half/musl/include/limits.h | 2 -- stub-pthreads/README.md | 16 ++++++++++ stub-pthreads/stub-pthreads-good.c | 9 ++++++ 8 files changed, 100 insertions(+), 12 deletions(-) create mode 100644 stub-pthreads/README.md create mode 100644 stub-pthreads/stub-pthreads-good.c diff --git a/Makefile b/Makefile index 4eb619295..a6bdcaf5a 100644 --- a/Makefile +++ b/Makefile @@ -76,6 +76,7 @@ DLMALLOC_SOURCES = $(DLMALLOC_SRC_DIR)/dlmalloc.c DLMALLOC_INC = $(DLMALLOC_DIR)/include EMMALLOC_DIR = emmalloc EMMALLOC_SOURCES = $(EMMALLOC_DIR)/emmalloc.c +STUB_PTHREADS_DIR = stub-pthreads LIBC_BOTTOM_HALF_DIR = libc-bottom-half LIBC_BOTTOM_HALF_CLOUDLIBC_SRC = $(LIBC_BOTTOM_HALF_DIR)/cloudlibc/src LIBC_BOTTOM_HALF_CLOUDLIBC_SRC_INC = $(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC)/include @@ -274,7 +275,21 @@ LIBC_TOP_HALF_MUSL_SOURCES += \ ) endif +# pthreads functions (possibly stub) for either thread model +LIBC_TOP_HALF_MUSL_SOURCES += \ + $(addprefix $(LIBC_TOP_HALF_MUSL_SRC_DIR)/, \ + thread/default_attr.c \ + thread/pthread_attr_destroy.c \ + thread/pthread_attr_get.c \ + thread/pthread_attr_init.c \ + thread/pthread_attr_setdetachstate.c \ + thread/pthread_attr_setguardsize.c \ + thread/pthread_attr_setschedparam.c \ + thread/pthread_attr_setstack.c \ + thread/pthread_attr_setstacksize.c \ + ) ifeq ($(THREAD_MODEL), posix) +# pthreads functions needed for actual thread support LIBC_TOP_HALF_MUSL_SOURCES += \ $(addprefix $(LIBC_TOP_HALF_MUSL_SRC_DIR)/, \ env/__init_tls.c \ @@ -285,15 +300,6 @@ LIBC_TOP_HALF_MUSL_SOURCES += \ thread/__lock.c \ thread/__wait.c \ thread/__timedwait.c \ - thread/default_attr.c \ - thread/pthread_attr_destroy.c \ - thread/pthread_attr_get.c \ - thread/pthread_attr_init.c \ - thread/pthread_attr_setdetachstate.c \ - thread/pthread_attr_setguardsize.c \ - thread/pthread_attr_setstack.c \ - thread/pthread_attr_setstacksize.c \ - thread/pthread_attr_setschedparam.c \ thread/pthread_barrier_destroy.c \ thread/pthread_barrier_init.c \ thread/pthread_barrier_wait.c \ @@ -366,6 +372,11 @@ LIBC_TOP_HALF_MUSL_SOURCES += \ thread/wasm32/wasi_thread_start.s \ ) endif +ifeq ($(THREAD_MODEL), single) +# pthreads stubs for single-threaded environment +LIBC_TOP_HALF_MUSL_SOURCES += \ + $(STUB_PTHREADS_DIR)/stub-pthreads-good.c +endif MUSL_PRINTSCAN_SOURCES = \ $(LIBC_TOP_HALF_MUSL_SRC_DIR)/internal/floatscan.c \ @@ -418,10 +429,10 @@ ifeq ($(THREAD_MODEL), posix) # https://reviews.llvm.org/D130053). CFLAGS += -mthread-model posix -pthread -ftls-model=local-exec ASMFLAGS += -matomics +endif # Include cloudlib's directory to access the structure definition of clockid_t CFLAGS += -I$(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC) -endif ifneq ($(LTO),no) ifeq ($(LTO),full) diff --git a/expected/wasm32-wasip1/defined-symbols.txt b/expected/wasm32-wasip1/defined-symbols.txt index a94920b90..f5e9061cf 100644 --- a/expected/wasm32-wasip1/defined-symbols.txt +++ b/expected/wasm32-wasip1/defined-symbols.txt @@ -11,6 +11,7 @@ __EINVAL __ENOMEM __SIG_ERR __SIG_IGN +__acquire_ptc __asctime_r __assert_fail __c_dot_utf8 @@ -34,6 +35,8 @@ __ctype_tolower_loc __ctype_toupper_loc __cxa_atexit __cxa_finalize +__default_guardsize +__default_stacksize __des_setkey __do_des __duplocale @@ -179,6 +182,7 @@ __putenv __qsort_r __rand48_step __reallocarray +__release_ptc __rem_pio2 __rem_pio2_large __rem_pio2f @@ -921,6 +925,26 @@ program_invocation_name program_invocation_short_name pselect psignal +pthread_attr_destroy +pthread_attr_getdetachstate +pthread_attr_getguardsize +pthread_attr_getschedparam +pthread_attr_getstack +pthread_attr_getstacksize +pthread_attr_init +pthread_attr_setdetachstate +pthread_attr_setguardsize +pthread_attr_setschedparam +pthread_attr_setstack +pthread_attr_setstacksize +pthread_barrierattr_getpshared +pthread_condattr_getclock +pthread_condattr_getpshared +pthread_mutexattr_getprotocol +pthread_mutexattr_getpshared +pthread_mutexattr_getrobust +pthread_mutexattr_gettype +pthread_rwlockattr_getpshared putc putc_unlocked putchar diff --git a/expected/wasm32-wasip1/predefined-macros.txt b/expected/wasm32-wasip1/predefined-macros.txt index 2ddc59bc7..cb18bf06f 100644 --- a/expected/wasm32-wasip1/predefined-macros.txt +++ b/expected/wasm32-wasip1/predefined-macros.txt @@ -1463,8 +1463,10 @@ #define PTHREAD_COND_INITIALIZER {{{0}}} #define PTHREAD_CREATE_DETACHED 1 #define PTHREAD_CREATE_JOINABLE 0 +#define PTHREAD_DESTRUCTOR_ITERATIONS 4 #define PTHREAD_EXPLICIT_SCHED 1 #define PTHREAD_INHERIT_SCHED 0 +#define PTHREAD_KEYS_MAX 128 #define PTHREAD_MUTEX_DEFAULT 0 #define PTHREAD_MUTEX_ERRORCHECK 2 #define PTHREAD_MUTEX_INITIALIZER {{{0}}} @@ -1482,6 +1484,7 @@ #define PTHREAD_RWLOCK_INITIALIZER {{{0}}} #define PTHREAD_SCOPE_PROCESS 1 #define PTHREAD_SCOPE_SYSTEM 0 +#define PTHREAD_STACK_MIN 2048 #define PTRBITS (sizeof(char *) * 8) #define PTRDIFF_MAX INT32_MAX #define PTRDIFF_MIN INT32_MIN diff --git a/expected/wasm32-wasip2/defined-symbols.txt b/expected/wasm32-wasip2/defined-symbols.txt index d850aa3cf..6306f32ad 100644 --- a/expected/wasm32-wasip2/defined-symbols.txt +++ b/expected/wasm32-wasip2/defined-symbols.txt @@ -12,6 +12,7 @@ __EINVAL __ENOMEM __SIG_ERR __SIG_IGN +__acquire_ptc __asctime_r __assert_fail __c_dot_utf8 @@ -37,6 +38,8 @@ __ctype_tolower_loc __ctype_toupper_loc __cxa_atexit __cxa_finalize +__default_guardsize +__default_stacksize __des_setkey __do_des __duplocale @@ -182,6 +185,7 @@ __putenv __qsort_r __rand48_step __reallocarray +__release_ptc __rem_pio2 __rem_pio2_large __rem_pio2f @@ -1054,6 +1058,26 @@ program_invocation_name program_invocation_short_name pselect psignal +pthread_attr_destroy +pthread_attr_getdetachstate +pthread_attr_getguardsize +pthread_attr_getschedparam +pthread_attr_getstack +pthread_attr_getstacksize +pthread_attr_init +pthread_attr_setdetachstate +pthread_attr_setguardsize +pthread_attr_setschedparam +pthread_attr_setstack +pthread_attr_setstacksize +pthread_barrierattr_getpshared +pthread_condattr_getclock +pthread_condattr_getpshared +pthread_mutexattr_getprotocol +pthread_mutexattr_getpshared +pthread_mutexattr_getrobust +pthread_mutexattr_gettype +pthread_rwlockattr_getpshared putc putc_unlocked putchar diff --git a/expected/wasm32-wasip2/predefined-macros.txt b/expected/wasm32-wasip2/predefined-macros.txt index 68b05cbf1..267371225 100644 --- a/expected/wasm32-wasip2/predefined-macros.txt +++ b/expected/wasm32-wasip2/predefined-macros.txt @@ -1594,8 +1594,10 @@ #define PTHREAD_COND_INITIALIZER {{{0}}} #define PTHREAD_CREATE_DETACHED 1 #define PTHREAD_CREATE_JOINABLE 0 +#define PTHREAD_DESTRUCTOR_ITERATIONS 4 #define PTHREAD_EXPLICIT_SCHED 1 #define PTHREAD_INHERIT_SCHED 0 +#define PTHREAD_KEYS_MAX 128 #define PTHREAD_MUTEX_DEFAULT 0 #define PTHREAD_MUTEX_ERRORCHECK 2 #define PTHREAD_MUTEX_INITIALIZER {{{0}}} @@ -1613,6 +1615,7 @@ #define PTHREAD_RWLOCK_INITIALIZER {{{0}}} #define PTHREAD_SCOPE_PROCESS 1 #define PTHREAD_SCOPE_SYSTEM 0 +#define PTHREAD_STACK_MIN 2048 #define PTRBITS (sizeof(char *) * 8) #define PTRDIFF_MAX INT32_MAX #define PTRDIFF_MIN INT32_MIN diff --git a/libc-top-half/musl/include/limits.h b/libc-top-half/musl/include/limits.h index 2fc0d2a38..c160568cd 100644 --- a/libc-top-half/musl/include/limits.h +++ b/libc-top-half/musl/include/limits.h @@ -65,11 +65,9 @@ /* Implementation choices... */ -#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) #define PTHREAD_KEYS_MAX 128 #define PTHREAD_STACK_MIN 2048 #define PTHREAD_DESTRUCTOR_ITERATIONS 4 -#endif #if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) #define SEM_VALUE_MAX 0x7fffffff #define SEM_NSEMS_MAX 256 diff --git a/stub-pthreads/README.md b/stub-pthreads/README.md new file mode 100644 index 000000000..fe2161000 --- /dev/null +++ b/stub-pthreads/README.md @@ -0,0 +1,16 @@ +# Single-threaded pthreads stubs + +The goal of these files is to provide stub implementations of pthreads +functions for `THREAD_MODEL=single`. This implementation should _always_ +follow the strict letter of the POSIX specifications. This means that +"doing nothing", "always succeeding", etc. are not proper implementations +-- these stubs aim for higher conformance than that. + +The code that is "more" aligned with the spirit of the POSIX specifications + ends up compiled into libc itself. This primarily consists of synchronization + primitives (which are implemented to actually track state). + +The code that is "less" aligned with the spirit of the specifications +(e.g. by "rules-lawyering" and always failing) are built into a library +`wasi-emulated-pthread.a`. The distinction is ultimately made by vibes and a +judgement call, not formal criteria. diff --git a/stub-pthreads/stub-pthreads-good.c b/stub-pthreads/stub-pthreads-good.c new file mode 100644 index 000000000..df7e3b04b --- /dev/null +++ b/stub-pthreads/stub-pthreads-good.c @@ -0,0 +1,9 @@ +// This file is linked into libc + +#include "pthread_impl.h" + +static void dummy_0() +{ +} +weak_alias(dummy_0, __acquire_ptc); +weak_alias(dummy_0, __release_ptc); From 7e41cef8ebef3045ffe9c358bd08c4bba0fefea3 Mon Sep 17 00:00:00 2001 From: R Date: Tue, 16 Jul 2024 04:52:02 +0100 Subject: [PATCH 02/13] Add a stub implementation of barriers --- Makefile | 7 ++++--- expected/wasm32-wasip1/defined-symbols.txt | 6 ++++++ expected/wasm32-wasip2/defined-symbols.txt | 6 ++++++ stub-pthreads/barrier.c | 23 ++++++++++++++++++++++ 4 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 stub-pthreads/barrier.c diff --git a/Makefile b/Makefile index a6bdcaf5a..8e560c53f 100644 --- a/Makefile +++ b/Makefile @@ -287,6 +287,9 @@ LIBC_TOP_HALF_MUSL_SOURCES += \ thread/pthread_attr_setschedparam.c \ thread/pthread_attr_setstack.c \ thread/pthread_attr_setstacksize.c \ + thread/pthread_barrierattr_destroy.c \ + thread/pthread_barrierattr_init.c \ + thread/pthread_barrierattr_setpshared.c \ ) ifeq ($(THREAD_MODEL), posix) # pthreads functions needed for actual thread support @@ -303,9 +306,6 @@ LIBC_TOP_HALF_MUSL_SOURCES += \ thread/pthread_barrier_destroy.c \ thread/pthread_barrier_init.c \ thread/pthread_barrier_wait.c \ - thread/pthread_barrierattr_destroy.c \ - thread/pthread_barrierattr_init.c \ - thread/pthread_barrierattr_setpshared.c \ thread/pthread_cleanup_push.c \ thread/pthread_cancel.c \ thread/pthread_cond_broadcast.c \ @@ -375,6 +375,7 @@ endif ifeq ($(THREAD_MODEL), single) # pthreads stubs for single-threaded environment LIBC_TOP_HALF_MUSL_SOURCES += \ + $(STUB_PTHREADS_DIR)/barrier.c \ $(STUB_PTHREADS_DIR)/stub-pthreads-good.c endif diff --git a/expected/wasm32-wasip1/defined-symbols.txt b/expected/wasm32-wasip1/defined-symbols.txt index f5e9061cf..7a531b2e1 100644 --- a/expected/wasm32-wasip1/defined-symbols.txt +++ b/expected/wasm32-wasip1/defined-symbols.txt @@ -937,7 +937,13 @@ pthread_attr_setguardsize pthread_attr_setschedparam pthread_attr_setstack pthread_attr_setstacksize +pthread_barrier_destroy +pthread_barrier_init +pthread_barrier_wait +pthread_barrierattr_destroy pthread_barrierattr_getpshared +pthread_barrierattr_init +pthread_barrierattr_setpshared pthread_condattr_getclock pthread_condattr_getpshared pthread_mutexattr_getprotocol diff --git a/expected/wasm32-wasip2/defined-symbols.txt b/expected/wasm32-wasip2/defined-symbols.txt index 6306f32ad..ad8725f78 100644 --- a/expected/wasm32-wasip2/defined-symbols.txt +++ b/expected/wasm32-wasip2/defined-symbols.txt @@ -1070,7 +1070,13 @@ pthread_attr_setguardsize pthread_attr_setschedparam pthread_attr_setstack pthread_attr_setstacksize +pthread_barrier_destroy +pthread_barrier_init +pthread_barrier_wait +pthread_barrierattr_destroy pthread_barrierattr_getpshared +pthread_barrierattr_init +pthread_barrierattr_setpshared pthread_condattr_getclock pthread_condattr_getpshared pthread_mutexattr_getprotocol diff --git a/stub-pthreads/barrier.c b/stub-pthreads/barrier.c new file mode 100644 index 000000000..e0ceed06a --- /dev/null +++ b/stub-pthreads/barrier.c @@ -0,0 +1,23 @@ +#include "pthread_impl.h" +/* + Note on PTHREAD_PROCESS_SHARED: + Because WASM doesn't have virtual memory nor subprocesses, + there isn't any way for the same synchronization object to have multiple mappings. + Thus we can completely ignore it here. +*/ + +int pthread_barrier_init(pthread_barrier_t *restrict b, const pthread_barrierattr_t *restrict a, unsigned count) +{ + if (count-1 > INT_MAX-1) return EINVAL; + *b = (pthread_barrier_t){ ._b_limit = count-1 }; + return 0; +} +int pthread_barrier_destroy(pthread_barrier_t *b) +{ + return 0; +} +int pthread_barrier_wait(pthread_barrier_t *b) +{ + if (!b->_b_limit) return PTHREAD_BARRIER_SERIAL_THREAD; + __builtin_trap(); +} From be912c4bfe18286349814442a4262d80bcf7b5c1 Mon Sep 17 00:00:00 2001 From: R Date: Tue, 16 Jul 2024 05:42:08 +0100 Subject: [PATCH 03/13] Add a stub implementation of mutexes --- Makefile | 17 +++--- expected/wasm32-wasip1/defined-symbols.txt | 18 ++++++ expected/wasm32-wasip2/defined-symbols.txt | 18 ++++++ stub-pthreads/mutex.c | 67 ++++++++++++++++++++++ 4 files changed, 112 insertions(+), 8 deletions(-) create mode 100644 stub-pthreads/mutex.c diff --git a/Makefile b/Makefile index 8e560c53f..1677f7921 100644 --- a/Makefile +++ b/Makefile @@ -290,6 +290,14 @@ LIBC_TOP_HALF_MUSL_SOURCES += \ thread/pthread_barrierattr_destroy.c \ thread/pthread_barrierattr_init.c \ thread/pthread_barrierattr_setpshared.c \ + thread/pthread_mutex_destroy.c \ + thread/pthread_mutex_init.c \ + thread/pthread_mutexattr_destroy.c \ + thread/pthread_mutexattr_init.c \ + thread/pthread_mutexattr_setprotocol.c \ + thread/pthread_mutexattr_setpshared.c \ + thread/pthread_mutexattr_setrobust.c \ + thread/pthread_mutexattr_settype.c \ ) ifeq ($(THREAD_MODEL), posix) # pthreads functions needed for actual thread support @@ -326,19 +334,11 @@ LIBC_TOP_HALF_MUSL_SOURCES += \ thread/pthread_join.c \ thread/pthread_key_create.c \ thread/pthread_mutex_consistent.c \ - thread/pthread_mutex_destroy.c \ - thread/pthread_mutex_init.c \ thread/pthread_mutex_getprioceiling.c \ thread/pthread_mutex_lock.c \ thread/pthread_mutex_timedlock.c \ thread/pthread_mutex_trylock.c \ thread/pthread_mutex_unlock.c \ - thread/pthread_mutexattr_destroy.c \ - thread/pthread_mutexattr_init.c \ - thread/pthread_mutexattr_setprotocol.c \ - thread/pthread_mutexattr_setpshared.c \ - thread/pthread_mutexattr_setrobust.c \ - thread/pthread_mutexattr_settype.c \ thread/pthread_once.c \ thread/pthread_rwlock_destroy.c \ thread/pthread_rwlock_init.c \ @@ -376,6 +376,7 @@ ifeq ($(THREAD_MODEL), single) # pthreads stubs for single-threaded environment LIBC_TOP_HALF_MUSL_SOURCES += \ $(STUB_PTHREADS_DIR)/barrier.c \ + $(STUB_PTHREADS_DIR)/mutex.c \ $(STUB_PTHREADS_DIR)/stub-pthreads-good.c endif diff --git a/expected/wasm32-wasip1/defined-symbols.txt b/expected/wasm32-wasip1/defined-symbols.txt index 7a531b2e1..a31553c33 100644 --- a/expected/wasm32-wasip1/defined-symbols.txt +++ b/expected/wasm32-wasip1/defined-symbols.txt @@ -178,6 +178,11 @@ __pow_log_data __powf_log2_data __progname __progname_full +__pthread_mutex_consistent +__pthread_mutex_lock +__pthread_mutex_timedlock +__pthread_mutex_trylock +__pthread_mutex_unlock __putenv __qsort_r __rand48_step @@ -946,10 +951,23 @@ pthread_barrierattr_init pthread_barrierattr_setpshared pthread_condattr_getclock pthread_condattr_getpshared +pthread_mutex_consistent +pthread_mutex_destroy +pthread_mutex_init +pthread_mutex_lock +pthread_mutex_timedlock +pthread_mutex_trylock +pthread_mutex_unlock +pthread_mutexattr_destroy pthread_mutexattr_getprotocol pthread_mutexattr_getpshared pthread_mutexattr_getrobust pthread_mutexattr_gettype +pthread_mutexattr_init +pthread_mutexattr_setprotocol +pthread_mutexattr_setpshared +pthread_mutexattr_setrobust +pthread_mutexattr_settype pthread_rwlockattr_getpshared putc putc_unlocked diff --git a/expected/wasm32-wasip2/defined-symbols.txt b/expected/wasm32-wasip2/defined-symbols.txt index ad8725f78..0ee46035d 100644 --- a/expected/wasm32-wasip2/defined-symbols.txt +++ b/expected/wasm32-wasip2/defined-symbols.txt @@ -181,6 +181,11 @@ __pow_log_data __powf_log2_data __progname __progname_full +__pthread_mutex_consistent +__pthread_mutex_lock +__pthread_mutex_timedlock +__pthread_mutex_trylock +__pthread_mutex_unlock __putenv __qsort_r __rand48_step @@ -1079,10 +1084,23 @@ pthread_barrierattr_init pthread_barrierattr_setpshared pthread_condattr_getclock pthread_condattr_getpshared +pthread_mutex_consistent +pthread_mutex_destroy +pthread_mutex_init +pthread_mutex_lock +pthread_mutex_timedlock +pthread_mutex_trylock +pthread_mutex_unlock +pthread_mutexattr_destroy pthread_mutexattr_getprotocol pthread_mutexattr_getpshared pthread_mutexattr_getrobust pthread_mutexattr_gettype +pthread_mutexattr_init +pthread_mutexattr_setprotocol +pthread_mutexattr_setpshared +pthread_mutexattr_setrobust +pthread_mutexattr_settype pthread_rwlockattr_getpshared putc putc_unlocked diff --git a/stub-pthreads/mutex.c b/stub-pthreads/mutex.c new file mode 100644 index 000000000..475bdcf8c --- /dev/null +++ b/stub-pthreads/mutex.c @@ -0,0 +1,67 @@ +#include "pthread_impl.h" +/* + Musl mutex (FYI) + + _m_type: + b[7] - process shared + b[3] - priority inherit + b[2] - robust + b[1:0] - type + 0 - normal + 1 - recursive + 2 - errorcheck + + _m_lock: + b[30] - owner dead, if robust + b[29:0] - tid, if not normal + b[4] - locked?, if normal +*/ + +int __pthread_mutex_consistent(pthread_mutex_t *m) +{ + /* cannot be a robust mutex, as they're entirely unsupported in WASI */ + return EINVAL; +} +weak_alias(__pthread_mutex_consistent, pthread_mutex_consistent); + +int __pthread_mutex_lock(pthread_mutex_t *m) +{ + if (m->_m_type&3 != PTHREAD_MUTEX_RECURSIVE) { + if (m->_m_count) return EDEADLK; + m->_m_count = 1; + } else { + if ((unsigned)m->_m_count >= INT_MAX) return EAGAIN; + m->_m_count++; + } + return 0; +} +weak_alias(__pthread_mutex_lock, pthread_mutex_lock); + +int __pthread_mutex_trylock(pthread_mutex_t *m) +{ + if (m->_m_type&3 != PTHREAD_MUTEX_RECURSIVE) { + if (m->_m_count) return EBUSY; + m->_m_count = 1; + } else { + if ((unsigned)m->_m_count >= INT_MAX) return EAGAIN; + m->_m_count++; + } + return 0; +} +weak_alias(__pthread_mutex_trylock, pthread_mutex_trylock); + +int __pthread_mutex_unlock(pthread_mutex_t *m) +{ + if (!m->_m_count) return EPERM; + m->_m_count--; + return 0; +} +weak_alias(__pthread_mutex_unlock, pthread_mutex_unlock); + +int __pthread_mutex_timedlock(pthread_mutex_t *restrict m, const struct timespec *restrict at) +{ + /* "The pthread_mutex_timedlock() function may fail if: A deadlock condition was detected." */ + /* This means that we don't have to wait and then return timeout, we can just detect deadlock. */ + return pthread_mutex_lock(m); +} +weak_alias(__pthread_mutex_timedlock, pthread_mutex_timedlock); From 7d6fc8f43c7b0107a863e2bc7509eeafce3a30c0 Mon Sep 17 00:00:00 2001 From: R Date: Thu, 18 Jul 2024 03:06:07 +0100 Subject: [PATCH 04/13] Add a stub implementation of condvars --- Makefile | 9 +++--- expected/wasm32-wasip1/defined-symbols.txt | 11 +++++++ expected/wasm32-wasip2/defined-symbols.txt | 11 +++++++ stub-pthreads/condvar.c | 36 ++++++++++++++++++++++ 4 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 stub-pthreads/condvar.c diff --git a/Makefile b/Makefile index 1677f7921..c50e977ec 100644 --- a/Makefile +++ b/Makefile @@ -290,6 +290,10 @@ LIBC_TOP_HALF_MUSL_SOURCES += \ thread/pthread_barrierattr_destroy.c \ thread/pthread_barrierattr_init.c \ thread/pthread_barrierattr_setpshared.c \ + thread/pthread_condattr_destroy.c \ + thread/pthread_condattr_init.c \ + thread/pthread_condattr_setclock.c \ + thread/pthread_condattr_setpshared.c \ thread/pthread_mutex_destroy.c \ thread/pthread_mutex_init.c \ thread/pthread_mutexattr_destroy.c \ @@ -322,10 +326,6 @@ LIBC_TOP_HALF_MUSL_SOURCES += \ thread/pthread_cond_signal.c \ thread/pthread_cond_timedwait.c \ thread/pthread_cond_wait.c \ - thread/pthread_condattr_destroy.c \ - thread/pthread_condattr_init.c \ - thread/pthread_condattr_setclock.c \ - thread/pthread_condattr_setpshared.c \ thread/pthread_create.c \ thread/pthread_detach.c \ thread/pthread_equal.c \ @@ -376,6 +376,7 @@ ifeq ($(THREAD_MODEL), single) # pthreads stubs for single-threaded environment LIBC_TOP_HALF_MUSL_SOURCES += \ $(STUB_PTHREADS_DIR)/barrier.c \ + $(STUB_PTHREADS_DIR)/condvar.c \ $(STUB_PTHREADS_DIR)/mutex.c \ $(STUB_PTHREADS_DIR)/stub-pthreads-good.c endif diff --git a/expected/wasm32-wasip1/defined-symbols.txt b/expected/wasm32-wasip1/defined-symbols.txt index a31553c33..53cbe78d2 100644 --- a/expected/wasm32-wasip1/defined-symbols.txt +++ b/expected/wasm32-wasip1/defined-symbols.txt @@ -178,6 +178,7 @@ __pow_log_data __powf_log2_data __progname __progname_full +__pthread_cond_timedwait __pthread_mutex_consistent __pthread_mutex_lock __pthread_mutex_timedlock @@ -949,8 +950,18 @@ pthread_barrierattr_destroy pthread_barrierattr_getpshared pthread_barrierattr_init pthread_barrierattr_setpshared +pthread_cond_broadcast +pthread_cond_destroy +pthread_cond_init +pthread_cond_signal +pthread_cond_timedwait +pthread_cond_wait +pthread_condattr_destroy pthread_condattr_getclock pthread_condattr_getpshared +pthread_condattr_init +pthread_condattr_setclock +pthread_condattr_setpshared pthread_mutex_consistent pthread_mutex_destroy pthread_mutex_init diff --git a/expected/wasm32-wasip2/defined-symbols.txt b/expected/wasm32-wasip2/defined-symbols.txt index 0ee46035d..feaf1d9a2 100644 --- a/expected/wasm32-wasip2/defined-symbols.txt +++ b/expected/wasm32-wasip2/defined-symbols.txt @@ -181,6 +181,7 @@ __pow_log_data __powf_log2_data __progname __progname_full +__pthread_cond_timedwait __pthread_mutex_consistent __pthread_mutex_lock __pthread_mutex_timedlock @@ -1082,8 +1083,18 @@ pthread_barrierattr_destroy pthread_barrierattr_getpshared pthread_barrierattr_init pthread_barrierattr_setpshared +pthread_cond_broadcast +pthread_cond_destroy +pthread_cond_init +pthread_cond_signal +pthread_cond_timedwait +pthread_cond_wait +pthread_condattr_destroy pthread_condattr_getclock pthread_condattr_getpshared +pthread_condattr_init +pthread_condattr_setclock +pthread_condattr_setpshared pthread_mutex_consistent pthread_mutex_destroy pthread_mutex_init diff --git a/stub-pthreads/condvar.c b/stub-pthreads/condvar.c new file mode 100644 index 000000000..de65bac23 --- /dev/null +++ b/stub-pthreads/condvar.c @@ -0,0 +1,36 @@ +#include "pthread_impl.h" +#include + +int pthread_cond_init(pthread_cond_t *restrict c, const pthread_condattr_t *restrict a) +{ + return 0; +} +int pthread_cond_destroy(pthread_cond_t *c) +{ + return 0; +} +int pthread_cond_broadcast(pthread_cond_t *c) +{ + return 0; +} +int pthread_cond_signal(pthread_cond_t *c) +{ + return 0; +} +int pthread_cond_wait(pthread_cond_t *restrict c, pthread_mutex_t *restrict m) +{ + /* Because there is no other thread that can signal us, this is a deadlock immediately. + The other possible choice is to return immediately (spurious wakeup), but that is likely to + just result in the program spinning forever on a condition that cannot become true. */ + __builtin_trap(); +} +int __pthread_cond_timedwait(pthread_cond_t *restrict c, pthread_mutex_t *restrict m, const struct timespec *restrict ts) +{ + /* Error check mutexes must detect if they're not locked (UB for others) */ + if (!m->_m_count) return EPERM; + int ret = clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, ts, 0); + if (ret == 0) return ETIMEDOUT; + if (ret != EINTR) return ret; + return 0; +} +weak_alias(__pthread_cond_timedwait, pthread_cond_timedwait); From ce2d57de007a7f2674b649843df05a13d8dd15c2 Mon Sep 17 00:00:00 2001 From: R Date: Thu, 18 Jul 2024 03:13:05 +0100 Subject: [PATCH 05/13] Add a stub implementation of rwlocks --- Makefile | 11 ++-- expected/wasm32-wasip1/defined-symbols.txt | 19 +++++++ expected/wasm32-wasip2/defined-symbols.txt | 19 +++++++ stub-pthreads/rwlock.c | 60 ++++++++++++++++++++++ 4 files changed, 104 insertions(+), 5 deletions(-) create mode 100644 stub-pthreads/rwlock.c diff --git a/Makefile b/Makefile index c50e977ec..409b819e0 100644 --- a/Makefile +++ b/Makefile @@ -302,6 +302,11 @@ LIBC_TOP_HALF_MUSL_SOURCES += \ thread/pthread_mutexattr_setpshared.c \ thread/pthread_mutexattr_setrobust.c \ thread/pthread_mutexattr_settype.c \ + thread/pthread_rwlock_destroy.c \ + thread/pthread_rwlock_init.c \ + thread/pthread_rwlockattr_destroy.c \ + thread/pthread_rwlockattr_init.c \ + thread/pthread_rwlockattr_setpshared.c \ ) ifeq ($(THREAD_MODEL), posix) # pthreads functions needed for actual thread support @@ -340,8 +345,6 @@ LIBC_TOP_HALF_MUSL_SOURCES += \ thread/pthread_mutex_trylock.c \ thread/pthread_mutex_unlock.c \ thread/pthread_once.c \ - thread/pthread_rwlock_destroy.c \ - thread/pthread_rwlock_init.c \ thread/pthread_rwlock_rdlock.c \ thread/pthread_rwlock_timedrdlock.c \ thread/pthread_rwlock_timedwrlock.c \ @@ -349,9 +352,6 @@ LIBC_TOP_HALF_MUSL_SOURCES += \ thread/pthread_rwlock_trywrlock.c \ thread/pthread_rwlock_unlock.c \ thread/pthread_rwlock_wrlock.c \ - thread/pthread_rwlockattr_destroy.c \ - thread/pthread_rwlockattr_init.c \ - thread/pthread_rwlockattr_setpshared.c \ thread/pthread_setcancelstate.c \ thread/pthread_setcanceltype.c \ thread/pthread_setspecific.c \ @@ -378,6 +378,7 @@ LIBC_TOP_HALF_MUSL_SOURCES += \ $(STUB_PTHREADS_DIR)/barrier.c \ $(STUB_PTHREADS_DIR)/condvar.c \ $(STUB_PTHREADS_DIR)/mutex.c \ + $(STUB_PTHREADS_DIR)/rwlock.c \ $(STUB_PTHREADS_DIR)/stub-pthreads-good.c endif diff --git a/expected/wasm32-wasip1/defined-symbols.txt b/expected/wasm32-wasip1/defined-symbols.txt index 53cbe78d2..44ecf1b2b 100644 --- a/expected/wasm32-wasip1/defined-symbols.txt +++ b/expected/wasm32-wasip1/defined-symbols.txt @@ -184,6 +184,13 @@ __pthread_mutex_lock __pthread_mutex_timedlock __pthread_mutex_trylock __pthread_mutex_unlock +__pthread_rwlock_rdlock +__pthread_rwlock_timedrdlock +__pthread_rwlock_timedwrlock +__pthread_rwlock_tryrdlock +__pthread_rwlock_trywrlock +__pthread_rwlock_unlock +__pthread_rwlock_wrlock __putenv __qsort_r __rand48_step @@ -979,7 +986,19 @@ pthread_mutexattr_setprotocol pthread_mutexattr_setpshared pthread_mutexattr_setrobust pthread_mutexattr_settype +pthread_rwlock_destroy +pthread_rwlock_init +pthread_rwlock_rdlock +pthread_rwlock_timedrdlock +pthread_rwlock_timedwrlock +pthread_rwlock_tryrdlock +pthread_rwlock_trywrlock +pthread_rwlock_unlock +pthread_rwlock_wrlock +pthread_rwlockattr_destroy pthread_rwlockattr_getpshared +pthread_rwlockattr_init +pthread_rwlockattr_setpshared putc putc_unlocked putchar diff --git a/expected/wasm32-wasip2/defined-symbols.txt b/expected/wasm32-wasip2/defined-symbols.txt index feaf1d9a2..5b7450837 100644 --- a/expected/wasm32-wasip2/defined-symbols.txt +++ b/expected/wasm32-wasip2/defined-symbols.txt @@ -187,6 +187,13 @@ __pthread_mutex_lock __pthread_mutex_timedlock __pthread_mutex_trylock __pthread_mutex_unlock +__pthread_rwlock_rdlock +__pthread_rwlock_timedrdlock +__pthread_rwlock_timedwrlock +__pthread_rwlock_tryrdlock +__pthread_rwlock_trywrlock +__pthread_rwlock_unlock +__pthread_rwlock_wrlock __putenv __qsort_r __rand48_step @@ -1112,7 +1119,19 @@ pthread_mutexattr_setprotocol pthread_mutexattr_setpshared pthread_mutexattr_setrobust pthread_mutexattr_settype +pthread_rwlock_destroy +pthread_rwlock_init +pthread_rwlock_rdlock +pthread_rwlock_timedrdlock +pthread_rwlock_timedwrlock +pthread_rwlock_tryrdlock +pthread_rwlock_trywrlock +pthread_rwlock_unlock +pthread_rwlock_wrlock +pthread_rwlockattr_destroy pthread_rwlockattr_getpshared +pthread_rwlockattr_init +pthread_rwlockattr_setpshared putc putc_unlocked putchar diff --git a/stub-pthreads/rwlock.c b/stub-pthreads/rwlock.c new file mode 100644 index 000000000..ce0fc7a29 --- /dev/null +++ b/stub-pthreads/rwlock.c @@ -0,0 +1,60 @@ +#include "pthread_impl.h" +/* Musl uses bit31 to mark "has waiters", bit[30:0] all 1s to indicate writer */ + +/* These functions have the __ prefix to help stub out thread-specific data */ + +int __pthread_rwlock_rdlock(pthread_rwlock_t *rw) +{ + if (rw->_rw_lock == 0x7fffffff) return EDEADLK; + if (rw->_rw_lock == 0x7ffffffe) return EAGAIN; + rw->_rw_lock++; + return 0; +} +weak_alias(__pthread_rwlock_rdlock, pthread_rwlock_rdlock); + +int __pthread_rwlock_timedrdlock(pthread_rwlock_t *restrict rw, const struct timespec *restrict at) +{ + return pthread_rwlock_rdlock(rw); +} +weak_alias(__pthread_rwlock_timedrdlock, pthread_rwlock_timedrdlock); + +int __pthread_rwlock_tryrdlock(pthread_rwlock_t *rw) +{ + if (rw->_rw_lock == 0x7fffffff) return EBUSY; + if (rw->_rw_lock == 0x7ffffffe) return EAGAIN; + rw->_rw_lock++; + return 0; +} +weak_alias(__pthread_rwlock_tryrdlock, pthread_rwlock_tryrdlock); + +int __pthread_rwlock_wrlock(pthread_rwlock_t *rw) +{ + if (rw->_rw_lock) return EDEADLK; + rw->_rw_lock = 0x7fffffff; + return 0; +} +weak_alias(__pthread_rwlock_wrlock, pthread_rwlock_wrlock); + +int __pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict rw, const struct timespec *restrict at) +{ + return pthread_rwlock_wrlock(rw); +} +weak_alias(__pthread_rwlock_timedwrlock, pthread_rwlock_timedwrlock); + +int __pthread_rwlock_trywrlock(pthread_rwlock_t *rw) +{ + if (rw->_rw_lock) return EBUSY; + rw->_rw_lock = 0x7fffffff; + return 0; +} +weak_alias(__pthread_rwlock_trywrlock, pthread_rwlock_trywrlock); + +int __pthread_rwlock_unlock(pthread_rwlock_t *rw) +{ + if (rw->_rw_lock == 0x7fffffff) + rw->_rw_lock = 0; + else + rw->_rw_lock--; + return 0; +} +weak_alias(__pthread_rwlock_unlock, pthread_rwlock_unlock); From 406a6f37bc4b0a60aaa866d58f8f9a4eea8f9212 Mon Sep 17 00:00:00 2001 From: R Date: Thu, 18 Jul 2024 03:17:03 +0100 Subject: [PATCH 06/13] Add a stub implementation of spinlocks --- Makefile | 5 +++-- expected/wasm32-wasip1/defined-symbols.txt | 5 +++++ expected/wasm32-wasip2/defined-symbols.txt | 5 +++++ stub-pthreads/spinlock.c | 21 +++++++++++++++++++++ 4 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 stub-pthreads/spinlock.c diff --git a/Makefile b/Makefile index 409b819e0..63ee108bb 100644 --- a/Makefile +++ b/Makefile @@ -307,6 +307,8 @@ LIBC_TOP_HALF_MUSL_SOURCES += \ thread/pthread_rwlockattr_destroy.c \ thread/pthread_rwlockattr_init.c \ thread/pthread_rwlockattr_setpshared.c \ + thread/pthread_spin_destroy.c \ + thread/pthread_spin_init.c \ ) ifeq ($(THREAD_MODEL), posix) # pthreads functions needed for actual thread support @@ -356,8 +358,6 @@ LIBC_TOP_HALF_MUSL_SOURCES += \ thread/pthread_setcanceltype.c \ thread/pthread_setspecific.c \ thread/pthread_self.c \ - thread/pthread_spin_destroy.c \ - thread/pthread_spin_init.c \ thread/pthread_spin_lock.c \ thread/pthread_spin_trylock.c \ thread/pthread_spin_unlock.c \ @@ -379,6 +379,7 @@ LIBC_TOP_HALF_MUSL_SOURCES += \ $(STUB_PTHREADS_DIR)/condvar.c \ $(STUB_PTHREADS_DIR)/mutex.c \ $(STUB_PTHREADS_DIR)/rwlock.c \ + $(STUB_PTHREADS_DIR)/spinlock.c \ $(STUB_PTHREADS_DIR)/stub-pthreads-good.c endif diff --git a/expected/wasm32-wasip1/defined-symbols.txt b/expected/wasm32-wasip1/defined-symbols.txt index 44ecf1b2b..2abefe83e 100644 --- a/expected/wasm32-wasip1/defined-symbols.txt +++ b/expected/wasm32-wasip1/defined-symbols.txt @@ -999,6 +999,11 @@ pthread_rwlockattr_destroy pthread_rwlockattr_getpshared pthread_rwlockattr_init pthread_rwlockattr_setpshared +pthread_spin_destroy +pthread_spin_init +pthread_spin_lock +pthread_spin_trylock +pthread_spin_unlock putc putc_unlocked putchar diff --git a/expected/wasm32-wasip2/defined-symbols.txt b/expected/wasm32-wasip2/defined-symbols.txt index 5b7450837..d947a6de7 100644 --- a/expected/wasm32-wasip2/defined-symbols.txt +++ b/expected/wasm32-wasip2/defined-symbols.txt @@ -1132,6 +1132,11 @@ pthread_rwlockattr_destroy pthread_rwlockattr_getpshared pthread_rwlockattr_init pthread_rwlockattr_setpshared +pthread_spin_destroy +pthread_spin_init +pthread_spin_lock +pthread_spin_trylock +pthread_spin_unlock putc putc_unlocked putchar diff --git a/stub-pthreads/spinlock.c b/stub-pthreads/spinlock.c new file mode 100644 index 000000000..1099f7e07 --- /dev/null +++ b/stub-pthreads/spinlock.c @@ -0,0 +1,21 @@ + +#include "pthread_impl.h" +/* The only reason why we have to do anything is trylock */ + +int pthread_spin_lock(pthread_spinlock_t *s) +{ + if (*s) return EDEADLK; + *s = 1; + return 0; +} +int pthread_spin_trylock(pthread_spinlock_t *s) +{ + if (*s) return EBUSY; + *s = 1; + return 0; +} +int pthread_spin_unlock(pthread_spinlock_t *s) +{ + *s = 0; + return 0; +} From d0feebaf6df543684495270269c58d779785bd8d Mon Sep 17 00:00:00 2001 From: R Date: Wed, 17 Jul 2024 19:42:13 +0100 Subject: [PATCH 07/13] Enable pthread_self This is needed in order to *correctly* implement things such as cancellation handlers being invoked on pthread_exit --- Makefile | 2 +- expected/wasm32-wasip1/defined-symbols.txt | 3 +++ expected/wasm32-wasip2/defined-symbols.txt | 3 +++ libc-top-half/musl/src/thread/pthread_self.c | 3 +-- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 63ee108bb..dc80c90c2 100644 --- a/Makefile +++ b/Makefile @@ -307,6 +307,7 @@ LIBC_TOP_HALF_MUSL_SOURCES += \ thread/pthread_rwlockattr_destroy.c \ thread/pthread_rwlockattr_init.c \ thread/pthread_rwlockattr_setpshared.c \ + thread/pthread_self.c \ thread/pthread_spin_destroy.c \ thread/pthread_spin_init.c \ ) @@ -357,7 +358,6 @@ LIBC_TOP_HALF_MUSL_SOURCES += \ thread/pthread_setcancelstate.c \ thread/pthread_setcanceltype.c \ thread/pthread_setspecific.c \ - thread/pthread_self.c \ thread/pthread_spin_lock.c \ thread/pthread_spin_trylock.c \ thread/pthread_spin_unlock.c \ diff --git a/expected/wasm32-wasip1/defined-symbols.txt b/expected/wasm32-wasip1/defined-symbols.txt index 2abefe83e..b595ebed7 100644 --- a/expected/wasm32-wasip1/defined-symbols.txt +++ b/expected/wasm32-wasip1/defined-symbols.txt @@ -347,6 +347,7 @@ __wasilibc_nocwd_symlinkat __wasilibc_nocwd_utimensat __wasilibc_open_nomode __wasilibc_populate_preopens +__wasilibc_pthread_self __wasilibc_register_preopened_fd __wasilibc_rename_newat __wasilibc_rename_oldat @@ -999,6 +1000,7 @@ pthread_rwlockattr_destroy pthread_rwlockattr_getpshared pthread_rwlockattr_init pthread_rwlockattr_setpshared +pthread_self pthread_spin_destroy pthread_spin_init pthread_spin_lock @@ -1185,6 +1187,7 @@ tfind tgamma tgammaf tgammal +thrd_current thrd_sleep time timegm diff --git a/expected/wasm32-wasip2/defined-symbols.txt b/expected/wasm32-wasip2/defined-symbols.txt index d947a6de7..d687b9972 100644 --- a/expected/wasm32-wasip2/defined-symbols.txt +++ b/expected/wasm32-wasip2/defined-symbols.txt @@ -363,6 +363,7 @@ __wasilibc_nocwd_symlinkat __wasilibc_nocwd_utimensat __wasilibc_open_nomode __wasilibc_populate_preopens +__wasilibc_pthread_self __wasilibc_register_preopened_fd __wasilibc_rename_newat __wasilibc_rename_oldat @@ -1132,6 +1133,7 @@ pthread_rwlockattr_destroy pthread_rwlockattr_getpshared pthread_rwlockattr_init pthread_rwlockattr_setpshared +pthread_self pthread_spin_destroy pthread_spin_init pthread_spin_lock @@ -1418,6 +1420,7 @@ tfind tgamma tgammaf tgammal +thrd_current thrd_sleep time timegm diff --git a/libc-top-half/musl/src/thread/pthread_self.c b/libc-top-half/musl/src/thread/pthread_self.c index 1f3eee1d1..1ea2856d6 100644 --- a/libc-top-half/musl/src/thread/pthread_self.c +++ b/libc-top-half/musl/src/thread/pthread_self.c @@ -1,8 +1,7 @@ #include "pthread_impl.h" #include -#if !defined(__wasilibc_unmodified_upstream) && defined(__wasm__) && \ - defined(_REENTRANT) +#if !defined(__wasilibc_unmodified_upstream) && defined(__wasm__) _Thread_local struct pthread __wasilibc_pthread_self; #endif From cc0fbfe32cdfa4cb9ef7e8d115e339d72d42694d Mon Sep 17 00:00:00 2001 From: R Date: Wed, 17 Jul 2024 19:58:42 +0100 Subject: [PATCH 08/13] Enable a number of functions that now work now that we have pthread_self --- Makefile | 16 ++++++++-------- expected/wasm32-wasip1/defined-symbols.txt | 21 +++++++++++++++++++++ expected/wasm32-wasip2/defined-symbols.txt | 21 +++++++++++++++++++++ 3 files changed, 50 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index dc80c90c2..e70709b91 100644 --- a/Makefile +++ b/Makefile @@ -290,10 +290,14 @@ LIBC_TOP_HALF_MUSL_SOURCES += \ thread/pthread_barrierattr_destroy.c \ thread/pthread_barrierattr_init.c \ thread/pthread_barrierattr_setpshared.c \ + thread/pthread_cancel.c \ thread/pthread_condattr_destroy.c \ thread/pthread_condattr_init.c \ thread/pthread_condattr_setclock.c \ thread/pthread_condattr_setpshared.c \ + thread/pthread_equal.c \ + thread/pthread_getspecific.c \ + thread/pthread_key_create.c \ thread/pthread_mutex_destroy.c \ thread/pthread_mutex_init.c \ thread/pthread_mutexattr_destroy.c \ @@ -308,8 +312,12 @@ LIBC_TOP_HALF_MUSL_SOURCES += \ thread/pthread_rwlockattr_init.c \ thread/pthread_rwlockattr_setpshared.c \ thread/pthread_self.c \ + thread/pthread_setcancelstate.c \ + thread/pthread_setcanceltype.c \ + thread/pthread_setspecific.c \ thread/pthread_spin_destroy.c \ thread/pthread_spin_init.c \ + thread/pthread_testcancel.c \ ) ifeq ($(THREAD_MODEL), posix) # pthreads functions needed for actual thread support @@ -327,7 +335,6 @@ LIBC_TOP_HALF_MUSL_SOURCES += \ thread/pthread_barrier_init.c \ thread/pthread_barrier_wait.c \ thread/pthread_cleanup_push.c \ - thread/pthread_cancel.c \ thread/pthread_cond_broadcast.c \ thread/pthread_cond_destroy.c \ thread/pthread_cond_init.c \ @@ -336,11 +343,8 @@ LIBC_TOP_HALF_MUSL_SOURCES += \ thread/pthread_cond_wait.c \ thread/pthread_create.c \ thread/pthread_detach.c \ - thread/pthread_equal.c \ thread/pthread_getattr_np.c \ - thread/pthread_getspecific.c \ thread/pthread_join.c \ - thread/pthread_key_create.c \ thread/pthread_mutex_consistent.c \ thread/pthread_mutex_getprioceiling.c \ thread/pthread_mutex_lock.c \ @@ -355,13 +359,9 @@ LIBC_TOP_HALF_MUSL_SOURCES += \ thread/pthread_rwlock_trywrlock.c \ thread/pthread_rwlock_unlock.c \ thread/pthread_rwlock_wrlock.c \ - thread/pthread_setcancelstate.c \ - thread/pthread_setcanceltype.c \ - thread/pthread_setspecific.c \ thread/pthread_spin_lock.c \ thread/pthread_spin_trylock.c \ thread/pthread_spin_unlock.c \ - thread/pthread_testcancel.c \ thread/sem_destroy.c \ thread/sem_getvalue.c \ thread/sem_init.c \ diff --git a/expected/wasm32-wasip1/defined-symbols.txt b/expected/wasm32-wasip1/defined-symbols.txt index b595ebed7..5862aadf9 100644 --- a/expected/wasm32-wasip1/defined-symbols.txt +++ b/expected/wasm32-wasip1/defined-symbols.txt @@ -179,6 +179,8 @@ __powf_log2_data __progname __progname_full __pthread_cond_timedwait +__pthread_key_create +__pthread_key_delete __pthread_mutex_consistent __pthread_mutex_lock __pthread_mutex_timedlock @@ -191,6 +193,11 @@ __pthread_rwlock_tryrdlock __pthread_rwlock_trywrlock __pthread_rwlock_unlock __pthread_rwlock_wrlock +__pthread_setcancelstate +__pthread_testcancel +__pthread_tsd_main +__pthread_tsd_run_dtors +__pthread_tsd_size __putenv __qsort_r __rand48_step @@ -251,6 +258,9 @@ __sysv_signal __tan __tandf __tanl +__testcancel +__tl_lock +__tl_unlock __tm_to_secs __tm_to_tzname __tolower_l @@ -958,6 +968,7 @@ pthread_barrierattr_destroy pthread_barrierattr_getpshared pthread_barrierattr_init pthread_barrierattr_setpshared +pthread_cancel pthread_cond_broadcast pthread_cond_destroy pthread_cond_init @@ -970,6 +981,10 @@ pthread_condattr_getpshared pthread_condattr_init pthread_condattr_setclock pthread_condattr_setpshared +pthread_equal +pthread_getspecific +pthread_key_create +pthread_key_delete pthread_mutex_consistent pthread_mutex_destroy pthread_mutex_init @@ -1001,11 +1016,15 @@ pthread_rwlockattr_getpshared pthread_rwlockattr_init pthread_rwlockattr_setpshared pthread_self +pthread_setcancelstate +pthread_setcanceltype +pthread_setspecific pthread_spin_destroy pthread_spin_init pthread_spin_lock pthread_spin_trylock pthread_spin_unlock +pthread_testcancel putc putc_unlocked putchar @@ -1188,6 +1207,7 @@ tgamma tgammaf tgammal thrd_current +thrd_equal thrd_sleep time timegm @@ -1209,6 +1229,7 @@ truncate truncf truncl tsearch +tss_get twalk uname ungetc diff --git a/expected/wasm32-wasip2/defined-symbols.txt b/expected/wasm32-wasip2/defined-symbols.txt index d687b9972..db80ee882 100644 --- a/expected/wasm32-wasip2/defined-symbols.txt +++ b/expected/wasm32-wasip2/defined-symbols.txt @@ -182,6 +182,8 @@ __powf_log2_data __progname __progname_full __pthread_cond_timedwait +__pthread_key_create +__pthread_key_delete __pthread_mutex_consistent __pthread_mutex_lock __pthread_mutex_timedlock @@ -194,6 +196,11 @@ __pthread_rwlock_tryrdlock __pthread_rwlock_trywrlock __pthread_rwlock_unlock __pthread_rwlock_wrlock +__pthread_setcancelstate +__pthread_testcancel +__pthread_tsd_main +__pthread_tsd_run_dtors +__pthread_tsd_size __putenv __qsort_r __rand48_step @@ -254,6 +261,9 @@ __sysv_signal __tan __tandf __tanl +__testcancel +__tl_lock +__tl_unlock __tm_to_secs __tm_to_tzname __tolower_l @@ -1091,6 +1101,7 @@ pthread_barrierattr_destroy pthread_barrierattr_getpshared pthread_barrierattr_init pthread_barrierattr_setpshared +pthread_cancel pthread_cond_broadcast pthread_cond_destroy pthread_cond_init @@ -1103,6 +1114,10 @@ pthread_condattr_getpshared pthread_condattr_init pthread_condattr_setclock pthread_condattr_setpshared +pthread_equal +pthread_getspecific +pthread_key_create +pthread_key_delete pthread_mutex_consistent pthread_mutex_destroy pthread_mutex_init @@ -1134,11 +1149,15 @@ pthread_rwlockattr_getpshared pthread_rwlockattr_init pthread_rwlockattr_setpshared pthread_self +pthread_setcancelstate +pthread_setcanceltype +pthread_setspecific pthread_spin_destroy pthread_spin_init pthread_spin_lock pthread_spin_trylock pthread_spin_unlock +pthread_testcancel putc putc_unlocked putchar @@ -1421,6 +1440,7 @@ tgamma tgammaf tgammal thrd_current +thrd_equal thrd_sleep time timegm @@ -1442,6 +1462,7 @@ truncate truncf truncl tsearch +tss_get twalk udp_accept udp_bind From 45adc9fa215701fc23405af52a992c5bd0571502 Mon Sep 17 00:00:00 2001 From: R Date: Tue, 6 Aug 2024 21:13:39 +0100 Subject: [PATCH 09/13] Don't invoke notify builtin in single-threaded mode This fixes compatibility with old versions of clang --- libc-top-half/musl/src/internal/pthread_impl.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libc-top-half/musl/src/internal/pthread_impl.h b/libc-top-half/musl/src/internal/pthread_impl.h index 1e7b9741d..0106ac385 100644 --- a/libc-top-half/musl/src/internal/pthread_impl.h +++ b/libc-top-half/musl/src/internal/pthread_impl.h @@ -186,8 +186,10 @@ static inline void __wake(volatile void *addr, int cnt, int priv) __syscall(SYS_futex, addr, FUTEX_WAKE|priv, cnt) != -ENOSYS || __syscall(SYS_futex, addr, FUTEX_WAKE, cnt); #else +#ifdef _REENTRANT __builtin_wasm_memory_atomic_notify((int*)addr, cnt); #endif +#endif } static inline void __futexwait(volatile void *addr, int val, int priv) { From 7ea3949cbf23a33077de718e0191cfaafac78f35 Mon Sep 17 00:00:00 2001 From: R Date: Wed, 25 Sep 2024 18:16:25 +0100 Subject: [PATCH 10/13] Add a stub for pthread_once --- expected/wasm32-wasip1/defined-symbols.txt | 1 + expected/wasm32-wasip2/defined-symbols.txt | 1 + stub-pthreads/stub-pthreads-good.c | 9 +++++++++ 3 files changed, 11 insertions(+) diff --git a/expected/wasm32-wasip1/defined-symbols.txt b/expected/wasm32-wasip1/defined-symbols.txt index 5862aadf9..ed482ba95 100644 --- a/expected/wasm32-wasip1/defined-symbols.txt +++ b/expected/wasm32-wasip1/defined-symbols.txt @@ -1002,6 +1002,7 @@ pthread_mutexattr_setprotocol pthread_mutexattr_setpshared pthread_mutexattr_setrobust pthread_mutexattr_settype +pthread_once pthread_rwlock_destroy pthread_rwlock_init pthread_rwlock_rdlock diff --git a/expected/wasm32-wasip2/defined-symbols.txt b/expected/wasm32-wasip2/defined-symbols.txt index db80ee882..28aba8869 100644 --- a/expected/wasm32-wasip2/defined-symbols.txt +++ b/expected/wasm32-wasip2/defined-symbols.txt @@ -1135,6 +1135,7 @@ pthread_mutexattr_setprotocol pthread_mutexattr_setpshared pthread_mutexattr_setrobust pthread_mutexattr_settype +pthread_once pthread_rwlock_destroy pthread_rwlock_init pthread_rwlock_rdlock diff --git a/stub-pthreads/stub-pthreads-good.c b/stub-pthreads/stub-pthreads-good.c index df7e3b04b..3c059b324 100644 --- a/stub-pthreads/stub-pthreads-good.c +++ b/stub-pthreads/stub-pthreads-good.c @@ -7,3 +7,12 @@ static void dummy_0() } weak_alias(dummy_0, __acquire_ptc); weak_alias(dummy_0, __release_ptc); + +int pthread_once(pthread_once_t *control, void (*init)(void)) +{ + if (!*control) { + init(); + *control = 1; + } + return 0; +} From 93fd9f5e3262b13dc6aa70a0aa2e64096e9ffd89 Mon Sep 17 00:00:00 2001 From: R Date: Wed, 17 Jul 2024 23:34:06 +0100 Subject: [PATCH 11/13] Implement single_threaded pthread_exit This is "good" as it actually does perform all the cancellation actions and then calls exit() --- Makefile | 2 +- expected/wasm32-wasip1/defined-symbols.txt | 5 +++++ expected/wasm32-wasip2/defined-symbols.txt | 5 +++++ stub-pthreads/stub-pthreads-good.c | 25 ++++++++++++++++++++++ 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e70709b91..51da30f22 100644 --- a/Makefile +++ b/Makefile @@ -291,6 +291,7 @@ LIBC_TOP_HALF_MUSL_SOURCES += \ thread/pthread_barrierattr_init.c \ thread/pthread_barrierattr_setpshared.c \ thread/pthread_cancel.c \ + thread/pthread_cleanup_push.c \ thread/pthread_condattr_destroy.c \ thread/pthread_condattr_init.c \ thread/pthread_condattr_setclock.c \ @@ -334,7 +335,6 @@ LIBC_TOP_HALF_MUSL_SOURCES += \ thread/pthread_barrier_destroy.c \ thread/pthread_barrier_init.c \ thread/pthread_barrier_wait.c \ - thread/pthread_cleanup_push.c \ thread/pthread_cond_broadcast.c \ thread/pthread_cond_destroy.c \ thread/pthread_cond_init.c \ diff --git a/expected/wasm32-wasip1/defined-symbols.txt b/expected/wasm32-wasip1/defined-symbols.txt index ed482ba95..15c306b2e 100644 --- a/expected/wasm32-wasip1/defined-symbols.txt +++ b/expected/wasm32-wasip1/defined-symbols.txt @@ -38,6 +38,8 @@ __cxa_finalize __default_guardsize __default_stacksize __des_setkey +__do_cleanup_pop +__do_cleanup_push __do_des __duplocale __env_rm_add @@ -380,6 +382,8 @@ _environ _exit _flushlbf _initialize +_pthread_cleanup_pop +_pthread_cleanup_push _start a64l abort @@ -982,6 +986,7 @@ pthread_condattr_init pthread_condattr_setclock pthread_condattr_setpshared pthread_equal +pthread_exit pthread_getspecific pthread_key_create pthread_key_delete diff --git a/expected/wasm32-wasip2/defined-symbols.txt b/expected/wasm32-wasip2/defined-symbols.txt index 28aba8869..2c52ecd7c 100644 --- a/expected/wasm32-wasip2/defined-symbols.txt +++ b/expected/wasm32-wasip2/defined-symbols.txt @@ -41,6 +41,8 @@ __cxa_finalize __default_guardsize __default_stacksize __des_setkey +__do_cleanup_pop +__do_cleanup_push __do_des __duplocale __env_rm_add @@ -396,6 +398,8 @@ _environ _exit _flushlbf _initialize +_pthread_cleanup_pop +_pthread_cleanup_push _start a64l abort @@ -1115,6 +1119,7 @@ pthread_condattr_init pthread_condattr_setclock pthread_condattr_setpshared pthread_equal +pthread_exit pthread_getspecific pthread_key_create pthread_key_delete diff --git a/stub-pthreads/stub-pthreads-good.c b/stub-pthreads/stub-pthreads-good.c index 3c059b324..0f6328404 100644 --- a/stub-pthreads/stub-pthreads-good.c +++ b/stub-pthreads/stub-pthreads-good.c @@ -7,6 +7,7 @@ static void dummy_0() } weak_alias(dummy_0, __acquire_ptc); weak_alias(dummy_0, __release_ptc); +weak_alias(dummy_0, __pthread_tsd_run_dtors); int pthread_once(pthread_once_t *control, void (*init)(void)) { @@ -16,3 +17,27 @@ int pthread_once(pthread_once_t *control, void (*init)(void)) } return 0; } + +_Noreturn void pthread_exit(void *result) +{ + /* + We are the only thread, so when we exit the whole process exits. + But we still have to run cancellation handlers... + */ + pthread_t self = __pthread_self(); + + self->canceldisable = 1; + self->cancelasync = 0; + self->result = result; + + while (self->cancelbuf) { + void (*f)(void *) = self->cancelbuf->__f; + void *x = self->cancelbuf->__x; + self->cancelbuf = self->cancelbuf->__next; + f(x); + } + + __pthread_tsd_run_dtors(); + + exit(0); +} From 1b0706dc96a743a99289ff78c594fbe60e92c812 Mon Sep 17 00:00:00 2001 From: R Date: Wed, 25 Sep 2024 18:38:20 +0100 Subject: [PATCH 12/13] Add emulated thread-creation-related functions These functions always fail --- Makefile | 19 ++++++++++ expected/wasm32-wasip1/defined-symbols.txt | 8 +++++ expected/wasm32-wasip2/defined-symbols.txt | 8 +++++ stub-pthreads/stub-pthreads-emulated.c | 40 ++++++++++++++++++++++ 4 files changed, 75 insertions(+) create mode 100644 stub-pthreads/stub-pthreads-emulated.c diff --git a/Makefile b/Makefile index 51da30f22..c4796c409 100644 --- a/Makefile +++ b/Makefile @@ -143,6 +143,8 @@ LIBWASI_EMULATED_SIGNAL_SOURCES = \ LIBWASI_EMULATED_SIGNAL_MUSL_SOURCES = \ $(LIBC_TOP_HALF_MUSL_SRC_DIR)/signal/psignal.c \ $(LIBC_TOP_HALF_MUSL_SRC_DIR)/string/strsignal.c +LIBWASI_EMULATED_PTHREAD_SOURCES = \ + $(STUB_PTHREADS_DIR)/stub-pthreads-emulated.c LIBDL_SOURCES = $(LIBC_TOP_HALF_MUSL_SRC_DIR)/misc/dl.c LIBSETJMP_SOURCES = $(LIBC_TOP_HALF_MUSL_SRC_DIR)/setjmp/wasm32/rt.c LIBC_BOTTOM_HALF_CRT_SOURCES = $(wildcard $(LIBC_BOTTOM_HALF_DIR)/crt/*.c) @@ -506,6 +508,7 @@ LIBWASI_EMULATED_PROCESS_CLOCKS_OBJS = $(call objs,$(LIBWASI_EMULATED_PROCESS_CL LIBWASI_EMULATED_GETPID_OBJS = $(call objs,$(LIBWASI_EMULATED_GETPID_SOURCES)) LIBWASI_EMULATED_SIGNAL_OBJS = $(call objs,$(LIBWASI_EMULATED_SIGNAL_SOURCES)) LIBWASI_EMULATED_SIGNAL_MUSL_OBJS = $(call objs,$(LIBWASI_EMULATED_SIGNAL_MUSL_SOURCES)) +LIBWASI_EMULATED_PTHREAD_OBJS = $(call objs,$(LIBWASI_EMULATED_PTHREAD_SOURCES)) LIBDL_OBJS = $(call objs,$(LIBDL_SOURCES)) LIBSETJMP_OBJS = $(call objs,$(LIBSETJMP_SOURCES)) LIBC_BOTTOM_HALF_CRT_OBJS = $(call objs,$(LIBC_BOTTOM_HALF_CRT_SOURCES)) @@ -609,6 +612,7 @@ LIBWASI_EMULATED_PROCESS_CLOCKS_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBWASI_EMULA LIBWASI_EMULATED_GETPID_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBWASI_EMULATED_GETPID_OBJS)) LIBWASI_EMULATED_SIGNAL_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBWASI_EMULATED_SIGNAL_OBJS)) LIBWASI_EMULATED_SIGNAL_MUSL_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBWASI_EMULATED_SIGNAL_MUSL_OBJS)) +LIBWASI_EMULATED_PTHREAD_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBWASI_EMULATED_PTHREAD_OBJS)) LIBDL_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBDL_OBJS)) LIBSETJMP_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBSETJMP_OBJS)) BULK_MEMORY_SO_OBJS = $(patsubst %.o,%.pic.o,$(BULK_MEMORY_OBJS)) @@ -624,6 +628,7 @@ PIC_OBJS = \ $(LIBWASI_EMULATED_GETPID_SO_OBJS) \ $(LIBWASI_EMULATED_SIGNAL_SO_OBJS) \ $(LIBWASI_EMULATED_SIGNAL_MUSL_SO_OBJS) \ + $(LIBWASI_EMULATED_PTHREAD_SO_OBJS) \ $(LIBDL_SO_OBJS) \ $(LIBSETJMP_SO_OBJS) \ $(BULK_MEMORY_SO_OBJS) \ @@ -665,6 +670,8 @@ $(OBJDIR)/libwasi-emulated-getpid.so.a: $(LIBWASI_EMULATED_GETPID_SO_OBJS) $(OBJDIR)/libwasi-emulated-signal.so.a: $(LIBWASI_EMULATED_SIGNAL_SO_OBJS) $(LIBWASI_EMULATED_SIGNAL_MUSL_SO_OBJS) +$(OBJDIR)/libwasi-emulated-pthread.so.a: $(LIBWASI_EMULATED_PTHREAD_SO_OBJS) + $(OBJDIR)/libdl.so.a: $(LIBDL_SO_OBJS) $(OBJDIR)/libsetjmp.so.a: $(LIBSETJMP_SO_OBJS) @@ -683,6 +690,8 @@ $(SYSROOT_LIB)/libwasi-emulated-getpid.a: $(LIBWASI_EMULATED_GETPID_OBJS) $(SYSROOT_LIB)/libwasi-emulated-signal.a: $(LIBWASI_EMULATED_SIGNAL_OBJS) $(LIBWASI_EMULATED_SIGNAL_MUSL_OBJS) +$(SYSROOT_LIB)/libwasi-emulated-pthread.a: $(LIBWASI_EMULATED_PTHREAD_OBJS) + $(SYSROOT_LIB)/libdl.a: $(LIBDL_OBJS) $(SYSROOT_LIB)/libsetjmp.a: $(LIBSETJMP_OBJS) @@ -785,6 +794,11 @@ $(FTS_OBJS): CFLAGS += \ $(LIBWASI_EMULATED_PROCESS_CLOCKS_OBJS) $(LIBWASI_EMULATED_PROCESS_CLOCKS_SO_OBJS): CFLAGS += \ -I$(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC) +$(LIBWASI_EMULATED_PTHREAD_OBJS) $(LIBWASI_EMULATED_PTHREAD_SO_OBJS): CFLAGS += \ + -I$(LIBC_TOP_HALF_MUSL_SRC_DIR)/include \ + -I$(LIBC_TOP_HALF_MUSL_SRC_DIR)/internal \ + -I$(LIBC_TOP_HALF_MUSL_DIR)/arch/wasm32 + # emmalloc uses a lot of pointer type-punning, which is UB under strict aliasing, # and this was found to have real miscompilations in wasi-libc#421. $(EMMALLOC_OBJS): CFLAGS += \ @@ -836,6 +850,7 @@ LIBC_SO = \ $(SYSROOT_LIB)/libwasi-emulated-process-clocks.so \ $(SYSROOT_LIB)/libwasi-emulated-getpid.so \ $(SYSROOT_LIB)/libwasi-emulated-signal.so \ + $(SYSROOT_LIB)/libwasi-emulated-pthread.so \ $(SYSROOT_LIB)/libdl.so ifeq ($(BUILD_LIBSETJMP),yes) LIBC_SO += \ @@ -854,6 +869,10 @@ STATIC_LIBS = \ $(SYSROOT_LIB)/libwasi-emulated-getpid.a \ $(SYSROOT_LIB)/libwasi-emulated-signal.a \ $(SYSROOT_LIB)/libdl.a +ifneq ($(THREAD_MODEL), posix) + STATIC_LIBS += \ + $(SYSROOT_LIB)/libwasi-emulated-pthread.a +endif ifeq ($(BUILD_LIBSETJMP),yes) STATIC_LIBS += \ $(SYSROOT_LIB)/libsetjmp.a diff --git a/expected/wasm32-wasip1/defined-symbols.txt b/expected/wasm32-wasip1/defined-symbols.txt index 15c306b2e..6e06d64ff 100644 --- a/expected/wasm32-wasip1/defined-symbols.txt +++ b/expected/wasm32-wasip1/defined-symbols.txt @@ -181,6 +181,9 @@ __powf_log2_data __progname __progname_full __pthread_cond_timedwait +__pthread_create +__pthread_detach +__pthread_join __pthread_key_create __pthread_key_delete __pthread_mutex_consistent @@ -985,9 +988,12 @@ pthread_condattr_getpshared pthread_condattr_init pthread_condattr_setclock pthread_condattr_setpshared +pthread_create +pthread_detach pthread_equal pthread_exit pthread_getspecific +pthread_join pthread_key_create pthread_key_delete pthread_mutex_consistent @@ -1031,6 +1037,8 @@ pthread_spin_lock pthread_spin_trylock pthread_spin_unlock pthread_testcancel +pthread_timedjoin_np +pthread_tryjoin_np putc putc_unlocked putchar diff --git a/expected/wasm32-wasip2/defined-symbols.txt b/expected/wasm32-wasip2/defined-symbols.txt index 2c52ecd7c..35e5c3913 100644 --- a/expected/wasm32-wasip2/defined-symbols.txt +++ b/expected/wasm32-wasip2/defined-symbols.txt @@ -184,6 +184,9 @@ __powf_log2_data __progname __progname_full __pthread_cond_timedwait +__pthread_create +__pthread_detach +__pthread_join __pthread_key_create __pthread_key_delete __pthread_mutex_consistent @@ -1118,9 +1121,12 @@ pthread_condattr_getpshared pthread_condattr_init pthread_condattr_setclock pthread_condattr_setpshared +pthread_create +pthread_detach pthread_equal pthread_exit pthread_getspecific +pthread_join pthread_key_create pthread_key_delete pthread_mutex_consistent @@ -1164,6 +1170,8 @@ pthread_spin_lock pthread_spin_trylock pthread_spin_unlock pthread_testcancel +pthread_timedjoin_np +pthread_tryjoin_np putc putc_unlocked putchar diff --git a/stub-pthreads/stub-pthreads-emulated.c b/stub-pthreads/stub-pthreads-emulated.c new file mode 100644 index 000000000..d7e04774f --- /dev/null +++ b/stub-pthreads/stub-pthreads-emulated.c @@ -0,0 +1,40 @@ +// This file is linked into wasi-emulated-pthread + +#include "pthread_impl.h" + +int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict attrp, void *(*entry)(void *), void *restrict arg) +{ + /* + "The system lacked the necessary resources to create another thread, + or the system-imposed limit on the total number of threads in a process + {PTHREAD_THREADS_MAX} would be exceeded." + */ + return EAGAIN; +} +weak_alias(__pthread_create, pthread_create); +int __pthread_detach(pthread_t t) +{ + /* + If we are the only thread, when we exit the whole process exits. + So the storage will be reclaimed no matter what. + */ + return 0; +} +weak_alias(__pthread_detach, pthread_detach); +int __pthread_join(pthread_t t, void **res) +{ + /* + "The behavior is undefined if the value specified by the thread argument + to pthread_join() refers to the calling thread." + */ + return 0; +} +weak_alias(__pthread_join, pthread_join); +int pthread_tryjoin_np(pthread_t t, void **res) +{ + return 0; +} +int pthread_timedjoin_np(pthread_t t, void **res, const struct timespec *at) +{ + return 0; +} From 9b80a8ea43899cc5aa14a9049e6d38a0649439a4 Mon Sep 17 00:00:00 2001 From: R Date: Wed, 25 Sep 2024 20:57:04 +0100 Subject: [PATCH 13/13] Make always-fail functions error if _WASI_EMULATED_PTHREAD isn't defined --- Makefile | 3 +- expected/wasm32-wasip1/predefined-macros.txt | 5 ++++ expected/wasm32-wasip2/predefined-macros.txt | 5 ++++ libc-top-half/musl/include/pthread.h | 30 ++++++++++++++++++-- 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index c4796c409..935b012b1 100644 --- a/Makefile +++ b/Makefile @@ -797,7 +797,8 @@ $(LIBWASI_EMULATED_PROCESS_CLOCKS_OBJS) $(LIBWASI_EMULATED_PROCESS_CLOCKS_SO_OBJ $(LIBWASI_EMULATED_PTHREAD_OBJS) $(LIBWASI_EMULATED_PTHREAD_SO_OBJS): CFLAGS += \ -I$(LIBC_TOP_HALF_MUSL_SRC_DIR)/include \ -I$(LIBC_TOP_HALF_MUSL_SRC_DIR)/internal \ - -I$(LIBC_TOP_HALF_MUSL_DIR)/arch/wasm32 + -I$(LIBC_TOP_HALF_MUSL_DIR)/arch/wasm32 \ + -D_WASI_EMULATED_PTHREAD # emmalloc uses a lot of pointer type-punning, which is UB under strict aliasing, # and this was found to have real miscompilations in wasi-libc#421. diff --git a/expected/wasm32-wasip1/predefined-macros.txt b/expected/wasm32-wasip1/predefined-macros.txt index cb18bf06f..a85cfb340 100644 --- a/expected/wasm32-wasip1/predefined-macros.txt +++ b/expected/wasm32-wasip1/predefined-macros.txt @@ -3389,7 +3389,12 @@ #define preadv64 preadv #define pthread_cleanup_pop(r) _pthread_cleanup_pop(&__cb, (r)); } while(0) #define pthread_cleanup_push(f,x) do { struct __ptcb __cb; _pthread_cleanup_push(&__cb, f, x); +#define pthread_create(...) ({ _Static_assert(0, "This mode of WASI does not have threads enabled; to enable stub functions which always fail, compile with -D_WASI_EMULATED_PTHREAD and link with -lwasi-emulated-pthread"); 0;}) +#define pthread_detach(...) ({ _Static_assert(0, "This mode of WASI does not have threads enabled; to enable stub functions which always fail, compile with -D_WASI_EMULATED_PTHREAD and link with -lwasi-emulated-pthread"); 0;}) #define pthread_equal(x,y) ((x)==(y)) +#define pthread_join(...) ({ _Static_assert(0, "This mode of WASI does not have threads enabled; to enable stub functions which always fail, compile with -D_WASI_EMULATED_PTHREAD and link with -lwasi-emulated-pthread"); 0;}) +#define pthread_timedjoin_np(...) ({ _Static_assert(0, "This mode of WASI does not have threads enabled; to enable stub functions which always fail, compile with -D_WASI_EMULATED_PTHREAD and link with -lwasi-emulated-pthread"); 0;}) +#define pthread_tryjoin_np(...) ({ _Static_assert(0, "This mode of WASI does not have threads enabled; to enable stub functions which always fail, compile with -D_WASI_EMULATED_PTHREAD and link with -lwasi-emulated-pthread"); 0;}) #define pwrite64 pwrite #define pwritev64 pwritev #define readdir64 readdir diff --git a/expected/wasm32-wasip2/predefined-macros.txt b/expected/wasm32-wasip2/predefined-macros.txt index 267371225..6ebd9803d 100644 --- a/expected/wasm32-wasip2/predefined-macros.txt +++ b/expected/wasm32-wasip2/predefined-macros.txt @@ -3544,7 +3544,12 @@ #define preadv64 preadv #define pthread_cleanup_pop(r) _pthread_cleanup_pop(&__cb, (r)); } while(0) #define pthread_cleanup_push(f,x) do { struct __ptcb __cb; _pthread_cleanup_push(&__cb, f, x); +#define pthread_create(...) ({ _Static_assert(0, "This mode of WASI does not have threads enabled; to enable stub functions which always fail, compile with -D_WASI_EMULATED_PTHREAD and link with -lwasi-emulated-pthread"); 0;}) +#define pthread_detach(...) ({ _Static_assert(0, "This mode of WASI does not have threads enabled; to enable stub functions which always fail, compile with -D_WASI_EMULATED_PTHREAD and link with -lwasi-emulated-pthread"); 0;}) #define pthread_equal(x,y) ((x)==(y)) +#define pthread_join(...) ({ _Static_assert(0, "This mode of WASI does not have threads enabled; to enable stub functions which always fail, compile with -D_WASI_EMULATED_PTHREAD and link with -lwasi-emulated-pthread"); 0;}) +#define pthread_timedjoin_np(...) ({ _Static_assert(0, "This mode of WASI does not have threads enabled; to enable stub functions which always fail, compile with -D_WASI_EMULATED_PTHREAD and link with -lwasi-emulated-pthread"); 0;}) +#define pthread_tryjoin_np(...) ({ _Static_assert(0, "This mode of WASI does not have threads enabled; to enable stub functions which always fail, compile with -D_WASI_EMULATED_PTHREAD and link with -lwasi-emulated-pthread"); 0;}) #define pwrite64 pwrite #define pwritev64 pwritev #define readdir64 readdir diff --git a/libc-top-half/musl/include/pthread.h b/libc-top-half/musl/include/pthread.h index 2c35d0b51..fa9f66ae8 100644 --- a/libc-top-half/musl/include/pthread.h +++ b/libc-top-half/musl/include/pthread.h @@ -77,12 +77,29 @@ extern "C" { #define PTHREAD_NULL ((pthread_t)0) +#ifdef __wasilibc_unmodified_upstream int pthread_create(pthread_t *__restrict, const pthread_attr_t *__restrict, void *(*)(void *), void *__restrict); int pthread_detach(pthread_t); -#ifdef __wasilibc_unmodified_upstream _Noreturn void pthread_exit(void *); -#endif int pthread_join(pthread_t, void **); +#else +#if defined(_WASI_EMULATED_PTHREAD) || defined(_REENTRANT) +int pthread_create(pthread_t *__restrict, const pthread_attr_t *__restrict, void *(*)(void *), void *__restrict); +int pthread_detach(pthread_t); +int pthread_join(pthread_t, void **); +#else +#include +#define pthread_create(...) ({ _Static_assert(0, "This mode of WASI does not have threads enabled; \ +to enable stub functions which always fail, \ +compile with -D_WASI_EMULATED_PTHREAD and link with -lwasi-emulated-pthread"); 0;}) +#define pthread_detach(...) ({ _Static_assert(0, "This mode of WASI does not have threads enabled; \ +to enable stub functions which always fail, \ +compile with -D_WASI_EMULATED_PTHREAD and link with -lwasi-emulated-pthread"); 0;}) +#define pthread_join(...) ({ _Static_assert(0, "This mode of WASI does not have threads enabled; \ +to enable stub functions which always fail, \ +compile with -D_WASI_EMULATED_PTHREAD and link with -lwasi-emulated-pthread"); 0;}) +#endif +#endif #ifdef __GNUC__ __attribute__((const)) @@ -232,8 +249,17 @@ int pthread_setname_np(pthread_t, const char *); int pthread_getname_np(pthread_t, char *, size_t); int pthread_getattr_default_np(pthread_attr_t *); int pthread_setattr_default_np(const pthread_attr_t *); +#if defined(__wasilibc_unmodified_upstream) || defined(_WASI_EMULATED_PTHREAD) || defined(_REENTRANT) int pthread_tryjoin_np(pthread_t, void **); int pthread_timedjoin_np(pthread_t, void **, const struct timespec *); +#else +#define pthread_tryjoin_np(...) ({ _Static_assert(0, "This mode of WASI does not have threads enabled; \ +to enable stub functions which always fail, \ +compile with -D_WASI_EMULATED_PTHREAD and link with -lwasi-emulated-pthread"); 0;}) +#define pthread_timedjoin_np(...) ({ _Static_assert(0, "This mode of WASI does not have threads enabled; \ +to enable stub functions which always fail, \ +compile with -D_WASI_EMULATED_PTHREAD and link with -lwasi-emulated-pthread"); 0;}) +#endif #endif #if _REDIR_TIME64