1;;! component_model_async = true 2;;! reference_types = true 3;;! gc_types = true 4;;! multi_memory = true 5 6;; - Component B asks component A to enable backpressure 7;; - Component B makes an async call to component A 8;; - Component B asserts this subtask is in the "STARTING" state 9;; - Component B adds the subtask to a waitable set and calls waitable-set.wait 10;; 11;; This leaves both tasks in a deadlock situation, which, as of this writing, 12;; Wasmtime will handle by trapping. In the future, once there's a host API for 13;; cancelling tasks, that behavior may change, in which case this test will need 14;; to be updated. 15(component 16 17 (component $A 18 (core func $backpressure.inc (canon backpressure.inc)) 19 (core module $m 20 (import "" "backpressure.inc" (func $backpressure.inc)) 21 22 (func (export "f") (result i32) unreachable) 23 (func (export "callback") (param i32 i32 i32) (result i32) unreachable) 24 25 (func (export "turn-on-backpressure") 26 (call $backpressure.inc)) 27 ) 28 29 (core instance $i (instantiate $m 30 (with "" (instance 31 (export "backpressure.inc" (func $backpressure.inc)) 32 )) 33 )) 34 35 (func (export "turn-on-backpressure") (canon lift (core func $i "turn-on-backpressure"))) 36 (func (export "f") 37 (canon lift (core func $i "f") async (callback (func $i "callback")))) 38 ) 39 (instance $A (instantiate $A)) 40 41 (component $B 42 (import "A" (instance $A 43 (export "f" (func)) 44 (export "turn-on-backpressure" (func)) 45 )) 46 47 (core module $libc (memory (export "mem") 1)) 48 (core instance $libc (instantiate $libc)) 49 50 (core func $f (canon lower (func $A "f") async (memory $libc "mem"))) 51 (core func $turn-on-backpressure (canon lower (func $A "turn-on-backpressure"))) 52 (core func $waitable-set.new (canon waitable-set.new)) 53 (core func $waitable.join (canon waitable.join)) 54 (core func $waitable-set.wait (canon waitable-set.wait (memory $libc "mem"))) 55 56 (core module $m 57 (import "" "f" (func $f (result i32))) 58 (import "" "turn-on-backpressure" (func $turn-on-backpressure)) 59 (import "" "waitable-set.new" (func $waitable-set.new (result i32))) 60 (import "" "waitable.join" (func $waitable.join (param i32 i32))) 61 (import "" "waitable-set.wait" (func $waitable-set.wait (param i32 i32) (result i32))) 62 63 (func (export "f") 64 (local $status i32) 65 (local $set i32) 66 call $turn-on-backpressure 67 68 (local.set $status (call $f)) 69 70 ;; low 4 bits should be "STARTING == 0" 71 (i32.ne 72 (i32.const 0) 73 (i32.and 74 (local.get $status) 75 (i32.const 0xf))) 76 if unreachable end 77 78 ;; make a new waitable set and join our subtask into it 79 (local.set $set (call $waitable-set.new)) 80 (call $waitable.join 81 (i32.shr_u (local.get $status) (i32.const 4)) 82 (local.get $set)) 83 84 ;; block waiting for our task, which should deadlock (?) 85 (call $waitable-set.wait (local.get $set) (i32.const 0)) 86 unreachable 87 ) 88 ) 89 90 (core instance $i (instantiate $m 91 (with "" (instance 92 (export "f" (func $f)) 93 (export "turn-on-backpressure" (func $turn-on-backpressure)) 94 (export "waitable-set.new" (func $waitable-set.new)) 95 (export "waitable.join" (func $waitable.join)) 96 (export "waitable-set.wait" (func $waitable-set.wait)) 97 )) 98 )) 99 100 (func (export "f") async (canon lift (core func $i "f"))) 101 ) 102 103 (instance $B (instantiate $B (with "A" (instance $A)))) 104 105 (func (export "f") (alias export $B "f")) 106) 107 108(assert_trap (invoke "f") "deadlock detected") 109