From 24d8d12caf05e52fe938d1eb01211b2470cffb41 Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Mon, 9 Jan 2023 19:17:06 +0100 Subject: [PATCH] Update wasi-libc to a1c7c2c7a4b2813c6f67bd2ef6e0f430d31cebad Some notable changes: - `ENOENT` is returned instead of `ENOTCAPABLE` when a path has not be pre-opened (https://github.com/WebAssembly/wasi-libc/pull/370) - `fd_readdir()`: some implementations may not set the inode number, so an additional call to `fstatat()` is now done in order to get it when that happens. --- lib/libc/include/wasm-wasi-musl/wasi/api.h | 2 +- .../cloudlibc/src/libc/dirent/scandirat.c | 25 ++++- .../wasi/libc-bottom-half/signal/signal.c | 4 +- .../sources/__wasilibc_real.c | 5 +- .../wasi/libc-bottom-half/sources/isatty.c | 2 +- .../wasi/libc-bottom-half/sources/posix.c | 100 +++++++++--------- .../wasi/libc-top-half/musl/include/pthread.h | 2 + .../wasi/libc-top-half/musl/include/unistd.h | 2 + .../libc-top-half/musl/src/env/__init_tls.c | 51 +++++++++ .../libc-top-half/musl/src/include/pthread.h | 2 + .../musl/src/internal/pthread_impl.h | 5 + .../libc-top-half/musl/src/thread/__wait.c | 2 +- .../musl/src/thread/pthread_attr_get.c | 4 + .../musl/src/thread/pthread_barrier_destroy.c | 2 + .../musl/src/thread/pthread_barrier_wait.c | 8 ++ .../musl/src/thread/pthread_create.c | 54 +++++++--- .../musl/src/thread/pthread_key_create.c | 4 + 17 files changed, 198 insertions(+), 76 deletions(-) diff --git a/lib/libc/include/wasm-wasi-musl/wasi/api.h b/lib/libc/include/wasm-wasi-musl/wasi/api.h index 1ab76994ed177989ac7618d3c91178faac62d6a1..45a6506e2ffa022e081bea9aa8e14cf8b7c4da5a 100644 --- a/lib/libc/include/wasm-wasi-musl/wasi/api.h +++ b/lib/libc/include/wasm-wasi-musl/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/lib/libc/wasi/libc-bottom-half/cloudlibc/src/libc/dirent/scandirat.c b/lib/libc/wasi/libc-bottom-half/cloudlibc/src/libc/dirent/scandirat.c index 06feae9e13c9875b372501f9d412df16affc6a36..079b3b3b29efd8fe1b597dff16d63c488b9a1403 100644 --- a/lib/libc/wasi/libc-bottom-half/cloudlibc/src/libc/dirent/scandirat.c +++ b/lib/libc/wasi/libc-bottom-half/cloudlibc/src/libc/dirent/scandirat.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "dirent_impl.h" @@ -21,6 +22,8 @@ static int sel_true(const struct dirent *de) { int __wasilibc_nocwd_scandirat(int dirfd, const char *dir, struct dirent ***namelist, int (*sel)(const struct dirent *), int (*compar)(const struct dirent **, const struct dirent **)) { + struct stat statbuf; + // Match all files if no select function is provided. if (sel == NULL) sel = sel_true; @@ -89,10 +92,30 @@ int __wasilibc_nocwd_scandirat(int dirfd, const char *dir, struct dirent ***name malloc(offsetof(struct dirent, d_name) + entry.d_namlen + 1); if (dirent == NULL) goto bad; - dirent->d_ino = entry.d_ino; dirent->d_type = entry.d_type; memcpy(dirent->d_name, name, entry.d_namlen); dirent->d_name[entry.d_namlen] = '\0'; + + // `fd_readdir` implementations may set the inode field to zero if the + // the inode number is unknown. In that case, do an `fstatat` to get the + // inode number. + off_t d_ino = entry.d_ino; + unsigned char d_type = entry.d_type; + if (d_ino == 0) { + if (fstatat(fd, dirent->d_name, &statbuf, AT_SYMLINK_NOFOLLOW) != 0) { + return -1; + } + + // Fill in the inode. + d_ino = statbuf.st_ino; + + // In case someone raced with us and replaced the object with this name + // with another of a different type, update the type too. + d_type = __wasilibc_iftodt(statbuf.st_mode & S_IFMT); + } + dirent->d_ino = d_ino; + dirent->d_type = d_type; + cookie = entry.d_next; if (sel(dirent)) { diff --git a/lib/libc/wasi/libc-bottom-half/signal/signal.c b/lib/libc/wasi/libc-bottom-half/signal/signal.c index b4634f959096f6a50f48ebb953e45b3ff6de04b9..290d6b27431d7ce66c91f867bceffa2e04daebbd 100644 --- a/lib/libc/wasi/libc-bottom-half/signal/signal.c +++ b/lib/libc/wasi/libc-bottom-half/signal/signal.c @@ -138,5 +138,5 @@ void (*signal(int sig, void (*func)(int)))(int) { return old; } -extern __typeof(signal) bsd_signal __attribute__((__weak__, alias("signal"))); -extern __typeof(signal) __sysv_signal __attribute__((__weak__, alias("signal"))); +extern __typeof(signal) bsd_signal __attribute__((weak, alias("signal"))); +extern __typeof(signal) __sysv_signal __attribute__((weak, alias("signal"))); diff --git a/lib/libc/wasi/libc-bottom-half/sources/__wasilibc_real.c b/lib/libc/wasi/libc-bottom-half/sources/__wasilibc_real.c index 855a2c6ddd2d878ea49fa8fc0ba057ea963bbdb5..d2e6b71c6467f8acd33e754ae780479758b81e47 100644 --- a/lib/libc/wasi/libc-bottom-half/sources/__wasilibc_real.c +++ b/lib/libc/wasi/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/lib/libc/wasi/libc-bottom-half/sources/isatty.c b/lib/libc/wasi/libc-bottom-half/sources/isatty.c index 54aee809c7342612295b2eff17ea5f00bf26b892..c6f8662816a009d0f7e8a8b6a88627fb435b1aaa 100644 --- a/lib/libc/wasi/libc-bottom-half/sources/isatty.c +++ b/lib/libc/wasi/libc-bottom-half/sources/isatty.c @@ -19,4 +19,4 @@ int __isatty(int fd) { return 1; } -extern __typeof(__isatty) isatty __attribute__((__weak__, alias("__isatty"))); +extern __typeof(__isatty) isatty __attribute__((weak, alias("__isatty"))); diff --git a/lib/libc/wasi/libc-bottom-half/sources/posix.c b/lib/libc/wasi/libc-bottom-half/sources/posix.c index 35dd99b309b09e0a4ba835283419ce588f31e76c..b3e59ec3948fd1c7cf24637c42955583e197ac66 100644 --- a/lib/libc/wasi/libc-bottom-half/sources/posix.c +++ b/lib/libc/wasi/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/lib/libc/wasi/libc-top-half/musl/include/pthread.h b/lib/libc/wasi/libc-top-half/musl/include/pthread.h index 01fe5f29307ab0e9d2688e9317b0f5f6af15a5a6..b14fe826d74b3101a4fd4ab901ce9839c63cab75 100644 --- a/lib/libc/wasi/libc-top-half/musl/include/pthread.h +++ b/lib/libc/wasi/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/lib/libc/wasi/libc-top-half/musl/include/unistd.h b/lib/libc/wasi/libc-top-half/musl/include/unistd.h index b5cb5c6630169415c4e155c6d57cc7b943910d16..0be83e368c4c87224fb8a9b39808e3f642c948a9 100644 --- a/lib/libc/wasi/libc-top-half/musl/include/unistd.h +++ b/lib/libc/wasi/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/lib/libc/wasi/libc-top-half/musl/src/env/__init_tls.c b/lib/libc/wasi/libc-top-half/musl/src/env/__init_tls.c index ee785bc11e4c517d93c10b1e3a750366724497f3..ece8d24e86004cca92d96abcbe3ce8fa9182a5d1 100644 --- a/lib/libc/wasi/libc-top-half/musl/src/env/__init_tls.c +++ b/lib/libc/wasi/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/lib/libc/wasi/libc-top-half/musl/src/include/pthread.h b/lib/libc/wasi/libc-top-half/musl/src/include/pthread.h index 7167d3e11a11eff076d6fa8066f03df64c616ffc..0aba813e9a47911b96cfbefb35f1660702e70818 100644 --- a/lib/libc/wasi/libc-top-half/musl/src/include/pthread.h +++ b/lib/libc/wasi/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/lib/libc/wasi/libc-top-half/musl/src/internal/pthread_impl.h b/lib/libc/wasi/libc-top-half/musl/src/internal/pthread_impl.h index a6d188bb3cfbbdcc1f91dba26edd6cb44dbb3ad9..1e7b9741dba75b158f702080c94a3cf9d87d0c0d 100644 --- a/lib/libc/wasi/libc-top-half/musl/src/internal/pthread_impl.h +++ b/lib/libc/wasi/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/lib/libc/wasi/libc-top-half/musl/src/thread/__wait.c b/lib/libc/wasi/libc-top-half/musl/src/thread/__wait.c index c0e4aac796cfd6cf4d5b2eda977246f01109e097..7ffa9872d954e748225bf26ac5e6d9a83bfc8fe1 100644 --- a/lib/libc/wasi/libc-top-half/musl/src/thread/__wait.c +++ b/lib/libc/wasi/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/lib/libc/wasi/libc-top-half/musl/src/thread/pthread_attr_get.c b/lib/libc/wasi/libc-top-half/musl/src/thread/pthread_attr_get.c index f12ff442548dd65e85410a2606bb2904f511b256..0ac251c674c18d721c29801335aadd6f532b061e 100644 --- a/lib/libc/wasi/libc-top-half/musl/src/thread/pthread_attr_get.c +++ b/lib/libc/wasi/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/lib/libc/wasi/libc-top-half/musl/src/thread/pthread_barrier_destroy.c b/lib/libc/wasi/libc-top-half/musl/src/thread/pthread_barrier_destroy.c index 4ce0b2e1278499de5e417f870d4e4e6c04655638..a347a2c12a4804831b741aae7e86987c650e1c50 100644 --- a/lib/libc/wasi/libc-top-half/musl/src/thread/pthread_barrier_destroy.c +++ b/lib/libc/wasi/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/lib/libc/wasi/libc-top-half/musl/src/thread/pthread_barrier_wait.c b/lib/libc/wasi/libc-top-half/musl/src/thread/pthread_barrier_wait.c index cc2a8bbf58a9cfee193d7f30bf2bcfd778debe7a..0891b713ece90255fd43682d37162e9bfab2644b 100644 --- a/lib/libc/wasi/libc-top-half/musl/src/thread/pthread_barrier_wait.c +++ b/lib/libc/wasi/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/lib/libc/wasi/libc-top-half/musl/src/thread/pthread_create.c b/lib/libc/wasi/libc-top-half/musl/src/thread/pthread_create.c index 1aa7be71a57d5edd3adcb26684bd8de75aa2604e..676e2ccf95d2a2b54398da61f83c1716df20de85 100644 --- a/lib/libc/wasi/libc-top-half/musl/src/thread/pthread_create.c +++ b/lib/libc/wasi/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 - void *(*start_func)(void *); - void *start_arg; + /* + * 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; #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/lib/libc/wasi/libc-top-half/musl/src/thread/pthread_key_create.c b/lib/libc/wasi/libc-top-half/musl/src/thread/pthread_key_create.c index d112094122b316d161a6fd17f1c08d12d0b58e05..dd47caa51d0a065318c30c7ea2abfaa0664f605d 100644 --- a/lib/libc/wasi/libc-top-half/musl/src/thread/pthread_key_create.c +++ b/lib/libc/wasi/libc-top-half/musl/src/thread/pthread_key_create.c @@ -50,7 +50,9 @@ int __pthread_key_delete(pthread_key_t k) sigset_t set; pthread_t self = __pthread_self(), td=self; +#ifdef __wasilibc_unmodified_upstream __block_app_sigs(&set); +#endif __pthread_rwlock_wrlock(&key_lock); __tl_lock(); @@ -61,7 +63,9 @@ int __pthread_key_delete(pthread_key_t k) keys[k] = 0; __pthread_rwlock_unlock(&key_lock); +#ifdef __wasilibc_unmodified_upstream __restore_sigs(&set); +#endif return 0; } -- 2.54.0