Relaxed Memory Model

The execution of a WebAssembly program gives rise to a trace of events. WebAssembly’s relaxed memory model constrains the observable behaviours of the program’s execution by defining a consistency condition on the trace of events.

Note

A relaxed memory model is necessary to describe the behaviour of programs exhibiting shared memory concurrency. WebAssembly’s relaxed memory model is heavily based on those of C/C++11 and JavaScript. The relaxed memory model described here is derived from the following article: 1.

Preliminary Definitions

\[\begin{split}\begin{array}{rcl} \href{../exec/relaxed.html#relaxed-aux}{\mathrm{time}}(\href{../exec/runtime.html#syntax-act}{\mathit{act}}^\ast~\href{../exec/runtime.html#syntax-time}{\mathbin{\mathsf{at}}}~\href{../exec/runtime.html#syntax-time}{\mathit{time}}_p~\href{../exec/runtime.html#syntax-time}{\mathit{time}}) & = & \href{../exec/runtime.html#syntax-time}{\mathit{time}} \\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{time}}_p(\href{../exec/runtime.html#syntax-act}{\mathit{act}}^\ast~\href{../exec/runtime.html#syntax-time}{\mathbin{\mathsf{at}}}~\href{../exec/runtime.html#syntax-time}{\mathit{time}}_p~\href{../exec/runtime.html#syntax-time}{\mathit{time}}) & = & \href{../exec/runtime.html#syntax-time}{\mathit{time}}_p \\ &&\\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{loc}}(\href{../exec/runtime.html#syntax-act}{\mathsf{rd}}_{\href{../exec/runtime.html#syntax-ord}{\mathit{ord}}}~\href{../exec/runtime.html#syntax-loc}{\mathit{loc}}~\href{../syntax/values.html#syntax-byte}{\mathit{byte}}^\ast~\href{../exec/runtime.html#syntax-ord}{\mathsf{notears}}^?) & = & \href{../exec/runtime.html#syntax-loc}{\mathit{loc}} \\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{loc}}(\href{../exec/runtime.html#syntax-act}{\mathsf{wr}}_{\href{../exec/runtime.html#syntax-ord}{\mathit{ord}}}~\href{../exec/runtime.html#syntax-loc}{\mathit{loc}}~\href{../syntax/values.html#syntax-byte}{\mathit{byte}}^\ast~\href{../exec/runtime.html#syntax-ord}{\mathsf{notears}}^?) & = & \href{../exec/runtime.html#syntax-loc}{\mathit{loc}} \\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{loc}}(\href{../exec/runtime.html#syntax-act}{\mathsf{rmw}}~\href{../exec/runtime.html#syntax-loc}{\mathit{loc}}~{\href{../syntax/values.html#syntax-byte}{\mathit{byte}}_1}^\ast~{\href{../syntax/values.html#syntax-byte}{\mathit{byte}}_2}^\ast) & = & \href{../exec/runtime.html#syntax-loc}{\mathit{loc}} \\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{loc}}(\href{../exec/runtime.html#syntax-act}{\mathsf{wait}}~\href{../exec/runtime.html#syntax-loc}{\mathit{loc}}~\href{../syntax/values.html#syntax-int}{\mathit{s64}}) & = & \href{../exec/runtime.html#syntax-loc}{\mathit{loc}} \\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{loc}}(\href{../exec/runtime.html#syntax-act}{\mathsf{woken}}~\href{../exec/runtime.html#syntax-loc}{\mathit{loc}}) & = & \href{../exec/runtime.html#syntax-loc}{\mathit{loc}} \\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{loc}}(\href{../exec/runtime.html#syntax-act}{\mathsf{timeout}}~\href{../exec/runtime.html#syntax-loc}{\mathit{loc}}) & = & \href{../exec/runtime.html#syntax-loc}{\mathit{loc}} \\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{loc}}(\href{../exec/runtime.html#syntax-act}{\mathsf{notify}}~\href{../exec/runtime.html#syntax-loc}{\mathit{loc}}~\href{../syntax/values.html#syntax-int}{\mathit{u32}}~\href{../syntax/values.html#syntax-int}{\mathit{u32}}) & = & \href{../exec/runtime.html#syntax-loc}{\mathit{loc}} \\ &&\\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{ord}}(\href{../exec/runtime.html#syntax-act}{\mathsf{rd}}_{\href{../exec/runtime.html#syntax-ord}{\mathit{ord}}}~\href{../exec/runtime.html#syntax-loc}{\mathit{loc}}~\href{../syntax/values.html#syntax-byte}{\mathit{byte}}^\ast~\href{../exec/runtime.html#syntax-ord}{\mathsf{notears}}^?) & = & \href{../exec/runtime.html#syntax-ord}{\mathit{ord}} \\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{ord}}(\href{../exec/runtime.html#syntax-act}{\mathsf{wr}}_{\href{../exec/runtime.html#syntax-ord}{\mathit{ord}}}~\href{../exec/runtime.html#syntax-loc}{\mathit{loc}}~\href{../syntax/values.html#syntax-byte}{\mathit{byte}}^\ast~\href{../exec/runtime.html#syntax-ord}{\mathsf{notears}}^?) & = & \href{../exec/runtime.html#syntax-ord}{\mathit{ord}} \\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{ord}}(\href{../exec/runtime.html#syntax-act}{\mathsf{rmw}}~\href{../exec/runtime.html#syntax-loc}{\mathit{loc}}~{\href{../syntax/values.html#syntax-byte}{\mathit{byte}}_1}^\ast~{\href{../syntax/values.html#syntax-byte}{\mathit{byte}}_2}^\ast) & = & \href{../exec/runtime.html#syntax-ord}{\mathsf{seqcst}} \\ &&\\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{overlap}}(\href{../exec/runtime.html#syntax-act}{\mathit{act}}_1, \href{../exec/runtime.html#syntax-act}{\mathit{act}}_2) & = & (\href{../exec/relaxed.html#relaxed-aux}{\mathrm{range}}(\href{../exec/runtime.html#syntax-act}{\mathit{act}}_1) \cup \href{../exec/relaxed.html#relaxed-aux}{\mathrm{range}}(\href{../exec/runtime.html#syntax-act}{\mathit{act}}_2) \neq \epsilon) \\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{same}}(\href{../exec/runtime.html#syntax-act}{\mathit{act}}_1, \href{../exec/runtime.html#syntax-act}{\mathit{act}}_2) & = & (\href{../exec/relaxed.html#relaxed-aux}{\mathrm{range}}(\href{../exec/runtime.html#syntax-act}{\mathit{act}}_1) = \href{../exec/relaxed.html#relaxed-aux}{\mathrm{range}}(\href{../exec/runtime.html#syntax-act}{\mathit{act}}_2)) \\ &&\\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{reading}}(\href{../exec/runtime.html#syntax-act}{\mathit{act}}) & = & (\href{../exec/relaxed.html#relaxed-aux}{\mathrm{read}}(\href{../exec/runtime.html#syntax-act}{\mathit{act}}) \neq \epsilon) \\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{writing}}(\href{../exec/runtime.html#syntax-act}{\mathit{act}}) & = & (\href{../exec/relaxed.html#relaxed-aux}{\mathrm{write}}(\href{../exec/runtime.html#syntax-act}{\mathit{act}}) \neq \epsilon) \\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{susp}}(\href{../syntax/values.html#syntax-int}{\mathit{u32}}, \href{../exec/runtime.html#syntax-act}{\mathsf{wait}}~\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}[\href{../syntax/values.html#syntax-int}{\mathit{u32}}]~\href{../syntax/values.html#syntax-int}{\mathit{s64}}) & = & \href{../exec/runtime.html#syntax-act}{\mathsf{wait}}~\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}[\href{../syntax/values.html#syntax-int}{\mathit{u32}}]~\href{../syntax/values.html#syntax-int}{\mathit{s64}} \\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{susp}}(\href{../syntax/values.html#syntax-int}{\mathit{u32}}, \href{../exec/runtime.html#syntax-act}{\mathsf{woken}}~\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}[\href{../syntax/values.html#syntax-int}{\mathit{u32}}]) & = & \href{../exec/runtime.html#syntax-act}{\mathsf{woken}}~\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}[\href{../syntax/values.html#syntax-int}{\mathit{u32}}] \\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{susp}}(\href{../syntax/values.html#syntax-int}{\mathit{u32}}, \href{../exec/runtime.html#syntax-act}{\mathsf{timeout}}~\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}[\href{../syntax/values.html#syntax-int}{\mathit{u32}}]) & = & \href{../exec/runtime.html#syntax-act}{\mathsf{timeout}}~\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}[\href{../syntax/values.html#syntax-int}{\mathit{u32}}] \\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{susp}}(\href{../syntax/values.html#syntax-int}{\mathit{u32}}, \href{../exec/runtime.html#syntax-act}{\mathsf{notify}}~\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}[\href{../syntax/values.html#syntax-int}{\mathit{u32}}]~\href{../syntax/values.html#syntax-int}{\mathit{u32}}'~\href{../syntax/values.html#syntax-int}{\mathit{u32}}'') & = & \href{../exec/runtime.html#syntax-act}{\mathsf{notify}}~\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}[\href{../syntax/values.html#syntax-int}{\mathit{u32}}]~\href{../syntax/values.html#syntax-int}{\mathit{u32}}'~\href{../syntax/values.html#syntax-int}{\mathit{u32}}'' \\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{susp}}(\href{../syntax/values.html#syntax-int}{\mathit{u32}}, \href{../exec/runtime.html#syntax-act}{\mathit{act}}) & = & \epsilon \qquad (\mathrel{\mbox{otherwise}}) \\ &&\\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{read}}(\href{../exec/runtime.html#syntax-act}{\mathsf{rd}}_{\href{../exec/runtime.html#syntax-ord}{\mathit{ord}}}~\href{../exec/runtime.html#syntax-loc}{\mathit{loc}}~\href{../syntax/values.html#syntax-byte}{\mathit{byte}}^\ast~\href{../exec/runtime.html#syntax-ord}{\mathsf{notears}}^?) & = & \href{../syntax/values.html#syntax-byte}{\mathit{byte}}^\ast \\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{read}}(\href{../exec/runtime.html#syntax-act}{\mathsf{rmw}}~\href{../exec/runtime.html#syntax-loc}{\mathit{loc}}~{\href{../syntax/values.html#syntax-byte}{\mathit{byte}}_1}^\ast~{\href{../syntax/values.html#syntax-byte}{\mathit{byte}}_2}^\ast) & = & {\href{../syntax/values.html#syntax-byte}{\mathit{byte}}_1}^\ast \\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{read}}(\href{../exec/runtime.html#syntax-act}{\mathit{act}}) & = & \epsilon \qquad (\mathrel{\mbox{otherwise}}) \\ &&\\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{write}}(\href{../exec/runtime.html#syntax-act}{\mathsf{wr}}_{\href{../exec/runtime.html#syntax-ord}{\mathit{ord}}}~\href{../exec/runtime.html#syntax-loc}{\mathit{loc}}~\href{../syntax/values.html#syntax-byte}{\mathit{byte}}^\ast~\href{../exec/runtime.html#syntax-ord}{\mathsf{notears}}^?) & = & \href{../syntax/values.html#syntax-byte}{\mathit{byte}}^\ast \\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{write}}(\href{../exec/runtime.html#syntax-act}{\mathsf{rmw}}~\href{../exec/runtime.html#syntax-loc}{\mathit{loc}}~{\href{../syntax/values.html#syntax-byte}{\mathit{byte}}_1}^\ast~{\href{../syntax/values.html#syntax-byte}{\mathit{byte}}_2}^\ast) & = & {\href{../syntax/values.html#syntax-byte}{\mathit{byte}}_2}^\ast \\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{write}}(\href{../exec/runtime.html#syntax-act}{\mathit{act}}) & = & \epsilon \qquad (\mathrel{\mbox{otherwise}}) \\ &&\\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{offset}}(\href{../exec/runtime.html#syntax-act}{\mathit{act}}) & = & \href{../syntax/values.html#syntax-int}{\mathit{u32}} \qquad (\mathrel{\mbox{if}}~\href{../exec/relaxed.html#relaxed-aux}{\mathrm{loc}}(\href{../exec/runtime.html#syntax-act}{\mathit{act}}) = \href{../exec/runtime.html#syntax-reg}{\mathit{reg}}[\href{../syntax/values.html#syntax-int}{\mathit{u32}}]) \\ &&\\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{sync}}(\href{../exec/runtime.html#syntax-act}{\mathit{act}}_1,\href{../exec/runtime.html#syntax-act}{\mathit{act}}_2) & = & (\href{../exec/relaxed.html#relaxed-aux}{\mathrm{same}}(\href{../exec/runtime.html#syntax-act}{\mathit{act}}_1,\href{../exec/runtime.html#syntax-act}{\mathit{act}}_2) \wedge \\ && \qquad \href{../exec/relaxed.html#relaxed-aux}{\mathrm{ord}}(\href{../exec/runtime.html#syntax-act}{\mathit{act}}_1) = \href{../exec/relaxed.html#relaxed-aux}{\mathrm{ord}}(\href{../exec/runtime.html#syntax-act}{\mathit{act}}_2) = \href{../exec/runtime.html#syntax-ord}{\mathsf{seqcst}}) \\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{range}}(\href{../exec/runtime.html#syntax-act}{\mathit{act}}) & = & [\href{../syntax/values.html#syntax-int}{\mathit{u32}} \ldots \href{../syntax/values.html#syntax-int}{\mathit{u32}} + n - 1] \\ && (\mathrel{\mbox{if}}~\href{../exec/relaxed.html#relaxed-aux}{\mathrm{loc}}(\href{../exec/runtime.html#syntax-act}{\mathit{act}}) = \href{../exec/runtime.html#syntax-reg}{\mathit{reg}}[\href{../syntax/values.html#syntax-int}{\mathit{u32}}] \wedge \\ && \quad n = \mathrm{max}(|\href{../exec/relaxed.html#relaxed-aux}{\mathrm{read}}(\href{../exec/runtime.html#syntax-act}{\mathit{act}})|,|\href{../exec/relaxed.html#relaxed-aux}{\mathrm{write}}(\href{../exec/runtime.html#syntax-act}{\mathit{act}})|)) \\ &&\\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{tearfree}}(\href{../exec/runtime.html#syntax-act}{\mathsf{rd}}_{\href{../exec/runtime.html#syntax-ord}{\mathit{ord}}}~\href{../exec/runtime.html#syntax-loc}{\mathit{loc}}~\href{../syntax/values.html#syntax-byte}{\mathit{byte}}^\ast) & = & \bot \qquad (\mathrel{\mbox{if}}~\href{../exec/runtime.html#syntax-ord}{\mathit{ord}} = \href{../exec/runtime.html#syntax-ord}{\mathsf{unord}} \vee \href{../exec/runtime.html#syntax-ord}{\mathit{ord}} = \href{../exec/runtime.html#syntax-ord}{\mathsf{init}}) \\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{tearfree}}(\href{../exec/runtime.html#syntax-act}{\mathsf{wr}}_{\href{../exec/runtime.html#syntax-ord}{\mathit{ord}}}~\href{../exec/runtime.html#syntax-loc}{\mathit{loc}}~\href{../syntax/values.html#syntax-byte}{\mathit{byte}}^\ast) & = & \bot \qquad (\mathrel{\mbox{if}}~\href{../exec/runtime.html#syntax-ord}{\mathit{ord}} = \href{../exec/runtime.html#syntax-ord}{\mathsf{unord}} \vee \href{../exec/runtime.html#syntax-ord}{\mathit{ord}} = \href{../exec/runtime.html#syntax-ord}{\mathsf{init}}) \\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{tearfree}}(\href{../exec/runtime.html#syntax-act}{\mathit{act}}) & = & \top \qquad (\mathrel{\mbox{otherwise}}) \\ &&\\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{id}}(\href{../exec/runtime.html#syntax-act}{\mathit{act}}) & = & \href{../exec/runtime.html#syntax-act}{\mathit{act}} \\ \end{array}\end{split}\]

The above operations on actions are raised to operations on events, indexed by region.

\[\begin{split}\begin{array}{rcl} \mathit{func}_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}(\href{../exec/runtime.html#syntax-act}{\mathit{act}}_1^\ast~\href{../exec/runtime.html#syntax-act}{\mathit{act}}~\href{../exec/runtime.html#syntax-act}{\mathit{act}}_2^\ast~\href{../exec/runtime.html#syntax-time}{\mathbin{\mathsf{at}}}~\href{../exec/runtime.html#syntax-time}{\mathit{time}}_p~\href{../exec/runtime.html#syntax-time}{\mathit{time}}) & = & \mathit{func}(\href{../exec/runtime.html#syntax-act}{\mathit{act}}) \\ && (\mathrel{\mbox{if}}~\href{../exec/relaxed.html#relaxed-aux}{\mathrm{loc}}(\href{../exec/runtime.html#syntax-act}{\mathit{act}}) = \href{../exec/runtime.html#syntax-reg}{\mathit{reg}}[\href{../syntax/values.html#syntax-int}{\mathit{u32}}]) \\ \mathit{func}_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}(\href{../exec/runtime.html#syntax-act}{\mathit{act}}_1^\ast~\href{../exec/runtime.html#syntax-act}{\mathit{act}}~\href{../exec/runtime.html#syntax-act}{\mathit{act}}_2^\ast~\href{../exec/runtime.html#syntax-time}{\mathbin{\mathsf{at}}}~\href{../exec/runtime.html#syntax-time}{\mathit{time}}_p~\href{../exec/runtime.html#syntax-time}{\mathit{time}}, \quad &&\\ \qquad \href{../exec/runtime.html#syntax-act}{\mathit{act}}_3^\ast~\href{../exec/runtime.html#syntax-act}{\mathit{act}}'~\href{../exec/runtime.html#syntax-act}{\mathit{act}}_4^\ast~\href{../exec/runtime.html#syntax-time}{\mathbin{\mathsf{at}}}~\href{../exec/runtime.html#syntax-time}{\mathit{time}}'_p~\href{../exec/runtime.html#syntax-time}{\mathit{time}}') & = & \mathit{func}(\href{../exec/runtime.html#syntax-act}{\mathit{act}},\href{../exec/runtime.html#syntax-act}{\mathit{act}}') \\ && (\mathrel{\mbox{if}}~\href{../exec/relaxed.html#relaxed-aux}{\mathrm{loc}}(\href{../exec/runtime.html#syntax-act}{\mathit{act}}) = \href{../exec/relaxed.html#relaxed-aux}{\mathrm{loc}}(\href{../exec/runtime.html#syntax-act}{\mathit{act}}') = \href{../exec/runtime.html#syntax-reg}{\mathit{reg}}[\href{../syntax/values.html#syntax-int}{\mathit{u32}}]) \\ \end{array}\end{split}\]

Traces

Todo

novel notation here?

A trace is a coinductive list of events. A trace is considered to be a pre-execution of a given global configuration if it represents the events emitted by the coinductive closure of the global reduction relation on that configuration, such that all of the trace’s consituent events have unique time stamps that are totally ordered according to the reduction order.

\[\begin{split}\begin{array}{c} \begin{array}{c}\href{../exec/runtime.html#syntax-config}{\mathit{config}} \href{../exec/conventions.html#formal-notation}{\hookrightarrow}^{\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}} \href{../exec/runtime.html#syntax-config}{\mathit{config}}' \qquad \vdash \href{../exec/runtime.html#syntax-config}{\mathit{config}}' : \href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}} \\ \forall \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}' \in \href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}}, \href{../exec/relaxed.html#relaxed-aux}{\mathrm{time}}(\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}') \href{../exec/runtime.html#relaxed-prectot}{\mathrel{\prec_{\mathsf{tot}}}} \href{../exec/relaxed.html#relaxed-aux}{\mathrm{time}}(\href{../exec/runtime.html#syntax-evt}{\mathit{evt}})\end{array} \qquad \begin{array}{l}\href{../exec/relaxed.html#relaxed-aux}{\mathrm{time}}(\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}) \notin \href{../exec/relaxed.html#relaxed-aux}{\mathrm{time}}^\ast(\href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}}) \\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{time}}_p(\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}) \notin \href{../exec/relaxed.html#relaxed-aux}{\mathrm{time}}_p^\ast(\href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}})\end{array} \\[0.2ex] \hline \\[-0.8ex] \hline \\[-0.8ex] \vdash \href{../exec/runtime.html#syntax-config}{\mathit{config}} : \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}~\href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}} \end{array}\end{split}\]

When a WebAssembly program is executed, all behaviours observed during that execution must correspond to a single consistent pre-execution of that execution’s starting configuration.

Consistency

\[\frac{ \forall \href{../exec/runtime.html#syntax-reg}{\mathit{reg}},~ \vdash_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}} \href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}}~\href{../exec/relaxed.html#relaxed-consistent}{\mathrel{\mbox{consistent-with}}} }{ \vdash \href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}}~\href{../exec/relaxed.html#relaxed-consistent}{\mathrel{\mbox{consistent}}} }\]
\[\begin{split}\frac{ \begin{array}[b]{@{}c@{}} \forall i, \vdash_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}^i \href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}}~\href{../exec/relaxed.html#relaxed-consistent}{\mathrel{\mbox{suspensions-consistent}}} \\ \forall \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_R \in \href{../exec/relaxed.html#relaxed-aux}{\mathrm{reading}}_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}(\href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}}), \exists \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W^\ast, \href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}} \vdash_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}} \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_R~\href{../exec/relaxed.html#relaxed-consistent}{\mathrel{\mbox{reads-each-from}}}~\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W^\ast \\ \forall \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_I, \href{../exec/runtime.html#syntax-evt}{\mathit{evt}} \in \href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}}, \, \href{../exec/relaxed.html#relaxed-aux}{\mathrm{ord}}_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}(\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_I) = \href{../exec/runtime.html#syntax-ord}{\mathsf{init}} \wedge \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_I \neq \href{../exec/runtime.html#syntax-evt}{\mathit{evt}} \wedge \href{../exec/relaxed.html#relaxed-aux}{\mathrm{overlap}}(\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_I, \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}) \Rightarrow \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_I \href{../exec/runtime.html#relaxed-prechb}{\mathrel{\prec_{\mathsf{hb}}}} \href{../exec/runtime.html#syntax-evt}{\mathit{evt}} \end{array} }{ \vdash_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}} \href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}}~\href{../exec/relaxed.html#relaxed-consistent}{\mathrel{\mbox{consistent-with}}} }\end{split}\]
\[\begin{split}\frac{ \begin{array}[b]{@{}c@{}} \left|\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W^\ast\right| = |\href{../exec/relaxed.html#relaxed-aux}{\mathrm{read}}_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}(\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_R)| \\ \forall i < |\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W^\ast|, \href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}} \vdash_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}^i \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_R~\href{../exec/relaxed.html#relaxed-consistent}{\mathrel{\mbox{reads-from}}}~\left(\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W^\ast[i]\right) \\ \vdash_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}} \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_R~\href{../exec/relaxed.html#relaxed-consistent}{\mathrel{\mbox{no-tear}}}~\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W^\ast \end{array} }{ \href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}} \vdash_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}} \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_R~\href{../exec/relaxed.html#relaxed-consistent}{\mathrel{\mbox{reads-each-from}}}~\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W^\ast }\end{split}\]
\[\begin{split}\frac{ \begin{array}[b]{@{}c} \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_R \neq \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W \\ \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W \in \href{../exec/relaxed.html#relaxed-aux}{\mathrm{writing}}_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}(\href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}}) \\ \href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}} \vdash_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}^{i,k} \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_R~\href{../exec/relaxed.html#relaxed-consistent}{\mathrel{\mbox{value-consistent}}}~\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W \\ \href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}} \vdash_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}^k \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_R~\href{../exec/relaxed.html#relaxed-consistent}{\mathrel{\mbox{hb-consistent}}}~\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W \\ \href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}} \vdash_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}} \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_R~\href{../exec/relaxed.html#relaxed-consistent}{\mathrel{\mbox{sc-last-visible}}}~\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}^\ast_W \end{array} }{ \href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}} \vdash_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}^i \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_R~\href{../exec/relaxed.html#relaxed-consistent}{\mathrel{\mbox{reads-from}}}~\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W }\end{split}\]
\[\begin{split}\frac{ \begin{array}[b]{@{}r@{~}c@{~}l@{}} \href{../exec/relaxed.html#relaxed-aux}{\mathrm{read}}_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}(\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_R)[i] &=& \href{../exec/relaxed.html#relaxed-aux}{\mathrm{write}}_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}(\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W)[j] \\ k = \href{../exec/relaxed.html#relaxed-aux}{\mathrm{offset}}_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}(\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_R) + i &=& \href{../exec/relaxed.html#relaxed-aux}{\mathrm{offset}}_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}(\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W) + j \end{array} }{ \href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}} \vdash_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}^{i,k} \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_R~\href{../exec/relaxed.html#relaxed-consistent}{\mathrel{\mbox{value-consistent}}}~\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W }\end{split}\]
\[\begin{split}\frac{ \begin{array}[b]{@{}c} \neg (\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_R \href{../exec/runtime.html#relaxed-prechb}{\mathrel{\prec_{\mathsf{hb}}}} \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W) \\ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{sync}}_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}(\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W, \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_R) \Rightarrow \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W \href{../exec/runtime.html#relaxed-prechb}{\mathrel{\prec_{\mathsf{hb}}}} \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_R \\ \forall \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}'_W \in \href{../exec/relaxed.html#relaxed-aux}{\mathrm{writing}}_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}(\href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}}), \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W \href{../exec/runtime.html#relaxed-prechb}{\mathrel{\prec_{\mathsf{hb}}}} \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}'_W \href{../exec/runtime.html#relaxed-prechb}{\mathrel{\prec_{\mathsf{hb}}}} \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_R \Rightarrow k \notin \href{../exec/relaxed.html#relaxed-aux}{\mathrm{range}}_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}(\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}'_W) \end{array} }{ \href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}} \vdash_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}^k \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_R~\href{../exec/relaxed.html#relaxed-consistent}{\mathrel{\mbox{hb-consistent}}}~\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W }\end{split}\]
\[\begin{split}\frac{ \begin{array}[b]{@{}l@{\qquad}l@{}} \forall \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}'_W \in \href{../exec/relaxed.html#relaxed-aux}{\mathrm{writing}}_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}(\href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}}), \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W \href{../exec/runtime.html#relaxed-prechb}{\mathrel{\prec_{\mathsf{hb}}}} \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_R \Rightarrow \\ \quad \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W \href{../exec/runtime.html#relaxed-prectot}{\mathrel{\prec_{\mathsf{tot}}}} \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}'_W \href{../exec/runtime.html#relaxed-prectot}{\mathrel{\prec_{\mathsf{tot}}}} \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_R \wedge \href{../exec/relaxed.html#relaxed-aux}{\mathrm{sync}}_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}(\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W, \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_R) \Rightarrow \neg \href{../exec/relaxed.html#relaxed-aux}{\mathrm{sync}}_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}(\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}'_W, \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_R) \\ \quad \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W \href{../exec/runtime.html#relaxed-prechb}{\mathrel{\prec_{\mathsf{hb}}}} \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}'_W \href{../exec/runtime.html#relaxed-prectot}{\mathrel{\prec_{\mathsf{tot}}}} \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_R \Rightarrow \neg\href{../exec/relaxed.html#relaxed-aux}{\mathrm{sync}}_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}(\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}'_W, \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_R) \\ \quad \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W \href{../exec/runtime.html#relaxed-prectot}{\mathrel{\prec_{\mathsf{tot}}}} \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}'_W \href{../exec/runtime.html#relaxed-prechb}{\mathrel{\prec_{\mathsf{hb}}}} \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_R \Rightarrow \neg\href{../exec/relaxed.html#relaxed-aux}{\mathrm{sync}}_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}(\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W, \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}'_W) \end{array} }{ \href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}} \vdash_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}} \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_R~\href{../exec/relaxed.html#relaxed-consistent}{\mathrel{\mbox{sc-last-visible}}}~\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W }\end{split}\]
\[\begin{split}\frac{ \begin{array}[b]{l@{}} \href{../exec/relaxed.html#relaxed-aux}{\mathrm{tearfree}}_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}(\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_R) \Rightarrow \\ \quad |\{\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W \in \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W^\ast ~|~ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{same}}_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}(\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_R, \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W) \wedge \href{../exec/relaxed.html#relaxed-aux}{\mathrm{tearfree}}_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}(\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W)\}| \leq 1 \end{array} }{ \vdash_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}} \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_R~\href{../exec/relaxed.html#relaxed-consistent}{\mathrel{\mbox{no-tear}}}~\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_W^\ast }\end{split}\]
\[\begin{split}\frac{ \begin{array}{c}\href{../exec/relaxed.html#relaxed-aux}{\mathrm{susp}}_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}^\ast(i, \href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}}) = \href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}}' \qquad \vdash_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}^i \href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}}'~\href{../exec/relaxed.html#relaxed-consistent}{\mathrel{\mbox{suspensions-consistent-with}}}(\epsilon) \\ \forall \href{../exec/runtime.html#syntax-evt}{\mathit{evt}},\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}' \in \href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}}',~\href{../exec/runtime.html#syntax-evt}{\mathit{evt}} \href{../exec/runtime.html#relaxed-prectot}{\mathrel{\prec_{\mathsf{tot}}}} \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}' \Longrightarrow \href{../exec/runtime.html#syntax-evt}{\mathit{evt}} \href{../exec/runtime.html#relaxed-prechb}{\mathrel{\prec_{\mathsf{hb}}}} \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}'\end{array} }{ \vdash_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}^i \href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}}~\href{../exec/relaxed.html#relaxed-consistent}{\mathrel{\mbox{suspensions-consistent}}} }\end{split}\]
\[\frac{ }{ \vdash_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}^i \epsilon~\href{../exec/relaxed.html#relaxed-consistent}{\mathrel{\mbox{suspensions-consistent-with}}}(\href{../exec/runtime.html#syntax-time}{\mathit{time}}^\ast) }\]
\[\frac{ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{id}}_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}(\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}) = (\href{../exec/runtime.html#syntax-act}{\mathsf{wait}}~\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}[i]~\href{../syntax/values.html#syntax-int}{\mathit{s64}}) \qquad \vdash_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}^i \href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}}~\href{../exec/relaxed.html#relaxed-consistent}{\mathrel{\mbox{suspensions-consistent-with}}}(\href{../exec/relaxed.html#relaxed-aux}{\mathrm{time}}(\href{../exec/runtime.html#syntax-evt}{\mathit{evt}})~\href{../exec/runtime.html#syntax-time}{\mathit{time}}^\ast) }{ \vdash_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}^i \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}~\href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}}~\href{../exec/relaxed.html#relaxed-consistent}{\mathrel{\mbox{suspensions-consistent-with}}}(\href{../exec/runtime.html#syntax-time}{\mathit{time}}^\ast) }\]
\[\frac{ \href{../exec/relaxed.html#relaxed-aux}{\mathrm{id}}_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}(\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}) = (\href{../exec/runtime.html#syntax-act}{\mathsf{timeout}}~\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}[i]) \qquad \vdash_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}^i \href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}}~\href{../exec/relaxed.html#relaxed-consistent}{\mathrel{\mbox{suspensions-consistent-with}}}(\href{../exec/runtime.html#syntax-time}{\mathit{time}}^\ast~\href{../exec/runtime.html#syntax-time}{\mathit{time}}'^\ast) }{ \vdash_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}^i \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}~\href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}}~\href{../exec/relaxed.html#relaxed-consistent}{\mathrel{\mbox{suspensions-consistent-with}}}(\href{../exec/runtime.html#syntax-time}{\mathit{time}}^\ast~\href{../exec/relaxed.html#relaxed-aux}{\mathrm{time}}_p(\href{../exec/runtime.html#syntax-evt}{\mathit{evt}})~\href{../exec/runtime.html#syntax-time}{\mathit{time}}'^\ast) }\]
\[\begin{split}\frac{ \begin{array}{c}\href{../exec/relaxed.html#relaxed-aux}{\mathrm{id}}_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}^n(\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}^n) = (\href{../exec/runtime.html#syntax-act}{\mathsf{woken}}~\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}[i]) \qquad \href{../exec/relaxed.html#relaxed-aux}{\mathrm{id}}_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}(\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_N) = (\href{../exec/runtime.html#syntax-act}{\mathsf{notify}}~\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}[i]~n~k) \\ n < k \Longrightarrow m = 0 \qquad \vdash_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}^i \href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}}~\href{../exec/relaxed.html#relaxed-consistent}{\mathrel{\mbox{suspensions-consistent-with}}}(\href{../exec/runtime.html#syntax-time}{\mathit{time}}^m)\end{array} }{ \vdash_{\href{../exec/runtime.html#syntax-reg}{\mathit{reg}}}^i \href{../exec/runtime.html#syntax-evt}{\mathit{evt}}_N~\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}^n~\href{../exec/relaxed.html#relaxed-trace}{\mathit{tr}}~\href{../exec/relaxed.html#relaxed-consistent}{\mathrel{\mbox{suspensions-consistent-with}}}(\href{../exec/runtime.html#syntax-time}{\mathit{time}}^m~\href{../exec/relaxed.html#relaxed-aux}{\mathrm{time}}_p^n(\href{../exec/runtime.html#syntax-evt}{\mathit{evt}}^n)) }\end{split}\]

Note

The following is a non-normative and non-exhaustive explanation of WebAssembly’s relaxed memory model in plain English. Note that the definition of Consistency is the sole normative definition of the relaxed memory model.

When a WebAssembly operation reads from shared mutable state, the WebAssembly relaxed memory model determines the value that this read access observes, in terms of the write access to the same location(s) that have occurred in the execution.

The WebAssembly memory model is built around the concept of a happens-before transitive partial order between accesses of shared mutable state, \(\href{../exec/runtime.html#relaxed-prechb}{\mathrel{\prec_{\mathsf{hb}}}}\), which captures a strong notion of causality. All sequential accesses in the same thread are related by \(\href{../exec/runtime.html#relaxed-prechb}{\mathrel{\prec_{\mathsf{hb}}}}\) according to execution order. Certain operations also establish a \(\href{../exec/runtime.html#relaxed-prechb}{\mathrel{\prec_{\mathsf{hb}}}}\) relation between operations of different threads (see atomic accesses below). A read access may never take its value from a write access that comes later in \(\href{../exec/runtime.html#relaxed-prechb}{\mathrel{\prec_{\mathsf{hb}}}}\). Moreover, if two write accesses ordered by \(\href{../exec/runtime.html#relaxed-prechb}{\mathrel{\prec_{\mathsf{hb}}}}\) come before a read access in \(\href{../exec/runtime.html#relaxed-prechb}{\mathrel{\prec_{\mathsf{hb}}}}\), the read access must take its value from the later of the two write accesses according to \(\href{../exec/runtime.html#relaxed-prechb}{\mathrel{\prec_{\mathsf{hb}}}}\). In the case that \(\href{../exec/runtime.html#relaxed-prechb}{\mathrel{\prec_{\mathsf{hb}}}}\) does not uniquely determine a write access that a given read access must take its value from, the read access may non-deterministically take its value from any permitted write.

In the case that a read operation is a multi-byte memory access, the value of each byte may in certain circumstances be determined by a different write event. If this happens, we describe the read operation as tearing. In general, naturally aligned multi-byte reads are not allowed to tear, unless they race with a partially overlapping write or are greater than four bytes in width.

Most WebAssembly accesses of shared mutable state are classified as non-atomic. However a number of operations are classified as performing atomic accesses. Atomic accesses must always be naturally aligned. If an atomic read takes its value from an atomic write of the same width, the write access is fixed as coming before the read access in \(\href{../exec/runtime.html#relaxed-prechb}{\mathrel{\prec_{\mathsf{hb}}}}\). This is the main mechanism by which a \(\href{../exec/runtime.html#relaxed-prechb}{\mathrel{\prec_{\mathsf{hb}}}}\) relation is established between threads.

WebAssembly’s atomic operations are also required to be sequentially consistent. The relaxed memory model defines a toal order on all events of the execution, \(\href{../exec/runtime.html#relaxed-prectot}{\mathrel{\prec_{\mathsf{tot}}}}\), and sequentially consistent operations to identical ranges must respect this ordering - i.e. sequentially consistent reads cannot read from any sequentially consistent write of idential range other than the most recent preceding one according to \(\href{../exec/runtime.html#relaxed-prectot}{\mathrel{\prec_{\mathsf{tot}}}}\).

Some operations such as memory accesses must perform a bounds check in addition to accessing data. The relaxed memory model treats these accesses as additionally accessing a distinguished length location, with the observed value respecting the constraints of the relaxed memory model. Most bounds checks are non-atomic, but bounds checks peformed during instantiation are atomic, and changes to the length (e.g. \(\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{memory.grow}}\)) are modelled as atomic read-modify-write accesses.

In some circumstances, two accesses to overlapping locations may occur in an execution without any relation in \(\href{../exec/runtime.html#relaxed-prechb}{\mathrel{\prec_{\mathsf{hb}}}}\). This situation is known as a race. If at least one of these accesses is a non-atomic write, we describe this situation as a data race. Unlike some other relaxed memory models, WebAssembly does not declare data races to be undefined behaviour. However, the allowed execution behaviours may still be highly non-deterministic as the lack of \(\href{../exec/runtime.html#relaxed-prechb}{\mathrel{\prec_{\mathsf{hb}}}}\) relations means that reads participating in or overlapping with the location of the data race may non-deterministically observe a number of different values.

The relaxed memory model also describes the concurrent behaviour of WebAssembly’s wait (\(\href{../syntax/instructions.html#syntax-instr-atomic-memory}{\mathsf{memory.atomic.wait}}\)) and notify (\(\href{../syntax/instructions.html#syntax-instr-atomic-memory}{\mathsf{memory.atomic.notify}}\)) operations. Each memory location is associated with a queue of waiting threads. A thread suspending as the result of a wait operation enters the queue, and a notify operation to that location will attempt to wake up as many threads as possible from the head of the associated queue, up to the maximum specified by the arguments of the notify operation. All operations on the same location which change the state of that location’s wait queue are sequentially consistent and totally ordered by \(\href{../exec/runtime.html#relaxed-prechb}{\mathrel{\prec_{\mathsf{hb}}}}\).

1

The semantics of the relaxed memory model is derived from the following article: Conrad Watt, Andreas Rossberg, Jean Pichon-Pharabod. Weakening WebAssembly. Proceedings of the ACM on Programming Languages (OOPSLA 2019). ACM 2019.