|
4 | 4 | (import "" "memory" (memory $shmem 1 1 shared)) |
5 | 5 | (import "wasi_snapshot_preview1" "fd_write" |
6 | 6 | (func $__wasi_fd_write (param i32 i32 i32 i32) (result i32))) |
| 7 | + (import "wasi_snapshot_preview1" "proc_exit" |
| 8 | + (func $__wasi_proc_exit (param i32))) |
7 | 9 | (import "wasi" "thread_spawn" |
8 | 10 | (func $__wasi_thread_spawn (param i32) (result i32))) |
9 | 11 |
|
10 | 12 | (func (export "_start") |
11 | 13 | (local $i i32) |
12 | 14 |
|
13 | | - ;; Print "Hello _start". |
14 | | - (call $print (i32.const 32) (i32.const 13)) |
| 15 | + ;; Print "Called _start". |
| 16 | + (call $print (i32.const 32) (i32.const 14)) |
15 | 17 |
|
16 | | - ;; Print "Hello wasi_thread_start" in several threads. |
| 18 | + ;; Print "Running wasi_thread_start" in several threads. |
17 | 19 | (drop (call $__wasi_thread_spawn (i32.const 0))) |
18 | 20 | (drop (call $__wasi_thread_spawn (i32.const 0))) |
19 | 21 | (drop (call $__wasi_thread_spawn (i32.const 0))) |
20 | 22 |
|
21 | | - ;; Spin to allow the threads to do their work. TODO: replace this with |
22 | | - ;; a loop over `wait` with `notify` instructions in the |
23 | | - ;; `wasi_thread_start` entry point. |
24 | | - (local.set $i (i32.const 4000000)) |
| 23 | + ;; Wait for all the threads to notify us that they are done. |
25 | 24 | (loop $again |
26 | | - (local.set $i (i32.sub (local.get $i) (i32.const 1))) |
27 | | - (br_if $again (i32.gt_s (local.get $i) (i32.const 0))) |
| 25 | + ;; Retrieve the i32 at address 128, compare it to -1 (it should always |
| 26 | + ;; fail) and load it atomically to check if all three threads are |
| 27 | + ;; complete. This wait is for 1ms or until notified, whichever is first. |
| 28 | + (drop (memory.atomic.wait32 (i32.const 128) (i32.const -1) (i64.const 1000000))) |
| 29 | + (br_if $again (i32.lt_s (i32.atomic.load (i32.const 128)) (i32.const 3))) |
28 | 30 | ) |
29 | 31 |
|
30 | | - ;; Print "Hello done". |
31 | | - (call $print (i32.const 64) (i32.const 11)) |
| 32 | + ;; Print "Done". |
| 33 | + (call $print (i32.const 64) (i32.const 5)) |
32 | 34 | ) |
33 | 35 |
|
34 | 36 | ;; A threads-enabled module must export this spec-designated entry point. |
35 | 37 | (func (export "wasi_thread_start") (param $tid i32) (param $start_arg i32) |
36 | | - (call $print (i32.const 96) (i32.const 24)) |
| 38 | + (call $print (i32.const 96) (i32.const 26)) |
| 39 | + ;; After printing, we atomically increment the value at address 128 and then |
| 40 | + ;; wake up the main thread's join loop. |
| 41 | + (drop (i32.atomic.rmw.add (i32.const 128) (i32.const 1))) |
| 42 | + (drop (memory.atomic.notify (i32.const 128) (i32.const 1))) |
37 | 43 | ) |
38 | 44 |
|
39 | 45 | ;; A helper function for printing ptr-len strings. |
|
50 | 56 | ;; We still need to export the shared memory for Wiggle's sake. |
51 | 57 | (export "memory" (memory $shmem)) |
52 | 58 |
|
53 | | - (data (i32.const 32) "Hello _start\0a") |
54 | | - (data (i32.const 64) "Hello done\0a") |
55 | | - (data (i32.const 96) "Hello wasi_thread_start\0a") |
| 59 | + (data (i32.const 32) "Called _start\0a") |
| 60 | + (data (i32.const 64) "Done\0a") |
| 61 | + (data (i32.const 96) "Running wasi_thread_start\0a") |
56 | 62 | ) |
0 commit comments