From 51072358a714f050fe30227b6449206ae4186b3d Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 30 May 2024 05:11:56 +0200 Subject: Merging upstream version 0.0~git20230621.7018e24. Signed-off-by: Daniel Baumann --- libc-bottom-half/cloudlibc/src/libc/unistd/close.c | 16 ------ libc-bottom-half/crt/crt1-reactor.c | 20 ++++++++ .../headers/public/__header_sys_socket.h | 2 +- libc-bottom-half/headers/public/wasi/libc.h | 6 +++ libc-bottom-half/sources/__wasilibc_fd_renumber.c | 22 ++++++++ libc-bottom-half/sources/__wasilibc_real.c | 2 +- libc-bottom-half/sources/preopens.c | 58 +++++++++++++++------- 7 files changed, 91 insertions(+), 35 deletions(-) delete mode 100644 libc-bottom-half/cloudlibc/src/libc/unistd/close.c (limited to 'libc-bottom-half') diff --git a/libc-bottom-half/cloudlibc/src/libc/unistd/close.c b/libc-bottom-half/cloudlibc/src/libc/unistd/close.c deleted file mode 100644 index 2f5814b..0000000 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/close.c +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2015-2016 Nuxi, https://nuxi.nl/ -// -// SPDX-License-Identifier: BSD-2-Clause - -#include -#include -#include - -int close(int fildes) { - __wasi_errno_t error = __wasi_fd_close(fildes); - if (error != 0) { - errno = error; - return -1; - } - return 0; -} diff --git a/libc-bottom-half/crt/crt1-reactor.c b/libc-bottom-half/crt/crt1-reactor.c index f507c9e..ea4a84f 100644 --- a/libc-bottom-half/crt/crt1-reactor.c +++ b/libc-bottom-half/crt/crt1-reactor.c @@ -1,7 +1,27 @@ +#if defined(_REENTRANT) +#include +extern void __wasi_init_tp(void); +#endif extern void __wasm_call_ctors(void); __attribute__((export_name("_initialize"))) void _initialize(void) { +#if defined(_REENTRANT) + static volatile atomic_int initialized = 0; + int expected = 0; + if (!atomic_compare_exchange_strong(&initialized, &expected, 1)) { + __builtin_trap(); + } + + __wasi_init_tp(); +#else + static volatile int initialized = 0; + if (initialized != 0) { + __builtin_trap(); + } + initialized = 1; +#endif + // The linker synthesizes this to call constructors. __wasm_call_ctors(); } diff --git a/libc-bottom-half/headers/public/__header_sys_socket.h b/libc-bottom-half/headers/public/__header_sys_socket.h index 9fa8684..77aaa1b 100644 --- a/libc-bottom-half/headers/public/__header_sys_socket.h +++ b/libc-bottom-half/headers/public/__header_sys_socket.h @@ -13,7 +13,7 @@ #define MSG_PEEK __WASI_RIFLAGS_RECV_PEEK #define MSG_WAITALL __WASI_RIFLAGS_RECV_WAITALL -#define MSG_TRUNC __WASI_RIFLAGS_RECV_DATA_TRUNCATED +#define MSG_TRUNC __WASI_ROFLAGS_RECV_DATA_TRUNCATED #define SOCK_DGRAM __WASI_FILETYPE_SOCKET_DGRAM #define SOCK_STREAM __WASI_FILETYPE_SOCKET_STREAM diff --git a/libc-bottom-half/headers/public/wasi/libc.h b/libc-bottom-half/headers/public/wasi/libc.h index b50518b..18d8e9e 100644 --- a/libc-bottom-half/headers/public/wasi/libc.h +++ b/libc-bottom-half/headers/public/wasi/libc.h @@ -11,6 +11,12 @@ extern "C" { struct stat; struct timespec; +/// Populate libc's preopen tables. This is normally done automatically +/// just before it's needed, however if you call `__wasi_fd_renumber` or +/// `__wasi_fd_close` directly, and you need the preopens to be accurate +/// afterward, you should call this before doing so. +void __wasilibc_populate_preopens(void); + /// Register the given pre-opened file descriptor under the given path. /// /// This function does not take ownership of `prefix` (it makes its own copy). diff --git a/libc-bottom-half/sources/__wasilibc_fd_renumber.c b/libc-bottom-half/sources/__wasilibc_fd_renumber.c index aa9d8dc..47992e9 100644 --- a/libc-bottom-half/sources/__wasilibc_fd_renumber.c +++ b/libc-bottom-half/sources/__wasilibc_fd_renumber.c @@ -4,6 +4,9 @@ #include int __wasilibc_fd_renumber(int fd, int newfd) { + // Scan the preopen fds before making any changes. + __wasilibc_populate_preopens(); + __wasi_errno_t error = __wasi_fd_renumber(fd, newfd); if (error != 0) { errno = error; @@ -11,3 +14,22 @@ int __wasilibc_fd_renumber(int fd, int newfd) { } return 0; } + +int close(int fd) { + // Scan the preopen fds before making any changes. + __wasilibc_populate_preopens(); + + __wasi_errno_t error = __wasi_fd_close(fd); + if (error != 0) { + errno = error; + return -1; + } + + return 0; +} + +weak void __wasilibc_populate_preopens(void) { + // This version does nothing. It may be overridden by a version which does + // something if `__wasilibc_find_abspath` or `__wasilibc_find_relpath` are + // used. +} diff --git a/libc-bottom-half/sources/__wasilibc_real.c b/libc-bottom-half/sources/__wasilibc_real.c index d2e6b71..186de01 100644 --- a/libc-bottom-half/sources/__wasilibc_real.c +++ b/libc-bottom-half/sources/__wasilibc_real.c @@ -662,7 +662,7 @@ __wasi_errno_t __wasi_sock_shutdown( #ifdef _REENTRANT int32_t __imported_wasi_thread_spawn(int32_t arg0) __attribute__(( __import_module__("wasi"), - __import_name__("thread_spawn") + __import_name__("thread-spawn") )); int32_t __wasi_thread_spawn(void* start_arg) { diff --git a/libc-bottom-half/sources/preopens.c b/libc-bottom-half/sources/preopens.c index 7293c8c..b495433 100644 --- a/libc-bottom-half/sources/preopens.c +++ b/libc-bottom-half/sources/preopens.c @@ -25,6 +25,7 @@ typedef struct preopen { } preopen; /// A simple growable array of `preopen`. +static _Atomic _Bool preopens_populated = false; static preopen *preopens; static size_t num_preopens; static size_t preopen_capacity; @@ -100,12 +101,9 @@ static const char *strip_prefixes(const char *path) { return path; } -/// Register the given preopened file descriptor under the given path. -/// -/// This function takes ownership of `prefix`. -static int internal_register_preopened_fd(__wasi_fd_t fd, const char *relprefix) { - LOCK(lock); - +/// Similar to `internal_register_preopened_fd_unlocked` but does not +/// take a lock. +static int internal_register_preopened_fd_unlocked(__wasi_fd_t fd, const char *relprefix) { // Check preconditions. assert_invariants(); assert(fd != AT_FDCWD); @@ -113,22 +111,32 @@ static int internal_register_preopened_fd(__wasi_fd_t fd, const char *relprefix) 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; } +/// Register the given preopened file descriptor under the given path. +/// +/// This function takes ownership of `prefix`. +static int internal_register_preopened_fd(__wasi_fd_t fd, const char *relprefix) { + LOCK(lock); + + int r = internal_register_preopened_fd_unlocked(fd, relprefix); + + UNLOCK(lock); + + return r; +} + /// Are the `prefix_len` bytes pointed to by `prefix` a prefix of `path`? static bool prefix_matches(const char *prefix, size_t prefix_len, const char *path) { // Allow an empty string as a prefix of any relative path. @@ -152,6 +160,8 @@ static bool prefix_matches(const char *prefix, size_t prefix_len, const char *pa // See the documentation in libc.h int __wasilibc_register_preopened_fd(int fd, const char *prefix) { + __wasilibc_populate_preopens(); + return internal_register_preopened_fd((__wasi_fd_t)fd, prefix); } @@ -172,6 +182,8 @@ int __wasilibc_find_relpath(const char *path, int __wasilibc_find_abspath(const char *path, const char **abs_prefix, const char **relative_path) { + __wasilibc_populate_preopens(); + // Strip leading `/` characters, the prefixes we're mataching won't have // them. while (*path == '/') @@ -219,13 +231,20 @@ int __wasilibc_find_abspath(const char *path, return fd; } -/// This is referenced by weak reference from crt1.c and lives in the same -/// source file as `__wasilibc_find_relpath` so that it's linked in when it's -/// needed. -// Concerning the 51 -- see the comment by the constructor priority in -// libc-bottom-half/sources/environ.c. -__attribute__((constructor(51))) -static void __wasilibc_populate_preopens(void) { +void __wasilibc_populate_preopens(void) { + // Fast path: If the preopens are already initialized, do nothing. + if (preopens_populated) { + return; + } + + LOCK(lock); + + // Check whether another thread initialized the preopens already. + if (preopens_populated) { + UNLOCK(lock); + return; + } + // Skip stdin, stdout, and stderr, and count up until we reach an invalid // file descriptor. for (__wasi_fd_t fd = 3; fd != 0; ++fd) { @@ -249,7 +268,7 @@ static void __wasilibc_populate_preopens(void) { goto oserr; prefix[prestat.u.dir.pr_name_len] = '\0'; - if (internal_register_preopened_fd(fd, prefix) != 0) + if (internal_register_preopened_fd_unlocked(fd, prefix) != 0) goto software; free(prefix); @@ -260,6 +279,11 @@ static void __wasilibc_populate_preopens(void) { } } + // Preopens are now initialized. + preopens_populated = true; + + UNLOCK(lock); + return; oserr: _Exit(EX_OSERR); -- cgit v1.2.3