mirror of
https://github.com/ziglang/zig.git
synced 2024-11-14 16:13:24 +00:00
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.
This commit is contained in:
parent
0cba60afed
commit
24d8d12caf
2
lib/libc/include/wasm-wasi-musl/wasi/api.h
vendored
2
lib/libc/include/wasm-wasi-musl/wasi/api.h
vendored
@ -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.
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#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)) {
|
||||
|
@ -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")));
|
||||
|
@ -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
|
||||
|
@ -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")));
|
||||
|
100
lib/libc/wasi/libc-bottom-half/sources/posix.c
vendored
100
lib/libc/wasi/libc-bottom-half/sources/posix.c
vendored
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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__
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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 *);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user