Skip to content

Commit 372f6fe

Browse files
committed
Update simple test
* don't assume the return value of the `__wasi_thread_spawn` API should be zero; assert on thread ID * implement wasi_thread_start in ASM to avoid potential stack corruption
1 parent f203624 commit 372f6fe

File tree

3 files changed

+54
-17
lines changed

3 files changed

+54
-17
lines changed

test/build.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ for input in testsuite/*.c; do
77

88
if [ "$input" -nt "$output" ]; then
99
echo "Compiling $input"
10-
$CC "$input" -o "$output"
10+
$CC "$input" testsuite/wasi_thread_spawn.S -o "$output"
1111
fi
1212
done

test/testsuite/thread_spawn-simple.c

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
#include <assert.h>
2+
#include <stdlib.h>
23
#include <wasi/api.h>
34

45
static const int64_t SECOND = 1000 * 1000 * 1000;
56

6-
typedef struct {
7+
typedef struct
8+
{
9+
char *stack;
710
int th_ready;
811
int th_continue;
912
int th_done;
@@ -12,16 +15,16 @@ typedef struct {
1215
int value;
1316
} shared_t;
1417

15-
__attribute__((export_name("wasi_thread_start"))) void
16-
wasi_thread_start(int thread_id, int *start_arg)
18+
void __wasi_thread_start_C(int thread_id, int *start_arg)
1719
{
1820
shared_t *data = (shared_t *)start_arg;
1921

2022
data->th_ready = 1;
2123
__builtin_wasm_memory_atomic_notify(&data->th_ready, 1);
2224

2325
// so we can have all the threads alive at the same time
24-
if (__builtin_wasm_memory_atomic_wait32(&data->th_continue, 0, SECOND) == 2) {
26+
if (__builtin_wasm_memory_atomic_wait32(&data->th_continue, 0, SECOND) == 2)
27+
{
2528
data->failed = 1;
2629
return;
2730
}
@@ -35,36 +38,42 @@ wasi_thread_start(int thread_id, int *start_arg)
3538
__builtin_wasm_memory_atomic_notify(&data->th_done, 1);
3639
}
3740

38-
int
39-
main(int argc, char **argv)
41+
int main(int argc, char **argv)
4042
{
41-
shared_t data[3] = { 0 };
43+
shared_t data[3] = {0};
44+
int tid[3];
4245
int data_count = sizeof(data) / sizeof(data[0]);
4346
int i, j;
4447

45-
for (i = 0; i < data_count; i++) {
48+
for (i = 0; i < data_count; i++)
49+
{
50+
data[i].stack = malloc(128);
4651
data[i].value = 52;
47-
assert(__wasi_thread_spawn(&data[i]) == 0);
52+
tid[i] = __wasi_thread_spawn(&data[i]);
53+
assert(tid[i] > 0);
4854
assert(__builtin_wasm_memory_atomic_wait32(&data[i].th_ready, 0,
49-
SECOND)
50-
!= 2); // not a timeout
55+
SECOND) != 2); // not a timeout
5156
}
5257

53-
for (i = 0; i < data_count; i++) {
58+
for (i = 0; i < data_count; i++)
59+
{
5460
__builtin_wasm_memory_atomic_notify(&data[i].th_continue, 1);
5561
}
5662

57-
for (i = 0; i < data_count; i++) {
63+
for (i = 0; i < data_count; i++)
64+
{
5865
assert(__builtin_wasm_memory_atomic_wait32(&data[i].th_done, 0,
59-
SECOND)
60-
!= 2); // not a timeout
66+
SECOND) != 2); // not a timeout
67+
assert(data[i].tid == tid[i]);
6168
assert(data[i].value == 60);
6269

63-
for (j = i + 1; j < data_count; j++) {
70+
for (j = i + 1; j < data_count; j++)
71+
{
6472
assert(data[i].tid != data[j].tid);
6573
}
6674

6775
assert(data[i].failed == 0);
76+
free(data[i].stack);
6877
}
6978

7079
return 0;

test/testsuite/wasi_thread_spawn.S

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# A copy of the wasi-libc implementation:
2+
# https://github.com/WebAssembly/wasi-libc/blob/main/libc-top-half/musl/src/thread/wasm32/wasi_thread_start.s
3+
.text
4+
5+
.export_name wasi_thread_start, wasi_thread_start
6+
7+
.globaltype __stack_pointer, i32
8+
.functype __wasi_thread_start_C (i32, i32) -> ()
9+
10+
.hidden wasi_thread_start
11+
.globl wasi_thread_start
12+
.type wasi_thread_start,@function
13+
14+
wasi_thread_start:
15+
.functype wasi_thread_start (i32, i32) -> ()
16+
17+
# Set up the minimum C environment.
18+
# Note: offsetof(start_arg, stack) == 0
19+
local.get 1 # start_arg
20+
i32.load 0 # stack
21+
global.set __stack_pointer
22+
23+
# Make the C function do the rest of work.
24+
local.get 0 # tid
25+
local.get 1 # start_arg
26+
call __wasi_thread_start_C
27+
28+
end_function

0 commit comments

Comments
 (0)