diff --git a/test/async/cancellable.wast b/test/async/cancellable.wast index a24acc85..34cd446c 100644 --- a/test/async/cancellable.wast +++ b/test/async/cancellable.wast @@ -4,7 +4,7 @@ ;; Component $C exports five async callback-lifted functions that block in ;; their initial core function (the callbacks are never invoked): ;; wait-cancel: blocks on cancellable waitable-set.wait, expects TASK_CANCELLED -;; yield-cancel: yields with cancellable, caller cancels during yield +;; yield-cancel: yields with cancellable until the caller cancels ;; poll-cancel-pending: blocks on non-cancellable wait, then polls with cancellable ;; yield-cancel-pending: blocks on non-cancellable wait, then yields with cancellable ;; @@ -40,11 +40,11 @@ ;; Test 2: direct cancel delivery through cancellable thread.yield (func $yield-cancel (export "yield-cancel") (result i32) - (local $ret i32) - ;; yield with cancellable; suspends with cancellable=true, caller cancels - (local.set $ret (call $thread.yield-cancellable)) - (if (i32.ne (i32.const 1 (; CANCELLED ;)) (local.get $ret)) - (then unreachable)) + ;; yield with cancellable until cancelled by the caller (a single + ;; yield may nondeterministically complete without suspending and + ;; thus without the cancellation being delivered) + (loop $again + (br_if $again (i32.eqz (call $thread.yield-cancellable)))) (call $task.cancel) (i32.const 0 (; EXIT ;)) ) diff --git a/test/async/during-sync-call-no-exclusive-resume.wast b/test/async/during-sync-call-no-exclusive-resume.wast index c054493d..1298fe8e 100644 --- a/test/async/during-sync-call-no-exclusive-resume.wast +++ b/test/async/during-sync-call-no-exclusive-resume.wast @@ -21,6 +21,7 @@ (global $setup-thread-index (mut i32) (i32.const 0xdead)) (global $implicit-thread-index (mut i32) (i32.const 0xdead)) + (global $in-sync-call (mut i32) (i32.const 0)) (func $thread-start (param i32) (local $r i32) @@ -38,23 +39,31 @@ (i32.const 0 (; EXIT ;))) ;; async callback task resolves, then parks its implicit thread, ready, - ;; in its event loop by returning YIELD, but must never be resumed. + ;; in its event loop by returning YIELD. Since a YIELD may + ;; nondeterministically complete without suspending, 'never-cb' may be + ;; called (with a NONE event) while no non-async-typed call is in + ;; progress and parks the thread again; it must never be called during + ;; 'sync-block'. (func (export "arm") (result i32) (call $task.return (i32.const 1)) (i32.const 1 (; YIELD ;))) (func (export "never-cb") (param i32 i32 i32) (result i32) - unreachable) + (if (global.get $in-sync-call) + (then unreachable)) + (i32.const 1 (; YIELD ;))) ;; non-async-typed: 4 rounds of switching to $thread-start and being made ready ;; again by it (func (export "sync-block") (result i32) (local $r i32) + (global.set $in-sync-call (i32.const 1)) (global.set $implicit-thread-index (call $thread.index)) (loop $rounds (drop (call $thread.suspend-then-resume (global.get $setup-thread-index))) (local.set $r (i32.add (local.get $r) (i32.const 1))) (br_if $rounds (i32.lt_u (local.get $r) (i32.const 4)))) + (global.set $in-sync-call (i32.const 0)) (i32.const 42)) ) (core type $start-func-ty (func (param i32))) @@ -117,17 +126,25 @@ (import "" "task.return" (func $task.return (param i32))) (import "" "thread.suspend" (func $thread.suspend (result i32))) + (global $in-sync-call (mut i32) (i32.const 0)) + ;; async callback task resolves, then parks its implicit thread, ready, - ;; in its event loop by returning YIELD, but must never be resumed. + ;; in its event loop by returning YIELD. Since a YIELD may + ;; nondeterministically complete without suspending, 'never-cb' may be + ;; called (with a NONE event) while no non-async-typed call is in progress + ;; and parks the thread again; it must never be called during 'sync-block'. (func (export "arm") (result i32) (call $task.return (i32.const 1)) (i32.const 1 (; YIELD ;))) (func (export "never-cb") (param i32 i32 i32) (result i32) - unreachable) + (if (global.get $in-sync-call) + (then unreachable)) + (i32.const 1 (; YIELD ;))) ;; non-async-typed: suspend with no valid thread to switch to (func (export "sync-block") + (global.set $in-sync-call (i32.const 1)) (drop (call $thread.suspend)) unreachable) ) diff --git a/test/async/sync-barges-in.wast b/test/async/sync-barges-in.wast index b9eb4fa5..355b6395 100644 --- a/test/async/sync-barges-in.wast +++ b/test/async/sync-barges-in.wast @@ -79,11 +79,20 @@ (global.set $unblock-value (local.get $val)) ) + ;; 'yielder'/'yielder-cb' yield until 'poker' has been called (a single + ;; yield may nondeterministically complete without suspending, which + ;; would resolve the task before the caller gets to call 'poker'). + (global $poked (mut i32) (i32.const 0)) + (func (export "yielder") - (drop (call $thread.yield)) + (global.set $poked (i32.const 0)) + (loop $again + (drop (call $thread.yield)) + (br_if $again (i32.eqz (global.get $poked)))) (call $task.return (global.get $unblock-value)) ) (func (export "yielder-cb") (result i32) + (global.set $poked (i32.const 0)) (i32.const 1 (; YIELD ;)) ) (func (export "yielder-cb-cb") (param $event_code i32) (param $index i32) (param $payload i32) (result i32) @@ -93,10 +102,13 @@ (then unreachable)) (if (i32.ne (i32.const 0) (local.get $payload)) (then unreachable)) + (if (i32.eqz (global.get $poked)) + (then (return (i32.const 1 (; YIELD ;))))) (call $task.return (global.get $unblock-value)) (i32.const 0 (; EXIT ;)) ) (func (export "poker") (param $val i32) + (global.set $poked (i32.const 1)) (global.set $unblock-value (local.get $val)) ) )