Skip to content

Commit dcd28cf

Browse files
abrownsbc100
andauthoredAug 9, 2022
Fix make THREAD_MODEL=posix (#311)
* Fixes for the THREAD_MODEL=posix build * Fix expected symbols from previous commit * Enable `lock` in `random.c` when threads are enabled This uses the `_REENTRANT` definition to indicate when the `lock` should be available. * Disable `aio.h` when compiling for threads In talking to @sunfishcode about `aio.h`, this functionality is not yet a primary concern (it was already disabled in the default, single-threaded mode). Additionally, this change adds expectation lines for the new symbols/includes added and removed by `pthread.h`. This change was reached by running: ```console $ git diff --no-index expected/wasm32-wasi sysroot/share/wasm32-wasi > patch.diff # replace "sysroot/share" with "expected" in `patch.diff` $ git apply patch.diff --reject # manually fix any rejections ``` * Specify the TLS model until LLVM 15 is released The `-ftls-model` configuration can be removed once https://reviews.llvm.org/D130053 makes its way into an upstream release. * Rename `__wasi_libc_pthread_self` to `__wasilibc_pthread_self` The symbol is still undefined, though. * Add different sets of expected output based on THREAD_MODEL * Re-add trailing whitespace to `predefined-macros.txt` @sbc100 wanted to retain the whitespace trailing after certain predefined macro lines. This change restores that whitespace from upstream and re-generates the POSIX version using the following command: ```console $ git diff --no-index expected/wasm32-wasi/posix/predefined-macros.txt sysroot/share/wasm32-wasi/predefined-macros.txt | sed 's/sysroot\/share\/wasm32-wasi/expected\/wasm32-wasi\/posix/' | git apply ``` * Protect `preopens.c` against concurrent access * Only build thread-capable wasi-libc on latest version of Clang * Use `thrd_sleep` from MUSL instead of aliasing `nanosleep` * Define `pthread_setcancelstate` in `THREAD_MODEL=posix` builds There are other options here (e.g., always define the `pthread_*` symbols with stubs) but until we discuss that this is an intermediate working step. * Define a Wasm global to store `pthread_self` * Remove `g_needs_dynamic_alloc` global * Document the state of pthread support * review: de-duplicate symbols based on #314 * review: only define `__wasilibc_cwd_{un}lock` when needed * review: add #ifdefs to `__pthread_setcancelstate` * review: add additional #ifdefs to `pthread_self.c` * review: put lock definition behind #ifdef _REENTRANT * review: remove pthread_setcancelstate.c * review: re-fix indentation * review: alias __clock_nanosleep in bottom half * review: remove extra line Co-authored-by: Sam Clegg <[email protected]>
1 parent 69031b6 commit dcd28cf

26 files changed

+4973
-46
lines changed
 

‎.github/workflows/main.yml

+8
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,14 @@ jobs:
6666
name: ${{ format( 'sysroot-{0}.tgz', matrix.os) }}
6767
path: sysroot
6868

69+
- name: Build libc + threads
70+
# Only build the thread-capable wasi-libc in the latest supported Clang
71+
# version; the earliest version does not have all necessary builtins
72+
# (e.g., `__builtin_wasm_memory_atomic_notify`).
73+
if: matrix.clang_version != '10.0.0'
74+
shell: bash
75+
run: make -j4 THREAD_MODEL=posix
76+
6977
# Disable the headerstest job for now, while WASI transitions from the
7078
# witx snapshots to wit proposals, and we have a few manual edits to the
7179
# generated header to make life easier for folks.

‎Makefile

+10-5
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ EXTRA_CFLAGS ?= -O2 -DNDEBUG
1313
SYSROOT ?= $(CURDIR)/sysroot
1414
# A directory to install to for "make install".
1515
INSTALL_DIR ?= /usr/local
16-
# single or posix
16+
# single or posix; note that pthread support is still a work-in-progress.
1717
THREAD_MODEL ?= single
1818
# dlmalloc or none
1919
MALLOC_IMPL ?= dlmalloc
@@ -147,6 +147,7 @@ LIBC_TOP_HALF_MUSL_SOURCES = \
147147
unistd/posix_close.c \
148148
stat/futimesat.c \
149149
legacy/getpagesize.c \
150+
thread/thrd_sleep.c \
150151
) \
151152
$(filter-out %/procfdname.c %/syscall.c %/syscall_ret.c %/vdso.c %/version.c, \
152153
$(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/internal/*.c)) \
@@ -185,6 +186,7 @@ LIBC_TOP_HALF_MUSL_SOURCES = \
185186
%/cimagf.c %/cimag.c %cimagl.c, \
186187
$(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/complex/*.c)) \
187188
$(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/crypt/*.c)
189+
188190
MUSL_PRINTSCAN_SOURCES = \
189191
$(LIBC_TOP_HALF_MUSL_SRC_DIR)/internal/floatscan.c \
190192
$(LIBC_TOP_HALF_MUSL_SRC_DIR)/stdio/vfprintf.c \
@@ -227,7 +229,9 @@ ifeq ($(THREAD_MODEL), single)
227229
CFLAGS += -mthread-model single
228230
endif
229231
ifeq ($(THREAD_MODEL), posix)
230-
CFLAGS += -mthread-model posix -pthread
232+
# Specify the tls-model until LLVM 15 is released (which should contain
233+
# https://reviews.llvm.org/D130053).
234+
CFLAGS += -mthread-model posix -pthread -ftls-model=local-exec
231235
endif
232236

233237
# Expose the public headers to the implementation. We use `-isystem` for
@@ -356,11 +360,12 @@ MUSL_OMIT_HEADERS += \
356360
"netinet/ether.h" \
357361
"sys/timerfd.h" \
358362
"libintl.h" \
359-
"sys/sysmacros.h"
363+
"sys/sysmacros.h" \
364+
"aio.h"
360365

361366
ifeq ($(THREAD_MODEL), single)
362367
# Remove headers not supported in single-threaded mode.
363-
MUSL_OMIT_HEADERS += "aio.h" "pthread.h"
368+
MUSL_OMIT_HEADERS += "pthread.h"
364369
endif
365370

366371
default: finish
@@ -595,7 +600,7 @@ check-symbols: startup_files libc
595600

596601
# Check that the computed metadata matches the expected metadata.
597602
# This ignores whitespace because on Windows the output has CRLF line endings.
598-
diff -wur "$(CURDIR)/expected/$(MULTIARCH_TRIPLE)" "$(SYSROOT_SHARE)"
603+
diff -wur "$(CURDIR)/expected/$(MULTIARCH_TRIPLE)/$(THREAD_MODEL)" "$(SYSROOT_SHARE)"
599604

600605
install: finish
601606
mkdir -p "$(INSTALL_DIR)"

‎README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ environment variables, program startup, and many other APIs.
77

88
WASI Libc is sufficiently stable and usable for many purposes, as most of the
99
POSIX-compatible APIs are stable, though it is continuing to evolve to better
10-
align with wasm and WASI.
10+
align with wasm and WASI. For example, pthread support is still a work in
11+
progress.
1112

1213
## Usage
1314

‎expected/wasm32-wasi/posix/defined-symbols.txt

+1,210
Large diffs are not rendered by default.
+171
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
#include <__errno.h>
2+
#include <__errno_values.h>
3+
#include <__fd_set.h>
4+
#include <__function___isatty.h>
5+
#include <__functions_malloc.h>
6+
#include <__functions_memcpy.h>
7+
#include <__header_dirent.h>
8+
#include <__header_fcntl.h>
9+
#include <__header_inttypes.h>
10+
#include <__header_netinet_in.h>
11+
#include <__header_poll.h>
12+
#include <__header_stdlib.h>
13+
#include <__header_string.h>
14+
#include <__header_sys_ioctl.h>
15+
#include <__header_sys_resource.h>
16+
#include <__header_sys_socket.h>
17+
#include <__header_sys_stat.h>
18+
#include <__header_time.h>
19+
#include <__header_unistd.h>
20+
#include <__macro_FD_SETSIZE.h>
21+
#include <__macro_PAGESIZE.h>
22+
#include <__mode_t.h>
23+
#include <__seek.h>
24+
#include <__struct_dirent.h>
25+
#include <__struct_in6_addr.h>
26+
#include <__struct_in_addr.h>
27+
#include <__struct_iovec.h>
28+
#include <__struct_msghdr.h>
29+
#include <__struct_pollfd.h>
30+
#include <__struct_rusage.h>
31+
#include <__struct_sockaddr.h>
32+
#include <__struct_sockaddr_in.h>
33+
#include <__struct_sockaddr_in6.h>
34+
#include <__struct_sockaddr_storage.h>
35+
#include <__struct_sockaddr_un.h>
36+
#include <__struct_stat.h>
37+
#include <__struct_timespec.h>
38+
#include <__struct_timeval.h>
39+
#include <__struct_tm.h>
40+
#include <__struct_tms.h>
41+
#include <__typedef_DIR.h>
42+
#include <__typedef_blkcnt_t.h>
43+
#include <__typedef_blksize_t.h>
44+
#include <__typedef_clock_t.h>
45+
#include <__typedef_clockid_t.h>
46+
#include <__typedef_dev_t.h>
47+
#include <__typedef_fd_set.h>
48+
#include <__typedef_gid_t.h>
49+
#include <__typedef_in_addr_t.h>
50+
#include <__typedef_in_port_t.h>
51+
#include <__typedef_ino_t.h>
52+
#include <__typedef_mode_t.h>
53+
#include <__typedef_nfds_t.h>
54+
#include <__typedef_nlink_t.h>
55+
#include <__typedef_off_t.h>
56+
#include <__typedef_sa_family_t.h>
57+
#include <__typedef_sigset_t.h>
58+
#include <__typedef_socklen_t.h>
59+
#include <__typedef_ssize_t.h>
60+
#include <__typedef_suseconds_t.h>
61+
#include <__typedef_time_t.h>
62+
#include <__typedef_uid_t.h>
63+
#include <alloca.h>
64+
#include <ar.h>
65+
#include <arpa/ftp.h>
66+
#include <arpa/inet.h>
67+
#include <arpa/nameser.h>
68+
#include <arpa/nameser_compat.h>
69+
#include <arpa/telnet.h>
70+
#include <arpa/tftp.h>
71+
#include <assert.h>
72+
#include <byteswap.h>
73+
#include <complex.h>
74+
#include <cpio.h>
75+
#include <crypt.h>
76+
#include <ctype.h>
77+
#include <dirent.h>
78+
#include <endian.h>
79+
#include <err.h>
80+
#include <errno.h>
81+
#include <fcntl.h>
82+
#include <features.h>
83+
#include <fenv.h>
84+
#include <float.h>
85+
#include <fmtmsg.h>
86+
#include <fnmatch.h>
87+
#include <ftw.h>
88+
#include <getopt.h>
89+
#include <glob.h>
90+
#include <iconv.h>
91+
#include <ifaddrs.h>
92+
#include <inttypes.h>
93+
#include <iso646.h>
94+
#include <langinfo.h>
95+
#include <libgen.h>
96+
#include <limits.h>
97+
#include <locale.h>
98+
#include <malloc.h>
99+
#include <math.h>
100+
#include <memory.h>
101+
#include <monetary.h>
102+
#include <mqueue.h>
103+
#include <netinet/icmp6.h>
104+
#include <netinet/igmp.h>
105+
#include <netinet/in.h>
106+
#include <netinet/in_systm.h>
107+
#include <netinet/ip.h>
108+
#include <netinet/ip6.h>
109+
#include <netinet/ip_icmp.h>
110+
#include <netinet/tcp.h>
111+
#include <netinet/udp.h>
112+
#include <netpacket/packet.h>
113+
#include <nl_types.h>
114+
#include <poll.h>
115+
#include <pthread.h>
116+
#include <regex.h>
117+
#include <sched.h>
118+
#include <search.h>
119+
#include <semaphore.h>
120+
#include <stdalign.h>
121+
#include <stdbool.h>
122+
#include <stdc-predef.h>
123+
#include <stdint.h>
124+
#include <stdio.h>
125+
#include <stdio_ext.h>
126+
#include <stdlib.h>
127+
#include <stdnoreturn.h>
128+
#include <string.h>
129+
#include <strings.h>
130+
#include <stropts.h>
131+
#include <sys/dir.h>
132+
#include <sys/errno.h>
133+
#include <sys/eventfd.h>
134+
#include <sys/fcntl.h>
135+
#include <sys/file.h>
136+
#include <sys/ioctl.h>
137+
#include <sys/param.h>
138+
#include <sys/poll.h>
139+
#include <sys/random.h>
140+
#include <sys/reg.h>
141+
#include <sys/select.h>
142+
#include <sys/socket.h>
143+
#include <sys/stat.h>
144+
#include <sys/stropts.h>
145+
#include <sys/syscall.h>
146+
#include <sys/sysinfo.h>
147+
#include <sys/time.h>
148+
#include <sys/timeb.h>
149+
#include <sys/timex.h>
150+
#include <sys/ttydefaults.h>
151+
#include <sys/types.h>
152+
#include <sys/uio.h>
153+
#include <sys/un.h>
154+
#include <sys/utsname.h>
155+
#include <syscall.h>
156+
#include <sysexits.h>
157+
#include <tar.h>
158+
#include <tgmath.h>
159+
#include <threads.h>
160+
#include <time.h>
161+
#include <uchar.h>
162+
#include <unistd.h>
163+
#include <utime.h>
164+
#include <values.h>
165+
#include <wasi/api.h>
166+
#include <wasi/libc-environ.h>
167+
#include <wasi/libc-find-relpath.h>
168+
#include <wasi/libc-nocwd.h>
169+
#include <wasi/libc.h>
170+
#include <wchar.h>
171+
#include <wctype.h>

‎expected/wasm32-wasi/posix/predefined-macros.txt

+3,396
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
__addtf3
2+
__divtf3
3+
__eqtf2
4+
__extenddftf2
5+
__extendsftf2
6+
__fixtfdi
7+
__fixtfsi
8+
__fixunstfsi
9+
__floatsitf
10+
__floatunsitf
11+
__getf2
12+
__gttf2
13+
__heap_base
14+
__imported_wasi_snapshot_preview1_args_get
15+
__imported_wasi_snapshot_preview1_args_sizes_get
16+
__imported_wasi_snapshot_preview1_clock_res_get
17+
__imported_wasi_snapshot_preview1_clock_time_get
18+
__imported_wasi_snapshot_preview1_environ_get
19+
__imported_wasi_snapshot_preview1_environ_sizes_get
20+
__imported_wasi_snapshot_preview1_fd_advise
21+
__imported_wasi_snapshot_preview1_fd_allocate
22+
__imported_wasi_snapshot_preview1_fd_close
23+
__imported_wasi_snapshot_preview1_fd_datasync
24+
__imported_wasi_snapshot_preview1_fd_fdstat_get
25+
__imported_wasi_snapshot_preview1_fd_fdstat_set_flags
26+
__imported_wasi_snapshot_preview1_fd_fdstat_set_rights
27+
__imported_wasi_snapshot_preview1_fd_filestat_get
28+
__imported_wasi_snapshot_preview1_fd_filestat_set_size
29+
__imported_wasi_snapshot_preview1_fd_filestat_set_times
30+
__imported_wasi_snapshot_preview1_fd_pread
31+
__imported_wasi_snapshot_preview1_fd_prestat_dir_name
32+
__imported_wasi_snapshot_preview1_fd_prestat_get
33+
__imported_wasi_snapshot_preview1_fd_pwrite
34+
__imported_wasi_snapshot_preview1_fd_read
35+
__imported_wasi_snapshot_preview1_fd_readdir
36+
__imported_wasi_snapshot_preview1_fd_renumber
37+
__imported_wasi_snapshot_preview1_fd_seek
38+
__imported_wasi_snapshot_preview1_fd_sync
39+
__imported_wasi_snapshot_preview1_fd_tell
40+
__imported_wasi_snapshot_preview1_fd_write
41+
__imported_wasi_snapshot_preview1_path_create_directory
42+
__imported_wasi_snapshot_preview1_path_filestat_get
43+
__imported_wasi_snapshot_preview1_path_filestat_set_times
44+
__imported_wasi_snapshot_preview1_path_link
45+
__imported_wasi_snapshot_preview1_path_open
46+
__imported_wasi_snapshot_preview1_path_readlink
47+
__imported_wasi_snapshot_preview1_path_remove_directory
48+
__imported_wasi_snapshot_preview1_path_rename
49+
__imported_wasi_snapshot_preview1_path_symlink
50+
__imported_wasi_snapshot_preview1_path_unlink_file
51+
__imported_wasi_snapshot_preview1_poll_oneoff
52+
__imported_wasi_snapshot_preview1_proc_exit
53+
__imported_wasi_snapshot_preview1_random_get
54+
__imported_wasi_snapshot_preview1_sched_yield
55+
__imported_wasi_snapshot_preview1_sock_accept
56+
__imported_wasi_snapshot_preview1_sock_recv
57+
__imported_wasi_snapshot_preview1_sock_send
58+
__imported_wasi_snapshot_preview1_sock_shutdown
59+
__letf2
60+
__lock
61+
__lockfile
62+
__lttf2
63+
__main_argc_argv
64+
__netf2
65+
__stack_pointer
66+
__subtf3
67+
__tls_base
68+
__trunctfdf2
69+
__trunctfsf2
70+
__unlock
71+
__unlockfile
72+
__unordtf2
73+
__wasilibc_pthread_self
74+
__wasm_call_ctors
75+
pthread_setcancelstate

‎expected/wasm32-wasi/defined-symbols.txt ‎expected/wasm32-wasi/single/defined-symbols.txt

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ __c_dot_utf8_locale
1818
__c_locale
1919
__clock
2020
__clock_gettime
21+
__clock_nanosleep
2122
__cos
2223
__cosdf
2324
__cosl
@@ -1082,6 +1083,7 @@ tfind
10821083
tgamma
10831084
tgammaf
10841085
tgammal
1086+
thrd_sleep
10851087
time
10861088
timegm
10871089
times
File renamed without changes.

‎libc-bottom-half/cloudlibc/src/libc/time/clock_nanosleep.c

+2
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,5 @@ int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp,
3333
__wasi_errno_t error = __wasi_poll_oneoff(&sub, &ev, 1, &nevents);
3434
return error == 0 && ev.error == 0 ? 0 : ENOTSUP;
3535
}
36+
37+
weak_alias(clock_nanosleep, __clock_nanosleep);

‎libc-bottom-half/cloudlibc/src/libc/time/nanosleep.c

-6
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
// SPDX-License-Identifier: BSD-2-Clause
44

55
#include <errno.h>
6-
#include <threads.h>
76
#include <time.h>
8-
#include <_/cdefs.h>
97

108
int nanosleep(const struct timespec *rqtp, struct timespec *rem) {
119
int error = clock_nanosleep(CLOCK_REALTIME, 0, rqtp, rem);
@@ -15,7 +13,3 @@ int nanosleep(const struct timespec *rqtp, struct timespec *rem) {
1513
}
1614
return 0;
1715
}
18-
19-
#if defined(_REENTRANT)
20-
__strong_reference(nanosleep, thrd_sleep);
21-
#endif

‎libc-bottom-half/sources/chdir.c

+23-4
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@
99
#include <wasi/libc.h>
1010

1111
#ifdef _REENTRANT
12-
#error "chdir doesn't yet support multiple threads"
12+
void __wasilibc_cwd_lock(void);
13+
void __wasilibc_cwd_unlock(void);
14+
#else
15+
#define __wasilibc_cwd_lock() (void)0
16+
#define __wasilibc_cwd_unlock() (void)0
1317
#endif
14-
1518
extern char *__wasilibc_cwd;
1619
static int __wasilibc_cwd_mallocd = 0;
1720

@@ -60,8 +63,10 @@ int chdir(const char *path)
6063

6164
// And set our new malloc'd buffer into the global cwd, freeing the
6265
// previous one if necessary.
66+
__wasilibc_cwd_lock();
6367
char *prev_cwd = __wasilibc_cwd;
6468
__wasilibc_cwd = new_cwd;
69+
__wasilibc_cwd_unlock();
6570
if (__wasilibc_cwd_mallocd)
6671
free(prev_cwd);
6772
__wasilibc_cwd_mallocd = 1;
@@ -77,11 +82,13 @@ static const char *make_absolute(const char *path) {
7782
return path;
7883
}
7984

85+
#ifndef _REENTRANT
8086
// If the path is empty, or points to the current directory, then return
8187
// the current directory.
8288
if (path[0] == 0 || !strcmp(path, ".") || !strcmp(path, "./")) {
8389
return __wasilibc_cwd;
8490
}
91+
#endif
8592

8693
// If the path starts with `./` then we won't be appending that to the cwd.
8794
if (path[0] == '.' && path[1] == '/')
@@ -90,18 +97,30 @@ static const char *make_absolute(const char *path) {
9097
// Otherwise we'll take the current directory, add a `/`, and then add the
9198
// input `path`. Note that this doesn't do any normalization (like removing
9299
// `/./`).
100+
__wasilibc_cwd_lock();
93101
size_t cwd_len = strlen(__wasilibc_cwd);
94-
size_t path_len = strlen(path);
102+
size_t path_len = path ? strlen(path) : 0;
103+
__wasilibc_cwd_unlock();
95104
int need_slash = __wasilibc_cwd[cwd_len - 1] == '/' ? 0 : 1;
96105
size_t alloc_len = cwd_len + path_len + 1 + need_slash;
97106
if (alloc_len > make_absolute_len) {
98107
char *tmp = realloc(make_absolute_buf, alloc_len);
99-
if (tmp == NULL)
108+
if (tmp == NULL) {
109+
__wasilibc_cwd_unlock();
100110
return NULL;
111+
}
101112
make_absolute_buf = tmp;
102113
make_absolute_len = alloc_len;
103114
}
104115
strcpy(make_absolute_buf, __wasilibc_cwd);
116+
__wasilibc_cwd_unlock();
117+
118+
#ifdef _REENTRANT
119+
if (path[0] == 0 || !strcmp(path, ".") || !strcmp(path, "./")) {
120+
return make_absolute_buf;
121+
}
122+
#endif
123+
105124
if (need_slash)
106125
strcpy(make_absolute_buf + cwd_len, "/");
107126
strcpy(make_absolute_buf + cwd_len + need_slash, path);

‎libc-bottom-half/sources/getcwd.c

+13-4
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,39 @@
11
#include <unistd.h>
22
#include <errno.h>
33
#include <string.h>
4+
#include "lock.h"
5+
6+
char *__wasilibc_cwd = "/";
47

5-
// For threads this needs to synchronize with chdir
68
#ifdef _REENTRANT
7-
#error "getcwd doesn't yet support multiple threads"
9+
static volatile int lock[1];
10+
void __wasilibc_cwd_lock(void) { LOCK(lock); }
11+
void __wasilibc_cwd_unlock(void) { UNLOCK(lock); }
12+
#else
13+
#define __wasilibc_cwd_lock() (void)0
14+
#define __wasilibc_cwd_unlock() (void)0
815
#endif
916

10-
char *__wasilibc_cwd = "/";
11-
1217
char *getcwd(char *buf, size_t size)
1318
{
19+
__wasilibc_cwd_lock();
1420
if (!buf) {
1521
buf = strdup(__wasilibc_cwd);
1622
if (!buf) {
1723
errno = ENOMEM;
24+
__wasilibc_cwd_unlock();
1825
return NULL;
1926
}
2027
} else {
2128
size_t len = strlen(__wasilibc_cwd);
2229
if (size < len + 1) {
2330
errno = ERANGE;
31+
__wasilibc_cwd_unlock();
2432
return NULL;
2533
}
2634
strcpy(buf, __wasilibc_cwd);
2735
}
36+
__wasilibc_cwd_unlock();
2837
return buf;
2938
}
3039

‎libc-bottom-half/sources/getentropy.c

+1-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
1-
#include <wasi/api.h>
21
#include <errno.h>
32
#include <unistd.h>
4-
5-
#ifdef _REENTRANT
6-
#error With threads support, getentropy is not intended to be a cancellation point.
7-
#endif
3+
#include <wasi/api.h>
84

95
int __getentropy(void *buffer, size_t len) {
106
if (len > 256) {

‎libc-bottom-half/sources/preopens.c

+17-4
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,11 @@
22
//! environment, with associated path prefixes, which can be used to map
33
//! absolute paths to capabilities with relative paths.
44

5-
#ifdef _REENTRANT
6-
#error "__wasilibc_register_preopened_fd doesn't yet support multiple threads"
7-
#endif
8-
95
#include <assert.h>
106
#include <errno.h>
117
#include <fcntl.h>
128
#include <limits.h>
9+
#include <lock.h>
1310
#include <stdbool.h>
1411
#include <stdlib.h>
1512
#include <string.h>
@@ -32,6 +29,12 @@ static preopen *preopens;
3229
static size_t num_preopens;
3330
static size_t preopen_capacity;
3431

32+
/// Access to the the above preopen must be protected in the presence of
33+
/// threads.
34+
#ifdef _REENTRANT
35+
static volatile int lock[1];
36+
#endif
37+
3538
#ifdef NDEBUG
3639
#define assert_invariants() // assertions disabled
3740
#else
@@ -55,13 +58,15 @@ static void assert_invariants(void) {
5558

5659
/// Allocate space for more preopens. Returns 0 on success and -1 on failure.
5760
static int resize(void) {
61+
LOCK(lock);
5862
size_t start_capacity = 4;
5963
size_t old_capacity = preopen_capacity;
6064
size_t new_capacity = old_capacity == 0 ? start_capacity : old_capacity * 2;
6165

6266
preopen *old_preopens = preopens;
6367
preopen *new_preopens = calloc(sizeof(preopen), new_capacity);
6468
if (new_preopens == NULL)
69+
UNLOCK(lock);
6570
return -1;
6671

6772
memcpy(new_preopens, old_preopens, num_preopens * sizeof(preopen));
@@ -70,6 +75,7 @@ static int resize(void) {
7075
free(old_preopens);
7176

7277
assert_invariants();
78+
UNLOCK(lock);
7379
return 0;
7480
}
7581

@@ -97,21 +103,26 @@ static const char *strip_prefixes(const char *path) {
97103
///
98104
/// This function takes ownership of `prefix`.
99105
static int internal_register_preopened_fd(__wasi_fd_t fd, const char *relprefix) {
106+
LOCK(lock);
107+
100108
// Check preconditions.
101109
assert_invariants();
102110
assert(fd != AT_FDCWD);
103111
assert(fd != -1);
104112
assert(relprefix != NULL);
105113

106114
if (num_preopens == preopen_capacity && resize() != 0)
115+
UNLOCK(lock);
107116
return -1;
108117

109118
char *prefix = strdup(strip_prefixes(relprefix));
110119
if (prefix == NULL)
120+
UNLOCK(lock);
111121
return -1;
112122
preopens[num_preopens++] = (preopen) { prefix, fd, };
113123

114124
assert_invariants();
125+
UNLOCK(lock);
115126
return 0;
116127
}
117128

@@ -166,6 +177,7 @@ int __wasilibc_find_abspath(const char *path,
166177
// recently added preopens take precedence over less recently addded ones.
167178
size_t match_len = 0;
168179
int fd = -1;
180+
LOCK(lock);
169181
for (size_t i = num_preopens; i > 0; --i) {
170182
const preopen *pre = &preopens[i - 1];
171183
const char *prefix = pre->prefix;
@@ -182,6 +194,7 @@ int __wasilibc_find_abspath(const char *path,
182194
*abs_prefix = prefix;
183195
}
184196
}
197+
UNLOCK(lock);
185198

186199
if (fd == -1) {
187200
errno = ENOENT;

‎libc-top-half/musl/arch/wasm32/atomic_arch.h

-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
#ifdef _REENTRANT
2-
#error "multiple threads not supported in musl yet"
3-
#endif
4-
51
#define a_barrier() (__sync_synchronize())
62
#define a_cas(p, t, s) (__sync_val_compare_and_swap((p), (t), (s)))
73
#define a_crash() (__builtin_trap())
+9-10
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
#ifdef _REENTRANT
2-
#error "multiple threads not supported in musl yet"
1+
uintptr_t __get_tp(void) {
2+
#if _REENTRANT
3+
int val;
4+
__asm__("global.get __wasilibc_pthread_self\n"
5+
"local.set %0"
6+
: "=r"(val));
7+
return val;
8+
#else
9+
return 0;
310
#endif
4-
5-
static inline struct pthread *__pthread_self(void)
6-
{
7-
return (struct pthread *)-1;
811
}
9-
10-
#define TP_ADJ(p) (p)
11-
12-
#define tls_mod_off_t unsigned long long

‎libc-top-half/musl/include/pthread.h

+4
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,10 @@ int pthread_setcanceltype(int, int *);
103103
void pthread_testcancel(void);
104104
int pthread_cancel(pthread_t);
105105

106+
#ifdef __wasilibc_unmodified_upstream /* WASI has no CPU scheduling support. */
106107
int pthread_getschedparam(pthread_t, int *__restrict, struct sched_param *__restrict);
107108
int pthread_setschedparam(pthread_t, int, const struct sched_param *);
109+
#endif
108110
int pthread_setschedprio(pthread_t, int);
109111

110112
int pthread_once(pthread_once_t *, void (*)(void));
@@ -167,8 +169,10 @@ int pthread_attr_getscope(const pthread_attr_t *__restrict, int *__restrict);
167169
int pthread_attr_setscope(pthread_attr_t *, int);
168170
int pthread_attr_getschedpolicy(const pthread_attr_t *__restrict, int *__restrict);
169171
int pthread_attr_setschedpolicy(pthread_attr_t *, int);
172+
#ifdef __wasilibc_unmodified_upstream /* WASI has no CPU scheduling support. */
170173
int pthread_attr_getschedparam(const pthread_attr_t *__restrict, struct sched_param *__restrict);
171174
int pthread_attr_setschedparam(pthread_attr_t *__restrict, const struct sched_param *__restrict);
175+
#endif
172176
int pthread_attr_getinheritsched(const pthread_attr_t *__restrict, int *__restrict);
173177
int pthread_attr_setinheritsched(pthread_attr_t *, int);
174178

‎libc-top-half/musl/src/conf/sysconf.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -251,15 +251,15 @@ long sysconf(int name)
251251
return DELAYTIMER_MAX;
252252
case JT_NPROCESSORS_CONF & 255:
253253
case JT_NPROCESSORS_ONLN & 255: ;
254-
#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
254+
#ifdef __wasilibc_unmodified_upstream
255255
unsigned char set[128] = {1};
256256
int i, cnt;
257257
__syscall(SYS_sched_getaffinity, 0, sizeof set, set);
258258
for (i=cnt=0; i<sizeof set; i++)
259259
for (; set[i]; set[i]&=set[i]-1, cnt++);
260260
return cnt;
261261
#else
262-
// With no thread support, just say there's 1 processor.
262+
// WASI has no way to query the processor count
263263
return 1;
264264
#endif
265265
#ifdef __wasilibc_unmodified_upstream // WASI has no sysinfo

‎libc-top-half/musl/src/internal/pthread_impl.h

+16
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,18 @@
22
#define _PTHREAD_IMPL_H
33

44
#include <pthread.h>
5+
#ifdef __wasilibc_unmodified_upstream
56
#include <signal.h>
7+
#endif
68
#include <errno.h>
79
#include <limits.h>
10+
#ifdef __wasilibc_unmodified_upstream
811
#include <sys/mman.h>
12+
#endif
913
#include "libc.h"
14+
#ifdef __wasilibc_unmodified_upstream
1015
#include "syscall.h"
16+
#endif
1117
#include "atomic.h"
1218
#include "futex.h"
1319

@@ -159,7 +165,9 @@ extern hidden volatile int __eintr_valid_flag;
159165

160166
hidden int __clone(int (*)(void *), void *, int, void *, ...);
161167
hidden int __set_thread_area(void *);
168+
#ifdef __wasilibc_unmodified_upstream /* WASI has no sigaction */
162169
hidden int __libc_sigaction(int, const struct sigaction *, struct sigaction *);
170+
#endif
163171
hidden void __unmapself(void *, size_t);
164172

165173
hidden int __timedwait(volatile int *, int, clockid_t, const struct timespec *, int);
@@ -169,14 +177,22 @@ static inline void __wake(volatile void *addr, int cnt, int priv)
169177
{
170178
if (priv) priv = FUTEX_PRIVATE;
171179
if (cnt<0) cnt = INT_MAX;
180+
#ifdef __wasilibc_unmodified_upstream
172181
__syscall(SYS_futex, addr, FUTEX_WAKE|priv, cnt) != -ENOSYS ||
173182
__syscall(SYS_futex, addr, FUTEX_WAKE, cnt);
183+
#else
184+
__builtin_wasm_memory_atomic_notify((int*)addr, cnt);
185+
#endif
174186
}
175187
static inline void __futexwait(volatile void *addr, int val, int priv)
176188
{
189+
#ifdef __wasilibc_unmodified_upstream
177190
if (priv) priv = FUTEX_PRIVATE;
178191
__syscall(SYS_futex, addr, FUTEX_WAIT|priv, val, 0) != -ENOSYS ||
179192
__syscall(SYS_futex, addr, FUTEX_WAIT, val, 0);
193+
#else
194+
__wait(addr, NULL, val, priv);
195+
#endif
180196
}
181197

182198
hidden void __acquire_ptc(void);

‎libc-top-half/musl/src/prng/random.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ static int n = 31;
2323
static int i = 3;
2424
static int j = 0;
2525
static uint32_t *x = init+1;
26-
#ifdef __wasilibc_unmodified_upstream
26+
#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
2727
static volatile int lock[1];
2828
volatile int *const __random_lockptr = lock;
2929
#endif

‎libc-top-half/musl/src/thread/pthread_self.c

+7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
#include "pthread_impl.h"
22
#include <threads.h>
33

4+
#if !defined(__wasilibc_unmodified_upstream) && defined(__wasm__) && \
5+
defined(_REENTRANT)
6+
// We need some place to store the thread ID. This WebAssembly global fits the
7+
// bill and is used by `__get_tp` elsewhere.
8+
__asm__(".globaltype __wasilibc_pthread_self, i32\n");
9+
#endif
10+
411
static pthread_t __pthread_self_internal()
512
{
613
return __pthread_self();

‎libc-top-half/musl/src/thread/pthread_setcancelstate.c

+2
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22

33
int __pthread_setcancelstate(int new, int *old)
44
{
5+
#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
56
if (new > 2U) return EINVAL;
67
struct pthread *self = __pthread_self();
78
if (old) *old = self->canceldisable;
89
self->canceldisable = new;
10+
#endif
911
return 0;
1012
}
1113

‎libc-top-half/musl/src/thread/thrd_sleep.c

+2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#include <threads.h>
22
#include <time.h>
33
#include <errno.h>
4+
#ifdef __wasilibc_unmodified_upstream
45
#include "syscall.h"
6+
#endif
57

68
int thrd_sleep(const struct timespec *req, struct timespec *rem)
79
{

0 commit comments

Comments
 (0)
Please sign in to comment.