summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile51
-rw-r--r--dlmalloc/src/malloc.c33
-rw-r--r--expected/wasm32-wasi-threads/defined-symbols.txt (renamed from expected/wasm32-wasi/posix/defined-symbols.txt)29
-rw-r--r--expected/wasm32-wasi-threads/include-all.c (renamed from expected/wasm32-wasi/posix/include-all.c)0
-rw-r--r--expected/wasm32-wasi-threads/predefined-macros.txt (renamed from expected/wasm32-wasi/posix/predefined-macros.txt)3
-rw-r--r--expected/wasm32-wasi-threads/undefined-symbols.txt (renamed from expected/wasm32-wasi/posix/undefined-symbols.txt)2
-rw-r--r--expected/wasm32-wasi/defined-symbols.txt (renamed from expected/wasm32-wasi/single/defined-symbols.txt)0
-rw-r--r--expected/wasm32-wasi/include-all.c (renamed from expected/wasm32-wasi/single/include-all.c)0
-rw-r--r--expected/wasm32-wasi/predefined-macros.txt (renamed from expected/wasm32-wasi/single/predefined-macros.txt)2
-rw-r--r--expected/wasm32-wasi/undefined-symbols.txt (renamed from expected/wasm32-wasi/single/undefined-symbols.txt)0
-rw-r--r--libc-bottom-half/headers/public/__struct_sockaddr.h3
-rw-r--r--libc-bottom-half/headers/public/__struct_sockaddr_in.h5
-rw-r--r--libc-bottom-half/headers/public/__struct_sockaddr_in6.h5
-rw-r--r--libc-bottom-half/headers/public/__struct_sockaddr_storage.h5
-rw-r--r--libc-bottom-half/headers/public/__struct_sockaddr_un.h5
-rw-r--r--libc-bottom-half/headers/public/wasi/api.h2
-rw-r--r--libc-bottom-half/sources/__wasilibc_real.c5
-rw-r--r--libc-bottom-half/sources/posix.c100
-rw-r--r--libc-top-half/musl/include/pthread.h2
-rw-r--r--libc-top-half/musl/include/unistd.h2
-rw-r--r--libc-top-half/musl/src/env/__init_tls.c51
-rw-r--r--libc-top-half/musl/src/include/pthread.h2
-rw-r--r--libc-top-half/musl/src/internal/pthread_impl.h5
-rw-r--r--libc-top-half/musl/src/thread/__wait.c2
-rw-r--r--libc-top-half/musl/src/thread/pthread_attr_get.c4
-rw-r--r--libc-top-half/musl/src/thread/pthread_barrier_destroy.c2
-rw-r--r--libc-top-half/musl/src/thread/pthread_barrier_wait.c8
-rw-r--r--libc-top-half/musl/src/thread/pthread_create.c52
-rw-r--r--libc-top-half/musl/src/thread/wasm32/wasi_thread_start.s31
29 files changed, 295 insertions, 116 deletions
diff --git a/Makefile b/Makefile
index 37551cb..57975a7 100644
--- a/Makefile
+++ b/Makefile
@@ -20,7 +20,7 @@ MALLOC_IMPL ?= dlmalloc
# yes or no
BUILD_LIBC_TOP_HALF ?= yes
# The directory where we will store intermediate artifacts.
-OBJDIR ?= $(CURDIR)/build
+OBJDIR ?= $(CURDIR)/build/$(TARGET_TRIPLE)
# When the length is no larger than this threshold, we consider the
# overhead of bulk memory opcodes to outweigh the performance benefit,
@@ -32,10 +32,14 @@ BULK_MEMORY_THRESHOLD ?= 32
# Variables from this point on are not meant to be overridable via the
# make command-line.
-# Set the target variables. Multiarch triples notably omit the vendor field,
-# which happens to be what we do for the main target triple too.
+# Set the default WASI target triple.
TARGET_TRIPLE = wasm32-wasi
-MULTIARCH_TRIPLE = wasm32-wasi
+
+# Threaded version necessitates a different traget, as objects from different
+# targets can't be mixed together while linking.
+ifeq ($(THREAD_MODEL), posix)
+TARGET_TRIPLE = wasm32-wasi-threads
+endif
# These variables describe the locations of various files and directories in
# the source tree.
@@ -195,14 +199,22 @@ LIBC_TOP_HALF_MUSL_SOURCES += \
$(addprefix $(LIBC_TOP_HALF_MUSL_SRC_DIR)/, \
env/__init_tls.c \
stdio/__lockfile.c \
+ stdio/flockfile.c \
+ stdio/ftrylockfile.c \
+ stdio/funlockfile.c \
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_setstack.c \
+ thread/pthread_attr_setdetachstate.c \
thread/pthread_attr_setstacksize.c \
+ 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 \
@@ -215,6 +227,8 @@ LIBC_TOP_HALF_MUSL_SOURCES += \
thread/pthread_condattr_setclock.c \
thread/pthread_condattr_setpshared.c \
thread/pthread_create.c \
+ thread/pthread_detach.c \
+ thread/pthread_equal.c \
thread/pthread_getspecific.c \
thread/pthread_join.c \
thread/pthread_key_create.c \
@@ -256,6 +270,7 @@ LIBC_TOP_HALF_MUSL_SOURCES += \
thread/sem_timedwait.c \
thread/sem_trywait.c \
thread/sem_wait.c \
+ thread/wasm32/wasi_thread_start.s \
)
endif
@@ -274,12 +289,13 @@ LIBC_TOP_HALF_HEADERS_PRIVATE = $(LIBC_TOP_HALF_DIR)/headers/private
LIBC_TOP_HALF_SOURCES = $(LIBC_TOP_HALF_DIR)/sources
LIBC_TOP_HALF_ALL_SOURCES = \
$(LIBC_TOP_HALF_MUSL_SOURCES) \
- $(sort $(shell find $(LIBC_TOP_HALF_SOURCES) -name \*.c))
+ $(sort $(shell find $(LIBC_TOP_HALF_SOURCES) -name \*.[cs]))
# Add any extra flags
CFLAGS = $(EXTRA_CFLAGS)
# Set the target.
CFLAGS += --target=$(TARGET_TRIPLE)
+ASMFLAGS += --target=$(TARGET_TRIPLE)
# WebAssembly floating-point match doesn't trap.
# TODO: Add -fno-signaling-nans when the compiler supports it.
CFLAGS += -fno-trapping-math
@@ -326,10 +342,11 @@ CFLAGS += -isystem "$(SYSROOT_INC)"
# These variables describe the locations of various files and directories in
# the build tree.
objs = $(patsubst $(CURDIR)/%.c,$(OBJDIR)/%.o,$(1))
+asmobjs = $(patsubst $(CURDIR)/%.s,$(OBJDIR)/%.o,$(1))
DLMALLOC_OBJS = $(call objs,$(DLMALLOC_SOURCES))
EMMALLOC_OBJS = $(call objs,$(EMMALLOC_SOURCES))
LIBC_BOTTOM_HALF_ALL_OBJS = $(call objs,$(LIBC_BOTTOM_HALF_ALL_SOURCES))
-LIBC_TOP_HALF_ALL_OBJS = $(call objs,$(LIBC_TOP_HALF_ALL_SOURCES))
+LIBC_TOP_HALF_ALL_OBJS = $(call asmobjs,$(call objs,$(LIBC_TOP_HALF_ALL_SOURCES)))
ifeq ($(MALLOC_IMPL),dlmalloc)
LIBC_OBJS += $(DLMALLOC_OBJS)
else ifeq ($(MALLOC_IMPL),emmalloc)
@@ -357,9 +374,9 @@ LIBWASI_EMULATED_SIGNAL_MUSL_OBJS = $(call objs,$(LIBWASI_EMULATED_SIGNAL_MUSL_S
# These variables describe the locations of various files and
# directories in the generated sysroot tree.
-SYSROOT_LIB := $(SYSROOT)/lib/$(MULTIARCH_TRIPLE)
+SYSROOT_LIB := $(SYSROOT)/lib/$(TARGET_TRIPLE)
SYSROOT_INC = $(SYSROOT)/include
-SYSROOT_SHARE = $(SYSROOT)/share/$(MULTIARCH_TRIPLE)
+SYSROOT_SHARE = $(SYSROOT)/share/$(TARGET_TRIPLE)
# Files from musl's include directory that we don't want to install in the
# sysroot's include directory.
@@ -504,6 +521,10 @@ $(OBJDIR)/%.o: $(CURDIR)/%.c include_dirs
@mkdir -p "$(@D)"
$(CC) $(CFLAGS) -MD -MP -o $@ -c $<
+$(OBJDIR)/%.o: $(CURDIR)/%.s include_dirs
+ @mkdir -p "$(@D)"
+ $(CC) $(ASMFLAGS) -o $@ -c $<
+
-include $(shell find $(OBJDIR) -name \*.d)
$(DLMALLOC_OBJS): CFLAGS += \
@@ -645,11 +666,13 @@ check-symbols: startup_files libc
@# its builtin include path first, which produces compiler-specific
@# output.
@#
- @# TODO: Undefine __FLOAT128__ for now since it's not in clang 8.0.
- @# TODO: Filter out __FLT16_* for now, as not all versions of clang have these.
@# TODO: Filter out __NO_MATH_ERRNO_ and a few __*WIDTH__ that are new to clang 14.
+ @# TODO: Filter out __GCC_HAVE_SYNC_COMPARE_AND_SWAP_* that are new to clang 16.
@# TODO: clang defined __FLT_EVAL_METHOD__ until clang 15, so we force-undefine it
@# for older versions.
+ @# TODO: Undefine __wasm_mutable_globals__ and __wasm_sign_ext__, that are new to
+ @# clang 16 for -mcpu=generic.
+ @# TODO: As of clang 16, __GNUC_VA_LIST is #defined without a value.
$(CC) $(CFLAGS) "$(SYSROOT_SHARE)/include-all.c" \
-isystem $(SYSROOT_INC) \
-std=gnu17 \
@@ -663,22 +686,24 @@ check-symbols: startup_files libc
-U__clang_version__ \
-U__clang_literal_encoding__ \
-U__clang_wide_literal_encoding__ \
+ -U__wasm_mutable_globals__ \
+ -U__wasm_sign_ext__ \
-U__GNUC__ \
-U__GNUC_MINOR__ \
-U__GNUC_PATCHLEVEL__ \
-U__VERSION__ \
- -U__FLOAT128__ \
-U__NO_MATH_ERRNO__ \
-U__BITINT_MAXWIDTH__ \
-U__FLT_EVAL_METHOD__ -Wno-builtin-macro-redefined \
| sed -e 's/__[[:upper:][:digit:]]*_ATOMIC_\([[:upper:][:digit:]_]*\)_LOCK_FREE/__compiler_ATOMIC_\1_LOCK_FREE/' \
- | grep -v '^#define __FLT16_' \
+ | sed -e 's/__GNUC_VA_LIST $$/__GNUC_VA_LIST 1/' \
| grep -v '^#define __\(BOOL\|INT_\(LEAST\|FAST\)\(8\|16\|32\|64\)\|INT\|LONG\|LLONG\|SHRT\)_WIDTH__' \
+ | grep -v '^#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_\(1\|2\|4\|8\)' \
> "$(SYSROOT_SHARE)/predefined-macros.txt"
# Check that the computed metadata matches the expected metadata.
# This ignores whitespace because on Windows the output has CRLF line endings.
- diff -wur "$(CURDIR)/expected/$(MULTIARCH_TRIPLE)/$(THREAD_MODEL)" "$(SYSROOT_SHARE)"
+ diff -wur "$(CURDIR)/expected/$(TARGET_TRIPLE)" "$(SYSROOT_SHARE)"
install: finish
mkdir -p "$(INSTALL_DIR)"
diff --git a/dlmalloc/src/malloc.c b/dlmalloc/src/malloc.c
index 03da739..6e7a15c 100644
--- a/dlmalloc/src/malloc.c
+++ b/dlmalloc/src/malloc.c
@@ -5214,26 +5214,43 @@ static void internal_inspect_all(mstate m,
/* ------------------ Exported try_init_allocator -------------------- */
/* Symbol marking the end of data, bss and explicit stack, provided by wasm-ld. */
-extern unsigned char __heap_base;
+extern char __heap_base;
+extern char __heap_end __attribute__((__weak__));
/* Initialize the initial state of dlmalloc to be able to use free memory between __heap_base and initial. */
static void try_init_allocator(void) {
/* Check that it is a first-time initialization. */
assert(!is_initialized(gm));
- char *base = (char *)&__heap_base;
- /* Calls sbrk(0) that returns the initial memory position. */
- char *init = (char *)CALL_MORECORE(0);
- int initial_heap_size = init - base;
+ /* Initialize mstate. */
+ ensure_initialization();
+
+ char *base = &__heap_base;
+ // Try to use the linker pseudo-symbol `__heap_end` for the initial size of
+ // the heap, but if that's not defined due to LLVM being too old perhaps then
+ // round up `base` to the nearest `PAGESIZE`. The initial size of linear
+ // memory will be at least the heap base to this page boundary, and it's then
+ // assumed that the initial linear memory image was truncated at that point.
+ // While this reflects the default behavior of `wasm-ld` it is also possible
+ // for users to craft larger linear memories by passing options to extend
+ // beyond this threshold. In this situation the memory will not be used for
+ // dlmalloc.
+ //
+ // Note that `sbrk(0)`, or in dlmalloc-ese `CALL_MORECORE(0)`, is specifically
+ // not used here. That captures the current size of the heap but is only
+ // correct if the we're the first to try to grow the heap. If the heap has
+ // grown elsewhere, such as a different allocator in place, then this would
+ // incorrectly claim such memroy as our own.
+ char *end = &__heap_end;
+ if (end == NULL)
+ end = (char*) page_align((size_t) base);
+ size_t initial_heap_size = end - base;
/* Check that initial heap is long enough to serve a minimal allocation request. */
if (initial_heap_size <= MIN_CHUNK_SIZE + TOP_FOOT_SIZE + MALLOC_ALIGNMENT) {
return;
}
- /* Initialize mstate. */
- ensure_initialization();
-
/* Initialize the dlmalloc internal state. */
gm->least_addr = base;
gm->seg.base = base;
diff --git a/expected/wasm32-wasi/posix/defined-symbols.txt b/expected/wasm32-wasi-threads/defined-symbols.txt
index 6e565dc..8dba0f1 100644
--- a/expected/wasm32-wasi/posix/defined-symbols.txt
+++ b/expected/wasm32-wasi-threads/defined-symbols.txt
@@ -46,6 +46,7 @@ __do_cleanup_pop
__do_cleanup_push
__do_des
__do_orphaned_stdio_locks
+__dummy_reference
__duplocale
__env_rm_add
__errno_location
@@ -193,7 +194,6 @@ __progname
__progname_full
__pthread_cond_timedwait
__pthread_create
-__pthread_exit
__pthread_join
__pthread_key_create
__pthread_key_delete
@@ -221,6 +221,7 @@ __qsort_r
__rand48_step
__random_lockptr
__reallocarray
+__register_locked_file
__release_ptc
__rem_pio2
__rem_pio2_large
@@ -354,6 +355,7 @@ __wasi_sock_recv
__wasi_sock_send
__wasi_sock_shutdown
__wasi_thread_spawn
+__wasi_thread_start_C
__wasilibc_access
__wasilibc_cwd
__wasilibc_cwd_lock
@@ -649,6 +651,7 @@ fileno
fileno_unlocked
finite
finitef
+flockfile
floor
floorf
floorl
@@ -704,6 +707,8 @@ ftello
ftello64
ftime
ftruncate
+ftrylockfile
+funlockfile
futimens
futimesat
fwide
@@ -972,9 +977,20 @@ program_invocation_short_name
pselect
psignal
pthread_attr_destroy
+pthread_attr_getdetachstate
+pthread_attr_getguardsize
+pthread_attr_getinheritsched
+pthread_attr_getscope
+pthread_attr_getstack
+pthread_attr_getstacksize
pthread_attr_init
+pthread_attr_setdetachstate
pthread_attr_setstack
pthread_attr_setstacksize
+pthread_barrier_destroy
+pthread_barrier_init
+pthread_barrier_wait
+pthread_barrierattr_getpshared
pthread_cond_broadcast
pthread_cond_destroy
pthread_cond_init
@@ -982,11 +998,13 @@ pthread_cond_signal
pthread_cond_timedwait
pthread_cond_wait
pthread_condattr_destroy
+pthread_condattr_getpshared
pthread_condattr_init
pthread_condattr_setclock
pthread_condattr_setpshared
pthread_create
-pthread_exit
+pthread_detach
+pthread_equal
pthread_getspecific
pthread_join
pthread_key_create
@@ -1000,6 +1018,10 @@ 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
@@ -1016,6 +1038,7 @@ pthread_rwlock_trywrlock
pthread_rwlock_unlock
pthread_rwlock_wrlock
pthread_rwlockattr_destroy
+pthread_rwlockattr_getpshared
pthread_rwlockattr_init
pthread_rwlockattr_setpshared
pthread_self
@@ -1211,6 +1234,8 @@ tgamma
tgammaf
tgammal
thrd_current
+thrd_detach
+thrd_equal
thrd_sleep
time
timegm
diff --git a/expected/wasm32-wasi/posix/include-all.c b/expected/wasm32-wasi-threads/include-all.c
index 0b43b07..0b43b07 100644
--- a/expected/wasm32-wasi/posix/include-all.c
+++ b/expected/wasm32-wasi-threads/include-all.c
diff --git a/expected/wasm32-wasi/posix/predefined-macros.txt b/expected/wasm32-wasi-threads/predefined-macros.txt
index ac90920..a9f2982 100644
--- a/expected/wasm32-wasi/posix/predefined-macros.txt
+++ b/expected/wasm32-wasi-threads/predefined-macros.txt
@@ -2489,6 +2489,7 @@
#define __DEFINED_wctype_t
#define __DEFINED_wint_t
#define __FINITE_MATH_ONLY__ 0
+#define __FLOAT128__ 1
#define __FLT(x) (__IS_REAL(x) && sizeof(x) == sizeof(float))
#define __FLTCX(x) (__IS_CX(x) && sizeof(x) == sizeof(float complex))
#define __FLT_DECIMAL_DIG__ 9
@@ -3099,8 +3100,6 @@
#define __wasm__ 1
#define __wasm_atomics__ 1
#define __wasm_bulk_memory__ 1
-#define __wasm_mutable_globals__ 1
-#define __wasm_sign_ext__ 1
#define _tolower(a) ((a)|0x20)
#define _toupper(a) ((a)&0x5f)
#define acos(x) __tg_real_complex(acos, (x))
diff --git a/expected/wasm32-wasi/posix/undefined-symbols.txt b/expected/wasm32-wasi-threads/undefined-symbols.txt
index 7def0a9..a685151 100644
--- a/expected/wasm32-wasi/posix/undefined-symbols.txt
+++ b/expected/wasm32-wasi-threads/undefined-symbols.txt
@@ -1,4 +1,5 @@
__addtf3
+__data_end
__divtf3
__eqtf2
__extenddftf2
@@ -9,6 +10,7 @@ __fixunstfsi
__floatsitf
__floatunsitf
__getf2
+__global_base
__gttf2
__heap_base
__imported_wasi_snapshot_preview1_args_get
diff --git a/expected/wasm32-wasi/single/defined-symbols.txt b/expected/wasm32-wasi/defined-symbols.txt
index a692632..a692632 100644
--- a/expected/wasm32-wasi/single/defined-symbols.txt
+++ b/expected/wasm32-wasi/defined-symbols.txt
diff --git a/expected/wasm32-wasi/single/include-all.c b/expected/wasm32-wasi/include-all.c
index 86297f3..86297f3 100644
--- a/expected/wasm32-wasi/single/include-all.c
+++ b/expected/wasm32-wasi/include-all.c
diff --git a/expected/wasm32-wasi/single/predefined-macros.txt b/expected/wasm32-wasi/predefined-macros.txt
index 1f7b341..234ad3c 100644
--- a/expected/wasm32-wasi/single/predefined-macros.txt
+++ b/expected/wasm32-wasi/predefined-macros.txt
@@ -2123,7 +2123,6 @@
#define _POSIX_STREAM_MAX 8
#define _POSIX_SYMLINK_MAX 255
#define _POSIX_SYMLOOP_MAX 8
-#define _POSIX_THREADS _POSIX_VERSION
#define _POSIX_THREAD_ATTR_STACKADDR _POSIX_VERSION
#define _POSIX_THREAD_ATTR_STACKSIZE _POSIX_VERSION
#define _POSIX_THREAD_CPUTIME _POSIX_VERSION
@@ -2453,6 +2452,7 @@
#define __DEFINED_wctype_t
#define __DEFINED_wint_t
#define __FINITE_MATH_ONLY__ 0
+#define __FLOAT128__ 1
#define __FLT(x) (__IS_REAL(x) && sizeof(x) == sizeof(float))
#define __FLTCX(x) (__IS_CX(x) && sizeof(x) == sizeof(float complex))
#define __FLT_DECIMAL_DIG__ 9
diff --git a/expected/wasm32-wasi/single/undefined-symbols.txt b/expected/wasm32-wasi/undefined-symbols.txt
index b9cdb34..b9cdb34 100644
--- a/expected/wasm32-wasi/single/undefined-symbols.txt
+++ b/expected/wasm32-wasi/undefined-symbols.txt
diff --git a/libc-bottom-half/headers/public/__struct_sockaddr.h b/libc-bottom-half/headers/public/__struct_sockaddr.h
index 9891b90..2e14d95 100644
--- a/libc-bottom-half/headers/public/__struct_sockaddr.h
+++ b/libc-bottom-half/headers/public/__struct_sockaddr.h
@@ -1,9 +1,6 @@
#ifndef __wasilibc___struct_sockaddr_h
#define __wasilibc___struct_sockaddr_h
-#define __need_STDDEF_H_misc
-#include <stddef.h>
-
#include <__typedef_sa_family_t.h>
struct sockaddr {
diff --git a/libc-bottom-half/headers/public/__struct_sockaddr_in.h b/libc-bottom-half/headers/public/__struct_sockaddr_in.h
index 73dc5c6..5d4ce51 100644
--- a/libc-bottom-half/headers/public/__struct_sockaddr_in.h
+++ b/libc-bottom-half/headers/public/__struct_sockaddr_in.h
@@ -1,15 +1,12 @@
#ifndef __wasilibc___struct_sockaddr_in_h
#define __wasilibc___struct_sockaddr_in_h
-#define __need_STDDEF_H_misc
-#include <stddef.h>
-
#include <__typedef_sa_family_t.h>
#include <__typedef_in_port_t.h>
#include <__struct_in_addr.h>
struct sockaddr_in {
- _Alignas(max_align_t) sa_family_t sin_family;
+ __attribute__((aligned(__BIGGEST_ALIGNMENT__))) sa_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
};
diff --git a/libc-bottom-half/headers/public/__struct_sockaddr_in6.h b/libc-bottom-half/headers/public/__struct_sockaddr_in6.h
index a220f91..98703dc 100644
--- a/libc-bottom-half/headers/public/__struct_sockaddr_in6.h
+++ b/libc-bottom-half/headers/public/__struct_sockaddr_in6.h
@@ -1,15 +1,12 @@
#ifndef __wasilibc___struct_sockaddr_in6_h
#define __wasilibc___struct_sockaddr_in6_h
-#define __need_STDDEF_H_misc
-#include <stddef.h>
-
#include <__typedef_sa_family_t.h>
#include <__typedef_in_port_t.h>
#include <__struct_in6_addr.h>
struct sockaddr_in6 {
- _Alignas(max_align_t) sa_family_t sin6_family;
+ __attribute__((aligned(__BIGGEST_ALIGNMENT__))) sa_family_t sin6_family;
in_port_t sin6_port;
unsigned sin6_flowinfo;
struct in6_addr sin6_addr;
diff --git a/libc-bottom-half/headers/public/__struct_sockaddr_storage.h b/libc-bottom-half/headers/public/__struct_sockaddr_storage.h
index 1ae26a7..b4ebad2 100644
--- a/libc-bottom-half/headers/public/__struct_sockaddr_storage.h
+++ b/libc-bottom-half/headers/public/__struct_sockaddr_storage.h
@@ -1,13 +1,10 @@
#ifndef __wasilibc___struct_sockaddr_storage_h
#define __wasilibc___struct_sockaddr_storage_h
-#define __need_STDDEF_H_misc
-#include <stddef.h>
-
#include <__typedef_sa_family_t.h>
struct sockaddr_storage {
- _Alignas(max_align_t) sa_family_t ss_family;
+ __attribute__((aligned(__BIGGEST_ALIGNMENT__))) sa_family_t ss_family;
char __ss_data[32];
};
diff --git a/libc-bottom-half/headers/public/__struct_sockaddr_un.h b/libc-bottom-half/headers/public/__struct_sockaddr_un.h
index a5be6e5..6371194 100644
--- a/libc-bottom-half/headers/public/__struct_sockaddr_un.h
+++ b/libc-bottom-half/headers/public/__struct_sockaddr_un.h
@@ -1,13 +1,10 @@
#ifndef __wasilibc___struct_sockaddr_un_h
#define __wasilibc___struct_sockaddr_un_h
-#define __need_STDDEF_H_misc
-#include <stddef.h>
-
#include <__typedef_sa_family_t.h>
struct sockaddr_un {
- _Alignas(max_align_t) sa_family_t sun_family;
+ __attribute__((aligned(__BIGGEST_ALIGNMENT__))) sa_family_t sun_family;
};
#endif
diff --git a/libc-bottom-half/headers/public/wasi/api.h b/libc-bottom-half/headers/public/wasi/api.h
index 1ab7699..45a6506 100644
--- a/libc-bottom-half/headers/public/wasi/api.h
+++ b/libc-bottom-half/headers/public/wasi/api.h
@@ -2099,7 +2099,7 @@ __wasi_errno_t __wasi_sock_shutdown(
*
* @see https://github.com/WebAssembly/wasi-threads/#readme
*/
-__wasi_errno_t __wasi_thread_spawn(
+int32_t __wasi_thread_spawn(
/**
* A pointer to an opaque struct to be passed to the module's entry
* function.
diff --git a/libc-bottom-half/sources/__wasilibc_real.c b/libc-bottom-half/sources/__wasilibc_real.c
index 855a2c6..d2e6b71 100644
--- a/libc-bottom-half/sources/__wasilibc_real.c
+++ b/libc-bottom-half/sources/__wasilibc_real.c
@@ -665,8 +665,7 @@ int32_t __imported_wasi_thread_spawn(int32_t arg0) __attribute__((
__import_name__("thread_spawn")
));
-__wasi_errno_t __wasi_thread_spawn(void* start_arg) {
- int32_t ret = __imported_wasi_thread_spawn((int32_t) start_arg);
- return (uint16_t) ret;
+int32_t __wasi_thread_spawn(void* start_arg) {
+ return __imported_wasi_thread_spawn((int32_t) start_arg);
}
#endif
diff --git a/libc-bottom-half/sources/posix.c b/libc-bottom-half/sources/posix.c
index 35dd99b..b3e59ec 100644
--- a/libc-bottom-half/sources/posix.c
+++ b/libc-bottom-half/sources/posix.c
@@ -58,9 +58,9 @@ int __wasilibc_open_nomode(const char *path, int oflag) {
char *relative_path;
int dirfd = find_relpath(path, &relative_path);
- // If we can't find a preopen for it, indicate that we lack capabilities.
+ // If we can't find a preopen for it, fail as if we can't find the path.
if (dirfd == -1) {
- errno = ENOTCAPABLE;
+ errno = ENOENT;
return -1;
}
@@ -71,9 +71,9 @@ int access(const char *path, int amode) {
char *relative_path;
int dirfd = find_relpath(path, &relative_path);
- // If we can't find a preopen for it, indicate that we lack capabilities.
+ // If we can't find a preopen for it, fail as if we can't find the path.
if (dirfd == -1) {
- errno = ENOTCAPABLE;
+ errno = ENOENT;
return -1;
}
@@ -88,9 +88,9 @@ ssize_t readlink(
char *relative_path;
int dirfd = find_relpath(path, &relative_path);
- // If we can't find a preopen for it, indicate that we lack capabilities.
+ // If we can't find a preopen for it, fail as if we can't find the path.
if (dirfd == -1) {
- errno = ENOTCAPABLE;
+ errno = ENOENT;
return -1;
}
@@ -101,9 +101,9 @@ int stat(const char *restrict path, struct stat *restrict buf) {
char *relative_path;
int dirfd = find_relpath(path, &relative_path);
- // If we can't find a preopen for it, indicate that we lack capabilities.
+ // If we can't find a preopen for it, fail as if we can't find the path.
if (dirfd == -1) {
- errno = ENOTCAPABLE;
+ errno = ENOENT;
return -1;
}
@@ -114,9 +114,9 @@ int lstat(const char *restrict path, struct stat *restrict buf) {
char *relative_path;
int dirfd = find_relpath(path, &relative_path);
- // If we can't find a preopen for it, indicate that we lack capabilities.
+ // If we can't find a preopen for it, fail as if we can't find the path.
if (dirfd == -1) {
- errno = ENOTCAPABLE;
+ errno = ENOENT;
return -1;
}
@@ -127,9 +127,9 @@ int utime(const char *path, const struct utimbuf *times) {
char *relative_path;
int dirfd = find_relpath(path, &relative_path);
- // If we can't find a preopen for it, indicate that we lack capabilities.
+ // If we can't find a preopen for it, fail as if we can't find the path.
if (dirfd == -1) {
- errno = ENOTCAPABLE;
+ errno = ENOENT;
return -1;
}
@@ -147,9 +147,9 @@ int utimes(const char *path, const struct timeval times[2]) {
char *relative_path;
int dirfd = find_relpath(path, &relative_path);
- // If we can't find a preopen for it, indicate that we lack capabilities.
+ // If we can't find a preopen for it, fail as if we can't find the path.
if (dirfd == -1) {
- errno = ENOTCAPABLE;
+ errno = ENOENT;
return -1;
}
@@ -169,9 +169,9 @@ int unlink(const char *path) {
char *relative_path;
int dirfd = find_relpath(path, &relative_path);
- // If we can't find a preopen for it, indicate that we lack capabilities.
+ // If we can't find a preopen for it, fail as if we can't find the path.
if (dirfd == -1) {
- errno = ENOTCAPABLE;
+ errno = ENOENT;
return -1;
}
@@ -185,9 +185,9 @@ int rmdir(const char *path) {
char *relative_path;
int dirfd = find_relpath(path, &relative_path);
- // If we can't find a preopen for it, indicate that we lack capabilities.
+ // If we can't find a preopen for it, fail as if we can't find the path.
if (dirfd == -1) {
- errno = ENOTCAPABLE;
+ errno = ENOENT;
return -1;
}
@@ -198,21 +198,21 @@ int remove(const char *path) {
char *relative_path;
int dirfd = find_relpath(path, &relative_path);
- // If we can't find a preopen for it, indicate that we lack capabilities.
+ // If we can't find a preopen for it, fail as if we can't find the path.
if (dirfd == -1) {
- errno = ENOTCAPABLE;
+ errno = ENOENT;
return -1;
}
// First try to remove it as a file.
int r = __wasilibc_nocwd___wasilibc_unlinkat(dirfd, relative_path);
- if (r != 0 && (errno == EISDIR || errno == ENOTCAPABLE)) {
+ if (r != 0 && (errno == EISDIR || errno == ENOENT)) {
// That failed, but it might be a directory.
r = __wasilibc_nocwd___wasilibc_rmdirat(dirfd, relative_path);
// If it isn't a directory, we lack capabilities to remove it as a file.
if (errno == ENOTDIR)
- errno = ENOTCAPABLE;
+ errno = ENOENT;
}
return r;
}
@@ -221,9 +221,9 @@ int mkdir(const char *path, mode_t mode) {
char *relative_path;
int dirfd = find_relpath(path, &relative_path);
- // If we can't find a preopen for it, indicate that we lack capabilities.
+ // If we can't find a preopen for it, fail as if we can't find the path.
if (dirfd == -1) {
- errno = ENOTCAPABLE;
+ errno = ENOENT;
return -1;
}
@@ -234,9 +234,9 @@ DIR *opendir(const char *dirname) {
char *relative_path;
int dirfd = find_relpath(dirname, &relative_path);
- // If we can't find a preopen for it, indicate that we lack capabilities.
+ // If we can't find a preopen for it, fail as if we can't find the path.
if (dirfd == -1) {
- errno = ENOTCAPABLE;
+ errno = ENOENT;
return NULL;
}
@@ -252,9 +252,9 @@ int scandir(
char *relative_path;
int dirfd = find_relpath(dir, &relative_path);
- // If we can't find a preopen for it, indicate that we lack capabilities.
+ // If we can't find a preopen for it, fail as if we can't find the path.
if (dirfd == -1) {
- errno = ENOTCAPABLE;
+ errno = ENOENT;
return -1;
}
@@ -265,9 +265,9 @@ int symlink(const char *target, const char *linkpath) {
char *relative_path;
int dirfd = find_relpath(linkpath, &relative_path);
- // If we can't find a preopen for it, indicate that we lack capabilities.
+ // If we can't find a preopen for it, fail as if we can't find the path.
if (dirfd == -1) {
- errno = ENOTCAPABLE;
+ errno = ENOENT;
return -1;
}
@@ -287,8 +287,8 @@ int link(const char *old, const char *new) {
new_dirfd, new_relative_path, 0);
}
- // We couldn't find a preopen for it; indicate that we lack capabilities.
- errno = ENOTCAPABLE;
+ // We couldn't find a preopen for it; fail as if we can't find the path.
+ errno = ENOENT;
return -1;
}
@@ -305,8 +305,8 @@ int rename(const char *old, const char *new) {
new_dirfd, new_relative_path);
}
- // We couldn't find a preopen for it; indicate that we lack capabilities.
- errno = ENOTCAPABLE;
+ // We couldn't find a preopen for it; fail as if we can't find the path.
+ errno = ENOENT;
return -1;
}
@@ -317,9 +317,9 @@ __wasilibc_access(const char *path, int mode, int flags)
char *relative_path;
int dirfd = find_relpath(path, &relative_path);
- // If we can't find a preopen for it, indicate that we lack capabilities.
+ // If we can't find a preopen for it, fail as if we can't find the path.
if (dirfd == -1) {
- errno = ENOTCAPABLE;
+ errno = ENOENT;
return -1;
}
@@ -334,9 +334,9 @@ __wasilibc_utimens(const char *path, const struct timespec times[2], int flags)
char *relative_path;
int dirfd = find_relpath(path, &relative_path);
- // If we can't find a preopen for it, indicate that we lack capabilities.
+ // If we can't find a preopen for it, fail as if we can't find the path.
if (dirfd == -1) {
- errno = ENOTCAPABLE;
+ errno = ENOENT;
return -1;
}
@@ -351,9 +351,9 @@ __wasilibc_stat(const char *__restrict path, struct stat *__restrict st, int fla
char *relative_path;
int dirfd = find_relpath(path, &relative_path);
- // If we can't find a preopen for it, indicate that we lack capabilities.
+ // If we can't find a preopen for it, fail as if we can't find the path.
if (dirfd == -1) {
- errno = ENOTCAPABLE;
+ errno = ENOENT;
return -1;
}
@@ -369,9 +369,9 @@ __wasilibc_link(const char *oldpath, const char *newpath, int flags)
int old_dirfd = find_relpath(oldpath, &old_relative_path);
int new_dirfd = find_relpath(newpath, &new_relative_path);
- // If we can't find a preopen for it, indicate that we lack capabilities.
+ // If we can't find a preopen for it, fail as if we can't find the path.
if (old_dirfd == -1 || new_dirfd == -1) {
- errno = ENOTCAPABLE;
+ errno = ENOENT;
return -1;
}
@@ -387,9 +387,9 @@ __wasilibc_link_oldat(int olddirfd, const char *oldpath, const char *newpath, in
char *new_relative_path;
int new_dirfd = find_relpath(newpath, &new_relative_path);
- // If we can't find a preopen for it, indicate that we lack capabilities.
+ // If we can't find a preopen for it, fail as if we can't find the path.
if (new_dirfd == -1) {
- errno = ENOTCAPABLE;
+ errno = ENOENT;
return -1;
}
@@ -405,9 +405,9 @@ __wasilibc_link_newat(const char *oldpath, int newdirfd, const char *newpath, in
char *old_relative_path;
int old_dirfd = find_relpath(oldpath, &old_relative_path);
- // If we can't find a preopen for it, indicate that we lack capabilities.
+ // If we can't find a preopen for it, fail as if we can't find the path.
if (old_dirfd == -1) {
- errno = ENOTCAPABLE;
+ errno = ENOENT;
return -1;
}
@@ -423,9 +423,9 @@ __wasilibc_rename_oldat(int fromdirfd, const char *from, const char *to)
char *to_relative_path;
int to_dirfd = find_relpath(to, &to_relative_path);
- // If we can't find a preopen for it, indicate that we lack capabilities.
+ // If we can't find a preopen for it, fail as if we can't find the path.
if (to_dirfd == -1) {
- errno = ENOTCAPABLE;
+ errno = ENOENT;
return -1;
}
@@ -439,9 +439,9 @@ __wasilibc_rename_newat(const char *from, int todirfd, const char *to)
char *from_relative_path;
int from_dirfd = find_relpath(from, &from_relative_path);
- // If we can't find a preopen for it, indicate that we lack capabilities.
+ // If we can't find a preopen for it, fail as if we can't find the path.
if (from_dirfd == -1) {
- errno = ENOTCAPABLE;
+ errno = ENOENT;
return -1;
}
diff --git a/libc-top-half/musl/include/pthread.h b/libc-top-half/musl/include/pthread.h
index 01fe5f2..b14fe82 100644
--- a/libc-top-half/musl/include/pthread.h
+++ b/libc-top-half/musl/include/pthread.h
@@ -85,7 +85,9 @@ extern "C" {
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 **);
#ifdef __GNUC__
diff --git a/libc-top-half/musl/include/unistd.h b/libc-top-half/musl/include/unistd.h
index b5cb5c6..0be83e3 100644
--- a/libc-top-half/musl/include/unistd.h
+++ b/libc-top-half/musl/include/unistd.h
@@ -336,7 +336,9 @@ pid_t gettid(void);
#endif
#define _POSIX_VDISABLE 0
+#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
#define _POSIX_THREADS _POSIX_VERSION
+#endif
#define _POSIX_THREAD_PROCESS_SHARED _POSIX_VERSION
#define _POSIX_THREAD_SAFE_FUNCTIONS _POSIX_VERSION
#define _POSIX_THREAD_ATTR_STACKADDR _POSIX_VERSION
diff --git a/libc-top-half/musl/src/env/__init_tls.c b/libc-top-half/musl/src/env/__init_tls.c
index ee785bc..ece8d24 100644
--- a/libc-top-half/musl/src/env/__init_tls.c
+++ b/libc-top-half/musl/src/env/__init_tls.c
@@ -16,6 +16,43 @@
volatile int __thread_list_lock;
#ifndef __wasilibc_unmodified_upstream
+
+/* These symbols are generated by wasm-ld. __stack_high/__stack_low
+ * symbols are only available in LLVM v16 and higher, therefore they're
+ * defined as weak symbols and if not available, __heap_base/__data_end
+ * is used instead.
+ *
+ * TODO: remove usage of __heap_base/__data_end for stack size calculation
+ * once we drop support for LLVM v15 and older.
+ */
+extern unsigned char __heap_base;
+extern unsigned char __data_end;
+extern unsigned char __global_base;
+extern weak unsigned char __stack_high;
+extern weak unsigned char __stack_low;
+
+static inline void setup_default_stack_size()
+{
+ ptrdiff_t stack_size;
+
+ if (&__stack_high)
+ stack_size = &__stack_high - &__stack_low;
+ else {
+ unsigned char *sp;
+ __asm__(
+ ".globaltype __stack_pointer, i32\n"
+ "global.get __stack_pointer\n"
+ "local.set %0\n"
+ : "=r"(sp));
+ stack_size = sp > &__global_base ? &__heap_base - &__data_end : (ptrdiff_t)&__global_base;
+ }
+
+ if (stack_size > __default_stacksize)
+ __default_stacksize =
+ stack_size < DEFAULT_STACK_MAX ?
+ stack_size : DEFAULT_STACK_MAX;
+}
+
void __wasi_init_tp() {
__init_tp((void *)__get_tp());
}
@@ -31,6 +68,20 @@ int __init_tp(void *p)
if (!r) libc.can_do_threads = 1;
td->detach_state = DT_JOINABLE;
td->tid = __syscall(SYS_set_tid_address, &__thread_list_lock);
+#else
+ setup_default_stack_size();
+ td->detach_state = DT_JOINABLE;
+ /*
+ * Initialize the TID to a value which doesn't conflict with
+ * host-allocated TIDs, so that TID-based locks can work.
+ *
+ * Note:
+ * - Host-allocated TIDs range from 1 to 0x1fffffff. (inclusive)
+ * - __tl_lock and __lockfile uses TID 0 as "unlocked".
+ * - __lockfile relies on the fact the most significant two bits
+ * of TIDs are 0.
+ */
+ td->tid = 0x3fffffff;
#endif
td->locale = &libc.global_locale;
td->robust_list.head = &td->robust_list.head;
diff --git a/libc-top-half/musl/src/include/pthread.h b/libc-top-half/musl/src/include/pthread.h
index 7167d3e..0aba813 100644
--- a/libc-top-half/musl/src/include/pthread.h
+++ b/libc-top-half/musl/src/include/pthread.h
@@ -7,7 +7,9 @@ hidden int __pthread_once(pthread_once_t *, void (*)(void));
hidden void __pthread_testcancel(void);
hidden int __pthread_setcancelstate(int, int *);
hidden int __pthread_create(pthread_t *restrict, const pthread_attr_t *restrict, void *(*)(void *), void *restrict);
+#ifdef __wasilibc_unmodified_upstream
hidden _Noreturn void __pthread_exit(void *);
+#endif
hidden int __pthread_join(pthread_t, void **);
hidden int __pthread_mutex_lock(pthread_mutex_t *);
hidden int __pthread_mutex_trylock(pthread_mutex_t *);
diff --git a/libc-top-half/musl/src/internal/pthread_impl.h b/libc-top-half/musl/src/internal/pthread_impl.h
index a6d188b..1e7b974 100644
--- a/libc-top-half/musl/src/internal/pthread_impl.h
+++ b/libc-top-half/musl/src/internal/pthread_impl.h
@@ -216,7 +216,12 @@ extern hidden unsigned __default_stacksize;
extern hidden unsigned __default_guardsize;
#define DEFAULT_STACK_SIZE 131072
+#ifdef __wasilibc_unmodified_upstream
#define DEFAULT_GUARD_SIZE 8192
+#else
+/* guard doesn't make much sense without mprotect. */
+#define DEFAULT_GUARD_SIZE 0
+#endif
#define DEFAULT_STACK_MAX (8<<20)
#define DEFAULT_GUARD_MAX (1<<20)
diff --git a/libc-top-half/musl/src/thread/__wait.c b/libc-top-half/musl/src/thread/__wait.c
index c0e4aac..7ffa987 100644
--- a/libc-top-half/musl/src/thread/__wait.c
+++ b/libc-top-half/musl/src/thread/__wait.c
@@ -48,7 +48,7 @@ void __wait(volatile int *addr, volatile int *waiters, int val, int priv)
__syscall(SYS_futex, addr, FUTEX_WAIT|priv, val, 0) != -ENOSYS
|| __syscall(SYS_futex, addr, FUTEX_WAIT, val, 0);
#else
- __wasilibc_futex_wait(addr, FUTEX_WAIT, val, 0);
+ __wasilibc_futex_wait(addr, FUTEX_WAIT, val, -1);
#endif
}
if (waiters) a_dec(waiters);
diff --git a/libc-top-half/musl/src/thread/pthread_attr_get.c b/libc-top-half/musl/src/thread/pthread_attr_get.c
index f12ff44..0ac251c 100644
--- a/libc-top-half/musl/src/thread/pthread_attr_get.c
+++ b/libc-top-half/musl/src/thread/pthread_attr_get.c
@@ -17,6 +17,7 @@ int pthread_attr_getinheritsched(const pthread_attr_t *restrict a, int *restrict
return 0;
}
+#ifdef __wasilibc_unmodified_upstream /* WASI has no CPU scheduling support. */
int pthread_attr_getschedparam(const pthread_attr_t *restrict a, struct sched_param *restrict param)
{
param->sched_priority = a->_a_prio;
@@ -28,6 +29,7 @@ int pthread_attr_getschedpolicy(const pthread_attr_t *restrict a, int *restrict
*policy = a->_a_policy;
return 0;
}
+#endif
int pthread_attr_getscope(const pthread_attr_t *restrict a, int *restrict scope)
{
@@ -56,11 +58,13 @@ int pthread_barrierattr_getpshared(const pthread_barrierattr_t *restrict a, int
return 0;
}
+#ifdef __wasilibc_unmodified_upstream /* Forward declaration of WASI's `__clockid` type. */
int pthread_condattr_getclock(const pthread_condattr_t *restrict a, clockid_t *restrict clk)
{
*clk = a->__attr & 0x7fffffff;
return 0;
}
+#endif
int pthread_condattr_getpshared(const pthread_condattr_t *restrict a, int *restrict pshared)
{
diff --git a/libc-top-half/musl/src/thread/pthread_barrier_destroy.c b/libc-top-half/musl/src/thread/pthread_barrier_destroy.c
index 4ce0b2e..a347a2c 100644
--- a/libc-top-half/musl/src/thread/pthread_barrier_destroy.c
+++ b/libc-top-half/musl/src/thread/pthread_barrier_destroy.c
@@ -9,7 +9,9 @@ int pthread_barrier_destroy(pthread_barrier_t *b)
while ((v = b->_b_lock) & INT_MAX)
__wait(&b->_b_lock, 0, v, 0);
}
+#ifdef __wasilibc_unmodified_upstream /* WASI does not understand processes or locking between them. */
__vm_wait();
+#endif
}
return 0;
}
diff --git a/libc-top-half/musl/src/thread/pthread_barrier_wait.c b/libc-top-half/musl/src/thread/pthread_barrier_wait.c
index cc2a8bb..0891b71 100644
--- a/libc-top-half/musl/src/thread/pthread_barrier_wait.c
+++ b/libc-top-half/musl/src/thread/pthread_barrier_wait.c
@@ -23,7 +23,9 @@ static int pshared_barrier_wait(pthread_barrier_t *b)
__wait(&b->_b_count, &b->_b_waiters2, v, 0);
}
+#ifdef __wasilibc_unmodified_upstream /* WASI does not understand processes or locking between them. */
__vm_lock();
+#endif
/* Ensure all threads have a vm lock before proceeding */
if (a_fetch_add(&b->_b_count, -1)==1-limit) {
@@ -44,7 +46,9 @@ static int pshared_barrier_wait(pthread_barrier_t *b)
if (v==INT_MIN+1 || (v==1 && w))
__wake(&b->_b_lock, 1, 0);
+#ifdef __wasilibc_unmodified_upstream /* WASI does not understand processes or locking between them. */
__vm_unlock();
+#endif
return ret;
}
@@ -84,8 +88,12 @@ int pthread_barrier_wait(pthread_barrier_t *b)
a_spin();
a_inc(&inst->finished);
while (inst->finished == 1)
+#ifdef __wasilibc_unmodified_upstream
__syscall(SYS_futex,&inst->finished,FUTEX_WAIT|FUTEX_PRIVATE,1,0) != -ENOSYS
|| __syscall(SYS_futex,&inst->finished,FUTEX_WAIT,1,0);
+#else
+ __futexwait(&inst->finished, 1, 0);
+#endif
return PTHREAD_BARRIER_SERIAL_THREAD;
}
diff --git a/libc-top-half/musl/src/thread/pthread_create.c b/libc-top-half/musl/src/thread/pthread_create.c
index 1aa7be7..676e2cc 100644
--- a/libc-top-half/musl/src/thread/pthread_create.c
+++ b/libc-top-half/musl/src/thread/pthread_create.c
@@ -60,7 +60,11 @@ void __tl_sync(pthread_t td)
if (tl_lock_waiters) __wake(&__thread_list_lock, 1, 0);
}
+#ifdef __wasilibc_unmodified_upstream
_Noreturn void __pthread_exit(void *result)
+#else
+static void __pthread_exit(void *result)
+#endif
{
pthread_t self = __pthread_self();
sigset_t set;
@@ -191,7 +195,7 @@ _Noreturn void __pthread_exit(void *result)
__tl_unlock();
free(self->map_base);
// Can't use `exit()` here, because it is too high level
- for (;;) __wasi_proc_exit(0);
+ return;
}
#endif
@@ -212,7 +216,6 @@ _Noreturn void __pthread_exit(void *result)
// do it manually here
__tl_unlock();
// Can't use `exit()` here, because it is too high level
- for (;;) __wasi_proc_exit(0);
#endif
}
@@ -235,9 +238,14 @@ struct start_args {
volatile int control;
unsigned long sig_mask[_NSIG/8/sizeof(long)];
#else
+ /*
+ * Note: the offset of the "stack" and "tls_base" members
+ * in this structure is hardcoded in wasi_thread_start.
+ */
+ void *stack;
+ void *tls_base;
void *(*start_func)(void *);
void *start_arg;
- void *tls_base;
#endif
};
@@ -271,32 +279,41 @@ static int start_c11(void *p)
return 0;
}
#else
-__attribute__((export_name("wasi_thread_start")))
-_Noreturn void wasi_thread_start(int tid, void *p)
+
+/*
+ * We want to ensure wasi_thread_start is linked whenever
+ * pthread_create is used. The following reference is to ensure that.
+ * Otherwise, the linker doesn't notice the dependency because
+ * wasi_thread_start is used indirectly via a wasm export.
+ */
+void wasi_thread_start(int tid, void *p);
+hidden void *__dummy_reference = wasi_thread_start;
+
+hidden void __wasi_thread_start_C(int tid, void *p)
{
struct start_args *args = p;
- __asm__(".globaltype __tls_base, i32\n"
- "local.get %0\n"
- "global.set __tls_base\n"
- :: "r"(args->tls_base));
pthread_t self = __pthread_self();
// Set the thread ID (TID) on the pthread structure. The TID is stored
// atomically since it is also stored by the parent thread; this way,
// whichever thread (parent or child) reaches this point first can proceed
// without waiting.
atomic_store((atomic_int *) &(self->tid), tid);
- // Set the stack pointer.
- __asm__(".globaltype __stack_pointer, i32\n"
- "local.get %0\n"
- "global.set __stack_pointer\n"
- :: "r"(self->stack));
// Execute the user's start function.
- int (*start)(void*) = (int(*)(void*)) args->start_func;
- __pthread_exit((void *)(uintptr_t)start(args->start_arg));
+ __pthread_exit(args->start_func(args->start_arg));
}
#endif
+#ifdef __wasilibc_unmodified_upstream
#define ROUND(x) (((x)+PAGE_SIZE-1)&-PAGE_SIZE)
+#else
+/*
+ * As we allocate stack with malloc() instead of mmap/mprotect,
+ * there is no point to round it up to PAGE_SIZE.
+ * Instead, round up to a sane alignment.
+ * Note: PAGE_SIZE is rather big on WASM. (65536)
+ */
+#define ROUND(x) (((x)+16-1)&-16)
+#endif
/* pthread_key_create.c overrides this */
static volatile size_t dummy = 0;
@@ -484,6 +501,7 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att
/* Correct the stack size */
new->stack_size = stack - stack_limit;
+ args->stack = new->stack; /* just for convenience of asm trampoline */
args->start_func = entry;
args->start_arg = arg;
args->tls_base = (void*)new_tls_base;
@@ -561,5 +579,7 @@ fail:
return EAGAIN;
}
+#ifdef __wasilibc_unmodified_upstream
weak_alias(__pthread_exit, pthread_exit);
+#endif
weak_alias(__pthread_create, pthread_create);
diff --git a/libc-top-half/musl/src/thread/wasm32/wasi_thread_start.s b/libc-top-half/musl/src/thread/wasm32/wasi_thread_start.s
new file mode 100644
index 0000000..0fe9854
--- /dev/null
+++ b/libc-top-half/musl/src/thread/wasm32/wasi_thread_start.s
@@ -0,0 +1,31 @@
+ .text
+
+ .export_name wasi_thread_start, wasi_thread_start
+
+ .globaltype __stack_pointer, i32
+ .globaltype __tls_base, i32
+ .functype __wasi_thread_start_C (i32, i32) -> ()
+
+ .hidden wasi_thread_start
+ .globl wasi_thread_start
+ .type wasi_thread_start,@function
+
+wasi_thread_start:
+ .functype wasi_thread_start (i32, i32) -> ()
+
+ # Set up the minimum C environment.
+ # Note: offsetof(start_arg, stack) == 0
+ local.get 1 # start_arg
+ i32.load 0 # stack
+ global.set __stack_pointer
+
+ local.get 1 # start_arg
+ i32.load 4 # tls_base
+ global.set __tls_base
+
+ # Make the C function do the rest of work.
+ local.get 0 # tid
+ local.get 1 # start_arg
+ call __wasi_thread_start_C
+
+ end_function