@@ -23,6 +23,7 @@ summary of the motivation and animated sketch of the design in action.
2323 * [ Returning] ( #returning )
2424 * [ Borrows] ( #borrows )
2525 * [ Cancellation] ( #cancellation )
26+ * [ Nondeterminism] ( #nondeterminism )
2627* [ Async ABI] ( #async-abi )
2728 * [ Async Import ABI] ( #async-import-abi )
2829 * [ Async Export ABI] ( #async-export-abi )
@@ -550,6 +551,60 @@ a callee can continue executing before exiting the task.
550551See the [ ` canon_subtask_cancel ` ] and [ ` canon_task_cancel ` ] functions in the
551552Canonical ABI explainer for more details.
552553
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+
553608## Async ABI
554609
555610At an ABI level, native async in the Component Model defines for every WIT
@@ -1001,6 +1056,8 @@ comes after:
10011056[ Unit ] : https://en.wikipedia.org/wiki/Unit_type
10021057[ Thread-local Storage ] : https://en.wikipedia.org/wiki/Thread-local_storage
10031058[ 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)
10041061
10051062[ AST Explainer ] : Explainer.md
10061063[ Lift and Lower Definitions ] : Explainer.md#canonical-definitions
@@ -1047,6 +1104,9 @@ comes after:
10471104[ Reentrance ] : Explainer.md#component-invariants
10481105[ `start` ] : Explainer.md#start-definitions
10491106
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+
10501110[ stack-switching ] : https://github.com/WebAssembly/stack-switching/
10511111[ JSPI ] : https://github.com/WebAssembly/js-promise-integration/
10521112[ shared-everything-threads ] : https://github.com/webAssembly/shared-everything-threads
0 commit comments