@@ -23,6 +23,7 @@ summary of the motivation and animated sketch of the design in action.
23
23
* [ Returning] ( #returning )
24
24
* [ Borrows] ( #borrows )
25
25
* [ Cancellation] ( #cancellation )
26
+ * [ Nondeterminism] ( #nondeterminism )
26
27
* [ Async ABI] ( #async-abi )
27
28
* [ Async Import ABI] ( #async-import-abi )
28
29
* [ Async Export ABI] ( #async-export-abi )
@@ -550,6 +551,60 @@ a callee can continue executing before exiting the task.
550
551
See the [ ` canon_subtask_cancel ` ] and [ ` canon_task_cancel ` ] functions in the
551
552
Canonical ABI explainer for more details.
552
553
554
+ ### Nondeterminism
555
+
556
+ Given the general goal of supporting concurrency, Component Model async
557
+ necessarily introduces a degree of nondeterminism. Async concurrency is however
558
+ [ cooperative] , meaning that nondeterministic behavior can only be observed at
559
+ well-defined points in the program. This contrasts with non-cooperative
560
+ [ multithreading] in which nondeterminism can be observed at every core wasm
561
+ instruction.
562
+
563
+ One inherent source of potential nondeterminism that is independent of async is
564
+ the behavior of host-defined import and export calls. Async extends this
565
+ host-dependent nondeterminism to the behavior of the ` read ` and ` write `
566
+ built-ins called on ` stream ` s and ` future ` s that have been passed to and from
567
+ the host via host-defined import and export calls. However, just as with import
568
+ and export calls, it is possible for a host to define a deterministic ordering
569
+ of ` stream ` and ` future ` ` read ` and ` write ` behavior such that overall
570
+ component execution is deterministic.
571
+
572
+ In addition to the inherent host-dependent nondeterminism, the Component Model
573
+ adds several internal sources of nondeterministic behavior that are described
574
+ next. However, each of these sources of nondeterminism can be removed by a host
575
+ implementing the WebAssembly [ Determinsic Profile] , maintaining the ability for
576
+ a host to provide spec-defined deterministic component execution for components
577
+ even when they use async.
578
+
579
+ The following sources of nondeterminism arise via internal built-in operations
580
+ defined by the Component Model:
581
+ * If there are multiple waitables with a pending event in a waitable set that
582
+ is being waited on or polled, there is a nondeterministic choice of which
583
+ waitable's event is delivered first.
584
+ * If multiple tasks wait on or poll the same waitable set at the same time,
585
+ the distribution of events to tasks is nondeterministic.
586
+ * If multiple tasks that previously blocked are unblocked at the same time, the
587
+ sequential order in which they are executed is nondeterministic.
588
+ * Whenever a task yields or waits on (or polls) a waitable set with an already
589
+ pending event, whether the task "blocks" and transfers execution to its async
590
+ caller is nondeterministic.
591
+
592
+ Despite the above, the following scenarios do behave deterministically:
593
+ * If a component ` a ` asynchronously calls the export of another component ` b ` ,
594
+ control flow deterministically transfers to ` b ` and then back to ` a ` when
595
+ ` b ` returns or blocks.
596
+ * If a component ` a ` asynchronously cancels a subtask in another component ` b ` ,
597
+ control flow deterministically transfers to ` b ` and then back to ` a ` when ` b `
598
+ resolves or blocks.
599
+ * If a component ` a ` asynchronously cancels a subtask in another component ` b `
600
+ that was blocked before starting due to backpressure, cancellation completes
601
+ deterministically and immediately.
602
+ * When both ends of a stream or future are owned by wasm components, the
603
+ behavior of all read, write, cancel and close operations is deterministic
604
+ (modulo any nondeterminitic execution that determines the ordering in which
605
+ the operations are performed).
606
+
607
+
553
608
## Async ABI
554
609
555
610
At an ABI level, native async in the Component Model defines for every WIT
@@ -1001,6 +1056,8 @@ comes after:
1001
1056
[ Unit ] : https://en.wikipedia.org/wiki/Unit_type
1002
1057
[ Thread-local Storage ] : https://en.wikipedia.org/wiki/Thread-local_storage
1003
1058
[ FS or GS Segment Base Address ] : https://docs.kernel.org/arch/x86/x86_64/fsgs.html
1059
+ [ Cooperative ] : https://en.wikipedia.org/wiki/Cooperative_multitasking
1060
+ [ Multithreading ] : https://en.wikipedia.org/wiki/Multithreading_(computer_architecture)
1004
1061
1005
1062
[ AST Explainer ] : Explainer.md
1006
1063
[ Lift and Lower Definitions ] : Explainer.md#canonical-definitions
@@ -1047,6 +1104,9 @@ comes after:
1047
1104
[ Reentrance ] : Explainer.md#component-invariants
1048
1105
[ `start` ] : Explainer.md#start-definitions
1049
1106
1107
+ [ Store ] : https://webassembly.github.io/spec/core/exec/runtime.html#syntax-store
1108
+ [ Deterministic Profile ] : https://webassembly.github.io/spec/versions/core/WebAssembly-3.0-draft.pdf#subsubsection*.798
1109
+
1050
1110
[ stack-switching ] : https://github.com/WebAssembly/stack-switching/
1051
1111
[ JSPI ] : https://github.com/WebAssembly/js-promise-integration/
1052
1112
[ shared-everything-threads ] : https://github.com/webAssembly/shared-everything-threads
0 commit comments