| author | |
| committer | |
| log | 24d8d12caf05e52fe938d1eb01211b2470cffb41 |
| tree | 85820c0a6bf542af3d0794fb029490460e439528 |
| parent | 0cba60afed935b9ea0f40324cc15730414f2550e |
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.17 files changed, 197 insertions(+), 75 deletions(-)
lib/libc/include/wasm-wasi-musl/wasi/api.h+1-1| ... | @@ -2099,7 +2099,7 @@ __wasi_errno_t __wasi_sock_shutdown( | ... | @@ -2099,7 +2099,7 @@ __wasi_errno_t __wasi_sock_shutdown( |
| 2099 | * | 2099 | * |
| 2100 | * @see https://github.com/WebAssembly/wasi-threads/#readme | 2100 | * @see https://github.com/WebAssembly/wasi-threads/#readme |
| 2101 | */ | 2101 | */ |
| 2102 | __wasi_errno_t __wasi_thread_spawn( | 2102 | int32_t __wasi_thread_spawn( |
| 2103 | /** | 2103 | /** |
| 2104 | * A pointer to an opaque struct to be passed to the module's entry | 2104 | * A pointer to an opaque struct to be passed to the module's entry |
| 2105 | * function. | 2105 | * function. |
lib/libc/wasi/libc-bottom-half/cloudlibc/src/libc/dirent/scandirat.c+24-1| ... | @@ -11,6 +11,7 @@ | ... | @@ -11,6 +11,7 @@ |
| 11 | #include <stdlib.h> | 11 | #include <stdlib.h> |
| 12 | #include <string.h> | 12 | #include <string.h> |
| 13 | #include <unistd.h> | 13 | #include <unistd.h> |
| 14 | #include <sys/stat.h> | ||
| 14 | 15 | ||
| 15 | #include "dirent_impl.h" | 16 | #include "dirent_impl.h" |
| 16 | 17 | ||
| ... | @@ -21,6 +22,8 @@ static int sel_true(const struct dirent *de) { | ... | @@ -21,6 +22,8 @@ static int sel_true(const struct dirent *de) { |
| 21 | int __wasilibc_nocwd_scandirat(int dirfd, const char *dir, struct dirent ***namelist, | 22 | int __wasilibc_nocwd_scandirat(int dirfd, const char *dir, struct dirent ***namelist, |
| 22 | int (*sel)(const struct dirent *), | 23 | int (*sel)(const struct dirent *), |
| 23 | int (*compar)(const struct dirent **, const struct dirent **)) { | 24 | int (*compar)(const struct dirent **, const struct dirent **)) { |
| 25 | struct stat statbuf; | ||
| 26 | |||
| 24 | // Match all files if no select function is provided. | 27 | // Match all files if no select function is provided. |
| 25 | if (sel == NULL) | 28 | if (sel == NULL) |
| 26 | sel = sel_true; | 29 | sel = sel_true; |
| ... | @@ -89,10 +92,30 @@ int __wasilibc_nocwd_scandirat(int dirfd, const char *dir, struct dirent ***name | ... | @@ -89,10 +92,30 @@ int __wasilibc_nocwd_scandirat(int dirfd, const char *dir, struct dirent ***name |
| 89 | malloc(offsetof(struct dirent, d_name) + entry.d_namlen + 1); | 92 | malloc(offsetof(struct dirent, d_name) + entry.d_namlen + 1); |
| 90 | if (dirent == NULL) | 93 | if (dirent == NULL) |
| 91 | goto bad; | 94 | goto bad; |
| 92 | dirent->d_ino = entry.d_ino; | ||
| 93 | dirent->d_type = entry.d_type; | 95 | dirent->d_type = entry.d_type; |
| 94 | memcpy(dirent->d_name, name, entry.d_namlen); | 96 | memcpy(dirent->d_name, name, entry.d_namlen); |
| 95 | dirent->d_name[entry.d_namlen] = '\0'; | 97 | dirent->d_name[entry.d_namlen] = '\0'; |
| 98 | |||
| 99 | // `fd_readdir` implementations may set the inode field to zero if the | ||
| 100 | // the inode number is unknown. In that case, do an `fstatat` to get the | ||
| 101 | // inode number. | ||
| 102 | off_t d_ino = entry.d_ino; | ||
| 103 | unsigned char d_type = entry.d_type; | ||
| 104 | if (d_ino == 0) { | ||
| 105 | if (fstatat(fd, dirent->d_name, &statbuf, AT_SYMLINK_NOFOLLOW) != 0) { | ||
| 106 | return -1; | ||
| 107 | } | ||
| 108 | |||
| 109 | // Fill in the inode. | ||
| 110 | d_ino = statbuf.st_ino; | ||
| 111 | |||
| 112 | // In case someone raced with us and replaced the object with this name | ||
| 113 | // with another of a different type, update the type too. | ||
| 114 | d_type = __wasilibc_iftodt(statbuf.st_mode & S_IFMT); | ||
| 115 | } | ||
| 116 | dirent->d_ino = d_ino; | ||
| 117 | dirent->d_type = d_type; | ||
| 118 | |||
| 96 | cookie = entry.d_next; | 119 | cookie = entry.d_next; |
| 97 | 120 | ||
| 98 | if (sel(dirent)) { | 121 | if (sel(dirent)) { |
lib/libc/wasi/libc-bottom-half/signal/signal.c+2-2| ... | @@ -138,5 +138,5 @@ void (*signal(int sig, void (*func)(int)))(int) { | ... | @@ -138,5 +138,5 @@ void (*signal(int sig, void (*func)(int)))(int) { |
| 138 | return old; | 138 | return old; |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | extern __typeof(signal) bsd_signal __attribute__((__weak__, alias("signal"))); | 141 | extern __typeof(signal) bsd_signal __attribute__((weak, alias("signal"))); |
| 142 | extern __typeof(signal) __sysv_signal __attribute__((__weak__, alias("signal"))); | 142 | extern __typeof(signal) __sysv_signal __attribute__((weak, alias("signal"))); |
lib/libc/wasi/libc-bottom-half/sources/__wasilibc_real.c+2-3| ... | @@ -665,8 +665,7 @@ int32_t __imported_wasi_thread_spawn(int32_t arg0) __attribute__(( | ... | @@ -665,8 +665,7 @@ int32_t __imported_wasi_thread_spawn(int32_t arg0) __attribute__(( |
| 665 | __import_name__("thread_spawn") | 665 | __import_name__("thread_spawn") |
| 666 | )); | 666 | )); |
| 667 | 667 | ||
| 668 | __wasi_errno_t __wasi_thread_spawn(void* start_arg) { | 668 | int32_t __wasi_thread_spawn(void* start_arg) { |
| 669 | 	int32_t ret = __imported_wasi_thread_spawn((int32_t) start_arg); | 669 | return __imported_wasi_thread_spawn((int32_t) start_arg); |
| 670 | return (uint16_t) ret; | ||
| 671 | } | 670 | } |
| 672 | #endif | 671 | #endif |
lib/libc/wasi/libc-bottom-half/sources/isatty.c+1-1| ... | @@ -19,4 +19,4 @@ int __isatty(int fd) { | ... | @@ -19,4 +19,4 @@ int __isatty(int fd) { |
| 19 | 19 | ||
| 20 | return 1; | 20 | return 1; |
| 21 | } | 21 | } |
| 22 | extern __typeof(__isatty) isatty __attribute__((__weak__, alias("__isatty"))); | 22 | extern __typeof(__isatty) isatty __attribute__((weak, alias("__isatty"))); |
lib/libc/wasi/libc-bottom-half/sources/posix.c+50-50| ... | @@ -58,9 +58,9 @@ int __wasilibc_open_nomode(const char *path, int oflag) { | ... | @@ -58,9 +58,9 @@ int __wasilibc_open_nomode(const char *path, int oflag) { |
| 58 | char *relative_path; | 58 | char *relative_path; |
| 59 | int dirfd = find_relpath(path, &relative_path); | 59 | int dirfd = find_relpath(path, &relative_path); |
| 60 | 60 | ||
| 61 | // If we can't find a preopen for it, indicate that we lack capabilities. | 61 | // If we can't find a preopen for it, fail as if we can't find the path. |
| 62 | if (dirfd == -1) { | 62 | if (dirfd == -1) { |
| 63 | errno = ENOTCAPABLE; | 63 | errno = ENOENT; |
| 64 | return -1; | 64 | return -1; |
| 65 | } | 65 | } |
| 66 | 66 | ||
| ... | @@ -71,9 +71,9 @@ int access(const char *path, int amode) { | ... | @@ -71,9 +71,9 @@ int access(const char *path, int amode) { |
| 71 | char *relative_path; | 71 | char *relative_path; |
| 72 | int dirfd = find_relpath(path, &relative_path); | 72 | int dirfd = find_relpath(path, &relative_path); |
| 73 | 73 | ||
| 74 | // If we can't find a preopen for it, indicate that we lack capabilities. | 74 | // If we can't find a preopen for it, fail as if we can't find the path. |
| 75 | if (dirfd == -1) { | 75 | if (dirfd == -1) { |
| 76 | errno = ENOTCAPABLE; | 76 | errno = ENOENT; |
| 77 | return -1; | 77 | return -1; |
| 78 | } | 78 | } |
| 79 | 79 | ||
| ... | @@ -88,9 +88,9 @@ ssize_t readlink( | ... | @@ -88,9 +88,9 @@ ssize_t readlink( |
| 88 | char *relative_path; | 88 | char *relative_path; |
| 89 | int dirfd = find_relpath(path, &relative_path); | 89 | int dirfd = find_relpath(path, &relative_path); |
| 90 | 90 | ||
| 91 | // If we can't find a preopen for it, indicate that we lack capabilities. | 91 | // If we can't find a preopen for it, fail as if we can't find the path. |
| 92 | if (dirfd == -1) { | 92 | if (dirfd == -1) { |
| 93 | errno = ENOTCAPABLE; | 93 | errno = ENOENT; |
| 94 | return -1; | 94 | return -1; |
| 95 | } | 95 | } |
| 96 | 96 | ||
| ... | @@ -101,9 +101,9 @@ int stat(const char *restrict path, struct stat *restrict buf) { | ... | @@ -101,9 +101,9 @@ int stat(const char *restrict path, struct stat *restrict buf) { |
| 101 | char *relative_path; | 101 | char *relative_path; |
| 102 | int dirfd = find_relpath(path, &relative_path); | 102 | int dirfd = find_relpath(path, &relative_path); |
| 103 | 103 | ||
| 104 | // If we can't find a preopen for it, indicate that we lack capabilities. | 104 | // If we can't find a preopen for it, fail as if we can't find the path. |
| 105 | if (dirfd == -1) { | 105 | if (dirfd == -1) { |
| 106 | errno = ENOTCAPABLE; | 106 | errno = ENOENT; |
| 107 | return -1; | 107 | return -1; |
| 108 | } | 108 | } |
| 109 | 109 | ||
| ... | @@ -114,9 +114,9 @@ int lstat(const char *restrict path, struct stat *restrict buf) { | ... | @@ -114,9 +114,9 @@ int lstat(const char *restrict path, struct stat *restrict buf) { |
| 114 | char *relative_path; | 114 | char *relative_path; |
| 115 | int dirfd = find_relpath(path, &relative_path); | 115 | int dirfd = find_relpath(path, &relative_path); |
| 116 | 116 | ||
| 117 | // If we can't find a preopen for it, indicate that we lack capabilities. | 117 | // If we can't find a preopen for it, fail as if we can't find the path. |
| 118 | if (dirfd == -1) { | 118 | if (dirfd == -1) { |
| 119 | errno = ENOTCAPABLE; | 119 | errno = ENOENT; |
| 120 | return -1; | 120 | return -1; |
| 121 | } | 121 | } |
| 122 | 122 | ||
| ... | @@ -127,9 +127,9 @@ int utime(const char *path, const struct utimbuf *times) { | ... | @@ -127,9 +127,9 @@ int utime(const char *path, const struct utimbuf *times) { |
| 127 | char *relative_path; | 127 | char *relative_path; |
| 128 | int dirfd = find_relpath(path, &relative_path); | 128 | int dirfd = find_relpath(path, &relative_path); |
| 129 | 129 | ||
| 130 | // If we can't find a preopen for it, indicate that we lack capabilities. | 130 | // If we can't find a preopen for it, fail as if we can't find the path. |
| 131 | if (dirfd == -1) { | 131 | if (dirfd == -1) { |
| 132 | errno = ENOTCAPABLE; | 132 | errno = ENOENT; |
| 133 | return -1; | 133 | return -1; |
| 134 | } | 134 | } |
| 135 | 135 | ||
| ... | @@ -147,9 +147,9 @@ int utimes(const char *path, const struct timeval times[2]) { | ... | @@ -147,9 +147,9 @@ int utimes(const char *path, const struct timeval times[2]) { |
| 147 | char *relative_path; | 147 | char *relative_path; |
| 148 | int dirfd = find_relpath(path, &relative_path); | 148 | int dirfd = find_relpath(path, &relative_path); |
| 149 | 149 | ||
| 150 | // If we can't find a preopen for it, indicate that we lack capabilities. | 150 | // If we can't find a preopen for it, fail as if we can't find the path. |
| 151 | if (dirfd == -1) { | 151 | if (dirfd == -1) { |
| 152 | errno = ENOTCAPABLE; | 152 | errno = ENOENT; |
| 153 | return -1; | 153 | return -1; |
| 154 | } | 154 | } |
| 155 | 155 | ||
| ... | @@ -169,9 +169,9 @@ int unlink(const char *path) { | ... | @@ -169,9 +169,9 @@ int unlink(const char *path) { |
| 169 | char *relative_path; | 169 | char *relative_path; |
| 170 | int dirfd = find_relpath(path, &relative_path); | 170 | int dirfd = find_relpath(path, &relative_path); |
| 171 | 171 | ||
| 172 | // If we can't find a preopen for it, indicate that we lack capabilities. | 172 | // If we can't find a preopen for it, fail as if we can't find the path. |
| 173 | if (dirfd == -1) { | 173 | if (dirfd == -1) { |
| 174 | errno = ENOTCAPABLE; | 174 | errno = ENOENT; |
| 175 | return -1; | 175 | return -1; |
| 176 | } | 176 | } |
| 177 | 177 | ||
| ... | @@ -185,9 +185,9 @@ int rmdir(const char *path) { | ... | @@ -185,9 +185,9 @@ int rmdir(const char *path) { |
| 185 | char *relative_path; | 185 | char *relative_path; |
| 186 | int dirfd = find_relpath(path, &relative_path); | 186 | int dirfd = find_relpath(path, &relative_path); |
| 187 | 187 | ||
| 188 | // If we can't find a preopen for it, indicate that we lack capabilities. | 188 | // If we can't find a preopen for it, fail as if we can't find the path. |
| 189 | if (dirfd == -1) { | 189 | if (dirfd == -1) { |
| 190 | errno = ENOTCAPABLE; | 190 | errno = ENOENT; |
| 191 | return -1; | 191 | return -1; |
| 192 | } | 192 | } |
| 193 | 193 | ||
| ... | @@ -198,21 +198,21 @@ int remove(const char *path) { | ... | @@ -198,21 +198,21 @@ int remove(const char *path) { |
| 198 | char *relative_path; | 198 | char *relative_path; |
| 199 | int dirfd = find_relpath(path, &relative_path); | 199 | int dirfd = find_relpath(path, &relative_path); |
| 200 | 200 | ||
| 201 | // If we can't find a preopen for it, indicate that we lack capabilities. | 201 | // If we can't find a preopen for it, fail as if we can't find the path. |
| 202 | if (dirfd == -1) { | 202 | if (dirfd == -1) { |
| 203 | errno = ENOTCAPABLE; | 203 | errno = ENOENT; |
| 204 | return -1; | 204 | return -1; |
| 205 | } | 205 | } |
| 206 | 206 | ||
| 207 | // First try to remove it as a file. | 207 | // First try to remove it as a file. |
| 208 | int r = __wasilibc_nocwd___wasilibc_unlinkat(dirfd, relative_path); | 208 | int r = __wasilibc_nocwd___wasilibc_unlinkat(dirfd, relative_path); |
| 209 | if (r != 0 && (errno == EISDIR || errno == ENOTCAPABLE)) { | 209 | if (r != 0 && (errno == EISDIR || errno == ENOENT)) { |
| 210 | // That failed, but it might be a directory. | 210 | // That failed, but it might be a directory. |
| 211 | r = __wasilibc_nocwd___wasilibc_rmdirat(dirfd, relative_path); | 211 | r = __wasilibc_nocwd___wasilibc_rmdirat(dirfd, relative_path); |
| 212 | 212 | ||
| 213 | // If it isn't a directory, we lack capabilities to remove it as a file. | 213 | // If it isn't a directory, we lack capabilities to remove it as a file. |
| 214 | if (errno == ENOTDIR) | 214 | if (errno == ENOTDIR) |
| 215 | errno = ENOTCAPABLE; | 215 | errno = ENOENT; |
| 216 | } | 216 | } |
| 217 | return r; | 217 | return r; |
| 218 | } | 218 | } |
| ... | @@ -221,9 +221,9 @@ int mkdir(const char *path, mode_t mode) { | ... | @@ -221,9 +221,9 @@ int mkdir(const char *path, mode_t mode) { |
| 221 | char *relative_path; | 221 | char *relative_path; |
| 222 | int dirfd = find_relpath(path, &relative_path); | 222 | int dirfd = find_relpath(path, &relative_path); |
| 223 | 223 | ||
| 224 | // If we can't find a preopen for it, indicate that we lack capabilities. | 224 | // If we can't find a preopen for it, fail as if we can't find the path. |
| 225 | if (dirfd == -1) { | 225 | if (dirfd == -1) { |
| 226 | errno = ENOTCAPABLE; | 226 | errno = ENOENT; |
| 227 | return -1; | 227 | return -1; |
| 228 | } | 228 | } |
| 229 | 229 | ||
| ... | @@ -234,9 +234,9 @@ DIR *opendir(const char *dirname) { | ... | @@ -234,9 +234,9 @@ DIR *opendir(const char *dirname) { |
| 234 | char *relative_path; | 234 | char *relative_path; |
| 235 | int dirfd = find_relpath(dirname, &relative_path); | 235 | int dirfd = find_relpath(dirname, &relative_path); |
| 236 | 236 | ||
| 237 | // If we can't find a preopen for it, indicate that we lack capabilities. | 237 | // If we can't find a preopen for it, fail as if we can't find the path. |
| 238 | if (dirfd == -1) { | 238 | if (dirfd == -1) { |
| 239 | errno = ENOTCAPABLE; | 239 | errno = ENOENT; |
| 240 | return NULL; | 240 | return NULL; |
| 241 | } | 241 | } |
| 242 | 242 | ||
| ... | @@ -252,9 +252,9 @@ int scandir( | ... | @@ -252,9 +252,9 @@ int scandir( |
| 252 | char *relative_path; | 252 | char *relative_path; |
| 253 | int dirfd = find_relpath(dir, &relative_path); | 253 | int dirfd = find_relpath(dir, &relative_path); |
| 254 | 254 | ||
| 255 | // If we can't find a preopen for it, indicate that we lack capabilities. | 255 | // If we can't find a preopen for it, fail as if we can't find the path. |
| 256 | if (dirfd == -1) { | 256 | if (dirfd == -1) { |
| 257 | errno = ENOTCAPABLE; | 257 | errno = ENOENT; |
| 258 | return -1; | 258 | return -1; |
| 259 | } | 259 | } |
| 260 | 260 | ||
| ... | @@ -265,9 +265,9 @@ int symlink(const char *target, const char *linkpath) { | ... | @@ -265,9 +265,9 @@ int symlink(const char *target, const char *linkpath) { |
| 265 | char *relative_path; | 265 | char *relative_path; |
| 266 | int dirfd = find_relpath(linkpath, &relative_path); | 266 | int dirfd = find_relpath(linkpath, &relative_path); |
| 267 | 267 | ||
| 268 | // If we can't find a preopen for it, indicate that we lack capabilities. | 268 | // If we can't find a preopen for it, fail as if we can't find the path. |
| 269 | if (dirfd == -1) { | 269 | if (dirfd == -1) { |
| 270 | errno = ENOTCAPABLE; | 270 | errno = ENOENT; |
| 271 | return -1; | 271 | return -1; |
| 272 | } | 272 | } |
| 273 | 273 | ||
| ... | @@ -287,8 +287,8 @@ int link(const char *old, const char *new) { | ... | @@ -287,8 +287,8 @@ int link(const char *old, const char *new) { |
| 287 | new_dirfd, new_relative_path, 0); | 287 | new_dirfd, new_relative_path, 0); |
| 288 | } | 288 | } |
| 289 | 289 | ||
| 290 | // We couldn't find a preopen for it; indicate that we lack capabilities. | 290 | // We couldn't find a preopen for it; fail as if we can't find the path. |
| 291 | errno = ENOTCAPABLE; | 291 | errno = ENOENT; |
| 292 | return -1; | 292 | return -1; |
| 293 | } | 293 | } |
| 294 | 294 | ||
| ... | @@ -305,8 +305,8 @@ int rename(const char *old, const char *new) { | ... | @@ -305,8 +305,8 @@ int rename(const char *old, const char *new) { |
| 305 | new_dirfd, new_relative_path); | 305 | new_dirfd, new_relative_path); |
| 306 | } | 306 | } |
| 307 | 307 | ||
| 308 | // We couldn't find a preopen for it; indicate that we lack capabilities. | 308 | // We couldn't find a preopen for it; fail as if we can't find the path. |
| 309 | errno = ENOTCAPABLE; | 309 | errno = ENOENT; |
| 310 | return -1; | 310 | return -1; |
| 311 | } | 311 | } |
| 312 | 312 | ||
| ... | @@ -317,9 +317,9 @@ __wasilibc_access(const char *path, int mode, int flags) | ... | @@ -317,9 +317,9 @@ __wasilibc_access(const char *path, int mode, int flags) |
| 317 | char *relative_path; | 317 | char *relative_path; |
| 318 | int dirfd = find_relpath(path, &relative_path); | 318 | int dirfd = find_relpath(path, &relative_path); |
| 319 | 319 | ||
| 320 | // If we can't find a preopen for it, indicate that we lack capabilities. | 320 | // If we can't find a preopen for it, fail as if we can't find the path. |
| 321 | if (dirfd == -1) { | 321 | if (dirfd == -1) { |
| 322 | errno = ENOTCAPABLE; | 322 | errno = ENOENT; |
| 323 | return -1; | 323 | return -1; |
| 324 | } | 324 | } |
| 325 | 325 | ||
| ... | @@ -334,9 +334,9 @@ __wasilibc_utimens(const char *path, const struct timespec times[2], int flags) | ... | @@ -334,9 +334,9 @@ __wasilibc_utimens(const char *path, const struct timespec times[2], int flags) |
| 334 | char *relative_path; | 334 | char *relative_path; |
| 335 | int dirfd = find_relpath(path, &relative_path); | 335 | int dirfd = find_relpath(path, &relative_path); |
| 336 | 336 | ||
| 337 | // If we can't find a preopen for it, indicate that we lack capabilities. | 337 | // If we can't find a preopen for it, fail as if we can't find the path. |
| 338 | if (dirfd == -1) { | 338 | if (dirfd == -1) { |
| 339 | errno = ENOTCAPABLE; | 339 | errno = ENOENT; |
| 340 | return -1; | 340 | return -1; |
| 341 | } | 341 | } |
| 342 | 342 | ||
| ... | @@ -351,9 +351,9 @@ __wasilibc_stat(const char *__restrict path, struct stat *__restrict st, int fla | ... | @@ -351,9 +351,9 @@ __wasilibc_stat(const char *__restrict path, struct stat *__restrict st, int fla |
| 351 | char *relative_path; | 351 | char *relative_path; |
| 352 | int dirfd = find_relpath(path, &relative_path); | 352 | int dirfd = find_relpath(path, &relative_path); |
| 353 | 353 | ||
| 354 | // If we can't find a preopen for it, indicate that we lack capabilities. | 354 | // If we can't find a preopen for it, fail as if we can't find the path. |
| 355 | if (dirfd == -1) { | 355 | if (dirfd == -1) { |
| 356 | errno = ENOTCAPABLE; | 356 | errno = ENOENT; |
| 357 | return -1; | 357 | return -1; |
| 358 | } | 358 | } |
| 359 | 359 | ||
| ... | @@ -369,9 +369,9 @@ __wasilibc_link(const char *oldpath, const char *newpath, int flags) | ... | @@ -369,9 +369,9 @@ __wasilibc_link(const char *oldpath, const char *newpath, int flags) |
| 369 | int old_dirfd = find_relpath(oldpath, &old_relative_path); | 369 | int old_dirfd = find_relpath(oldpath, &old_relative_path); |
| 370 | int new_dirfd = find_relpath(newpath, &new_relative_path); | 370 | int new_dirfd = find_relpath(newpath, &new_relative_path); |
| 371 | 371 | ||
| 372 | // If we can't find a preopen for it, indicate that we lack capabilities. | 372 | // If we can't find a preopen for it, fail as if we can't find the path. |
| 373 | if (old_dirfd == -1 || new_dirfd == -1) { | 373 | if (old_dirfd == -1 || new_dirfd == -1) { |
| 374 | errno = ENOTCAPABLE; | 374 | errno = ENOENT; |
| 375 | return -1; | 375 | return -1; |
| 376 | } | 376 | } |
| 377 | 377 | ||
| ... | @@ -387,9 +387,9 @@ __wasilibc_link_oldat(int olddirfd, const char *oldpath, const char *newpath, in | ... | @@ -387,9 +387,9 @@ __wasilibc_link_oldat(int olddirfd, const char *oldpath, const char *newpath, in |
| 387 | char *new_relative_path; | 387 | char *new_relative_path; |
| 388 | int new_dirfd = find_relpath(newpath, &new_relative_path); | 388 | int new_dirfd = find_relpath(newpath, &new_relative_path); |
| 389 | 389 | ||
| 390 | // If we can't find a preopen for it, indicate that we lack capabilities. | 390 | // If we can't find a preopen for it, fail as if we can't find the path. |
| 391 | if (new_dirfd == -1) { | 391 | if (new_dirfd == -1) { |
| 392 | errno = ENOTCAPABLE; | 392 | errno = ENOENT; |
| 393 | return -1; | 393 | return -1; |
| 394 | } | 394 | } |
| 395 | 395 | ||
| ... | @@ -405,9 +405,9 @@ __wasilibc_link_newat(const char *oldpath, int newdirfd, const char *newpath, in | ... | @@ -405,9 +405,9 @@ __wasilibc_link_newat(const char *oldpath, int newdirfd, const char *newpath, in |
| 405 | char *old_relative_path; | 405 | char *old_relative_path; |
| 406 | int old_dirfd = find_relpath(oldpath, &old_relative_path); | 406 | int old_dirfd = find_relpath(oldpath, &old_relative_path); |
| 407 | 407 | ||
| 408 | // If we can't find a preopen for it, indicate that we lack capabilities. | 408 | // If we can't find a preopen for it, fail as if we can't find the path. |
| 409 | if (old_dirfd == -1) { | 409 | if (old_dirfd == -1) { |
| 410 | errno = ENOTCAPABLE; | 410 | errno = ENOENT; |
| 411 | return -1; | 411 | return -1; |
| 412 | } | 412 | } |
| 413 | 413 | ||
| ... | @@ -423,9 +423,9 @@ __wasilibc_rename_oldat(int fromdirfd, const char *from, const char *to) | ... | @@ -423,9 +423,9 @@ __wasilibc_rename_oldat(int fromdirfd, const char *from, const char *to) |
| 423 | char *to_relative_path; | 423 | char *to_relative_path; |
| 424 | int to_dirfd = find_relpath(to, &to_relative_path); | 424 | int to_dirfd = find_relpath(to, &to_relative_path); |
| 425 | 425 | ||
| 426 | // If we can't find a preopen for it, indicate that we lack capabilities. | 426 | // If we can't find a preopen for it, fail as if we can't find the path. |
| 427 | if (to_dirfd == -1) { | 427 | if (to_dirfd == -1) { |
| 428 | errno = ENOTCAPABLE; | 428 | errno = ENOENT; |
| 429 | return -1; | 429 | return -1; |
| 430 | } | 430 | } |
| 431 | 431 | ||
| ... | @@ -439,9 +439,9 @@ __wasilibc_rename_newat(const char *from, int todirfd, const char *to) | ... | @@ -439,9 +439,9 @@ __wasilibc_rename_newat(const char *from, int todirfd, const char *to) |
| 439 | char *from_relative_path; | 439 | char *from_relative_path; |
| 440 | int from_dirfd = find_relpath(from, &from_relative_path); | 440 | int from_dirfd = find_relpath(from, &from_relative_path); |
| 441 | 441 | ||
| 442 | // If we can't find a preopen for it, indicate that we lack capabilities. | 442 | // If we can't find a preopen for it, fail as if we can't find the path. |
| 443 | if (from_dirfd == -1) { | 443 | if (from_dirfd == -1) { |
| 444 | errno = ENOTCAPABLE; | 444 | errno = ENOENT; |
| 445 | return -1; | 445 | return -1; |
| 446 | } | 446 | } |
| 447 | 447 |
lib/libc/wasi/libc-top-half/musl/include/pthread.h+2| ... | @@ -85,7 +85,9 @@ extern "C" { | ... | @@ -85,7 +85,9 @@ extern "C" { |
| 85 | 85 | ||
| 86 | int pthread_create(pthread_t *__restrict, const pthread_attr_t *__restrict, void *(*)(void *), void *__restrict); | 86 | int pthread_create(pthread_t *__restrict, const pthread_attr_t *__restrict, void *(*)(void *), void *__restrict); |
| 87 | int pthread_detach(pthread_t); | 87 | int pthread_detach(pthread_t); |
| 88 | #ifdef __wasilibc_unmodified_upstream | ||
| 88 | _Noreturn void pthread_exit(void *); | 89 | _Noreturn void pthread_exit(void *); |
| 90 | #endif | ||
| 89 | int pthread_join(pthread_t, void **); | 91 | int pthread_join(pthread_t, void **); |
| 90 | 92 | ||
| 91 | #ifdef __GNUC__ | 93 | #ifdef __GNUC__ |
lib/libc/wasi/libc-top-half/musl/include/unistd.h+2| ... | @@ -336,7 +336,9 @@ pid_t gettid(void); | ... | @@ -336,7 +336,9 @@ pid_t gettid(void); |
| 336 | #endif | 336 | #endif |
| 337 | #define _POSIX_VDISABLE 0 | 337 | #define _POSIX_VDISABLE 0 |
| 338 | 338 | ||
| 339 | #if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) | ||
| 339 | #define _POSIX_THREADS _POSIX_VERSION | 340 | #define _POSIX_THREADS _POSIX_VERSION |
| 341 | #endif | ||
| 340 | #define _POSIX_THREAD_PROCESS_SHARED _POSIX_VERSION | 342 | #define _POSIX_THREAD_PROCESS_SHARED _POSIX_VERSION |
| 341 | #define _POSIX_THREAD_SAFE_FUNCTIONS _POSIX_VERSION | 343 | #define _POSIX_THREAD_SAFE_FUNCTIONS _POSIX_VERSION |
| 342 | #define _POSIX_THREAD_ATTR_STACKADDR _POSIX_VERSION | 344 | #define _POSIX_THREAD_ATTR_STACKADDR _POSIX_VERSION |
lib/libc/wasi/libc-top-half/musl/src/env/__init_tls.c+51| ... | @@ -16,6 +16,43 @@ | ... | @@ -16,6 +16,43 @@ |
| 16 | volatile int __thread_list_lock; | 16 | volatile int __thread_list_lock; |
| 17 | 17 | ||
| 18 | #ifndef __wasilibc_unmodified_upstream | 18 | #ifndef __wasilibc_unmodified_upstream |
| 19 | |||
| 20 | /* These symbols are generated by wasm-ld. __stack_high/__stack_low | ||
| 21 | * symbols are only available in LLVM v16 and higher, therefore they're | ||
| 22 | * defined as weak symbols and if not available, __heap_base/__data_end | ||
| 23 | * is used instead. | ||
| 24 | * | ||
| 25 | * TODO: remove usage of __heap_base/__data_end for stack size calculation | ||
| 26 | * once we drop support for LLVM v15 and older. | ||
| 27 | */ | ||
| 28 | extern unsigned char __heap_base; | ||
| 29 | extern unsigned char __data_end; | ||
| 30 | extern unsigned char __global_base; | ||
| 31 | extern weak unsigned char __stack_high; | ||
| 32 | extern weak unsigned char __stack_low; | ||
| 33 | |||
| 34 | static inline void setup_default_stack_size() | ||
| 35 | { | ||
| 36 | 	ptrdiff_t stack_size; | ||
| 37 | |||
| 38 | 	if (&__stack_high) | ||
| 39 | 		stack_size = &__stack_high - &__stack_low; | ||
| 40 | 	else { | ||
| 41 | 		unsigned char *sp; | ||
| 42 | 		__asm__( | ||
| 43 | 			".globaltype __stack_pointer, i32\n" | ||
| 44 | 			"global.get __stack_pointer\n" | ||
| 45 | 			"local.set %0\n" | ||
| 46 | 			: "=r"(sp)); | ||
| 47 | 		stack_size = sp > &__global_base ? &__heap_base - &__data_end : (ptrdiff_t)&__global_base; | ||
| 48 | 	} | ||
| 49 | |||
| 50 | 	if (stack_size > __default_stacksize) | ||
| 51 | 		__default_stacksize = | ||
| 52 | 			stack_size < DEFAULT_STACK_MAX ? | ||
| 53 | 			stack_size : DEFAULT_STACK_MAX; | ||
| 54 | } | ||
| 55 | |||
| 19 | void __wasi_init_tp() { | 56 | void __wasi_init_tp() { |
| 20 | 	__init_tp((void *)__get_tp()); | 57 | 	__init_tp((void *)__get_tp()); |
| 21 | } | 58 | } |
| ... | @@ -31,6 +68,20 @@ int __init_tp(void *p) | ... | @@ -31,6 +68,20 @@ int __init_tp(void *p) |
| 31 | 	if (!r) libc.can_do_threads = 1; | 68 | 	if (!r) libc.can_do_threads = 1; |
| 32 | 	td->detach_state = DT_JOINABLE; | 69 | 	td->detach_state = DT_JOINABLE; |
| 33 | 	td->tid = __syscall(SYS_set_tid_address, &__thread_list_lock); | 70 | 	td->tid = __syscall(SYS_set_tid_address, &__thread_list_lock); |
| 71 | #else | ||
| 72 | 	setup_default_stack_size(); | ||
| 73 | 	td->detach_state = DT_JOINABLE; | ||
| 74 | 	/* | ||
| 75 | 	 * Initialize the TID to a value which doesn't conflict with | ||
| 76 | 	 * host-allocated TIDs, so that TID-based locks can work. | ||
| 77 | 	 * | ||
| 78 | 	 * Note: | ||
| 79 | 	 * - Host-allocated TIDs range from 1 to 0x1fffffff. (inclusive) | ||
| 80 | 	 * - __tl_lock and __lockfile uses TID 0 as "unlocked". | ||
| 81 | 	 * - __lockfile relies on the fact the most significant two bits | ||
| 82 | 	 * of TIDs are 0. | ||
| 83 | 	 */ | ||
| 84 | 	td->tid = 0x3fffffff; | ||
| 34 | #endif | 85 | #endif |
| 35 | 	td->locale = &libc.global_locale; | 86 | 	td->locale = &libc.global_locale; |
| 36 | 	td->robust_list.head = &td->robust_list.head; | 87 | 	td->robust_list.head = &td->robust_list.head; |
lib/libc/wasi/libc-top-half/musl/src/include/pthread.h+2| ... | @@ -7,7 +7,9 @@ hidden int __pthread_once(pthread_once_t *, void (*)(void)); | ... | @@ -7,7 +7,9 @@ hidden int __pthread_once(pthread_once_t *, void (*)(void)); |
| 7 | hidden void __pthread_testcancel(void); | 7 | hidden void __pthread_testcancel(void); |
| 8 | hidden int __pthread_setcancelstate(int, int *); | 8 | hidden int __pthread_setcancelstate(int, int *); |
| 9 | hidden int __pthread_create(pthread_t *restrict, const pthread_attr_t *restrict, void *(*)(void *), void *restrict); | 9 | hidden int __pthread_create(pthread_t *restrict, const pthread_attr_t *restrict, void *(*)(void *), void *restrict); |
| 10 | #ifdef __wasilibc_unmodified_upstream | ||
| 10 | hidden _Noreturn void __pthread_exit(void *); | 11 | hidden _Noreturn void __pthread_exit(void *); |
| 12 | #endif | ||
| 11 | hidden int __pthread_join(pthread_t, void **); | 13 | hidden int __pthread_join(pthread_t, void **); |
| 12 | hidden int __pthread_mutex_lock(pthread_mutex_t *); | 14 | hidden int __pthread_mutex_lock(pthread_mutex_t *); |
| 13 | hidden int __pthread_mutex_trylock(pthread_mutex_t *); | 15 | hidden int __pthread_mutex_trylock(pthread_mutex_t *); |
lib/libc/wasi/libc-top-half/musl/src/internal/pthread_impl.h+5| ... | @@ -216,7 +216,12 @@ extern hidden unsigned __default_stacksize; | ... | @@ -216,7 +216,12 @@ extern hidden unsigned __default_stacksize; |
| 216 | extern hidden unsigned __default_guardsize; | 216 | extern hidden unsigned __default_guardsize; |
| 217 | 217 | ||
| 218 | #define DEFAULT_STACK_SIZE 131072 | 218 | #define DEFAULT_STACK_SIZE 131072 |
| 219 | #ifdef __wasilibc_unmodified_upstream | ||
| 219 | #define DEFAULT_GUARD_SIZE 8192 | 220 | #define DEFAULT_GUARD_SIZE 8192 |
| 221 | #else | ||
| 222 | /* guard doesn't make much sense without mprotect. */ | ||
| 223 | #define DEFAULT_GUARD_SIZE 0 | ||
| 224 | #endif | ||
| 220 | 225 | ||
| 221 | #define DEFAULT_STACK_MAX (8<<20) | 226 | #define DEFAULT_STACK_MAX (8<<20) |
| 222 | #define DEFAULT_GUARD_MAX (1<<20) | 227 | #define DEFAULT_GUARD_MAX (1<<20) |
lib/libc/wasi/libc-top-half/musl/src/thread/__wait.c+1-1| ... | @@ -48,7 +48,7 @@ void __wait(volatile int *addr, volatile int *waiters, int val, int priv) | ... | @@ -48,7 +48,7 @@ void __wait(volatile int *addr, volatile int *waiters, int val, int priv) |
| 48 | 		__syscall(SYS_futex, addr, FUTEX_WAIT|priv, val, 0) != -ENOSYS | 48 | 		__syscall(SYS_futex, addr, FUTEX_WAIT|priv, val, 0) != -ENOSYS |
| 49 | 		|| __syscall(SYS_futex, addr, FUTEX_WAIT, val, 0); | 49 | 		|| __syscall(SYS_futex, addr, FUTEX_WAIT, val, 0); |
| 50 | #else | 50 | #else |
| 51 | 		__wasilibc_futex_wait(addr, FUTEX_WAIT, val, 0); | 51 | 		__wasilibc_futex_wait(addr, FUTEX_WAIT, val, -1); |
| 52 | #endif | 52 | #endif |
| 53 | 	} | 53 | 	} |
| 54 | 	if (waiters) a_dec(waiters); | 54 | 	if (waiters) a_dec(waiters); |
lib/libc/wasi/libc-top-half/musl/src/thread/pthread_attr_get.c+4| ... | @@ -17,6 +17,7 @@ int pthread_attr_getinheritsched(const pthread_attr_t *restrict a, int *restrict | ... | @@ -17,6 +17,7 @@ int pthread_attr_getinheritsched(const pthread_attr_t *restrict a, int *restrict |
| 17 | 	return 0; | 17 | 	return 0; |
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | #ifdef __wasilibc_unmodified_upstream /* WASI has no CPU scheduling support. */ | ||
| 20 | int pthread_attr_getschedparam(const pthread_attr_t *restrict a, struct sched_param *restrict param) | 21 | int pthread_attr_getschedparam(const pthread_attr_t *restrict a, struct sched_param *restrict param) |
| 21 | { | 22 | { |
| 22 | 	param->sched_priority = a->_a_prio; | 23 | 	param->sched_priority = a->_a_prio; |
| ... | @@ -28,6 +29,7 @@ int pthread_attr_getschedpolicy(const pthread_attr_t *restrict a, int *restrict | ... | @@ -28,6 +29,7 @@ int pthread_attr_getschedpolicy(const pthread_attr_t *restrict a, int *restrict |
| 28 | 	*policy = a->_a_policy; | 29 | 	*policy = a->_a_policy; |
| 29 | 	return 0; | 30 | 	return 0; |
| 30 | } | 31 | } |
| 32 | #endif | ||
| 31 | 33 | ||
| 32 | int pthread_attr_getscope(const pthread_attr_t *restrict a, int *restrict scope) | 34 | int pthread_attr_getscope(const pthread_attr_t *restrict a, int *restrict scope) |
| 33 | { | 35 | { |
| ... | @@ -56,11 +58,13 @@ int pthread_barrierattr_getpshared(const pthread_barrierattr_t *restrict a, int | ... | @@ -56,11 +58,13 @@ int pthread_barrierattr_getpshared(const pthread_barrierattr_t *restrict a, int |
| 56 | 	return 0; | 58 | 	return 0; |
| 57 | } | 59 | } |
| 58 | 60 | ||
| 61 | #ifdef __wasilibc_unmodified_upstream /* Forward declaration of WASI's `__clockid` type. */ | ||
| 59 | int pthread_condattr_getclock(const pthread_condattr_t *restrict a, clockid_t *restrict clk) | 62 | int pthread_condattr_getclock(const pthread_condattr_t *restrict a, clockid_t *restrict clk) |
| 60 | { | 63 | { |
| 61 | 	*clk = a->__attr & 0x7fffffff; | 64 | 	*clk = a->__attr & 0x7fffffff; |
| 62 | 	return 0; | 65 | 	return 0; |
| 63 | } | 66 | } |
| 67 | #endif | ||
| 64 | 68 | ||
| 65 | int pthread_condattr_getpshared(const pthread_condattr_t *restrict a, int *restrict pshared) | 69 | int pthread_condattr_getpshared(const pthread_condattr_t *restrict a, int *restrict pshared) |
| 66 | { | 70 | { |
lib/libc/wasi/libc-top-half/musl/src/thread/pthread_barrier_destroy.c+2| ... | @@ -9,7 +9,9 @@ int pthread_barrier_destroy(pthread_barrier_t *b) | ... | @@ -9,7 +9,9 @@ int pthread_barrier_destroy(pthread_barrier_t *b) |
| 9 | 			while ((v = b->_b_lock) & INT_MAX) | 9 | 			while ((v = b->_b_lock) & INT_MAX) |
| 10 | 				__wait(&b->_b_lock, 0, v, 0); | 10 | 				__wait(&b->_b_lock, 0, v, 0); |
| 11 | 		} | 11 | 		} |
| 12 | #ifdef __wasilibc_unmodified_upstream /* WASI does not understand processes or locking between them. */ | ||
| 12 | 		__vm_wait(); | 13 | 		__vm_wait(); |
| 14 | #endif | ||
| 13 | 	} | 15 | 	} |
| 14 | 	return 0; | 16 | 	return 0; |
| 15 | } | 17 | } |
lib/libc/wasi/libc-top-half/musl/src/thread/pthread_barrier_wait.c+8| ... | @@ -23,7 +23,9 @@ static int pshared_barrier_wait(pthread_barrier_t *b) | ... | @@ -23,7 +23,9 @@ static int pshared_barrier_wait(pthread_barrier_t *b) |
| 23 | 			__wait(&b->_b_count, &b->_b_waiters2, v, 0); | 23 | 			__wait(&b->_b_count, &b->_b_waiters2, v, 0); |
| 24 | 	} | 24 | 	} |
| 25 | 25 | ||
| 26 | #ifdef __wasilibc_unmodified_upstream /* WASI does not understand processes or locking between them. */ | ||
| 26 | 	__vm_lock(); | 27 | 	__vm_lock(); |
| 28 | #endif | ||
| 27 | 29 | ||
| 28 | 	/* Ensure all threads have a vm lock before proceeding */ | 30 | 	/* Ensure all threads have a vm lock before proceeding */ |
| 29 | 	if (a_fetch_add(&b->_b_count, -1)==1-limit) { | 31 | 	if (a_fetch_add(&b->_b_count, -1)==1-limit) { |
| ... | @@ -44,7 +46,9 @@ static int pshared_barrier_wait(pthread_barrier_t *b) | ... | @@ -44,7 +46,9 @@ static int pshared_barrier_wait(pthread_barrier_t *b) |
| 44 | 	if (v==INT_MIN+1 || (v==1 && w)) | 46 | 	if (v==INT_MIN+1 || (v==1 && w)) |
| 45 | 		__wake(&b->_b_lock, 1, 0); | 47 | 		__wake(&b->_b_lock, 1, 0); |
| 46 | 48 | ||
| 49 | #ifdef __wasilibc_unmodified_upstream /* WASI does not understand processes or locking between them. */ | ||
| 47 | 	__vm_unlock(); | 50 | 	__vm_unlock(); |
| 51 | #endif | ||
| 48 | 52 | ||
| 49 | 	return ret; | 53 | 	return ret; |
| 50 | } | 54 | } |
| ... | @@ -84,8 +88,12 @@ int pthread_barrier_wait(pthread_barrier_t *b) | ... | @@ -84,8 +88,12 @@ int pthread_barrier_wait(pthread_barrier_t *b) |
| 84 | 			a_spin(); | 88 | 			a_spin(); |
| 85 | 		a_inc(&inst->finished); | 89 | 		a_inc(&inst->finished); |
| 86 | 		while (inst->finished == 1) | 90 | 		while (inst->finished == 1) |
| 91 | #ifdef __wasilibc_unmodified_upstream | ||
| 87 | 			__syscall(SYS_futex,&inst->finished,FUTEX_WAIT|FUTEX_PRIVATE,1,0) != -ENOSYS | 92 | 			__syscall(SYS_futex,&inst->finished,FUTEX_WAIT|FUTEX_PRIVATE,1,0) != -ENOSYS |
| 88 | 			|| __syscall(SYS_futex,&inst->finished,FUTEX_WAIT,1,0); | 93 | 			|| __syscall(SYS_futex,&inst->finished,FUTEX_WAIT,1,0); |
| 94 | #else | ||
| 95 | 			__futexwait(&inst->finished, 1, 0); | ||
| 96 | #endif | ||
| 89 | 		return PTHREAD_BARRIER_SERIAL_THREAD; | 97 | 		return PTHREAD_BARRIER_SERIAL_THREAD; |
| 90 | 	} | 98 | 	} |
| 91 | 99 |
lib/libc/wasi/libc-top-half/musl/src/thread/pthread_create.c+36-16| ... | @@ -60,7 +60,11 @@ void __tl_sync(pthread_t td) | ... | @@ -60,7 +60,11 @@ void __tl_sync(pthread_t td) |
| 60 | 	if (tl_lock_waiters) __wake(&__thread_list_lock, 1, 0); | 60 | 	if (tl_lock_waiters) __wake(&__thread_list_lock, 1, 0); |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | #ifdef __wasilibc_unmodified_upstream | ||
| 63 | _Noreturn void __pthread_exit(void *result) | 64 | _Noreturn void __pthread_exit(void *result) |
| 65 | #else | ||
| 66 | static void __pthread_exit(void *result) | ||
| 67 | #endif | ||
| 64 | { | 68 | { |
| 65 | 	pthread_t self = __pthread_self(); | 69 | 	pthread_t self = __pthread_self(); |
| 66 | 	sigset_t set; | 70 | 	sigset_t set; |
| ... | @@ -191,7 +195,7 @@ _Noreturn void __pthread_exit(void *result) | ... | @@ -191,7 +195,7 @@ _Noreturn void __pthread_exit(void *result) |
| 191 | 		__tl_unlock(); | 195 | 		__tl_unlock(); |
| 192 | 		free(self->map_base); | 196 | 		free(self->map_base); |
| 193 | 		// Can't use `exit()` here, because it is too high level | 197 | 		// Can't use `exit()` here, because it is too high level |
| 194 | 		for (;;) __wasi_proc_exit(0); | 198 | 		return; |
| 195 | 	} | 199 | 	} |
| 196 | #endif | 200 | #endif |
| 197 | 201 | ||
| ... | @@ -212,7 +216,6 @@ _Noreturn void __pthread_exit(void *result) | ... | @@ -212,7 +216,6 @@ _Noreturn void __pthread_exit(void *result) |
| 212 | 	// do it manually here | 216 | 	// do it manually here |
| 213 | 	__tl_unlock(); | 217 | 	__tl_unlock(); |
| 214 | 	// Can't use `exit()` here, because it is too high level | 218 | 	// Can't use `exit()` here, because it is too high level |
| 215 | 	for (;;) __wasi_proc_exit(0); | ||
| 216 | #endif | 219 | #endif |
| 217 | } | 220 | } |
| 218 | 221 | ||
| ... | @@ -235,9 +238,14 @@ struct start_args { | ... | @@ -235,9 +238,14 @@ struct start_args { |
| 235 | 	volatile int control; | 238 | 	volatile int control; |
| 236 | 	unsigned long sig_mask[_NSIG/8/sizeof(long)]; | 239 | 	unsigned long sig_mask[_NSIG/8/sizeof(long)]; |
| 237 | #else | 240 | #else |
| 241 | 	/* | ||
| 242 | 	 * Note: the offset of the "stack" and "tls_base" members | ||
| 243 | 	 * in this structure is hardcoded in wasi_thread_start. | ||
| 244 | 	 */ | ||
| 245 | 	void *stack; | ||
| 246 | 	void *tls_base; | ||
| 238 | 	void *(*start_func)(void *); | 247 | 	void *(*start_func)(void *); |
| 239 | 	void *start_arg; | 248 | 	void *start_arg; |
| 240 | 	void *tls_base; | ||
| 241 | #endif | 249 | #endif |
| 242 | }; | 250 | }; |
| 243 | 251 | ||
| ... | @@ -271,32 +279,41 @@ static int start_c11(void *p) | ... | @@ -271,32 +279,41 @@ static int start_c11(void *p) |
| 271 | 	return 0; | 279 | 	return 0; |
| 272 | } | 280 | } |
| 273 | #else | 281 | #else |
| 274 | __attribute__((export_name("wasi_thread_start"))) | 282 | |
| 275 | _Noreturn void wasi_thread_start(int tid, void *p) | 283 | /* |
| 284 | * We want to ensure wasi_thread_start is linked whenever | ||
| 285 | * pthread_create is used. The following reference is to ensure that. | ||
| 286 | * Otherwise, the linker doesn't notice the dependency because | ||
| 287 | * wasi_thread_start is used indirectly via a wasm export. | ||
| 288 | */ | ||
| 289 | void wasi_thread_start(int tid, void *p); | ||
| 290 | hidden void *__dummy_reference = wasi_thread_start; | ||
| 291 | |||
| 292 | hidden void __wasi_thread_start_C(int tid, void *p) | ||
| 276 | { | 293 | { |
| 277 | 	struct start_args *args = p; | 294 | 	struct start_args *args = p; |
| 278 | 	__asm__(".globaltype __tls_base, i32\n" | ||
| 279 | 			"local.get %0\n" | ||
| 280 | 			"global.set __tls_base\n" | ||
| 281 | 			:: "r"(args->tls_base)); | ||
| 282 | 	pthread_t self = __pthread_self(); | 295 | 	pthread_t self = __pthread_self(); |
| 283 | 	// Set the thread ID (TID) on the pthread structure. The TID is stored | 296 | 	// Set the thread ID (TID) on the pthread structure. The TID is stored |
| 284 | 	// atomically since it is also stored by the parent thread; this way, | 297 | 	// atomically since it is also stored by the parent thread; this way, |
| 285 | 	// whichever thread (parent or child) reaches this point first can proceed | 298 | 	// whichever thread (parent or child) reaches this point first can proceed |
| 286 | 	// without waiting. | 299 | 	// without waiting. |
| 287 | 	atomic_store((atomic_int *) &(self->tid), tid); | 300 | 	atomic_store((atomic_int *) &(self->tid), tid); |
| 288 | 	// Set the stack pointer. | ||
| 289 | 	__asm__(".globaltype __stack_pointer, i32\n" | ||
| 290 | 			"local.get %0\n" | ||
| 291 | 			"global.set __stack_pointer\n" | ||
| 292 | 			:: "r"(self->stack)); | ||
| 293 | 	// Execute the user's start function. | 301 | 	// Execute the user's start function. |
| 294 | 	int (*start)(void*) = (int(*)(void*)) args->start_func; | 302 | 	__pthread_exit(args->start_func(args->start_arg)); |
| 295 | 	__pthread_exit((void *)(uintptr_t)start(args->start_arg)); | ||
| 296 | } | 303 | } |
| 297 | #endif | 304 | #endif |
| 298 | 305 | ||
| 306 | #ifdef __wasilibc_unmodified_upstream | ||
| 299 | #define ROUND(x) (((x)+PAGE_SIZE-1)&-PAGE_SIZE) | 307 | #define ROUND(x) (((x)+PAGE_SIZE-1)&-PAGE_SIZE) |
| 308 | #else | ||
| 309 | /* | ||
| 310 | * As we allocate stack with malloc() instead of mmap/mprotect, | ||
| 311 | * there is no point to round it up to PAGE_SIZE. | ||
| 312 | * Instead, round up to a sane alignment. | ||
| 313 | * Note: PAGE_SIZE is rather big on WASM. (65536) | ||
| 314 | */ | ||
| 315 | #define ROUND(x) (((x)+16-1)&-16) | ||
| 316 | #endif | ||
| 300 | 317 | ||
| 301 | /* pthread_key_create.c overrides this */ | 318 | /* pthread_key_create.c overrides this */ |
| 302 | static volatile size_t dummy = 0; | 319 | static volatile size_t dummy = 0; |
| ... | @@ -484,6 +501,7 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att | ... | @@ -484,6 +501,7 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att |
| 484 | 	/* Correct the stack size */ | 501 | 	/* Correct the stack size */ |
| 485 | 	new->stack_size = stack - stack_limit; | 502 | 	new->stack_size = stack - stack_limit; |
| 486 | 503 | ||
| 504 | 	args->stack = new->stack; /* just for convenience of asm trampoline */ | ||
| 487 | 	args->start_func = entry; | 505 | 	args->start_func = entry; |
| 488 | 	args->start_arg = arg; | 506 | 	args->start_arg = arg; |
| 489 | 	args->tls_base = (void*)new_tls_base; | 507 | 	args->tls_base = (void*)new_tls_base; |
| ... | @@ -561,5 +579,7 @@ fail: | ... | @@ -561,5 +579,7 @@ fail: |
| 561 | 	return EAGAIN; | 579 | 	return EAGAIN; |
| 562 | } | 580 | } |
| 563 | 581 | ||
| 582 | #ifdef __wasilibc_unmodified_upstream | ||
| 564 | weak_alias(__pthread_exit, pthread_exit); | 583 | weak_alias(__pthread_exit, pthread_exit); |
| 584 | #endif | ||
| 565 | weak_alias(__pthread_create, pthread_create); | 585 | weak_alias(__pthread_create, pthread_create); |
lib/libc/wasi/libc-top-half/musl/src/thread/pthread_key_create.c+4| ... | @@ -50,7 +50,9 @@ int __pthread_key_delete(pthread_key_t k) | ... | @@ -50,7 +50,9 @@ int __pthread_key_delete(pthread_key_t k) |
| 50 | 	sigset_t set; | 50 | 	sigset_t set; |
| 51 | 	pthread_t self = __pthread_self(), td=self; | 51 | 	pthread_t self = __pthread_self(), td=self; |
| 52 | 52 | ||
| 53 | #ifdef __wasilibc_unmodified_upstream | ||
| 53 | 	__block_app_sigs(&set); | 54 | 	__block_app_sigs(&set); |
| 55 | #endif | ||
| 54 | 	__pthread_rwlock_wrlock(&key_lock); | 56 | 	__pthread_rwlock_wrlock(&key_lock); |
| 55 | 57 | ||
| 56 | 	__tl_lock(); | 58 | 	__tl_lock(); |
| ... | @@ -61,7 +63,9 @@ int __pthread_key_delete(pthread_key_t k) | ... | @@ -61,7 +63,9 @@ int __pthread_key_delete(pthread_key_t k) |
| 61 | 	keys[k] = 0; | 63 | 	keys[k] = 0; |
| 62 | 64 | ||
| 63 | 	__pthread_rwlock_unlock(&key_lock); | 65 | 	__pthread_rwlock_unlock(&key_lock); |
| 66 | #ifdef __wasilibc_unmodified_upstream | ||
| 64 | 	__restore_sigs(&set); | 67 | 	__restore_sigs(&set); |
| 68 | #endif | ||
| 65 | 69 | ||
| 66 | 	return 0; | 70 | 	return 0; |
| 67 | } | 71 | } |