1edfa10d6SAndrew Brown(module 2edfa10d6SAndrew Brown ;; As we have discussed, it makes sense to make the shared memory an import 3edfa10d6SAndrew Brown ;; so that all 4edfa10d6SAndrew Brown (import "" "memory" (memory $shmem 1 1 shared)) 5edfa10d6SAndrew Brown (import "wasi_snapshot_preview1" "fd_write" 6edfa10d6SAndrew Brown (func $__wasi_fd_write (param i32 i32 i32 i32) (result i32))) 7edfa10d6SAndrew Brown (import "wasi_snapshot_preview1" "proc_exit" 8edfa10d6SAndrew Brown (func $__wasi_proc_exit (param i32))) 9cacc4160SAndrew Brown (import "wasi" "thread-spawn" 10edfa10d6SAndrew Brown (func $__wasi_thread_spawn (param i32) (result i32))) 11edfa10d6SAndrew Brown 12edfa10d6SAndrew Brown (func (export "_start") 13edfa10d6SAndrew Brown (local $i i32) 14edfa10d6SAndrew Brown 15edfa10d6SAndrew Brown ;; Print "Called _start". 16edfa10d6SAndrew Brown (call $print (i32.const 32) (i32.const 14)) 17edfa10d6SAndrew Brown 18edfa10d6SAndrew Brown ;; Print "Running wasi_thread_start" in several threads. 19edfa10d6SAndrew Brown (drop (call $__wasi_thread_spawn (i32.const 0))) 20edfa10d6SAndrew Brown (drop (call $__wasi_thread_spawn (i32.const 0))) 21edfa10d6SAndrew Brown (drop (call $__wasi_thread_spawn (i32.const 0))) 22edfa10d6SAndrew Brown 23edfa10d6SAndrew Brown ;; Wait for all the threads to notify us that they are done. 24*f6b16a71SAndrew Brown (local.set $i (i32.const 0)) 25edfa10d6SAndrew Brown (loop $again 26*f6b16a71SAndrew Brown ;; Wait for the i32 at address 128 to be incremented by each thread. We 27*f6b16a71SAndrew Brown ;; maintain a local $i with the atomically loaded value as the expected 28*f6b16a71SAndrew Brown ;; wait value and to check if all three threads are complete. This wait is 29*f6b16a71SAndrew Brown ;; for 1ms or until notified, whichever is first. 30*f6b16a71SAndrew Brown (drop (memory.atomic.wait32 (i32.const 128) (local.get $i) (i64.const 1000000))) 31*f6b16a71SAndrew Brown (local.set $i (i32.atomic.load (i32.const 128))) 32*f6b16a71SAndrew Brown (br_if $again (i32.lt_s (local.get $i) (i32.const 3))) 33edfa10d6SAndrew Brown ) 34edfa10d6SAndrew Brown 35edfa10d6SAndrew Brown ;; Print "Done". 36edfa10d6SAndrew Brown (call $print (i32.const 64) (i32.const 5)) 37edfa10d6SAndrew Brown ) 38edfa10d6SAndrew Brown 39edfa10d6SAndrew Brown ;; A threads-enabled module must export this spec-designated entry point. 40edfa10d6SAndrew Brown (func (export "wasi_thread_start") (param $tid i32) (param $start_arg i32) 41edfa10d6SAndrew Brown (call $print (i32.const 96) (i32.const 26)) 42edfa10d6SAndrew Brown ;; After printing, we atomically increment the value at address 128 and then 43edfa10d6SAndrew Brown ;; wake up the main thread's join loop. 44edfa10d6SAndrew Brown (drop (i32.atomic.rmw.add (i32.const 128) (i32.const 1))) 45edfa10d6SAndrew Brown (drop (memory.atomic.notify (i32.const 128) (i32.const 1))) 46edfa10d6SAndrew Brown ) 47edfa10d6SAndrew Brown 48edfa10d6SAndrew Brown ;; A helper function for printing ptr-len strings. 49edfa10d6SAndrew Brown (func $print (param $ptr i32) (param $len i32) 50edfa10d6SAndrew Brown (i32.store (i32.const 8) (local.get $len)) 51edfa10d6SAndrew Brown (i32.store (i32.const 4) (local.get $ptr)) 52edfa10d6SAndrew Brown (drop (call $__wasi_fd_write 53edfa10d6SAndrew Brown (i32.const 1) 54edfa10d6SAndrew Brown (i32.const 4) 55edfa10d6SAndrew Brown (i32.const 1) 56edfa10d6SAndrew Brown (i32.const 0))) 57edfa10d6SAndrew Brown ) 58edfa10d6SAndrew Brown 59edfa10d6SAndrew Brown ;; We still need to export the shared memory for Wiggle's sake. 60edfa10d6SAndrew Brown (export "memory" (memory $shmem)) 61edfa10d6SAndrew Brown 62edfa10d6SAndrew Brown (data (i32.const 32) "Called _start\0a") 63edfa10d6SAndrew Brown (data (i32.const 64) "Done\0a") 64edfa10d6SAndrew Brown (data (i32.const 96) "Running wasi_thread_start\0a") 65edfa10d6SAndrew Brown) 66