Hereinafter we assume the global CMRA functor (served up as a parameter to Iris) is obtained from a family of functors $(\iFunc_i)_{i \in I}$ for some finite $I$ by picking
We don't care so much about what concretely $\textlog{GhName}$ is, as long as it is countable and infinite.
With $M_i \eqdef\iFunc_i(\iProp)$, we write $\ownGhost{\gname}{\melt : M_i}$ (or just $\ownGhost{\gname}{\melt}$ if $M_i$ is clear from the context) for $\ownM{[i \mapsto[\gname\mapsto\melt]]}$.
In other words, $\ownGhost{\gname}{\melt : M_i}$ asserts that in the current state of monoid $M_i$, the ``ghost location'' $\gname$ is allocated and we own piece $\melt$.
From~\ruleref{pvs-update}, \ruleref{vs-update} and the frame-preserving updates in~\Sref{sec:prodm} and~\Sref{sec:fpfnm}, we have the following derived rules.
\begin{mathparpagebreakable}
\inferH{ghost-alloc-strong}{\text{$G$ infinite}}
{\TRUE\vs\Exists\gname\in G. \ownGhost\gname{\melt : M_i}
Let $\namesp\in\textlog{InvNamesp}\eqdef\textlog{list}(\textlog{InvName})$ be the type of \emph{namespaces} for invariant names.
Notice that there is an injection $\textlog{namesp\_inj}: \textlog{InvNamesp}\ra\textlog{InvName}$.
Whenever needed (in particular, for masks at view shifts and Hoare triples), we coerce $\namesp$ to its suffix-closure: \[\namecl\namesp\eqdef\setComp{\iname}{\Exists\namesp'. \iname=\textlog{namesp\_inj}(\namesp' \dplus\namesp)}\]
We use the notation $\namesp.\iname$ for the namespace $[\iname]\dplus\namesp$.
We define the inclusion relation on namespaces as $\namesp_1\sqsubseteq\namesp_2\Lra\Exists\namesp_3. \namesp_2=\namesp_3\dplus\namesp_1$, \ie$\namesp_1$ is a suffix of $\namesp_2$.
\ralf{TODO: This inclusion defn is now outdated.}
We have that $\namesp_1\sqsubseteq\namesp_2\Ra\namecl{\namesp_2}\subseteq\namecl{\namesp_1}$.
Similarly, we define $\namesp_1\disj\namesp_2\eqdef\Exists\namesp_1', \namesp_2'. \namesp_1' \sqsubseteq\namesp_1\land\namesp_2' \sqsubseteq\namesp_2\land |\namesp_1'| = |\namesp_2'| \land\namesp_1' \neq\namesp_2'$, \ie there exists a distinguishing suffix.
We have that $\namesp_1\disj\namesp_2\Ra\namecl{\namesp_2}\disj\namecl{\namesp_1}$, and furthermore $\iname_1\neq\iname_2\Ra\namesp.\iname_1\disj\namesp.\iname_2$.
We will overload the usual Iris notation for invariant assertions in the following:
To introduce invariants into our logic, we will define weakest precondition to explicitly thread through the proof that all the invariants are maintained throughout program execution.
To introduce invariants into our logic, we will define weakest precondition to explicitly thread through the proof that all the invariants are maintained throughout program execution.
However, in order to be able to access invariants, we will also have to provide a way to \emph{temporarily disable} (or ``open'') them.
However, in order to be able to access invariants, we will also have to provide a way to \emph{temporarily disable} (or ``open'') them.
...
@@ -84,12 +85,12 @@ Furthermore, we assume that instances named $\gname_{\textmon{State}}$, $\gname_
...
@@ -84,12 +85,12 @@ Furthermore, we assume that instances named $\gname_{\textmon{State}}$, $\gname_
\paragraph{World Satisfaction.}
\paragraph{World Satisfaction.}
We can now define the assertion $W$ (\emph{world satisfaction}) which ensures that the enabled invariants are actually maintained:
We can now define the assertion $W$ (\emph{world satisfaction}) which ensures that the enabled invariants are actually maintained:
\begin{align*}
\begin{align*}
W \eqdef{}&\Exists I : \mathbb N \fpfn\Prop. \ownGhost{\gname_{\textmon{Inv}}}{\setComp{\iname\mapsto\authfull\aginj(\latertinj(\wIso(I(\iname))))}{\iname\in\dom(I)}} * \Sep_{\iname\in\dom(I)}\left( \later I(\iname) * \ownGhost{\gname_{\textmon{Dis}}}{\set{\iname}}\lor\ownGhost{\gname_{\textmon{En}}}{\set{\iname}}\right)
W \eqdef{}&\Exists I : \mathbb N \fpfn\Prop. \ownGhost{\gname_{\textmon{Inv}}}{\authfull\setComp{\iname\mapsto\aginj(\latertinj(\wIso(I(\iname))))}{\iname\in\dom(I)}} * \Sep_{\iname\in\dom(I)}\left( \later I(\iname) * \ownGhost{\gname_{\textmon{Dis}}}{\set{\iname}}\lor\ownGhost{\gname_{\textmon{En}}}{\set{\iname}}\right)
\end{align*}
\end{align*}
\paragraph{Invariants.}
\paragraph{Invariants.}
The following assertion states that an invariant with name $\iname$ exists and maintains assertion $\prop$:
The following assertion states that an invariant with name $\iname$ exists and maintains assertion $\prop$:
Next, we define \emph{view updates}, which are essentially the same as the resource updates of the base logic ($\Sref{sec:base-logic}$), except that they also have access to world satisfaction and can enable and disable invariants:
Next, we define \emph{view updates}, which are essentially the same as the resource updates of the base logic ($\Sref{sec:base-logic}$), except that they also have access to world satisfaction and can enable and disable invariants:
...
@@ -268,28 +269,30 @@ In order to cover the most general case, those rules end up being more complicat
...
@@ -268,28 +269,30 @@ In order to cover the most general case, those rules end up being more complicat
\ralf{TODO: Right now, this is a dump of all the things that moved out of the base...}
\paragraph{Laws of weakest preconditions.}
\paragraph{Lifting of operational semantics.}~
\paragraph{Adequacy of weakest precondition.}
The adequacy statement concerning functional correctness reads as follows:
The adequacy statement concerning functional correctness reads as follows:
\begin{align*}
\begin{align*}
...
@@ -301,6 +304,7 @@ The adequacy statement concerning functional correctness reads as follows:
...
@@ -301,6 +304,7 @@ The adequacy statement concerning functional correctness reads as follows:
\\&\pred(\val)
\\&\pred(\val)
\end{align*}
\end{align*}
where $\pred$ is a \emph{meta-level} predicate over values, \ie it can mention neither resources nor invariants.
where $\pred$ is a \emph{meta-level} predicate over values, \ie it can mention neither resources nor invariants.
\ralf{TODO: We can't just embed meta-level predicates like this. After all, this is a deep embedding.}
Furthermore, the following adequacy statement shows that our weakest preconditions imply that the execution never gets \emph{stuck}: Every expression in the thread pool either is a value, or can reduce further.
Furthermore, the following adequacy statement shows that our weakest preconditions imply that the execution never gets \emph{stuck}: Every expression in the thread pool either is a value, or can reduce further.
\begin{align*}
\begin{align*}
...
@@ -313,51 +317,124 @@ Furthermore, the following adequacy statement shows that our weakest preconditio
...
@@ -313,51 +317,124 @@ Furthermore, the following adequacy statement shows that our weakest preconditio
\end{align*}
\end{align*}
Notice that this is stronger than saying that the thread pool can reduce; we actually assert that \emph{every} non-finished thread can take a step.
Notice that this is stronger than saying that the thread pool can reduce; we actually assert that \emph{every} non-finished thread can take a step.
\subsection{Iris model}
\paragraph{Hoare triples.}
It turns out that weakest precondition is actually quite convenient to work with, in particular when perfoming these proofs in Coq.
\paragraph{Semantic domain of assertions.}
Still, for a more traditional presentation, we can easily derive the notion of a Hoare triple:
We only give some of the proof rules for Hoare triples here, since we usually do all our reasoning directly with weakest preconditions and use Hoare triples only to write specifications.
\All\rs_\f, k, \mask_\f, \state.& 0 < k \leq n \land (\mask_1 \cup\mask_2) \disj\mask_\f\land k \in\wsat\state{\mask_1 \cup\mask_\f}{\rs\mtimes\rs_\f}\Ra{}\\&
In \Sref{sec:invariants}, we defined an assertion $\knowInv\iname\prop$ expressing knowledge (\ie the assertion is persistent) that $\prop$ is maintained as invariant with name $\iname$.
\Exists\rsB. k \in\prop(\rsB) \land k \in\wsat\state{\mask_2 \cup\mask_\f}{\rsB\mtimes\rs_\f}
The concrete name $\iname$ is picked when the invariant is allocated, so it cannot possibly be statically known -- it will always be a variable that's threaded through everything.
\end{aligned}}
However, we hardly care about the actual, concrete name.
\end{align*}
All we need to know is that this name is \emph{different} from the names of other invariants that we want to open at the same time.
Keeping track of the $n^2$ mutual inequalities that arise with $n$ invariants quickly gets in the way of the actual proof.
To solve this issue, instead of remembering the exact name picked for an invariant, we will keep track of the \emph{namespace} the invariant was allocated in.
Namesapces are sets of invariants, following a tree-like structure:
Think of the name of an invariant as a sequence of identifiers, much like a fully qualified Java class name.
A \emph{namespace}$\namesp$ then is like a Java package: it is a sequence of identifiers that we think of as \emph{containing} all invariant names that begin with this sequence. For example, \texttt{org.mpi-sws.iris} is a namespace containing the invariant name \texttt{org.mpi-sws.iris.heap}.
The crux is that all namespaces contain infinitely many invariants, and hence we can \emph{freely pick} the namespace an invariant is allocated in -- no further, unpredictable choice has to be made.
Furthermore, we will often know that namespaces are \emph{disjoint} just by looking at them.
The namespaces $\namesp.\texttt{iris}$ and $\namesp.\texttt{gps}$ are disjoint no matter the choice of $\namesp$.
As a result, there is often no need to track disjointness of namespaces, we just have to pick the namespaces that we allocate our invariants in accordingly.
Formally speaking, let $\namesp\in\textlog{InvNamesp}\eqdef\textlog{list}(\mathbb N)$ be the type of \emph{invariant namespaces}.
We use the notation $\namesp.\iname$ for the namespace $[\iname]\dplus\namesp$.
(In other words, the list is ``backwards''. This is because cons-ing to the list, like the dot does above, is easier to deal with in Coq than appending at the end.)
The elements of a namespaces are \emph{structured invariant names} (think: Java fully qualified class name).
They, too, are lists of $\mathbb N$, the same type as namespaces.
In order to connect this up to the definitions of \Sref{sec:invariants}, we need a way to map structued invariant names to $\mathbb N$, the type of ``plain'' invariant names.
Any injective mapping $\textlog{namesp\_inj}$ will do; and such a mapping has to exist because $\textlog{list}(\mathbb N)$ is countable.
Whenever needed, we (usually implicitly) coerce $\namesp$ to its encoded suffix-closure, \ie to the set of encoded structured invariant names contained in the namespace: \[\namecl\namesp\eqdef\setComp{\iname}{\Exists\namesp'. \iname=\textlog{namesp\_inj}(\namesp' \dplus\namesp)}\]
We will overload the notation for invariant assertions for using namespaces instead of names: