This paper was converted on www.awesomepapers.org from LaTeX by an anonymous user.
Want to know more? Visit the Converter page.

Owicki–Gries Logic for Timestamp Semantics

Tatsuya Abe111STAIR Lab, Chiba Institute of Technology, 2-17-1 Tsudanuma, Narashino, Chiba, 275-0016, Japan. abet@stair.center
(May 25, 2025)
Abstract

Whereas an extension with non-interference of Hoare logic for sequential programs Owicki–Gries logic ensures the correctness of concurrent programs on strict consistency, it is unsound to weak memory models adopted by modern computer architectures and specifications of programming languages. This paper proposes a novel non-interference notion and provides concurrent program logic sound to timestamp semantics corresponding to a weak memory model that allows delays in the effects of store instructions. This paper reports three theoretically interesting techniques for modifying non-interference to support delays in the effects of store instructions. The techniques contribute to a better understanding of constructing concurrent program logic.

Keywords: program logic, weak memory model, non-interference, timestamp, vector clock, auxiliary variable

1 Introduction

Modern computer architectures have multiple cores. Because using multiple cores is significant in computational performance, we cannot ignore weak memory models. On a weak memory model, delays in the effects of store instructions are allowed. For example, let us consider the example program called Store Buffering:

x := 1
r0 := y // 0
y := 1
r1 := x // 0

where xx and yy are shared variables and r0r_{0} and r1r_{1} are thread-local variables.

On the strongest memory model called strict consistency, r0=0r1=0r_{0}=0\wedge r_{1}=0 does not hold finally. If r0=0r_{0}=0 holds, r0yr_{0}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}y is executed earlier than y1y\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1. It implies that x1x\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1 is executed earlier than r1xr_{1}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x and therefore r1=1r_{1}=1 holds, and vice versa. On a weak memory model that allows delays in the effects of store instructions, r0=0r1=0r_{0}=0\wedge r_{1}=0 is allowed.

Because the example program has just six execution traces on strict consistency, the so-called exhaustive search enables us to confirm that r0=0r1=0r_{0}=0\wedge r_{1}=0 does not finally hold. Even if we cannot assume strict consistency, model checking with weak memory models is still a promising verification method (e.g., [1, 10]). However, we would like to focus on program logic sound to weak memory models in this paper.

Owicki–Gries logic is well-known to be sound to the standard state semantics based on strict consistency [15]. The logic is an extension for concurrent programs of Hoare logic for sequential programs [7]. Owicki and Gries invented the notion of non-interference to repair the unsoundness of the parallel composition rule without any side condition. They also invented the notion of auxiliary variables to enhance the provability of their logic.

Because Owicki–Gries logic fits strict consistency, it is too strong to be sound to weak memory models. In this paper, we modify the non-interference and propose program logic sound to a weak memory model that allows delays in the effects of store instructions.

In this paper, we adopt timestamp semantics as a weak memory model. Timestamp semantics are obtained by extending messages on memory to messages with timestamps and letting threads have the so-called vector clock, which has one clock at each shared variable [12, 14]. It is known that it expresses delays in the effects of store instructions. For example, because the store instructions that occur in Store Buffering send the messages x=1x=1 and y=1y=1 with timestamp 11 to the memory as follows:

x := 1 // <<x,1>,1>
r0 := y // <<y,0>,0>
y := 1 // <<y,1>,1>
r1 := x // <<x,0>,0>

the load instructions read the messages x=0x=0 and y=0y=0 with timestamp 0. Therefore, r0=0r1=0r_{0}=0\wedge r_{1}=0 is allowed to finally hold. On the other hand, in a similar example program called Coherence:

x := 1 // <<x,1>,1>
r0 := x // <<x,2>,2>
x := 2 // <<x,2>,2>
r1 := x // <<x,2>,2>

r0=2r1=1r_{0}=2\wedge r_{1}=1 is not allowed to finally hold because the memory requires a total order of messages with timestamps for the same shared variable.

In this paper, we modify the non-interference in Owicki–Gries logic and construct concurrent program logic sound to timestamp semantics. The key idea is to formalize different observations of shared variables by threads. Also, this study provides three theoretically interesting techniques clarified by the novel non-interference. The author believes that broadly sharing the techniques contributes to a better understanding of constructing logic. The techniques are explained in detail in Section 4 and clearly described in Section 6 that concludes the paper.

2 Owicki–Gries Logic

We introduce notation for describing the standard state semantics for concurrent programs and remember Owicki–Gries logic, which is sound to the semantics.

Expression EE and sequential program ss are defined as follows:

E\displaystyle E nvE+EEE\displaystyle\Coloneqq n\mid v\mid E+E\mid E-E\mid\ldots s\displaystyle s skipvEs;s.\displaystyle\Coloneqq\texttt{skip}\mid v\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}E\mid s;s\enspace.

where nn and vv denote a numeral and a variable, respectively. Expressions denoting arithmetic operations are appropriately defined.

In this paper, we do not adopt the so-called fork-join paradigm for parallel executions but fix the number of threads to NN. A concurrent program is denoted by

s0sisN1.s_{0}\parallel\cdots\parallel s_{i}\parallel\cdots\parallel s_{N-1}\enspace.

We also omit conditional and loop statements for the simplicity of the presentation.

State MM is a function from variables to numerals in a standard manner. Configurations consist of pairs s,M\mathord{\langle s,M\rangle} of programs and states. We define operational semantics as follows:

vE,Mskip,M[v[[E]]M]\dfrac{}{\mathord{\langle v\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}E,M\rangle}\to\mathord{\langle\texttt{skip},M[v\mapsto[\![E]\!]_{M}]\rangle}} s0,Mskip,Ms0;s1,Ms1,M\dfrac{\mathord{\langle s_{0},M\rangle}\to\mathord{\langle\texttt{skip},M^{\prime}\rangle}}{\mathord{\langle s_{0};s_{1},M\rangle}\to\mathord{\langle s_{1},M^{\prime}\rangle}}
s0,Ms0,Ms0;s1,Ms0;s1,M\dfrac{\mathord{\langle s_{0},M\rangle}\to\mathord{\langle s^{\prime}_{0},M^{\prime}\rangle}}{\mathord{\langle s_{0};s_{1},M\rangle}\to\mathord{\langle s^{\prime}_{0};s_{1},M^{\prime}\rangle}} si,Msi,Ms0sisN1,Ms0sisN1,M\dfrac{\mathord{\langle s_{i},M\rangle}\to\mathord{\langle s^{\prime}_{i},M^{\prime}\rangle}}{\genfrac{}{}{0.0pt}{0}{\mathord{\langle s_{0}\parallel\cdots\parallel s_{i}\parallel\cdots\parallel s_{N-1},M\rangle}\quad\;\;}{\to\mathord{\langle s_{0}\parallel\cdots\parallel s^{\prime}_{i}\parallel\cdots\parallel s_{N-1},M^{\prime}\rangle}}}

where [[E]]M[\![E]\!]_{M} means the interpretation EE by MM that is defined as follows:

[[n]]M\displaystyle[\![n]\!]_{M} =n\displaystyle=n [[v]]M\displaystyle[\![v]\!]_{M} =M(v)\displaystyle=M(v) [[E+E]]M\displaystyle[\![E+E^{\prime}]\!]_{M} =[[E]]M+[[E]]M\displaystyle=[\![E]\!]_{M}+[\![E^{\prime}]\!]_{M}\enspace\ldots

and the update function M[vn](v)M[v\mapsto n](v^{\prime}) is defined as follows:

M[vn](v)={nif v=vM(v)otherwise.M[v\mapsto n](v^{\prime})=\begin{cases}n&\mbox{if }v^{\prime}=v\\ M(v^{\prime})&\mbox{otherwise.}\end{cases}

To describe properties that concurrent programs enjoy, we define an assertion language as follows:

φ\displaystyle\varphi E=EEE¬φφφ.\displaystyle\Coloneqq E=E\mid E\leq E\mid\mathop{\neg}{\varphi}\mid\varphi\wedge\varphi\enspace.

We use abbreviations \top, φψ\varphi\vee\psi, and φψ\varphi\supset\psi in the standard manner.

We interpret φ\varphi by MM as follows:

ME=E\displaystyle M\vDash E=E^{\prime} [[E]]M=[[E]]M\displaystyle\Longleftrightarrow[\![E]\!]_{M}=[\![E^{\prime}]\!]_{M} MEE\displaystyle M\vDash E\leq E^{\prime} [[E]]M[[E]]M\displaystyle\Longleftrightarrow[\![E]\!]_{M}\leq[\![E^{\prime}]\!]_{M}
M¬φ\displaystyle M\vDash\mathop{\neg}{\varphi} M⊭φ\displaystyle\Longleftrightarrow M\not\vDash\varphi Mφψ\displaystyle M\vDash\varphi\wedge\psi Mφ and Mψ.\displaystyle\Longleftrightarrow M\vDash\varphi\mbox{ and }M\vDash\psi\enspace.

Owicki and Gries provided logic that is sound to the state semantics [15]. Owicki–Gries logic consists of the so-called Hoare triples. A triple φ{s}ψ\varphi\>\{\mathord{s}\}\>\psi means that an execution of the program ss under the pre-condition φ\varphi implies that the post-condition ψ\psi holds.

The following is a subset of their inference rules:

φ{skip}φ\dfrac{}{\varphi\>\{\mathord{\texttt{skip}}\}\>\varphi}[E/v]φ{vE}φ\dfrac{}{[E/v]\varphi\>\{\mathord{v\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}E}\}\>\varphi}φφφ{s}ψψψφ{s}ψ\dfrac{\vDash\varphi^{\prime}\supset\varphi\qquad\varphi\>\{\mathord{s}\}\>\psi\qquad\vDash\psi\supset\psi^{\prime}}{\varphi^{\prime}\>\{\mathord{s}\}\>\psi^{\prime}}
φ{s}ψψ{s}χφ{s;s}χ\dfrac{\varphi\>\{\mathord{s}\}\>\psi\qquad\psi\>\{\mathord{s^{\prime}}\}\>\chi}{\varphi\>\{\mathord{s;s^{\prime}}\}\>\chi}Δiφi{si}ψiΔis are non-interferenceφ0φN1{s0sN1}ψ0ψN1.\dfrac{\genfrac{}{}{0.0pt}{0}{\varDelta_{i}}{\varphi_{i}\>\{\mathord{s_{i}}\}\>\psi_{i}}\qquad\genfrac{}{}{0.0pt}{0}{}{\mbox{$\varDelta_{i}$s are non-interference}}}{\varphi_{0}\wedge\cdots\wedge\varphi_{N-1}\>\{\mathord{s_{0}\parallel\cdots\parallel s_{N-1}}\}\>\psi_{0}\wedge\cdots\wedge\psi_{N-1}}\enspace.

Formula [E/v]φ[E/v]\varphi in the assignment axiom denotes the formula obtained by replacing vv that occurs in φ\varphi by EE. Symbol \vDash occurring in the third inference rule denotes the standard satisfaction relation as seen in the first-order predicate logic. If there exists a derivation tree of the root φ{s0sN1}ψ\varphi\>\{\mathord{s_{0}\parallel\cdots\parallel s_{N-1}}\}\>\psi, we write φ{s0sN1}ψ\vdash\varphi\>\{\mathord{s_{0}\parallel\cdots\parallel s_{N-1}}\}\>\psi.

Owicki and Gries defined that Δ1\varDelta_{1} does not interfere with Δ0\varDelta_{0} if φ1φ0{v1E1}φ0\vdash\varphi_{1}\wedge\varphi_{0}\>\{\mathord{v_{1}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}E_{1}}\}\>\varphi_{0} and φ1ψ0{v1E1}ψ0\vdash\varphi_{1}\wedge\psi_{0}\>\{\mathord{v_{1}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}E_{1}}\}\>\psi_{0} hold for any φ0{v0E0}ψ0\varphi_{0}\>\{\mathord{v_{0}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}E_{0}}\}\>\psi_{0} in Δ0\varDelta_{0} and φ1{v1E1}_\varphi_{1}\>\{\mathord{v_{1}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}E_{1}}\}\>\_ in Δ1\varDelta_{1}. In this paper, we write φ1{v0E1}φ0\varphi_{1}\>\{v_{0}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}E_{1}\}\Vdash\varphi_{0} for φ1φ0{v1E1}φ0\vdash\varphi_{1}\wedge\varphi_{0}\>\{\mathord{v_{1}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}E_{1}}\}\>\varphi_{0}, for short, and call that φ0\varphi_{0} is stable under φ1{v1E1}_\varphi_{1}\>\{v_{1}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}E_{1}\}\Vdash\_. We call Δi\varDelta_{i}s (0i<N)(0\leq i<N) non-interference if Δi0\varDelta_{i_{0}} does not interfere with Δi1\varDelta_{i_{1}} for any i0i1i_{0}\neq i_{1}.

φ0{\varphi_{0}} φ1{\varphi_{1}} {y1}\scriptstyle{\{y\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}}{x1}\scriptstyle{\{x\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}} ψ0{\psi_{0}} φ1{\varphi_{1}} {y1}\scriptstyle{\{y\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}}{r0y}\scriptstyle{\{r_{0}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}y\}} χ0{\chi_{0}} φ1{\varphi_{1}} {y1}\scriptstyle{\{y\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}} φ0{\varphi_{0}} ψ1{\psi_{1}} {r1x}\scriptstyle{\{r_{1}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x\}}{x1}\scriptstyle{\{x\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}} ψ0{\psi_{0}} ψ1{\psi_{1}} {r0y}\scriptstyle{\{r_{0}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}y\}}{r1x}\scriptstyle{\{r_{1}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x\}} χ0{\chi_{0}} ψ1{\psi_{1}} {r1x}\scriptstyle{\{r_{1}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x\}} φ0{\varphi_{0}} χ1\chi_{1} {x1}\scriptstyle{\{x\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}} ψ0{\psi_{0}} χ1\chi_{1} {r0y}\scriptstyle{\{r_{0}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}y\}} χ0{\chi_{0}} χ1{\chi_{1}}
Figure 1: Parallel compositionality by non-interference.

In a standard manner, we define φ{s}ψ\vDash\varphi\>\{\mathord{s}\}\>\psi if MφM\vDash\varphi and s,Mskip,M\mathord{\langle s,M\rangle}\to\mathord{\langle\texttt{skip},M^{\prime}\rangle} implies MψM^{\prime}\vDash\psi for any MM and MM^{\prime}. Similarly, we define φ{s0sN1}ψ\vDash\varphi\>\{\mathord{s_{0}\parallel\cdots\parallel s_{N-1}}\}\>\psi. The logic is sound to the state semantics, as shown in Figure 1.

Let us see an example derivation. In this paper, we assume that initial values of variables are 0. Figure 2 shows a derivation of Coherence for ensuring the property ¬(r0=2r1=1)\mathop{\neg}{(r_{0}=2\wedge r_{1}=1)}. In this paper, we write xx and yy for shared variables and write rr for a thread-local variable.

x := 1
r0 := x
x := 2
r1 := x
{x1}{r0x}r0x\begin{array}[]{c}\smash{\top}\rule{0.0pt}{8.6111pt}\\ \smash{\{x\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}}\rule{0.0pt}{8.6111pt}\\ \smash{\top}\rule{0.0pt}{8.6111pt}\\ \smash{\{r_{0}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x\}}\rule{0.0pt}{8.6111pt}\\ \smash{r_{0}\leq x}\rule{0.0pt}{8.6111pt}\end{array}
{x2}1x{r1x}1r1xr1\begin{array}[]{c}\smash{\top}\rule{0.0pt}{8.6111pt}\\ \smash{\{x\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}2\}}\rule{0.0pt}{8.6111pt}\\ \smash{1\leq x}\rule{0.0pt}{8.6111pt}\\ \smash{\{r_{1}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x\}}\rule{0.0pt}{8.6111pt}\\ \smash{1\leq r_{1}\wedge x\leq r_{1}}\rule{0.0pt}{8.6111pt}\end{array}

invariant: (x=0x=1x=2)(r0=0r0=1r0=2)(r1=0r1=1r1=2)(x=0\vee x=1\vee x=2)\wedge(r_{0}=0\vee r_{0}=1\vee r_{0}=2)\wedge(r_{1}=0\vee r_{1}=1\vee r_{1}=2)

{x2}\top\>\{x\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}2\}\Vdash\top

{x2}\top\>\{x\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}2\}\Vdash\top

{x2}r0x\top\>\{x\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}2\}\Vdash r_{0}\leq x

1x{r1x}1\leq x\>\{r_{1}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x\}\Vdash\top

1x{r1x}1\leq x\>\{r_{1}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x\}\Vdash\top

1x{r1x}r0x1\leq x\>\{r_{1}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x\}\Vdash r_{0}\leq x

{x1}\top\>\{x\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash\top

{x1}1x\top\>\{x\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash 1\leq x

{x1}1r1xr1\top\>\{x\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash 1\leq r_{1}\wedge x\leq r_{1}

{r0x}\top\>\{r_{0}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x\}\Vdash\top

{r0x}1x\top\>\{r_{0}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x\}\Vdash 1\leq x

{r0x}1r1xr1\top\>\{r_{0}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x\}\Vdash 1\leq r_{1}\wedge x\leq r_{1}

Figure 2: Derivation of Coherence on non-interference.

Notably, the shared variable xx acts as an intermediary between r0r_{0} and r1r_{1} and ensures finally r0r1r_{0}\leq r_{1} as shown in the derivation. Such variables often enable us to describe assertions.

We checked all the derivations described in this paper by the Boogie program verifier [4].

The provability of the logic still needs to be improved. Figure 3 shows the concurrent program xx+1xx+2x\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x+1\parallel x\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x+2 and a derivation for ensuring that x=3x=3 finally holds. A reason that we can construct the derivation is that the assertions have sufficient information about the execution traces of the program. Specifically, the value of xx tells us how far the program is executed.

x := x + 1
x := x + 2
x=0x=2{xx+1}x=1x=3\begin{array}[]{c}\smash{x=0\vee x=2}\rule{0.0pt}{8.6111pt}\\ \smash{\{x\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x+1\}}\rule{0.0pt}{8.6111pt}\\ \smash{x=1\vee x=3}\rule{0.0pt}{8.6111pt}\end{array}
x=0x=1{xx+2}x=2x=3\begin{array}[]{c}\smash{x=0\vee x=1}\rule{0.0pt}{8.6111pt}\\ \smash{\{x\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x+2\}}\rule{0.0pt}{8.6111pt}\\ \smash{x=2\vee x=3}\rule{0.0pt}{8.6111pt}\end{array}

invariant: x=0x=1x=2x=3x=0\vee x=1\vee x=2\vee x=3

x=0x=1{xx+2}x=0x=2x=0\vee x=1\>\{x\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x+2\}\Vdash x=0\vee x=2

x=0x=1{xx+2}x=1x=3x=0\vee x=1\>\{x\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x+2\}\Vdash x=1\vee x=3

x=0x=2{xx+1}x=0x=1x=0\vee x=2\>\{x\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x+1\}\Vdash x=0\vee x=1

x=0x=2{xx+1}x=2x=3x=0\vee x=2\>\{x\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x+1\}\Vdash x=2\vee x=3

Figure 3: Derivation of One-Two on non-interference.

On the other hand, the value of xx in the parallel composition xx+1xx+1x\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x+1\parallel x\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x+1 does not tell us. Therefore, we cannot add appropriate assertions that do not interfere with each other to the as-is program.

atomic {
x := x + 1
a0 := 1
}
atomic {
x := x + 1
a1 := 1
}
ai=0(a1i=0x=0)(a1i=1x=1){xx+1;ai1}ai=1(a1i=0x=1)(a1i=1x=2)\begin{array}[]{c}\smash{a_{i}=0\wedge(a_{1-i}=0\supset x=0)\wedge(a_{1-i}=1\supset x=1)}\rule{0.0pt}{8.6111pt}\\ \smash{\{x\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x+1;a_{i}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}}\rule{0.0pt}{8.6111pt}\\ \smash{a_{i}=1\wedge(a_{1-i}=0\supset x=1)\wedge(a_{1-i}=1\supset x=2)}\rule{0.0pt}{8.6111pt}\end{array}

invariant: (x=0x=1x=2)(a0=0a0=1)(a1=0a1=1)(x=0\vee x=1\vee x=2)\wedge(a_{0}=0\vee a_{0}=1)\wedge(a_{1}=0\vee a_{1}=1)

a1i=0(ai=0x=0)(ai=1x=1){xx+1;a1i1}ai=0(a1i=0x=0)(a1i=1x=1)a_{1-i}=0\wedge(a_{i}=0\supset x=0)\wedge(a_{i}=1\supset x=1)\>\{x\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x+1;a_{1-i}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash a_{i}=0\wedge(a_{1-i}=0\supset x=0)\wedge(a_{1-i}=1\supset x=1)

a1i=0(ai=0x=0)(ai=1x=1){xx+1;a1i1}ai=1(a1i=0x=1)(a1i=1x=2)a_{1-i}=0\wedge(a_{i}=0\supset x=0)\wedge(a_{i}=1\supset x=1)\>\{x\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x+1;a_{1-i}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash a_{i}=1\wedge(a_{1-i}=0\supset x=1)\wedge(a_{1-i}=1\supset x=2)

Figure 4: Derivation of One-One on non-interference.

Owicki and Gries invented auxiliary variables, which are write-only in programs, atomically updated with existing assignments, described in assertions, and removed from programs later. Figure 4 shows a derivation for ensuring that x=2x=2 finally holds. The auxiliary variables a0a_{0} and a1a_{1} enable us to describe the assertions.

Theorem 1 ([15]).

φ{s0sN1}ψ\vdash\varphi\>\{\mathord{s_{0}\parallel\cdots\parallel s_{N-1}}\}\>\psi implies φ{s0sN1}ψ\vDash\varphi\>\{\mathord{s_{0}\parallel\cdots\parallel s_{N-1}}\}\>\psi.

Figure 5 shows a derivation of Store Buffering with auxiliary variables.

x := 1
atomic {
r0 := y
a0 := 1
}
y := 1
atomic {
r1 := x
a1 := 1
}
{x1}x=1{r0y,a01}a0=1\begin{array}[]{c}\smash{\top}\rule{0.0pt}{8.6111pt}\\ \smash{\{x\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}}\rule{0.0pt}{8.6111pt}\\ \smash{x=1}\rule{0.0pt}{8.6111pt}\\ \smash{\{r_{0}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}y,a_{0}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}}\rule{0.0pt}{8.6111pt}\\ \smash{a_{0}=1}\rule{0.0pt}{8.6111pt}\end{array}
(x=0a0=0)x=1{y1}y=1((x=0a0=0)x=1){r1x,a11}y=1(a0r0r1=1)\begin{array}[]{c}\smash{(x=0\wedge a_{0}=0)\vee x=1}\rule{0.0pt}{8.6111pt}\\ \smash{\{y\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}}\rule{0.0pt}{8.6111pt}\\ \smash{y=1\wedge((x=0\wedge a_{0}=0)\vee x=1)}\rule{0.0pt}{8.6111pt}\\ \smash{\{r_{1}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x,a_{1}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}}\rule{0.0pt}{8.6111pt}\\ \smash{y=1\wedge(a_{0}\leq r_{0}\vee r_{1}=1)}\rule{0.0pt}{8.6111pt}\end{array}

invariant: (x=0x=1)(y=0y=1)(r0=0r0=1)(r1=0r1=1)(x=0\vee x=1)\wedge(y=0\vee y=1)\wedge(r_{0}=0\vee r_{0}=1)\wedge(r_{1}=0\vee r_{1}=1)

(x=0a0=0)x=1{y1}(x=0\wedge a_{0}=0)\vee x=1\>\{y\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash\top

(x=0a0=0)x=1{y1}x=1(x=0\wedge a_{0}=0)\vee x=1\>\{y\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash x=1

(x=0a0=0)x=1{y1}a0=1(x=0\wedge a_{0}=0)\vee x=1\>\{y\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash a_{0}=1

y=1((x=0a0=0)x=1){r1x,a11}y=1\wedge((x=0\wedge a_{0}=0)\vee x=1)\>\{r_{1}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x,a_{1}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash\top

y=1((x=0a0=0)x=1){r1x,a11}x=1y=1\wedge((x=0\wedge a_{0}=0)\vee x=1)\>\{r_{1}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x,a_{1}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash x=1

y=1((x=0a0=0)x=1){r1x,a11}a0=1y=1\wedge((x=0\wedge a_{0}=0)\vee x=1)\>\{r_{1}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x,a_{1}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash a_{0}=1

{x1}(x=0a0=0)x=1\top\>\{x\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash(x=0\wedge a_{0}=0)\vee x=1

{x1}y=1((x=0a0=0)x=1)\top\>\{x\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash y=1\wedge((x=0\wedge a_{0}=0)\vee x=1)

{x1}y=1(a0r0r1=1)\top\>\{x\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash y=1\wedge(a_{0}\leq r_{0}\vee r_{1}=1)

x=1{r0y,a01}(x=0a0=0)x=1x=1\>\{r_{0}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}y,a_{0}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash(x=0\wedge a_{0}=0)\vee x=1

x=1{r0y,a01}y=1((x=0a0=0)x=1)x=1\>\{r_{0}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}y,a_{0}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash y=1\wedge((x=0\wedge a_{0}=0)\vee x=1)

x=1{r0y,a01}y=1(a0r0r1=1)x=1\>\{r_{0}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}y,a_{0}\stackrel{{\scriptstyle\smash{}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash y=1\wedge(a_{0}\leq r_{0}\vee r_{1}=1)

Figure 5: Derivation of Store Buffering on non-interference.

3 Timestamp Semantics

We formally define timestamp semantics.

In the following, we formally distinguish thread-local variables rr from shared variables xx. We also divide assignments into three kinds, thread-local, load, and store instructions as follows:

e\displaystyle e nre+e\displaystyle\Coloneqq n\mid r\mid e+e\mid\ldots c\displaystyle c rierixxie\displaystyle\Coloneqq r\stackrel{{\scriptstyle\smash{i}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}e\mid r\stackrel{{\scriptstyle\smash{i}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x\mid x\stackrel{{\scriptstyle\smash{i}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}e s\displaystyle s skipcs;s\displaystyle\Coloneqq\texttt{skip}\mid c\mid s;s

and each assignment has a thread identifier denoting the thread that executes the assignment. A sequentially compound statement contains a unique thread identifier.

On timestamp semantics, thread-local states SS are separated from the shared memory MM. Thread-local state SS is a function from thread-local variables to numerals. We define the interpretations of expressions by SS as follows:

[[n]]S\displaystyle[\![n]\!]_{S} =n\displaystyle=n [[r]]S\displaystyle[\![r]\!]_{S} =S(r)\displaystyle=S(r) [[e+e]]S\displaystyle[\![e+e^{\prime}]\!]_{S} =[[e]]S+[[e]]S.\displaystyle=[\![e]\!]_{S}+[\![e^{\prime}]\!]_{S}\enspace\ldots\enspace.
rie,S,T,Mskip,S[r[[e]]S],T,M\dfrac{}{\mathord{\langle\mathord{\langle r\stackrel{{\scriptstyle\smash{i}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}e,S,T\rangle},M\rangle}\to\mathord{\langle\mathord{\langle\texttt{skip},S[r\mapsto[\![e]\!]_{S}],T\rangle},M\rangle}}
M(x,t)=nT(x)trix,S,T,Mskip,S[rn],T[xt],M\dfrac{M(\mathord{\langle x,t\rangle})=n\qquad T(x)\leq t}{\mathord{\langle\mathord{\langle r\stackrel{{\scriptstyle\smash{i}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x,S,T\rangle},M\rangle}\to\mathord{\langle\mathord{\langle\texttt{skip},S[r\mapsto n],T[x\mapsto t]\rangle},M\rangle}}
T(x)<txie,S,T,Mskip,S,T[xt],M{x,t,[[e]]S}\dfrac{T(x)<t}{\mathord{\langle\mathord{\langle x\stackrel{{\scriptstyle\smash{i}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}e,S,T\rangle},M\rangle}\to\mathord{\langle\mathord{\langle\texttt{skip},S,T[x\mapsto t]\rangle},M\sqcup\{\mathord{\langle\mathord{\langle x,t\rangle},[\![e]\!]_{S}\rangle}\}\rangle}}
s0,S,T,Mskip,S,T,Ms0;s1,S,T,Ms1,S,T,M\dfrac{\mathord{\langle\mathord{\langle s_{0},S,T\rangle},M\rangle}\to\mathord{\langle\mathord{\langle\texttt{skip},S^{\prime},T^{\prime}\rangle},M^{\prime}\rangle}}{\mathord{\langle\mathord{\langle s_{0};s_{1},S,T\rangle},M\rangle}\to\mathord{\langle\mathord{\langle s_{1},S^{\prime},T^{\prime}\rangle},M^{\prime}\rangle}}
s0,S,T,Ms0,S,T,Ms0;s1,S,T,Ms0;s1,S,T,M\dfrac{\mathord{\langle\mathord{\langle s_{0},S,T\rangle},M\rangle}\to\mathord{\langle\mathord{\langle s^{\prime}_{0},S^{\prime},T^{\prime}\rangle},M^{\prime}\rangle}}{\mathord{\langle\mathord{\langle s_{0};s_{1},S,T\rangle},M\rangle}\to\mathord{\langle\mathord{\langle s^{\prime}_{0};s_{1},S^{\prime},T^{\prime}\rangle},M^{\prime}\rangle}}
(i),MC,M,M[iC],M\dfrac{\mathord{\langle\mathfrak{C}(i),M\rangle}\to\mathord{\langle C^{\prime},M^{\prime}\rangle}}{\mathord{\langle\mathfrak{C},M\rangle}\to\mathord{\langle\mathfrak{C}[i\mapsto C^{\prime}],M^{\prime}\rangle}}  .
Figure 6: Timestamp semantics.

The shared memory possesses messages with timestamps x,t,n\mathord{\langle\mathord{\langle x,t\rangle},n\rangle}, differently from physical memories that we know. In this paper, timestamps are rationals, i.e., elements of \mathbb{Q}. It is known that a set of timestamps should be dense (e.g. [9]). The shared memory MM is a function from pairs of shared variables and timestamps to numerals. Notably, MM is a function; a shared memory cannot possess multiple messages for the same shared variable and the same timestamp.

Each thread has a vector clock [12, 14]. A vector clock takes a shared variable and returns a timestamp. Differences between vector clocks that threads have express observations of shared variables by threads.

Thread-local configurations CC consist of triples s,S,T\mathord{\langle s,S,T\rangle} of programs, thread-local states, and vector clocks. Thread-local configurations with memory consist of pairs C,M\mathord{\langle C,M\rangle} of thread-local configurations CC and memories. Global Configurations consist of pairs ,M\mathord{\langle\mathfrak{C},M\rangle} of thread-local configurations \mathfrak{C} and memories MM where \mathfrak{C} takes a thread identifier ii and returns a configuration CC. Operational semantics are as shown in Figure 6.

No explanation for thread-local assignments is needed. An assignment of a load instruction takes any message in the memory whose timestamp is equal to or larger than the timestamp that the vector clock indicates. Furthermore, it updates the vector clock. An assignment of a store instruction sends a message whose timestamp is strictly larger than the timestamp that the vector clock indicates, and updates the vector clock. Timestamp semantics express a modern memory model on which effects of store instructions may be delayed (e.g. [9]).

4 Observation-Based Logic

In this section, we provide concurrent program logic for timestamp semantics.

4.1 Formal system

We introduce observation variable xix^{i}, which denotes xx observed by thread ii, for any shared variable xx. Whereas the notion of observation variables is previously provided by the author [2], we provide another logic in this paper.

The motivation for the introduction of observation variables is straightforward. In the standard state semantics, all variables are synchronous; if a thread updates the value of a variable, then other threads can immediately see the update. Variables that occur in assertions are also synchronous in stability checking. However, in timestamp semantics, that is not the case. Nevertheless, variables that occur in assertions in logic should be synchronous because stability checking is designed that way.

Observation variables fix the gap. Observation variables are synchronous in assertions in logic, that is, if a thread updates the value of an observation variable, then other threads can immediately see the update. Surely, a relation between observation variables xi0x^{i_{0}} and xi1(i0i1)x^{i_{1}}\;(i_{0}\neq i_{1}) is not a relation between distinct shared variables xx and yy. We clarify and formalize the relation between observation variables in logic.

We define a satisfaction relation that configurations enjoy assertions. For convenience, we write 𝔖\mathfrak{S} for the thread-local states of \mathfrak{C}, that is, 𝔖(i)\mathfrak{S}(i) denotes the thread-local state of (i)\mathfrak{C}(i). We also write 𝔗\mathfrak{T} for the vector clocks of \mathfrak{C}, that is, 𝔗(i)\mathfrak{T}(i) denotes the vector clock of (i)\mathfrak{C}(i). We define M,𝔖,𝔗tφ\mathord{\langle M,\mathord{\langle\mathfrak{S},\mathfrak{T}\rangle}\rangle}\vDash^{t}\varphi as follows:

Ee\displaystyle E\Coloneqq e xiE+EEE\displaystyle\mid x^{i}\mid E+E\mid E-E\mid\ldots
[[n]]M,𝔖,𝔗\displaystyle[\![n]\!]_{\mathord{\langle M,\mathord{\langle\mathfrak{S},\mathfrak{T}\rangle}\rangle}} =n\displaystyle=n
[[r]]M,𝔖,𝔗\displaystyle[\![r]\!]_{\mathord{\langle M,\mathord{\langle\mathfrak{S},\mathfrak{T}\rangle}\rangle}} =𝔖(i)(r)if thread i contains r\displaystyle=\mathfrak{S}(i)(r)\quad\mbox{if thread $i$ contains $r$}
[[xi]]M,𝔖,𝔗\displaystyle[\![x^{i}]\!]_{\mathord{\langle M,\mathord{\langle\mathfrak{S},\mathfrak{T}\rangle}\rangle}} =M(x,𝔗(i)(x))\displaystyle=M(\mathord{\langle x,\mathfrak{T}(i)(x)\rangle})
[[E+E]]M,𝔖,𝔗\displaystyle[\![E+E^{\prime}]\!]_{\mathord{\langle M,\mathord{\langle\mathfrak{S},\mathfrak{T}\rangle}\rangle}} =[[E]]M,𝔖,𝔗+[[E]]M,𝔖,𝔗\displaystyle=[\![E]\!]_{\mathord{\langle M,\mathord{\langle\mathfrak{S},\mathfrak{T}\rangle}\rangle}}+[\![E^{\prime}]\!]_{\mathord{\langle M,\mathord{\langle\mathfrak{S},\mathfrak{T}\rangle}\rangle}}\enspace\ldots
M,𝔖,𝔗tE=E\displaystyle\mathord{\langle M,\mathord{\langle\mathfrak{S},\mathfrak{T}\rangle}\rangle}\vDash^{t}E=E^{\prime} [[E]]M,𝔖,𝔗=[[E]]M,𝔖,𝔗\displaystyle\Longleftrightarrow[\![E]\!]_{\mathord{\langle M,\mathord{\langle\mathfrak{S},\mathfrak{T}\rangle}\rangle}}=[\![E^{\prime}]\!]_{\mathord{\langle M,\mathord{\langle\mathfrak{S},\mathfrak{T}\rangle}\rangle}}
M,𝔖,𝔗tEE\displaystyle\mathord{\langle M,\mathord{\langle\mathfrak{S},\mathfrak{T}\rangle}\rangle}\vDash^{t}E\leq E^{\prime} [[E]]M,𝔖,𝔗=[[E]]M,𝔖,𝔗\displaystyle\Longleftrightarrow[\![E]\!]_{\mathord{\langle M,\mathord{\langle\mathfrak{S},\mathfrak{T}\rangle}\rangle}}=[\![E^{\prime}]\!]_{\mathord{\langle M,\mathord{\langle\mathfrak{S},\mathfrak{T}\rangle}\rangle}}
M,𝔖,𝔗t¬φ\displaystyle\mathord{\langle M,\mathord{\langle\mathfrak{S},\mathfrak{T}\rangle}\rangle}\vDash^{t}\mathop{\neg}{\varphi} M,𝔖,𝔗⊭tφ\displaystyle\Longleftrightarrow\mathord{\langle M,\mathord{\langle\mathfrak{S},\mathfrak{T}\rangle}\rangle}\not{\vDash^{t}}\varphi
M,𝔖,𝔗tφψ\displaystyle\mathord{\langle M,\mathord{\langle\mathfrak{S},\mathfrak{T}\rangle}\rangle}\vDash^{t}\varphi\wedge\psi M,𝔖,𝔗tφ and M,𝔖,𝔗tψ.\displaystyle\Longleftrightarrow\mathord{\langle M,\mathord{\langle\mathfrak{S},\mathfrak{T}\rangle}\rangle}\vDash^{t}\varphi\mbox{ and }\mathord{\langle M,\mathord{\langle\mathfrak{S},\mathfrak{T}\rangle}\rangle}\vDash^{t}\psi\enspace.

We define Mtφ{s}ψM\vDash^{t}\varphi\>\{\mathord{s}\}\>\psi if M,𝔖,𝔗tφ\mathord{\langle M,\mathord{\langle\mathfrak{S},\mathfrak{T}\rangle}\rangle}\vDash^{t}\varphi and s,𝔖(i),𝔗(i),Mskip,𝔖(i),𝔗(i),M\mathord{\langle\mathord{\langle s,\mathfrak{S}(i),\mathfrak{T}(i)\rangle},M\rangle}\to\mathord{\langle\mathord{\langle\texttt{skip},\mathfrak{S^{\prime}}(i),\mathfrak{T^{\prime}}(i)\rangle},M^{\prime}\rangle} implies M,𝔖,𝔗tψ\mathord{\langle M^{\prime},\mathord{\langle\mathfrak{S^{\prime}},\mathfrak{T^{\prime}}\rangle}\rangle}\vDash^{t}\psi for any 𝔖\mathfrak{S} and 𝔗\mathfrak{T}. Similarly, we define Mtφ{s0sN1}ψM\vDash^{t}\varphi\>\{\mathord{s_{0}\parallel\cdots\parallel s_{N-1}}\}\>\psi.

We also introduce timestamp variable t@xt\mathrm{@}x for any shared variable xx. We describe how to use timestamp variables with the explanation of non-observation-interference described later. Timestamp variables in assertions are interpreted as thread-local variables. The following are inference rules consisting of extended judgments:

φ,L{skip}φ,L\dfrac{}{\varphi,\mathit{L}\>\{\mathord{\texttt{skip}}\}\>\varphi,\mathit{L}} [e/r]φ,L{rie}φ,L\dfrac{}{[e/r]\varphi,\mathit{L}\>\{\mathord{r\stackrel{{\scriptstyle\smash{i}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}e}\}\>\varphi,\mathit{L}}
[xi/r]φ,L{rix}φ,L\dfrac{}{[x^{i}/r]\varphi,\mathit{L}\>\{\mathord{r\stackrel{{\scriptstyle\smash{i}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x}\}\>\varphi,\mathit{L}}  t is fresh [e/xi]φ,L{xie}φ,L[xL(x):t@x]\dfrac{\mbox{ $t$ is fresh }}{[e/x^{i}]\varphi,\mathit{L}\>\{\mathord{x\stackrel{{\scriptstyle\smash{i}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}e}\}\>\varphi,\mathit{L}[x\mapsto\mathit{L}(x)\!\mathbin{:}\!t\mathrm{@}x]}
φφφ,L0{s}ψ,L1ψψφ,L0{s}ψ,L1\dfrac{\vDash\varphi^{\prime}\supset\varphi\qquad\varphi,\mathit{L}_{0}\>\{\mathord{s}\}\>\psi,\mathit{L}_{1}\qquad\vDash\psi\supset\psi^{\prime}}{\varphi^{\prime},\mathit{L}_{0}\>\{\mathord{s}\}\>\psi^{\prime},\mathit{L}_{1}}
φ,L0{s0}ψ,Lψ,L{s1}χ,L1φ,L0{s0;s1}χ,L1\dfrac{\varphi,\mathit{L}_{0}\>\{\mathord{s_{0}}\}\>\psi,\mathit{L}\qquad\psi,\mathit{L}\>\{\mathord{s_{1}}\}\>\chi,\mathit{L}_{1}}{\varphi,\mathit{L}_{0}\>\{\mathord{s_{0};s_{1}}\}\>\chi,\mathit{L}_{1}}
Δiφi,I{si}ψi,LiΔis are non-observation-interferenceφ0φN1{s0sN1}ψ0ψN1.\dfrac{\genfrac{}{}{0.0pt}{0}{\varDelta_{i}}{\varphi_{i},I\>\{\mathord{s_{i}}\}\>\psi_{i},\mathit{L}_{i}}\qquad\genfrac{}{}{0.0pt}{0}{}{\mbox{$\varDelta_{i}$s are non-observation-interference}}}{\varphi_{0}\wedge\cdots\wedge\varphi_{N-1}\>\{\mathord{s_{0}\parallel\cdots\parallel s_{N-1}}\}\>\psi_{0}\wedge\cdots\wedge\psi_{N-1}}\enspace.

Because assignments are divided into three kinds, the assignment axiom is also divided into three. Assignments of load instructions by thread ii replace thread-local variables with xix^{i}. Careful readers may wonder if the assignment axiom for load instructions is unconditionally unsound. The unsoundness is remedied by the non-observation-interference, as explained in detail in the following subsection.

The assignment axiom for store instructions is sound because we introduced observation variables to make it so. For example,

r+1=2xi1=0{xi0r+1}xi0=2xi1=0{r+1=2\wedge x^{i_{1}}=0\>\{\mathord{x\stackrel{{\scriptstyle\smash{i_{0}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}r+1}\}\>x^{i_{0}}=2\wedge x^{i_{1}}=0}

is valid because xi0r+1x\stackrel{{\scriptstyle\smash{i_{0}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}r+1 updates the vector clock of thread i0i_{0}.

Sequence LL consists of reverse lists of timestamp variables at each shared variable. An initial timestamp sequence II has exactly one timestamp variable for any shared variable. A timestamp variable is freshly generated at an assignment axiom of a store instruction to xx and is added to the end at xx of the timestamp sequence.

To ensure a total order of timestamps of each shared variable, we assume t@x<t@x\vDash t\mathrm{@}x<t^{\prime}\mathrm{@}x for any shared variable xx and :t@x::t@x:\ldots\!\mathbin{:}\!t\mathrm{@}x\!\mathbin{:}\!\ldots\!\mathbin{:}\!t^{\prime}\mathrm{@}x\!\mathbin{:}\!\ldots in L\mathit{L}. To ensure a total order of timestamps of each shared variable on memory, we assume t@x<t@xt@x<t@x\vDash t\mathrm{@}x<t^{\prime}\mathrm{@}x\vee t^{\prime}\mathrm{@}x<t\mathrm{@}x for any shared variable xx and any distinct tt and tt^{\prime}.

If there exists a derivation tree of the root φ,L{s}ψ,L\varphi,\mathit{L}\>\{\mathord{s}\}\>\psi,\mathit{L}^{\prime} in the system, we write tφ,L{s}ψ,L\vdash^{t}\varphi,\mathit{L}\>\{\mathord{s}\}\>\psi,\mathit{L}^{\prime}. Similarly, we define tφ{s0sN1}ψ\vdash^{t}\varphi\>\{\mathord{s_{0}\parallel\cdots\parallel s_{N-1}}\}\>\psi.

4.2 Non-observation-interference

Before providing the formal definition of non-observation-interference, we explain its intuition. For the simplicity, we often omit reverse lists of timestamp variables in judgments if they are clear from the context.

First, it appears that xi0=1{ri0x}r=1xi0=1x^{i_{0}}=1\>\{\mathord{r\stackrel{{\scriptstyle\smash{i_{0}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x}\}\>r=1\wedge x^{i_{0}}=1 is unsound to timestamp semantics because the value of xx at a timestamp tt, which may not be pointed by the vector clock satisfying xi0=1x^{i_{0}}=1, is loaded. That makes us want to add, for example, a necessity modality operator \Box meaning “always true” to xi0=1x^{i_{0}}=1 in the pre-condition. Alternatively, one may want to extend the assertion language with control predicates and modify the interpretation of Hoare triples [13]. However, we do not adopt them in this paper.

If the number of threads is 11, the judgment is still sound because the memory has no message from another thread. Soundness of φ0{ri0x}ψ0\varphi_{0}\>\{\mathord{r\stackrel{{\scriptstyle\smash{i_{0}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x}\}\>\psi_{0} is stained by a store instruction xi1ex\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}e by another thread i1i_{1}. It is reminiscent of the non-interference.

Let φ1{xi1e}ψ1\varphi_{1}\>\{\mathord{x\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}e}\}\>\psi_{1} in Δi1\varDelta_{i_{1}}. The store instruction xi1ex\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}e may not be simultaneously executed with ri0xr\stackrel{{\scriptstyle\smash{i_{0}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x. Therefore, for any pre-condition φ0\varphi^{\prime}_{0} that is sequentially composed on or before the ri0xr\stackrel{{\scriptstyle\smash{i_{0}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x, we have to check that the effect of xi1nx\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}n to the memory does not interfere φ0\varphi_{0} for any n|e|φ0φ1n\in\langle\!|e|\!\rangle_{\varphi^{\prime}_{0}\wedge\varphi_{1}}, which denotes arbitrary values of ee that are constrained by φ0φ1\varphi^{\prime}_{0}\wedge\varphi_{1}. For example, for xi1r1x\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}r_{1} under 0r1<30\leq r_{1}<3, we have to consider the judgments about xi10x\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}0, xi11x\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1, and xi12x\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}2.

How do we check whether the effect of xi1nx\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}n to the memory interferes φ0\varphi_{0} or not? A load instruction ri0xr\stackrel{{\scriptstyle\smash{i_{0}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x updates the vector clock of i0i_{0}, therefore, xix^{i}, and rr. We divide it into two phases. If the updates of the vector clock and xix^{i} are finished, the update of rr is sound. The unsoundness of the assignment axiom for load instructions is derived from updates of vector clocks.

Here, we do a trick. By replacing thread identifier i1i_{1} of the store instruction with thread identifier i0i_{0}, we can update the vector clock of thread identifier i0i_{0}. That is, for any φ1\varphi^{\prime}_{1} that is a pre/post-condition on or after the xi1ex\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}e, we check Mtφ1φ0{xi0n}φ0M\vDash^{t}\varphi^{\prime}_{1}\wedge\varphi_{0}\>\{\mathord{x\stackrel{{\scriptstyle\smash{i_{0}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}n}\}\>\varphi_{0} instead of any judgment consisting of xi1nx\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}n. Notably, our assertion language cannot directly refer to vector clocks. We notice updates of vector clocks through updates of observation variables.

Because judgments of store instructions are as-is sound, it is sufficient to check tφ1φ0{xi0n}φ0\vdash^{t}\varphi^{\prime}_{1}\wedge\varphi_{0}\>\{\mathord{x\stackrel{{\scriptstyle\smash{i_{0}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}n}\}\>\varphi_{0}. The following:

x0=0{r0x}r=0{x11}x0=0{x01}x0=0x0=0{r0xx11}r=0\dfrac{{x^{0}=0\>\{\mathord{r\stackrel{{\scriptstyle\smash{0}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x}\}\>r=0}\qquad{\top\>\{\mathord{x\stackrel{{\scriptstyle\smash{1}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1}\}\>\top}\qquad{\top\wedge x^{0}=0\>\{\mathord{x\stackrel{{\scriptstyle\smash{0}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1}\}\>x^{0}=0}}{x^{0}=0\>\{\mathord{r\stackrel{{\scriptstyle\smash{0}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x\parallel x\stackrel{{\scriptstyle\smash{1}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1}\}\>r=0}

is not derivable because x0=0{x01}x0=0{\top\wedge x^{0}=0\>\{\mathord{x\stackrel{{\scriptstyle\smash{0}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1}\}\>x^{0}=0} is not derivable. Thus, we reuse the notion of non-interference for soundness of judgments of load instructions.

Table 1: Remedying soundness.
Without non-(observation-)interference assignment axiom parallel composition rule
XloadX store
Owicki–Gries logic \checkmark
Our logic (11 thread) \checkmark \checkmark N/A
Our logic (2\geq 2 threads) \checkmark
With non-(observation-)interference assignment axiom parallel composition rule
XloadX store
Owicki–Gries logic \checkmark \checkmark
Our logic (11 thread) \checkmark \checkmark N/A
Our logic (2\geq 2 threads) \checkmark \checkmark \checkmark

The assignment axiom in Owicki–Gries logic is sound to the standard state semantics, but the parallel composition rule without any side condition is unsound. Therefore, Owicki and Gries introduced the notion of non-interference. The assignment axiom becomes unsound in our logic to timestamp semantics if another thread executes a store instruction. Non-observation-interference adopted by our logic plays a role in keeping the assignment axiom for load instructions sound to timestamp semantics. Table 1 summarizes it.

Next, we explain the extension of non-interference in our logic. If an interfering instruction is ri1er\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}e, we have to consider no issue in addition to non-interference. If an interfering instruction is xi1ex\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}e, we also have to consider no issue because xi1x^{i_{1}} in the assertion possessed by thread i0i_{0} is synchronous and stability checking is the same as that in Owicki–Gries logic, as explained in the beginning of Section 4.

If an interfering instruction is ri1xr\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x, we have to take care of that r1i1xr_{1}\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x updates not only r1r_{1} but also xi1x^{i_{1}} in φ0\varphi_{0} and ψ0\psi_{0}. Let φ0{c0}ψ0\varphi_{0}\>\{\mathord{c_{0}}\}\>\psi_{0} be a possibly interfered judgment. We have to confirm Mtφ1φ0{r1i1x}φ0M\vDash^{t}\varphi_{1}\wedge\varphi_{0}\>\{\mathord{r_{1}\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x}\}\>\varphi_{0} and Mtφ1ψ0{r1i1x}ψ0M\vDash^{t}\varphi_{1}\wedge\psi_{0}\>\{\mathord{r_{1}\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x}\}\>\psi_{0}. Similar to the discussion about the soundness of judgments of load instructions, we have to take care of that tφ1φ0{r1i1x}φ0\vdash^{t}\varphi_{1}\wedge\varphi_{0}\>\{\mathord{r_{1}\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x}\}\>\varphi_{0} and tφ1ψ0{r1i1x}ψ0\vdash^{t}\varphi_{1}\wedge\psi_{0}\>\{\mathord{r_{1}\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x}\}\>\psi_{0} are not sufficient because they are not ensured not to be interfered with any store instruction by another thread.

Thus, we have constructed logic that is sound to timestamp semantics. However, the provability still needs to be improved. Non-interference utilizes the pre-condition of the interfering judgment, but it is impossible because the effect of the store instruction may be delayed on timestamp semantics. It weakens the expressive power of assertion language. Therefore, we cannot delicately deal with execution traces; specifically, we cannot show the correctness of Coherence under timestamp semantics because how to grasp the difference between Store Buffering and Coherence, a total order of timestamps at each variable on memory, has not been explained yet.

We have introduced timestamp variables. Freshness in assignment axioms of store instructions and non-logical axioms ensure total orders at shared variables on memory. The variables are not updated by assignments. We can describe assertions. For any store instruction, a fresh timestamp variable is defined and added to the end of the sequence at each variable. It enables us to describe how far the program runs. Timestamp variables are also used to restrict ranges that instructions interfere in the definition of non-observation-interference. Whereas auxiliary variables with non-interference in Owicki–Gries logic do not restrict ranges that instructions interfere with, pre-conditions that interfering instructions have actually restricted ranges of interfered conditions. In our logic, where we cannot assume pre-conditions for interfering instructions, timestamp variables directly restrict ranges of instructions that interfere with each other.

Finally, we formally define non-observation-interference. We call Δi\varDelta_{i}s (0i<N0\leq i<N) non-observation-interference if for any i0i_{0}, i1i_{1}, and i2i_{2} such that i0i1i_{0}\neq i_{1} and i1i2i_{1}\neq i_{2} hold,

  • t0@x<t1@xφ1{xi0n}tφ0t_{0}\mathrm{@}x<t_{1}\mathrm{@}x\wedge\varphi^{\prime}_{1}\>\{x\stackrel{{\scriptstyle\smash{i_{0}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}n\}\Vdash^{t}\varphi_{0} holds for any φ0{ri0x}_,_:t0@x\varphi_{0}\>\{\mathord{r\stackrel{{\scriptstyle\smash{i_{0}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x}\}\>\_,\_\!\mathbin{:}\!t_{0}\mathrm{@}x in Δi0\varDelta_{i_{0}}, φ1{xi1e}_,_:t1@x\varphi_{1}\>\{\mathord{x\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}e}\}\>\_,\_\!\mathbin{:}\!t_{1}\mathrm{@}x in Δi1\varDelta_{i_{1}}, a pre-condition φ0\varphi^{\prime}_{0} that is sequentially composed on or before the ri0xr\stackrel{{\scriptstyle\smash{i_{0}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x in Δi0\varDelta_{i_{0}}, n|e|φ0φ1n\in\langle\!|e|\!\rangle_{\varphi^{\prime}_{0}\wedge\varphi_{1}}, and a pre/post-condition φ1\varphi^{\prime}_{1} that is sequentially composed on or after the xi1ex\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}e in Δi1\varDelta_{i_{1}},

  • φ1{ri1e}tφ0\varphi_{1}\>\{r\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}e\}\Vdash^{t}\varphi_{0} and φ1{ri1e}tψ0\varphi_{1}\>\{r\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}e\}\Vdash^{t}\psi_{0} hold for any φ0{c0}ψ0\varphi_{0}\>\{\mathord{c_{0}}\}\>\psi_{0} in Δi0\varDelta_{i_{0}} and φ1{ri1e}_\varphi_{1}\>\{\mathord{r\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}e}\}\>\_ in Δi1\varDelta_{i_{1}},

  • φ1{xi1e}tφ0\varphi_{1}\>\{x\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}e\}\Vdash^{t}\varphi_{0} and φ1{xi1e}tψ0\varphi_{1}\>\{x\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}e\}\Vdash^{t}\psi_{0} hold for any φ0{c0}ψ0\varphi_{0}\>\{\mathord{c_{0}}\}\>\psi_{0} in Δi0\varDelta_{i_{0}} and φ1{xi1e}_\varphi_{1}\>\{\mathord{x\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}e}\}\>\_ in Δi1\varDelta_{i_{1}}, and

  • φ1{ri1x}tφ0\varphi_{1}\>\{r\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x\}\Vdash^{t}\varphi_{0} and φ1{ri1x}tψ0\varphi_{1}\>\{r\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x\}\Vdash^{t}\psi_{0} hold for any φ0{c0}ψ0\varphi_{0}\>\{\mathord{c_{0}}\}\>\psi_{0} in Δi0\varDelta_{i_{0}} and φ1{ri1x}ψ1,_:t1@x\varphi_{1}\>\{\mathord{r\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x}\}\>\psi_{1},\_\!\mathbin{:}\!t_{1}\mathrm{@}x in Δi1\varDelta_{i_{1}}, moreover,

    • t1@x<t0@xφ0′′{xi1n}tφ1φ0t_{1}\mathrm{@}x<t_{0}\mathrm{@}x\wedge\varphi^{\prime\prime}_{0}\>\{x\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}n\}\Vdash^{t}\varphi_{1}\wedge\varphi_{0} and φ0′′{xi1n}tφ1ψ0\varphi^{\prime\prime}_{0}\>\{x\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}n\}\Vdash^{t}\varphi_{1}\wedge\psi_{0} hold for any φ0{xi0e}_,_:t0@x\varphi^{\prime}_{0}\>\{\mathord{x\stackrel{{\scriptstyle\smash{i_{0}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}e}\}\>\_,\_\!\mathbin{:}\!t_{0}\mathrm{@}x that is sequentially composed on or before the c0c_{0} in Δi0\varDelta_{i_{0}}, a pre-condition φ1\varphi^{\prime}_{1} that is sequentially composed on or before the ri1xr\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x in Δi1\varDelta_{i_{1}}, a pre/post-condition φ0′′\varphi^{\prime\prime}_{0} that is sequentially composed on or after the xi0ex\stackrel{{\scriptstyle\smash{i_{0}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}e and on or before c0c_{0} in Δi0\varDelta_{i_{0}}, and n|e|φ1φ0n\in\langle\!|e|\!\rangle_{\varphi^{\prime}_{1}\wedge\varphi^{\prime}_{0}}

    • t1@x<t2@xφ2{xi1n}tφ1φ0t_{1}\mathrm{@}x<t_{2}\mathrm{@}x\wedge\varphi^{\prime}_{2}\>\{x\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}n\}\Vdash^{t}\varphi_{1}\wedge\varphi_{0} and φ2{xi1n}tφ1ψ0\varphi^{\prime}_{2}\>\{x\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}n\}\Vdash^{t}\varphi_{1}\wedge\psi_{0} hold for any φ2{xi2e}_,_:t2@x\varphi_{2}\>\{\mathord{x\stackrel{{\scriptstyle\smash{i_{2}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}e}\}\>\_,\_\!\mathbin{:}\!t_{2}\mathrm{@}x in Δi2\varDelta_{i_{2}}, a pre-condition φ1\varphi^{\prime}_{1} that is sequentially composed on or before the ri1xr\stackrel{{\scriptstyle\smash{i_{1}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x in Δi1\varDelta_{i_{1}}, n|e|φ1φ2n\in\langle\!|e|\!\rangle_{\varphi^{\prime}_{1}\wedge\varphi_{2}}, and a pre/post-condition φ2\varphi^{\prime}_{2} that is sequentially composed on or after the xi2ex\stackrel{{\scriptstyle\smash{i_{2}}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}e in Δi2\varDelta_{i_{2}}

where we write φ1{c}tφ0\varphi_{1}\>\{c\}\Vdash^{t}\varphi_{0} for tφ1φ0{c}φ0\vdash^{t}\varphi_{1}\wedge\varphi_{0}\>\{\mathord{c}\}\>\varphi_{0}, for short.

Theorem 2.

tφ{s0sN1}ψ\vdash^{t}\varphi\>\{\mathord{s_{0}\parallel\cdots\parallel s_{N-1}}\}\>\psi implies [_,00]tφ{s0sN1}ψ\varnothing[\mathord{\langle\_,0\rangle}\mapsto 0]\vDash^{t}\varphi\>\{\mathord{s_{0}\parallel\cdots\parallel s_{N-1}}\}\>\psi.

x := 1
r0 := x
x := 2
r1 := x
r0=0r1x1{x01}0<x0r0=0r1x1{r00x}0<r0\begin{array}[]{c}\smash{r_{0}=0\wedge r_{1}\leq x^{1}}\rule{0.0pt}{8.6111pt}\\ \smash{\{x\stackrel{{\scriptstyle\smash{0}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}}\rule{0.0pt}{8.6111pt}\\ \smash{0<x^{0}\wedge r_{0}=0\wedge r_{1}\leq x^{1}}\rule{0.0pt}{8.6111pt}\\ \smash{\{r_{0}\stackrel{{\scriptstyle\smash{0}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x\}}\rule{0.0pt}{8.6111pt}\\ \smash{0<r_{0}}\rule{0.0pt}{8.6111pt}\end{array}
r1=0r0x0x0t1@x+1{x12}r1=0r0x0x0t1@x+1t1@x<x1{r11x}r0x0x0t1@x+1t1@x<r1\begin{array}[]{c}\smash{r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1}\rule{0.0pt}{8.6111pt}\\ \smash{\{x\stackrel{{\scriptstyle\smash{1}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}2\}}\rule{0.0pt}{8.6111pt}\\ \smash{r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<x^{1}}\rule{0.0pt}{8.6111pt}\\ \smash{\{r_{1}\stackrel{{\scriptstyle\smash{1}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x\}}\rule{0.0pt}{8.6111pt}\\ \smash{r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<r_{1}}\rule{0.0pt}{8.6111pt}\end{array}

invariant: (x0=0x0=1x0=2)(x1=0x1=1x1=2)(r0=0r0=1r0=2)(r1=0r1=1r1=2)(t0@x=0t0@x=1)(t1@x=0t1@x=1)(x^{0}=0\vee x^{0}=1\vee x^{0}=2)\wedge(x^{1}=0\vee x^{1}=1\vee x^{1}=2)\wedge(r_{0}=0\vee r_{0}=1\vee r_{0}=2)\wedge(r_{1}=0\vee r_{1}=1\vee r_{1}=2)\wedge(t_{0}\mathrm{@}x=0\vee t_{0}\mathrm{@}x=1)\wedge(t_{1}\mathrm{@}x=0\vee t_{1}\mathrm{@}x=1) where t0@xt_{0}\mathrm{@}x and t1@xt_{1}\mathrm{@}x are freshly generated at x01x\stackrel{{\scriptstyle\smash{0}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1 and x12x\stackrel{{\scriptstyle\smash{1}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}2 in the judgments, respectively.

Figure 7: Derivation of Coherence on non-observation-interference.

t0@x<t1@xr1=0r0x0x0t1@x+1t1@x<x1{x02}tr0=0r1x1t_{0}\mathrm{@}x<t_{1}\mathrm{@}x\wedge r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<x^{1}\>\{x\stackrel{{\scriptstyle\smash{0}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}2\}\Vdash^{t}r_{0}=0\wedge r_{1}\leq x^{1}

t0@x<t1@xr0x0x0t1@x+1t1@x<r1{x02}tr0=0r1x1t_{0}\mathrm{@}x<t_{1}\mathrm{@}x\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<r_{1}\>\{x\stackrel{{\scriptstyle\smash{0}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}2\}\Vdash^{t}r_{0}=0\wedge r_{1}\leq x^{1}

r1=0r0x0x0t1@x+1{x12}tr0=0r1x1r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\>\{x\stackrel{{\scriptstyle\smash{1}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}2\}\Vdash^{t}r_{0}=0\wedge r_{1}\leq x^{1}

r1=0r0x0x0t1@x+1{x12}t0<x0r0=0r1x1r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\>\{x\stackrel{{\scriptstyle\smash{1}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}2\}\Vdash^{t}0<x^{0}\wedge r_{0}=0\wedge r_{1}\leq x^{1}

r1=0r0x0x0t1@x+1{x12}t0<r0r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\>\{x\stackrel{{\scriptstyle\smash{1}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}2\}\Vdash^{t}0<r_{0}

r1=0r0x0x0t1@x+1t1@x<x1{r11x}tr0=0r1x1r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<x^{1}\>\{r_{1}\stackrel{{\scriptstyle\smash{1}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x\}\Vdash^{t}r_{0}=0\wedge r_{1}\leq x^{1}

r1=0r0x0x0t1@x+1t1@x<x1{r11x}t0<x0r0=0r1x1r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<x^{1}\>\{r_{1}\stackrel{{\scriptstyle\smash{1}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x\}\Vdash^{t}0<x^{0}\wedge r_{0}=0\wedge r_{1}\leq x^{1}

r1=0r0x0x0t1@x+1t1@x<x1{r11x}t0<r0r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<x^{1}\>\{r_{1}\stackrel{{\scriptstyle\smash{1}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x\}\Vdash^{t}0<r_{0}

t1@x<t0@xr0=0r1x1{x11}tr1=0r0x0x0t1@x+1t1@x<x1r0=0r1x1t_{1}\mathrm{@}x<t_{0}\mathrm{@}x\wedge r_{0}=0\wedge r_{1}\leq x^{1}\>\{x\stackrel{{\scriptstyle\smash{1}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash^{t}r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<x^{1}\wedge r_{0}=0\wedge r_{1}\leq x^{1}

t1@x<t0@xr0=0r1x1{x11}tr1=0r0x0x0t1@x+1t1@x<x10<x0r0=0r1x1t_{1}\mathrm{@}x<t_{0}\mathrm{@}x\wedge r_{0}=0\wedge r_{1}\leq x^{1}\>\{x\stackrel{{\scriptstyle\smash{1}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash^{t}r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<x^{1}\wedge 0<x^{0}\wedge r_{0}=0\wedge r_{1}\leq x^{1}

t1@x<t0@xr0=0r1x1{x11}tr1=0r0x0x0t1@x+1t1@x<x10<r0t_{1}\mathrm{@}x<t_{0}\mathrm{@}x\wedge r_{0}=0\wedge r_{1}\leq x^{1}\>\{x\stackrel{{\scriptstyle\smash{1}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash^{t}r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<x^{1}\wedge 0<r_{0}

t1@x<t0@x0<x0r0=0r1x1{x11}tr1=0r0x0x0t1@x+1t1@x<x1r0=0r1x1t_{1}\mathrm{@}x<t_{0}\mathrm{@}x\wedge 0<x^{0}\wedge r_{0}=0\wedge r_{1}\leq x^{1}\>\{x\stackrel{{\scriptstyle\smash{1}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash^{t}r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<x^{1}\wedge r_{0}=0\wedge r_{1}\leq x^{1}

t1@x<t0@x0<x0r0=0r1x1{x11}tr1=0r0x0x0t1@x+1t1@x<x10<x0r0=0r1x1t_{1}\mathrm{@}x<t_{0}\mathrm{@}x\wedge 0<x^{0}\wedge r_{0}=0\wedge r_{1}\leq x^{1}\>\{x\stackrel{{\scriptstyle\smash{1}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash^{t}r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<x^{1}\wedge 0<x^{0}\wedge r_{0}=0\wedge r_{1}\leq x^{1}

t1@x<t0@x0<x0r0=0r1x1{x11}tr1=0r0x0x0t1@x+1t1@x<x10<r0t_{1}\mathrm{@}x<t_{0}\mathrm{@}x\wedge 0<x^{0}\wedge r_{0}=0\wedge r_{1}\leq x^{1}\>\{x\stackrel{{\scriptstyle\smash{1}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash^{t}r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<x^{1}\wedge 0<r_{0}

t1@x<t0@x0<r0{x11}tr1=0r0x0x0t1@x+1t1@x<x1r0=0r1x1t_{1}\mathrm{@}x<t_{0}\mathrm{@}x\wedge 0<r_{0}\>\{x\stackrel{{\scriptstyle\smash{1}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash^{t}r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<x^{1}\wedge r_{0}=0\wedge r_{1}\leq x^{1}

t1@x<t0@x0<r0{x11}tr1=0r0x0x0t1@x+1t1@x<x10<x0r0=0r1x1t_{1}\mathrm{@}x<t_{0}\mathrm{@}x\wedge 0<r_{0}\>\{x\stackrel{{\scriptstyle\smash{1}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash^{t}r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<x^{1}\wedge 0<x^{0}\wedge r_{0}=0\wedge r_{1}\leq x^{1}

t1@x<t0@x0<r0{x11}tr1=0r0x0x0t1@x+1t1@x<x10<r0t_{1}\mathrm{@}x<t_{0}\mathrm{@}x\wedge 0<r_{0}\>\{x\stackrel{{\scriptstyle\smash{1}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash^{t}r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<x^{1}\wedge 0<r_{0} t1@x<t0@x0<x0r0=0r1x1{x11}tr1=0r0x0x0t1@x+1t_{1}\mathrm{@}x<t_{0}\mathrm{@}x\wedge 0<x^{0}\wedge r_{0}=0\wedge r_{1}\leq x^{1}\>\{x\stackrel{{\scriptstyle\smash{1}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash^{t}r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1

t1@x<t0@x0<r0{x11}tr1=0r0x0x0t1@x+1t_{1}\mathrm{@}x<t_{0}\mathrm{@}x\wedge 0<r_{0}\>\{x\stackrel{{\scriptstyle\smash{1}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash^{t}r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1

r0=0r1x1{x01}tr1=0r0x0x0t1@x+1r_{0}=0\wedge r_{1}\leq x^{1}\>\{x\stackrel{{\scriptstyle\smash{0}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash^{t}r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1

r0=0r1x1{x01}tr1=0r0x0x0t1@x+1t1@x<x1r_{0}=0\wedge r_{1}\leq x^{1}\>\{x\stackrel{{\scriptstyle\smash{0}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash^{t}r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<x^{1}

r0=0r1x1{x01}tr0x0x0t1@x+1t1@x<r1r_{0}=0\wedge r_{1}\leq x^{1}\>\{x\stackrel{{\scriptstyle\smash{0}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}1\}\Vdash^{t}r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<r_{1}

0<x0r0=0r1x1{r00x}tr1=0r0x0x0t1@x+10<x^{0}\wedge r_{0}=0\wedge r_{1}\leq x^{1}\>\{r_{0}\stackrel{{\scriptstyle\smash{0}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x\}\Vdash^{t}r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1

0<x0r0=0r1x1{r00x}tr1=0r0x0x0t1@x+1t1@x<x10<x^{0}\wedge r_{0}=0\wedge r_{1}\leq x^{1}\>\{r_{0}\stackrel{{\scriptstyle\smash{0}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x\}\Vdash^{t}r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<x^{1}

0<x0r0=0r1x1{r00x}tr0x0x0t1@x+1t1@x<r10<x^{0}\wedge r_{0}=0\wedge r_{1}\leq x^{1}\>\{r_{0}\stackrel{{\scriptstyle\smash{0}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}x\}\Vdash^{t}r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<r_{1}

t0@x<t1@xr1=0r0x0x0t1@x+1{x02}t0<x0r0=0r1x1r1=0r0x0x0t1@x+1t_{0}\mathrm{@}x<t_{1}\mathrm{@}x\wedge r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\>\{x\stackrel{{\scriptstyle\smash{0}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}2\}\Vdash^{t}0<x^{0}\wedge r_{0}=0\wedge r_{1}\leq x^{1}\wedge r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1

t0@x<t1@xr1=0r0x0x0t1@x+1{x02}t0<x0r0=0r1x1r1=0r0x0x0t1@x+1t1@x<x1t_{0}\mathrm{@}x<t_{1}\mathrm{@}x\wedge r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\>\{x\stackrel{{\scriptstyle\smash{0}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}2\}\Vdash^{t}0<x^{0}\wedge r_{0}=0\wedge r_{1}\leq x^{1}\wedge r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<x^{1}

t0@x<t1@xr1=0r0x0x0t1@x+1{x02}t0<x0r0=0r1x1r0x0x0t1@x+1t1@x<r1t_{0}\mathrm{@}x<t_{1}\mathrm{@}x\wedge r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\>\{x\stackrel{{\scriptstyle\smash{0}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}2\}\Vdash^{t}0<x^{0}\wedge r_{0}=0\wedge r_{1}\leq x^{1}\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<r_{1}

t0@x<t1@xr1=0r0x0x0t1@x+1t1@x<x1{x02}t0<x0r0=0r1x1r1=0r0x0x0t1@x+1t_{0}\mathrm{@}x<t_{1}\mathrm{@}x\wedge r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<x^{1}\>\{x\stackrel{{\scriptstyle\smash{0}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}2\}\Vdash^{t}0<x^{0}\wedge r_{0}=0\wedge r_{1}\leq x^{1}\wedge r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1

t0@x<t1@xr1=0r0x0x0t1@x+1t1@x<x1{x02}t0<x0r0=0r1x1r1=0r0x0x0t1@x+1t1@x<x1t_{0}\mathrm{@}x<t_{1}\mathrm{@}x\wedge r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<x^{1}\>\{x\stackrel{{\scriptstyle\smash{0}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}2\}\Vdash^{t}0<x^{0}\wedge r_{0}=0\wedge r_{1}\leq x^{1}\wedge r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<x^{1}

t0@x<t1@xr1=0r0x0x0t1@x+1t1@x<x1{x02}t0<x0r0=0r1x1r0x0x0t1@x+1t1@x<r1t_{0}\mathrm{@}x<t_{1}\mathrm{@}x\wedge r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<x^{1}\>\{x\stackrel{{\scriptstyle\smash{0}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}2\}\Vdash^{t}0<x^{0}\wedge r_{0}=0\wedge r_{1}\leq x^{1}\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<r_{1}

t0@x<t1@xr0x0x0t1@x+1t1@x<r1{x02}t0<x0r0=0r1x1r1=0r0x0x0t1@x+1t_{0}\mathrm{@}x<t_{1}\mathrm{@}x\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<r_{1}\>\{x\stackrel{{\scriptstyle\smash{0}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}2\}\Vdash^{t}0<x^{0}\wedge r_{0}=0\wedge r_{1}\leq x^{1}\wedge r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1

t0@x<t1@xr0x0x0t1@x+1t1@x<r1{x02}t0<x0r0=0r1x1r1=0r0x0x0t1@x+1t1@x<x1t_{0}\mathrm{@}x<t_{1}\mathrm{@}x\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<r_{1}\>\{x\stackrel{{\scriptstyle\smash{0}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}2\}\Vdash^{t}0<x^{0}\wedge r_{0}=0\wedge r_{1}\leq x^{1}\wedge r_{1}=0\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<x^{1}

t0@x<t1@xr0x0x0t1@x+1t1@x<r1{x02}t0<x0r0=0r1x1r0x0x0t1@x+1t1@x<r1t_{0}\mathrm{@}x<t_{1}\mathrm{@}x\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<r_{1}\>\{x\stackrel{{\scriptstyle\smash{0}\rule{0.0pt}{3.0pt}}}{{\coloneqq}}2\}\Vdash^{t}0<x^{0}\wedge r_{0}=0\wedge r_{1}\leq x^{1}\wedge r_{0}\leq x^{0}\wedge x^{0}\leq t_{1}\mathrm{@}x+1\wedge t_{1}\mathrm{@}x<r_{1}

Figure 8: Stability checking of Coherence on non-observation-interference.

Figures 7 and 8 show a derivation of Coherence on non-observation-interference. We can see that the timestamp variable t1@xt_{1}\mathrm{@}x acts as an intermediary between r0r_{0} and r1r_{1}.

5 Related Work and Discussion

Some logics handling dataracy programs are sound to semantics on which the effects of store instructions may be delayed [16, 11, 2, 5].

Dalvandi et al. provided Owicki–Gries logic for a C11 fragment memory model [5]. They also adopted timestamp semantics. However, they introduced multiple relations based on observations by thread to their assertion language. Each assignment has multiple axioms since their assertion language has multiple relations based on observations by threads. In this paper, we aim to construct theoretically simple logic. We adopted variables based on observations by threads. Each assignment has exactly one axiom.

Lahav and Vafeiadis proposed Owicki–Gries style logic for semantics by execution graphs [11], more axiomatic semantics than operational timestamp semantics. Their logic has high provability. They succeeded in providing derivations to ensure the correctness of Store Buffering with memory fences and a variant of Coherence. They also modified stability checking to ensure the correctness of concurrent programs on a weak memory model, as we did in this paper. Their logic differs from ours because they are constructed without observation and timestamp variables.

An unsatisfactory point is that it is necessary to check judgments of the form Γ⊬φ\varGamma\not\vdash\varphi in their logic. Specifically, the logic requires to find satisfiable values under the semantics when checking stability. This means that it is necessary to consider models when providing derivations. Whereas the author provided logic using observation variables [2], the logic also assumes the use of external knowledge called observation invariants.

Thus, semantics on which effects of store instructions often disturb us to construct a pure logic in which assertions are added to programs in the Floyd style [6] are syntactically operated. In our logic, it occurs as the arbitrariness of the values of store instructions in the definition of non-observation-interference as described in Section 4. This study is one of the challenges to finding a purely syntactical logic for weak memory models.

The author proposed observation variables in the previous work [2]. However, observation variables are almost regarded as shared variables in the logic. Relations between observation variables strongly depend on observation invariants, which are assumed to be externally given. In this paper, observation variables are explicitly handled in the definition of non-observation-interference. This work is positioned as a detailed investigation of shared variables observed by threads.

6 Conclusion and Future Work

In this paper, we provide Owicki–Gries style logic, which uses the notion of non-interference for timestamp semantics. It theoretically contributes to show techniques that 1)we used the notion of non-interference for ensuring soundness of assignment axiom, 2)we replaced thread identifiers for an update of a vector clock on timestamp semantics, and 3)we introduced timestamp variables in order to enhance the expressiveness of the assertion language.

This study has a lot left to do. In this paper, we do not refer to completeness to timestamp semantics. We do not confirm the minimality of assertions that occur in the derivations in this paper. Above all else, Owicki–Gries logic using non-interference is not compositional; the depths of derivations combinatorial increase the number of checking judgments. It means that Owicki–Gries logic and our logic could be more practical. Jones proposed a compositional logic using rely/guarantee reasoning [8]. Lahav and Vafeiadis tried to make their logic compositional using the rely/guarantee notion. However, because their “rely” and “guarantee” are not single assertions but finite sets of assertions [11], it is hard to say that combinatorial explosion is wholly avoided. Enriching the assertion language using the next variables (e.g. [17]) is promising. Our previous study also proposed a compositional logic using observation variables [2], so to speak, observation-based Jones logic. However, external knowledge is required, called observation invariants, as described in Section 5. Thus, it is challenging to construct compositional logic for weak memory models. We try to construct a compositional logic using observation variables by utilizing the knowledge obtained in this study.

This study considered store buffering only. It is not easy to consider load buffering. Whereas we previously proposed concurrent program logic sound and complete to semantics that support reordering of load instructions [3], the semantics support reordering of load instructions that are statically determined to be independent. For a weaker memory model, Kang et al. proposed a novel notion called promise for supporting load buffering on timestamp semantics [9]. For example, in the following program:

r0 := y // 0
x := 1
r1 := x
y := r1

assertion r0=0r_{0}=0 always holds on timestamp semantics. However, r0=1r_{0}=1 is allowed on timestamp semantics with promise. We try to combine the notion of promise with our logic and construct a novel logic to ensure the correctness of concurrent programs on semantics that allow load buffering.

Acknowledgments. This work was supported by JSPS KAKENHI Grant Number JP23K11051.

References

  • [1] P. A. Abdulla, M. F. Atig, B. Jonsson, and C. Leonardsson. Stateless model checking for POWER. In Proc. CAV, volume 9780 of LNCS, pages 134–156, 2016.
  • [2] T. Abe and T. Maeda. Observation-based concurrent program logic for relaxed memory consistency models. In Proc. APLAS, volume 10017 of LNCS, pages 63–84, 2016.
  • [3] T. Abe and T. Maeda. Concurrent program logic for relaxed memory consistency models with dependencies across loop iterations. Journal of Information Processing, 25:244–255, 2017.
  • [4] M. Barnett, B.-Y. E. Chang, R. DeLine, B. Jacobs, and K. R. M. Leino. Boogie: A modular reusable verifier for object-oriented programs. In Proc. FMCO, volume 4111 of LNCS, pages 364–387, 2005.
  • [5] S. Dalvandi, S. Doherty, B. Dongol, and H. Wehrheim. Owicki–Gries reasoning for C11 RAR. In Proc. ECOOP, 2020.
  • [6] R. W. Floyd. Assigning meanings to programs. In Proc. Symposia in Applied Mathematics, volume 19, pages 19–32, 1967.
  • [7] C. A. R. Hoare. An axiomatic basis for computer programming. CACM, 12(10):576–580, 583, 1969.
  • [8] C. B. Jones. Development Methods for Computer Programs Including a Notion of Interference. PhD thesis, Oxford University, 1981.
  • [9] J. Kang, C.-K. Hur, O. Lahav, V. Vafeiadis, and D. Dreyer. A promising semantics for relaxed-memory concurrency. In Proc. POPL, pages 175–189, 2017.
  • [10] M. Kokologiannakis and V. Vafeiadis. GenMC: A model checker for weak memory models. In Proc. CAV, volume 12759 of LNCS, pages 427–440, 2021.
  • [11] O. Lahav and V. Vafeiadis. Owicki–Gries reasoning for weak memory models. In Proc. ICALP, volume 9135 of LNCS, pages 311–323, 2015.
  • [12] L. Lamport. Time, clocks, and the ordering of events in a distributed system. CACM, 21(7):558–565, 1978.
  • [13] L. Lamport. Control predicates are better than dummy variables for reasoning about program control. TOPLAS, 10(2):267–281, 1988.
  • [14] F. Mattern. Virtual time and global states of distributed systems. In Parallel and Distributed Algorithms, pages 215–226. North-Holland, 1989.
  • [15] S. S. Owicki and D. Gries. An axiomatic proof technique for parallel programs I. Acta Informatica, 6:319–340, 1976.
  • [16] T. Ridge. A rely-guarantee proof system for x86-TSO. In Proc. VSTTE, volume 6217 of LNCS, pages 55–70, 2010.
  • [17] Q. Xu, W. P. de Roever, and J. He. The rely-guarantee method for verifying shared variable concurrent programs. Formal Aspects of Computing, 9(2):149–174, 1997.