Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix make THREAD_MODEL=posix #311

Merged
merged 24 commits into from
Aug 9, 2022
Merged
Changes from 19 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
626362a
Fixes for the THREAD_MODEL=posix build
sbc100 Jul 18, 2022
384da08
Fix expected symbols from previous commit
abrown Jul 26, 2022
0e7956a
Enable `lock` in `random.c` when threads are enabled
abrown Jul 26, 2022
2ab390a
Disable `aio.h` when compiling for threads
abrown Jul 26, 2022
b2f40de
Specify the TLS model until LLVM 15 is released
abrown Jul 27, 2022
9d3b1e4
Rename `__wasi_libc_pthread_self` to `__wasilibc_pthread_self`
abrown Jul 28, 2022
04f6c3f
Add different sets of expected output based on THREAD_MODEL
abrown Jul 28, 2022
d2d3e5c
Re-add trailing whitespace to `predefined-macros.txt`
abrown Jul 28, 2022
83a80a7
Protect `preopens.c` against concurrent access
abrown Jul 28, 2022
247bfeb
Only build thread-capable wasi-libc on latest version of Clang
abrown Jul 28, 2022
0acb15f
Use `thrd_sleep` from MUSL instead of aliasing `nanosleep`
abrown Jul 28, 2022
240c35f
Define `pthread_setcancelstate` in `THREAD_MODEL=posix` builds
abrown Jul 28, 2022
e74d263
Define a Wasm global to store `pthread_self`
abrown Aug 1, 2022
0878de7
Remove `g_needs_dynamic_alloc` global
abrown Aug 1, 2022
db89382
Document the state of pthread support
abrown Aug 1, 2022
53a4091
review: de-duplicate symbols based on #314
abrown Aug 1, 2022
6539705
review: only define `__wasilibc_cwd_{un}lock` when needed
abrown Aug 1, 2022
3784170
review: add #ifdefs to `__pthread_setcancelstate`
abrown Aug 1, 2022
2339e18
review: add additional #ifdefs to `pthread_self.c`
abrown Aug 1, 2022
80d9a43
review: put lock definition behind #ifdef _REENTRANT
abrown Aug 8, 2022
d5bf750
review: remove pthread_setcancelstate.c
abrown Aug 8, 2022
eb50290
review: re-fix indentation
abrown Aug 8, 2022
1d6a27c
review: alias __clock_nanosleep in bottom half
abrown Aug 8, 2022
831de19
review: remove extra line
abrown Aug 9, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -66,6 +66,14 @@ jobs:
name: ${{ format( 'sysroot-{0}.tgz', matrix.os) }}
path: sysroot

- name: Build libc + threads
# Only build the thread-capable wasi-libc in the latest supported Clang
# version; the earliest version does not have all necessary builtins
# (e.g., `__builtin_wasm_memory_atomic_notify`).
if: matrix.clang_version != '10.0.0'
shell: bash
run: make -j4 THREAD_MODEL=posix

# Disable the headerstest job for now, while WASI transitions from the
# witx snapshots to wit proposals, and we have a few manual edits to the
# generated header to make life easier for folks.
22 changes: 17 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ EXTRA_CFLAGS ?= -O2 -DNDEBUG
SYSROOT ?= $(CURDIR)/sysroot
# A directory to install to for "make install".
INSTALL_DIR ?= /usr/local
# single or posix
# single or posix; note that pthread support is still a work-in-progress.
THREAD_MODEL ?= single
# dlmalloc or none
MALLOC_IMPL ?= dlmalloc
@@ -146,6 +146,7 @@ LIBC_TOP_HALF_MUSL_SOURCES = \
unistd/posix_close.c \
stat/futimesat.c \
legacy/getpagesize.c \
thread/thrd_sleep.c \
) \
$(filter-out %/procfdname.c %/syscall.c %/syscall_ret.c %/vdso.c %/version.c, \
$(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/internal/*.c)) \
@@ -184,6 +185,14 @@ LIBC_TOP_HALF_MUSL_SOURCES = \
%/cimagf.c %/cimag.c %cimagl.c, \
$(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/complex/*.c)) \
$(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/crypt/*.c)

# Add some additional sources when threads are enabled.
ifeq ($(THREAD_MODEL), posix)
LIBC_TOP_HALF_MUSL_SOURCES += $(addprefix $(LIBC_TOP_HALF_MUSL_SRC_DIR)/, \
thread/pthread_setcancelstate.c \
)
endif

MUSL_PRINTSCAN_SOURCES = \
$(LIBC_TOP_HALF_MUSL_SRC_DIR)/internal/floatscan.c \
$(LIBC_TOP_HALF_MUSL_SRC_DIR)/stdio/vfprintf.c \
@@ -226,7 +235,9 @@ ifeq ($(THREAD_MODEL), single)
CFLAGS += -mthread-model single
endif
ifeq ($(THREAD_MODEL), posix)
CFLAGS += -mthread-model posix -pthread
# Specify the tls-model until LLVM 15 is released (which should contain
# https://reviews.llvm.org/D130053).
CFLAGS += -mthread-model posix -pthread -ftls-model=local-exec
endif

# Expose the public headers to the implementation. We use `-isystem` for
@@ -355,11 +366,12 @@ MUSL_OMIT_HEADERS += \
"netinet/ether.h" \
"sys/timerfd.h" \
"libintl.h" \
"sys/sysmacros.h"
"sys/sysmacros.h" \
"aio.h"

ifeq ($(THREAD_MODEL), single)
# Remove headers not supported in single-threaded mode.
MUSL_OMIT_HEADERS += "aio.h" "pthread.h"
MUSL_OMIT_HEADERS += "pthread.h"
endif

default: finish
@@ -594,7 +606,7 @@ check-symbols: startup_files libc

# 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)" "$(SYSROOT_SHARE)"
diff -wur "$(CURDIR)/expected/$(MULTIARCH_TRIPLE)/$(THREAD_MODEL)" "$(SYSROOT_SHARE)"

install: finish
mkdir -p "$(INSTALL_DIR)"
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -7,7 +7,8 @@ environment variables, program startup, and many other APIs.

WASI Libc is sufficiently stable and usable for many purposes, as most of the
POSIX-compatible APIs are stable, though it is continuing to evolve to better
align with wasm and WASI.
align with wasm and WASI. For example, pthread support is still a work in
progress.

## Usage

1,211 changes: 1,211 additions & 0 deletions expected/wasm32-wasi/posix/defined-symbols.txt

Large diffs are not rendered by default.

171 changes: 171 additions & 0 deletions expected/wasm32-wasi/posix/include-all.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
#include <__errno.h>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The naming of these new files seems a little odd.. since posix doesn't just mean threads. I would hope we could use pthreads here (or something like that), but that might mean changing the way we trigger the build. Something like make WITH_PTHREADS=1?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we do a follow-up to that later? It's quite convenient and clear to use $(THREAD_MODEL) throughout the Makefile...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather not rename these expectations file just to rename them again later.

Can you find a way to at least leave the existing files in place?

How about something like this:

#if THREAD_MODULE == posix
EXPECTATION_SUBDIR = '/pthreads'
#else
EXPECTATION_SUBDIR = ''
#endif

I know that isn't Makefile syntax but you get the idea. This way the old files stay in place, and the new files have more meaningful names.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I tried this and the issue is that we are using diff recursively so a structure like the following doesn't really work:

- expected
--- wasm-32-wasi
----- defined-symbols.txt
----- ...
----- posix (or pthreads)
------- defined-symbols.txt
------- ...

The posix/pthreads directory gets in the way of the diff.

Copy link
Collaborator Author

@abrown abrown Aug 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like we'll need two separate directory trees to diff with. Here are some options:
a. append /pthreads or /no-pthreads to the expected directory path; this at least means that the naming is a bit more accurate
b. append something, e.g., pthreads, to the target, so we would diff against either expected/wasm32-wasi or expected/wasm32-wasi-pthreads

#include <__errno_values.h>
#include <__fd_set.h>
#include <__function___isatty.h>
#include <__functions_malloc.h>
#include <__functions_memcpy.h>
#include <__header_dirent.h>
#include <__header_fcntl.h>
#include <__header_inttypes.h>
#include <__header_netinet_in.h>
#include <__header_poll.h>
#include <__header_stdlib.h>
#include <__header_string.h>
#include <__header_sys_ioctl.h>
#include <__header_sys_resource.h>
#include <__header_sys_socket.h>
#include <__header_sys_stat.h>
#include <__header_time.h>
#include <__header_unistd.h>
#include <__macro_FD_SETSIZE.h>
#include <__macro_PAGESIZE.h>
#include <__mode_t.h>
#include <__seek.h>
#include <__struct_dirent.h>
#include <__struct_in6_addr.h>
#include <__struct_in_addr.h>
#include <__struct_iovec.h>
#include <__struct_msghdr.h>
#include <__struct_pollfd.h>
#include <__struct_rusage.h>
#include <__struct_sockaddr.h>
#include <__struct_sockaddr_in.h>
#include <__struct_sockaddr_in6.h>
#include <__struct_sockaddr_storage.h>
#include <__struct_sockaddr_un.h>
#include <__struct_stat.h>
#include <__struct_timespec.h>
#include <__struct_timeval.h>
#include <__struct_tm.h>
#include <__struct_tms.h>
#include <__typedef_DIR.h>
#include <__typedef_blkcnt_t.h>
#include <__typedef_blksize_t.h>
#include <__typedef_clock_t.h>
#include <__typedef_clockid_t.h>
#include <__typedef_dev_t.h>
#include <__typedef_fd_set.h>
#include <__typedef_gid_t.h>
#include <__typedef_in_addr_t.h>
#include <__typedef_in_port_t.h>
#include <__typedef_ino_t.h>
#include <__typedef_mode_t.h>
#include <__typedef_nfds_t.h>
#include <__typedef_nlink_t.h>
#include <__typedef_off_t.h>
#include <__typedef_sa_family_t.h>
#include <__typedef_sigset_t.h>
#include <__typedef_socklen_t.h>
#include <__typedef_ssize_t.h>
#include <__typedef_suseconds_t.h>
#include <__typedef_time_t.h>
#include <__typedef_uid_t.h>
#include <alloca.h>
#include <ar.h>
#include <arpa/ftp.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <arpa/nameser_compat.h>
#include <arpa/telnet.h>
#include <arpa/tftp.h>
#include <assert.h>
#include <byteswap.h>
#include <complex.h>
#include <cpio.h>
#include <crypt.h>
#include <ctype.h>
#include <dirent.h>
#include <endian.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <features.h>
#include <fenv.h>
#include <float.h>
#include <fmtmsg.h>
#include <fnmatch.h>
#include <ftw.h>
#include <getopt.h>
#include <glob.h>
#include <iconv.h>
#include <ifaddrs.h>
#include <inttypes.h>
#include <iso646.h>
#include <langinfo.h>
#include <libgen.h>
#include <limits.h>
#include <locale.h>
#include <malloc.h>
#include <math.h>
#include <memory.h>
#include <monetary.h>
#include <mqueue.h>
#include <netinet/icmp6.h>
#include <netinet/igmp.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/ip_icmp.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netpacket/packet.h>
#include <nl_types.h>
#include <poll.h>
#include <pthread.h>
#include <regex.h>
#include <sched.h>
#include <search.h>
#include <semaphore.h>
#include <stdalign.h>
#include <stdbool.h>
#include <stdc-predef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdio_ext.h>
#include <stdlib.h>
#include <stdnoreturn.h>
#include <string.h>
#include <strings.h>
#include <stropts.h>
#include <sys/dir.h>
#include <sys/errno.h>
#include <sys/eventfd.h>
#include <sys/fcntl.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include <sys/poll.h>
#include <sys/random.h>
#include <sys/reg.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/stropts.h>
#include <sys/syscall.h>
#include <sys/sysinfo.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include <sys/timex.h>
#include <sys/ttydefaults.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/un.h>
#include <sys/utsname.h>
#include <syscall.h>
#include <sysexits.h>
#include <tar.h>
#include <tgmath.h>
#include <threads.h>
#include <time.h>
#include <uchar.h>
#include <unistd.h>
#include <utime.h>
#include <values.h>
#include <wasi/api.h>
#include <wasi/libc-environ.h>
#include <wasi/libc-find-relpath.h>
#include <wasi/libc-nocwd.h>
#include <wasi/libc.h>
#include <wchar.h>
#include <wctype.h>
3,396 changes: 3,396 additions & 0 deletions expected/wasm32-wasi/posix/predefined-macros.txt

Large diffs are not rendered by default.

74 changes: 74 additions & 0 deletions expected/wasm32-wasi/posix/undefined-symbols.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
__addtf3
__divtf3
__eqtf2
__extenddftf2
__extendsftf2
__fixtfdi
__fixtfsi
__fixunstfsi
__floatsitf
__floatunsitf
__getf2
__gttf2
__heap_base
__imported_wasi_snapshot_preview1_args_get
__imported_wasi_snapshot_preview1_args_sizes_get
__imported_wasi_snapshot_preview1_clock_res_get
__imported_wasi_snapshot_preview1_clock_time_get
__imported_wasi_snapshot_preview1_environ_get
__imported_wasi_snapshot_preview1_environ_sizes_get
__imported_wasi_snapshot_preview1_fd_advise
__imported_wasi_snapshot_preview1_fd_allocate
__imported_wasi_snapshot_preview1_fd_close
__imported_wasi_snapshot_preview1_fd_datasync
__imported_wasi_snapshot_preview1_fd_fdstat_get
__imported_wasi_snapshot_preview1_fd_fdstat_set_flags
__imported_wasi_snapshot_preview1_fd_fdstat_set_rights
__imported_wasi_snapshot_preview1_fd_filestat_get
__imported_wasi_snapshot_preview1_fd_filestat_set_size
__imported_wasi_snapshot_preview1_fd_filestat_set_times
__imported_wasi_snapshot_preview1_fd_pread
__imported_wasi_snapshot_preview1_fd_prestat_dir_name
__imported_wasi_snapshot_preview1_fd_prestat_get
__imported_wasi_snapshot_preview1_fd_pwrite
__imported_wasi_snapshot_preview1_fd_read
__imported_wasi_snapshot_preview1_fd_readdir
__imported_wasi_snapshot_preview1_fd_renumber
__imported_wasi_snapshot_preview1_fd_seek
__imported_wasi_snapshot_preview1_fd_sync
__imported_wasi_snapshot_preview1_fd_tell
__imported_wasi_snapshot_preview1_fd_write
__imported_wasi_snapshot_preview1_path_create_directory
__imported_wasi_snapshot_preview1_path_filestat_get
__imported_wasi_snapshot_preview1_path_filestat_set_times
__imported_wasi_snapshot_preview1_path_link
__imported_wasi_snapshot_preview1_path_open
__imported_wasi_snapshot_preview1_path_readlink
__imported_wasi_snapshot_preview1_path_remove_directory
__imported_wasi_snapshot_preview1_path_rename
__imported_wasi_snapshot_preview1_path_symlink
__imported_wasi_snapshot_preview1_path_unlink_file
__imported_wasi_snapshot_preview1_poll_oneoff
__imported_wasi_snapshot_preview1_proc_exit
__imported_wasi_snapshot_preview1_random_get
__imported_wasi_snapshot_preview1_sched_yield
__imported_wasi_snapshot_preview1_sock_accept
__imported_wasi_snapshot_preview1_sock_recv
__imported_wasi_snapshot_preview1_sock_send
__imported_wasi_snapshot_preview1_sock_shutdown
__letf2
__lock
__lockfile
__lttf2
__main_argc_argv
__netf2
__stack_pointer
__subtf3
__tls_base
__trunctfdf2
__trunctfsf2
__unlock
__unlockfile
__unordtf2
__wasilibc_pthread_self
__wasm_call_ctors
Original file line number Diff line number Diff line change
@@ -1082,6 +1082,7 @@ tfind
tgamma
tgammaf
tgammal
thrd_sleep
time
timegm
times
File renamed without changes.
File renamed without changes.
File renamed without changes.
6 changes: 0 additions & 6 deletions libc-bottom-half/cloudlibc/src/libc/time/nanosleep.c
Original file line number Diff line number Diff line change
@@ -3,9 +3,7 @@
// SPDX-License-Identifier: BSD-2-Clause

#include <errno.h>
#include <threads.h>
#include <time.h>
#include <_/cdefs.h>

int nanosleep(const struct timespec *rqtp, struct timespec *rem) {
int error = clock_nanosleep(CLOCK_REALTIME, 0, rqtp, rem);
@@ -15,7 +13,3 @@ int nanosleep(const struct timespec *rqtp, struct timespec *rem) {
}
return 0;
}

#if defined(_REENTRANT)
__strong_reference(nanosleep, thrd_sleep);
#endif
27 changes: 23 additions & 4 deletions libc-bottom-half/sources/chdir.c
Original file line number Diff line number Diff line change
@@ -9,9 +9,12 @@
#include <wasi/libc.h>

#ifdef _REENTRANT
#error "chdir doesn't yet support multiple threads"
void __wasilibc_cwd_lock(void);
void __wasilibc_cwd_unlock(void);
#else
#define __wasilibc_cwd_lock() (void)0
#define __wasilibc_cwd_unlock() (void)0
#endif

extern char *__wasilibc_cwd;
static int __wasilibc_cwd_mallocd = 0;

@@ -60,8 +63,10 @@ int chdir(const char *path)

// And set our new malloc'd buffer into the global cwd, freeing the
// previous one if necessary.
__wasilibc_cwd_lock();
char *prev_cwd = __wasilibc_cwd;
__wasilibc_cwd = new_cwd;
__wasilibc_cwd_unlock();
if (__wasilibc_cwd_mallocd)
free(prev_cwd);
__wasilibc_cwd_mallocd = 1;
@@ -77,11 +82,13 @@ static const char *make_absolute(const char *path) {
return path;
}

#ifndef _REENTRANT
// If the path is empty, or points to the current directory, then return
// the current directory.
if (path[0] == 0 || !strcmp(path, ".") || !strcmp(path, "./")) {
return __wasilibc_cwd;
}
#endif

// If the path starts with `./` then we won't be appending that to the cwd.
if (path[0] == '.' && path[1] == '/')
@@ -90,18 +97,30 @@ static const char *make_absolute(const char *path) {
// Otherwise we'll take the current directory, add a `/`, and then add the
// input `path`. Note that this doesn't do any normalization (like removing
// `/./`).
__wasilibc_cwd_lock();
size_t cwd_len = strlen(__wasilibc_cwd);
size_t path_len = strlen(path);
size_t path_len = path ? strlen(path) : 0;
__wasilibc_cwd_unlock();
int need_slash = __wasilibc_cwd[cwd_len - 1] == '/' ? 0 : 1;
size_t alloc_len = cwd_len + path_len + 1 + need_slash;
if (alloc_len > make_absolute_len) {
char *tmp = realloc(make_absolute_buf, alloc_len);
if (tmp == NULL)
if (tmp == NULL) {
__wasilibc_cwd_unlock();
return NULL;
}
make_absolute_buf = tmp;
make_absolute_len = alloc_len;
}
strcpy(make_absolute_buf, __wasilibc_cwd);
__wasilibc_cwd_unlock();

#ifdef _REENTRANT
if (path[0] == 0 || !strcmp(path, ".") || !strcmp(path, "./")) {
return make_absolute_buf;
}
#endif

if (need_slash)
strcpy(make_absolute_buf + cwd_len, "/");
strcpy(make_absolute_buf + cwd_len + need_slash, path);
17 changes: 13 additions & 4 deletions libc-bottom-half/sources/getcwd.c
Original file line number Diff line number Diff line change
@@ -1,30 +1,39 @@
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include "lock.h"

char *__wasilibc_cwd = "/";

// For threads this needs to synchronize with chdir
#ifdef _REENTRANT
#error "getcwd doesn't yet support multiple threads"
static volatile int lock[1];
void __wasilibc_cwd_lock(void) { LOCK(lock); }
void __wasilibc_cwd_unlock(void) { UNLOCK(lock); }
#else
#define __wasilibc_cwd_lock() (void)0
#define __wasilibc_cwd_unlock() (void)0
#endif

char *__wasilibc_cwd = "/";

char *getcwd(char *buf, size_t size)
{
__wasilibc_cwd_lock();
if (!buf) {
buf = strdup(__wasilibc_cwd);
if (!buf) {
errno = ENOMEM;
__wasilibc_cwd_unlock();
return NULL;
}
} else {
size_t len = strlen(__wasilibc_cwd);
if (size < len + 1) {
errno = ERANGE;
__wasilibc_cwd_unlock();
return NULL;
}
strcpy(buf, __wasilibc_cwd);
}
__wasilibc_cwd_unlock();
return buf;
}

7 changes: 2 additions & 5 deletions libc-bottom-half/sources/getentropy.c
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
#include <wasi/api.h>
#include <errno.h>
#include <unistd.h>

#ifdef _REENTRANT
#error With threads support, getentropy is not intended to be a cancellation point.
#endif
#include <wasi/api.h>

int __getentropy(void *buffer, size_t len) {
int cs;
if (len > 256) {
errno = EIO;
return -1;
19 changes: 15 additions & 4 deletions libc-bottom-half/sources/preopens.c
Original file line number Diff line number Diff line change
@@ -2,14 +2,11 @@
//! environment, with associated path prefixes, which can be used to map
//! absolute paths to capabilities with relative paths.

#ifdef _REENTRANT
#error "__wasilibc_register_preopened_fd doesn't yet support multiple threads"
#endif

#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <lock.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
@@ -32,6 +29,10 @@ static preopen *preopens;
static size_t num_preopens;
static size_t preopen_capacity;

/// Access to the the above preopen must be protected in the presence of
/// threads.
static volatile int lock[1];

#ifdef NDEBUG
#define assert_invariants() // assertions disabled
#else
@@ -55,13 +56,15 @@ static void assert_invariants(void) {

/// Allocate space for more preopens. Returns 0 on success and -1 on failure.
static int resize(void) {
LOCK(lock);
size_t start_capacity = 4;
size_t old_capacity = preopen_capacity;
size_t new_capacity = old_capacity == 0 ? start_capacity : old_capacity * 2;

preopen *old_preopens = preopens;
preopen *new_preopens = calloc(sizeof(preopen), new_capacity);
if (new_preopens == NULL)
UNLOCK(lock);
return -1;

memcpy(new_preopens, old_preopens, num_preopens * sizeof(preopen));
@@ -70,6 +73,7 @@ static int resize(void) {
free(old_preopens);

assert_invariants();
UNLOCK(lock);
return 0;
}

@@ -97,21 +101,26 @@ static const char *strip_prefixes(const char *path) {
///
/// This function takes ownership of `prefix`.
static int internal_register_preopened_fd(__wasi_fd_t fd, const char *relprefix) {
LOCK(lock);

// Check preconditions.
assert_invariants();
assert(fd != AT_FDCWD);
assert(fd != -1);
assert(relprefix != NULL);

if (num_preopens == preopen_capacity && resize() != 0)
UNLOCK(lock);
return -1;

char *prefix = strdup(strip_prefixes(relprefix));
if (prefix == NULL)
UNLOCK(lock);
return -1;
preopens[num_preopens++] = (preopen) { prefix, fd, };

assert_invariants();
UNLOCK(lock);
return 0;
}

@@ -166,6 +175,7 @@ int __wasilibc_find_abspath(const char *path,
// recently added preopens take precedence over less recently addded ones.
size_t match_len = 0;
int fd = -1;
LOCK(lock);
for (size_t i = num_preopens; i > 0; --i) {
const preopen *pre = &preopens[i - 1];
const char *prefix = pre->prefix;
@@ -182,6 +192,7 @@ int __wasilibc_find_abspath(const char *path,
*abs_prefix = prefix;
}
}
UNLOCK(lock);

if (fd == -1) {
errno = ENOENT;
4 changes: 0 additions & 4 deletions libc-top-half/musl/arch/wasm32/atomic_arch.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
#ifdef _REENTRANT
#error "multiple threads not supported in musl yet"
#endif

#define a_barrier() (__sync_synchronize())
#define a_cas(p, t, s) (__sync_val_compare_and_swap((p), (t), (s)))
#define a_crash() (__builtin_trap())
19 changes: 9 additions & 10 deletions libc-top-half/musl/arch/wasm32/pthread_arch.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
#ifdef _REENTRANT
#error "multiple threads not supported in musl yet"
uintptr_t __get_tp(void) {
#if _REENTRANT
int val;
__asm__("global.get __wasilibc_pthread_self\n"
"local.set %0"
: "=r"(val));
return val;
#else
return 0;
#endif

static inline struct pthread *__pthread_self(void)
{
return (struct pthread *)-1;
}

#define TP_ADJ(p) (p)

#define tls_mod_off_t unsigned long long
4 changes: 4 additions & 0 deletions libc-top-half/musl/include/pthread.h
Original file line number Diff line number Diff line change
@@ -103,8 +103,10 @@ int pthread_setcanceltype(int, int *);
void pthread_testcancel(void);
int pthread_cancel(pthread_t);

#ifdef __wasilibc_unmodified_upstream /* WASI has no CPU scheduling support. */
int pthread_getschedparam(pthread_t, int *__restrict, struct sched_param *__restrict);
int pthread_setschedparam(pthread_t, int, const struct sched_param *);
#endif
int pthread_setschedprio(pthread_t, int);

int pthread_once(pthread_once_t *, void (*)(void));
@@ -167,8 +169,10 @@ int pthread_attr_getscope(const pthread_attr_t *__restrict, int *__restrict);
int pthread_attr_setscope(pthread_attr_t *, int);
int pthread_attr_getschedpolicy(const pthread_attr_t *__restrict, int *__restrict);
int pthread_attr_setschedpolicy(pthread_attr_t *, int);
#ifdef __wasilibc_unmodified_upstream /* WASI has no CPU scheduling support. */
int pthread_attr_getschedparam(const pthread_attr_t *__restrict, struct sched_param *__restrict);
int pthread_attr_setschedparam(pthread_attr_t *__restrict, const struct sched_param *__restrict);
#endif
int pthread_attr_getinheritsched(const pthread_attr_t *__restrict, int *__restrict);
int pthread_attr_setinheritsched(pthread_attr_t *, int);

4 changes: 2 additions & 2 deletions libc-top-half/musl/src/conf/sysconf.c
Original file line number Diff line number Diff line change
@@ -251,15 +251,15 @@ long sysconf(int name)
return DELAYTIMER_MAX;
case JT_NPROCESSORS_CONF & 255:
case JT_NPROCESSORS_ONLN & 255: ;
#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
#ifdef __wasilibc_unmodified_upstream
unsigned char set[128] = {1};
int i, cnt;
__syscall(SYS_sched_getaffinity, 0, sizeof set, set);
for (i=cnt=0; i<sizeof set; i++)
for (; set[i]; set[i]&=set[i]-1, cnt++);
return cnt;
#else
// With no thread support, just say there's 1 processor.
// WASI has no way to query the processor count
return 1;
#endif
#ifdef __wasilibc_unmodified_upstream // WASI has no sysinfo
16 changes: 16 additions & 0 deletions libc-top-half/musl/src/internal/pthread_impl.h
Original file line number Diff line number Diff line change
@@ -2,12 +2,18 @@
#define _PTHREAD_IMPL_H

#include <pthread.h>
#ifdef __wasilibc_unmodified_upstream
#include <signal.h>
#endif
#include <errno.h>
#include <limits.h>
#ifdef __wasilibc_unmodified_upstream
#include <sys/mman.h>
#endif
#include "libc.h"
#ifdef __wasilibc_unmodified_upstream
#include "syscall.h"
#endif
#include "atomic.h"
#include "futex.h"

@@ -159,7 +165,9 @@ extern hidden volatile int __eintr_valid_flag;

hidden int __clone(int (*)(void *), void *, int, void *, ...);
hidden int __set_thread_area(void *);
#ifdef __wasilibc_unmodified_upstream /* WASI has no sigaction */
hidden int __libc_sigaction(int, const struct sigaction *, struct sigaction *);
#endif
hidden void __unmapself(void *, size_t);

hidden int __timedwait(volatile int *, int, clockid_t, const struct timespec *, int);
@@ -169,14 +177,22 @@ static inline void __wake(volatile void *addr, int cnt, int priv)
{
if (priv) priv = FUTEX_PRIVATE;
if (cnt<0) cnt = INT_MAX;
#ifdef __wasilibc_unmodified_upstream
__syscall(SYS_futex, addr, FUTEX_WAKE|priv, cnt) != -ENOSYS ||
__syscall(SYS_futex, addr, FUTEX_WAKE, cnt);
#else
__builtin_wasm_memory_atomic_notify((int*)addr, cnt);
#endif
}
static inline void __futexwait(volatile void *addr, int val, int priv)
{
#ifdef __wasilibc_unmodified_upstream
if (priv) priv = FUTEX_PRIVATE;
__syscall(SYS_futex, addr, FUTEX_WAIT|priv, val, 0) != -ENOSYS ||
__syscall(SYS_futex, addr, FUTEX_WAIT, val, 0);
#else
__wait(addr, NULL, val, priv);
#endif
}

hidden void __acquire_ptc(void);
2 changes: 1 addition & 1 deletion libc-top-half/musl/src/prng/random.c
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@ static int n = 31;
static int i = 3;
static int j = 0;
static uint32_t *x = init+1;
#ifdef __wasilibc_unmodified_upstream
#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
static volatile int lock[1];
volatile int *const __random_lockptr = lock;
#endif
7 changes: 7 additions & 0 deletions libc-top-half/musl/src/thread/pthread_self.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
#include "pthread_impl.h"
#include <threads.h>

#if !defined(__wasilibc_unmodified_upstream) && defined(__wasm__) && \
defined(_REENTRANT)
// We need some place to store the thread ID. This WebAssembly global fits the
// bill and is used by `__get_tp` elsewhere.
__asm__(".globaltype __wasilibc_pthread_self, i32\n");
#endif

static pthread_t __pthread_self_internal()
{
return __pthread_self();
12 changes: 7 additions & 5 deletions libc-top-half/musl/src/thread/pthread_setcancelstate.c
Original file line number Diff line number Diff line change
@@ -2,11 +2,13 @@

int __pthread_setcancelstate(int new, int *old)
{
if (new > 2U) return EINVAL;
struct pthread *self = __pthread_self();
if (old) *old = self->canceldisable;
self->canceldisable = new;
return 0;
#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
if (new > 2U) return EINVAL;
struct pthread *self = __pthread_self();
if (old) *old = self->canceldisable;
self->canceldisable = new;
#endif
return 0;
}

weak_alias(__pthread_setcancelstate, pthread_setcancelstate);
6 changes: 6 additions & 0 deletions libc-top-half/musl/src/thread/thrd_sleep.c
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
#include <threads.h>
#include <time.h>
#include <errno.h>
#ifdef __wasilibc_unmodified_upstream
#include "syscall.h"
#endif

int thrd_sleep(const struct timespec *req, struct timespec *rem)
{
#ifdef __wasilibc_unmodified_upstream
int ret = -__clock_nanosleep(CLOCK_REALTIME, 0, req, rem);
#else
int ret = -clock_nanosleep(CLOCK_REALTIME, 0, req, rem);
#endif
switch (ret) {
case 0: return 0;
case -EINTR: return -1; /* value specified by C11 */