diff --git a/lib/libc/include/wasm-wasi-musl/wasi/api.h b/lib/libc/include/wasm-wasi-musl/wasi/api.h index 1ab76994ed17..45a6506e2ffa 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 06feae9e13c9..079b3b3b29ef 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 b4634f959096..290d6b27431d 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 855a2c6ddd2d..d2e6b71c6467 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 54aee809c734..c6f8662816a0 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 35dd99b309b0..b3e59ec3948f 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 01fe5f29307a..b14fe826d74b 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 b5cb5c663016..0be83e368c4c 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 ee785bc11e4c..ece8d24e8600 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 7167d3e11a11..0aba813e9a47 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 a6d188bb3cfb..1e7b9741dba7 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 c0e4aac796cf..7ffa9872d954 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 f12ff442548d..0ac251c674c1 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 4ce0b2e12784..a347a2c12a48 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 cc2a8bbf58a9..0891b713ece9 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 1aa7be71a57d..676e2ccf95d2 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 + /* + * 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 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att 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 d112094122b3..dd47caa51d0a 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; }