authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2023-01-09 19:17:06+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-01-10 17:14:27-05:00
log24d8d12caf05e52fe938d1eb01211b2470cffb41
tree85820c0a6bf542af3d0794fb029490460e439528
parent0cba60afed935b9ea0f40324cc15730414f2550e

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.

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/#readme2100 * @see https://github.com/WebAssembly/wasi-threads/#readme
2101 */2101 */
2102__wasi_errno_t __wasi_thread_spawn(2102int32_t __wasi_thread_spawn(
2103 /**2103 /**
2104 * A pointer to an opaque struct to be passed to the module's entry2104 * 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>
1415
15#include "dirent_impl.h"16#include "dirent_impl.h"
1617
...@@ -21,6 +22,8 @@ static int sel_true(const struct dirent *de) {...@@ -21,6 +22,8 @@ static int sel_true(const struct dirent *de) {
21int __wasilibc_nocwd_scandirat(int dirfd, const char *dir, struct dirent ***namelist,22int __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;
97120
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}
140140
141extern __typeof(signal) bsd_signal __attribute__((__weak__, alias("signal")));141extern __typeof(signal) bsd_signal __attribute__((weak, alias("signal")));
142extern __typeof(signal) __sysv_signal __attribute__((__weak__, alias("signal")));142extern __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));
667667
668__wasi_errno_t __wasi_thread_spawn(void* start_arg) {668int32_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#endif671#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) {
1919
20 return 1;20 return 1;
21}21}
22extern __typeof(__isatty) isatty __attribute__((__weak__, alias("__isatty")));22extern __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);
6060
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 }
6666
...@@ -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);
7373
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 }
7979
...@@ -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);
9090
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 }
9696
...@@ -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);
103103
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 }
109109
...@@ -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);
116116
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 }
122122
...@@ -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);
129129
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 }
135135
...@@ -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);
149149
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 }
155155
...@@ -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);
171171
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 }
177177
...@@ -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);
187187
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 }
193193
...@@ -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);
200200
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 }
206206
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);
212212
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);
223223
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 }
229229
...@@ -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);
236236
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 }
242242
...@@ -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);
254254
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 }
260260
...@@ -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);
267267
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 }
273273
...@@ -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 }
289289
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}
294294
...@@ -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 }
307307
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}
312312
...@@ -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);
319319
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 }
325325
...@@ -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);
336336
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 }
342342
...@@ -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);
353353
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 }
359359
...@@ -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);
371371
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 }
377377
...@@ -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);
389389
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 }
395395
...@@ -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);
407407
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 }
413413
...@@ -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);
425425
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 }
431431
...@@ -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);
441441
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 }
447447
lib/libc/wasi/libc-top-half/musl/include/pthread.h+2
...@@ -85,7 +85,9 @@ extern "C" {...@@ -85,7 +85,9 @@ extern "C" {
8585
86int pthread_create(pthread_t *__restrict, const pthread_attr_t *__restrict, void *(*)(void *), void *__restrict);86int pthread_create(pthread_t *__restrict, const pthread_attr_t *__restrict, void *(*)(void *), void *__restrict);
87int pthread_detach(pthread_t);87int pthread_detach(pthread_t);
88#ifdef __wasilibc_unmodified_upstream
88_Noreturn void pthread_exit(void *);89_Noreturn void pthread_exit(void *);
90#endif
89int pthread_join(pthread_t, void **);91int pthread_join(pthread_t, void **);
9092
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#endif336#endif
337#define _POSIX_VDISABLE 0337#define _POSIX_VDISABLE 0
338338
339#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
339#define _POSIX_THREADS _POSIX_VERSION340#define _POSIX_THREADS _POSIX_VERSION
341#endif
340#define _POSIX_THREAD_PROCESS_SHARED _POSIX_VERSION342#define _POSIX_THREAD_PROCESS_SHARED _POSIX_VERSION
341#define _POSIX_THREAD_SAFE_FUNCTIONS _POSIX_VERSION343#define _POSIX_THREAD_SAFE_FUNCTIONS _POSIX_VERSION
342#define _POSIX_THREAD_ATTR_STACKADDR _POSIX_VERSION344#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 @@
16volatile int __thread_list_lock;16volatile int __thread_list_lock;
1717
18#ifndef __wasilibc_unmodified_upstream18#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 */
28extern unsigned char __heap_base;
29extern unsigned char __data_end;
30extern unsigned char __global_base;
31extern weak unsigned char __stack_high;
32extern weak unsigned char __stack_low;
33
34static 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
19void __wasi_init_tp() {56void __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#endif85#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));
7hidden void __pthread_testcancel(void);7hidden void __pthread_testcancel(void);
8hidden int __pthread_setcancelstate(int, int *);8hidden int __pthread_setcancelstate(int, int *);
9hidden int __pthread_create(pthread_t *restrict, const pthread_attr_t *restrict, void *(*)(void *), void *restrict);9hidden int __pthread_create(pthread_t *restrict, const pthread_attr_t *restrict, void *(*)(void *), void *restrict);
10#ifdef __wasilibc_unmodified_upstream
10hidden _Noreturn void __pthread_exit(void *);11hidden _Noreturn void __pthread_exit(void *);
12#endif
11hidden int __pthread_join(pthread_t, void **);13hidden int __pthread_join(pthread_t, void **);
12hidden int __pthread_mutex_lock(pthread_mutex_t *);14hidden int __pthread_mutex_lock(pthread_mutex_t *);
13hidden int __pthread_mutex_trylock(pthread_mutex_t *);15hidden 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;
216extern hidden unsigned __default_guardsize;216extern hidden unsigned __default_guardsize;
217217
218#define DEFAULT_STACK_SIZE 131072218#define DEFAULT_STACK_SIZE 131072
219#ifdef __wasilibc_unmodified_upstream
219#define DEFAULT_GUARD_SIZE 8192220#define DEFAULT_GUARD_SIZE 8192
221#else
222/* guard doesn't make much sense without mprotect. */
223#define DEFAULT_GUARD_SIZE 0
224#endif
220225
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) != -ENOSYS48 __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#else50#else
51 __wasilibc_futex_wait(addr, FUTEX_WAIT, val, 0);51 __wasilibc_futex_wait(addr, FUTEX_WAIT, val, -1);
52#endif52#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}
1919
20#ifdef __wasilibc_unmodified_upstream /* WASI has no CPU scheduling support. */
20int pthread_attr_getschedparam(const pthread_attr_t *restrict a, struct sched_param *restrict param)21int 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
3133
32int pthread_attr_getscope(const pthread_attr_t *restrict a, int *restrict scope)34int 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}
5860
61#ifdef __wasilibc_unmodified_upstream /* Forward declaration of WASI's `__clockid` type. */
59int pthread_condattr_getclock(const pthread_condattr_t *restrict a, clockid_t *restrict clk)62int 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
6468
65int pthread_condattr_getpshared(const pthread_condattr_t *restrict a, int *restrict pshared)69int 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 }
2525
26#ifdef __wasilibc_unmodified_upstream /* WASI does not understand processes or locking between them. */
26 __vm_lock();27 __vm_lock();
28#endif
2729
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);
4648
49#ifdef __wasilibc_unmodified_upstream /* WASI does not understand processes or locking between them. */
47 __vm_unlock();50 __vm_unlock();
51#endif
4852
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) != -ENOSYS92 __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 }
9199
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}
6262
63#ifdef __wasilibc_unmodified_upstream
63_Noreturn void __pthread_exit(void *result)64_Noreturn void __pthread_exit(void *result)
65#else
66static 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 level197 // Can't use `exit()` here, because it is too high level
194 for (;;) __wasi_proc_exit(0);198 return;
195 }199 }
196#endif200#endif
197201
...@@ -212,7 +216,6 @@ _Noreturn void __pthread_exit(void *result)...@@ -212,7 +216,6 @@ _Noreturn void __pthread_exit(void *result)
212 // do it manually here216 // do it manually here
213 __tl_unlock();217 __tl_unlock();
214 // Can't use `exit()` here, because it is too high level218 // Can't use `exit()` here, because it is too high level
215 for (;;) __wasi_proc_exit(0);
216#endif219#endif
217}220}
218221
...@@ -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#else240#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#endif249#endif
242};250};
243251
...@@ -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#else281#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 */
289void wasi_thread_start(int tid, void *p);
290hidden void *__dummy_reference = wasi_thread_start;
291
292hidden 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 stored296 // 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 proceed298 // 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#endif304#endif
298305
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
300317
301/* pthread_key_create.c overrides this */318/* pthread_key_create.c overrides this */
302static volatile size_t dummy = 0;319static 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;
486503
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}
563581
582#ifdef __wasilibc_unmodified_upstream
564weak_alias(__pthread_exit, pthread_exit);583weak_alias(__pthread_exit, pthread_exit);
584#endif
565weak_alias(__pthread_create, pthread_create);585weak_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;
5252
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);
5557
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;
6264
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
6569
66 return 0;70 return 0;
67}71}