This code contains Coq proofs supplementing the Making Weak Memory Models Fair paper. More on the artifact constructed from the code (including a VM image and installation guidelines) are stated in ARTIFACT.md.
- Coq 8.15.1
- Hahn library (
coq-hahn). This library provides useful definitions and proofs of various relations and sets properties, as well as a general trace definition used throughout the development.
The overall structure of Coq development in src folder is as follows:
basicfolder contains general definitions.equivalencefolder contains proofs of operational and declarative definitions' equivalence placed in corresponding subfolders. The fileequivalence/Equivalence.vpresents these results in a uniform fashion.libfolder contains auxiliary proofs and definitions not directly related to memory models.terminationfolder contains proofs of deadlock freedom for three lock implementations.robustnessfolder contains the formalization and proof of infinite robustness property.
- To formalize the LTS, the
HahnTrace.LTSdefinition from thehahnlibrary is used. - Both traces and runs of LTS are formalized as
HahnTrace.tracewhich is a finite or infinite enumeration of labels of arbitrary type. Note that we often refer both to traces and runs as to "traces" in Coq development because of the implementation type. - The definition of event labels (Def. 2.1) is formalized as
Labinsrc/basic/Labels.v. - As the paper notes, we don't specify a program under consideration explicitly but rather assume that its behaviors are expressed using a set of possible traces of LTS. That means that we cannot tell whether a given behavior is thread-fair since there is no sequential program to check if the corresponding thread has terminated. For this reason, we don't formalize Def. 2.8. See a comment for Section 4 for the explanation of why this is valid.
- We define operational behavior as sets of events corresponding to a run: see
src/equivalence/Equivalence.v, variabletrace_events. The notion of being a behavior of a specific program (Prop. 2.10) is instead replaced with the notion of correspondence to a particular trace (src/equivalence/Equivalence.v, propositionop_decl_def_equiv). - For operational definitions of memory models see:
- For SC (§2) -
src/equivalence/SC.v(sc_lts). - For TSO (§2.1) -
src/equivalence/tso/TSO.v(TSO_lts). - For RA (§2.2) -
src/equivalence/ra/RAop.v(ra_lts). - For StrongCOH (§2.3) -
src/equivalence/strong_coh/SCOHop.v(scoh_lts). Note that LTS for RA and StrongCOH are defined for labels that contain data besides thread and event label; this is a purely technical solution that doesn't affect reasoning.
- For SC (§2) -
- Operational memory fairness (Def. 2.12) predicates are specified by the values of a
run_fairvariable insrc/equivalence/Equivalence.vin memory model-specific theorems (e.g. TSO fairness is formalized by theTSO_fairpredicate, as specified in theTSO_equivtheorem).
-
The definition of graph events (Def. 3.1) is given in
src/basic/Events.v(Eventtype). -
Events extracted from a trace (Def. 3.3) are defined by
trace_eventsfunction mentioned above. This set of events also represents the declarative counterpart of the operational notion of behavior insrc/equivalence/Equivalence.v, propositionop_decl_def_equiv. -
The definition of a well-formed set of events (Def. 3.4) is included in the graph well-formedness predicate (
Wfinsrc/basic/Execution.v):Init <= Econdition is formalized inwf_initE- Requirement for
tidbeing defined for non-initializing events is formalized inwf_tid_initwith0used as⊥. The second part of the requirement regardingsnis not formalized as the definition ofThreadEvent(a non-initializing event) explicitly contains theindexfield (formalization ofsn). - Uniqueness of
tidandsnpairs is specified in thewf_index. - We do not formalize the last condition requiring that a thread's serial numbers are placed densely since it serves merely presentational purposes and doesn't affect Coq development.
The
Wfpredicate also specifies well-formedness conditions for graph relations. -
The execution graph definition (Def. 3.5) is given in
src/basic/Execution.v(executiontype). Note that there are some differences in notation:- The set
Eof graph events is formalized asacts_setfield ofexecution. - The program order (
G.poin the paper) is formalized assb("sequenced-before") relation. - The modification order (
G.moin the paper) is formalized asco("coherence order") field ofexecution.
- The set
-
As for operational semantics, we do not formalize thread fairness and the notion of being a specific program's behavior (Def. 3.7) explicitly. See a comment for Section 4 for the explanation of why this is valid.
-
For declarative definitions of memory models see:
- For SC (§3.1) -
src/equivalence/SC.v(sc_consistent). - For TSO (§3.2) -
src/equivalence/tso/TSO.v(TSO_consistent). - For RA (§3.3) -
src/equivalence/AltDefs.v(ra_consistent_alt). - For StrongCOH (§3.4) -
src/equivalence/AltDefs.v(scoh_consistent_alt).
Note that for RA and StrongCOH throughout the most part of the development we use other definitions -
ra_consistentinsrc/equivalence/ra/RAop.vandscoh_consistentinsrc/equivalence/strong_coh/SCOHop.vcorrespondingly. The equivalence between these and their paper counterparts (..._altdefinitions) is proved in theoremsra_consistent_defs_equivalenceandscoh_consistent_defs_equivinsrc/equivalence/AltDefs.v.Also, note that we formalize the irreflexivity of the
G.sc_locrelation in theSCpLpredicate. - For SC (§3.1) -
- The prefix-finiteness (Def. 4.1) is formalized as
fsupppredicate fromhahnlibrary. - The declarative definition of memory fairness (Def 4.2) is given in
src/basic/Execution.v(mem_fairpredicate). - The main result of the paper stating the equivalence of operational and declarative fair definitions (Theorem 4.5) is presented in
src/equivalence/Equivalence.vbySC_equiv,TSO_equiv,RA_equivandSCOH_equivtheorems which are instances of a generalop_decl_def_equivproposition. - For equivalence proofs of individual models see:
- For SC (Lemmas B.1 and B.2) -
SC_op_implies_declandSC_decl_implies_opinsrc/equivalence/SC.v. - For TSO (Lemmas B.8 and B.22) -
TSO_op_implies_declinsrc/equivalence/tso/TSO_op_decl.vandTSO_decl_implies_opinsrc/equivalence/tso/TSO_decl_op.v. - For RA (Lemmas B.3 and B.4) -
RA_op_implies_declinsrc/equivalence/ra/RAopToDecl.vandRA_decl_implies_opinsrc/equivalence/ra/RAdeclToOp.v. - For StrongCOH (Lemmas B.6 and B.7) -
SCOH_op_implies_declinsrc/equivalence/strong_coh/SCOHopToDecl.vandSCOH_decl_implies_opinsrc/equivalence/strong_coh/SCOHdeclToOp.v.
- For SC (Lemmas B.1 and B.2) -
- Definitions and proofs related to robustness (Section 4.4) are located in
src/robustness/Robustness.v.- The property of being a po|rf prefix (Def. 4.12) is formalized in
porf_prefixdefinition. - The SC compactness (Prop. 4.13) is proved in
sc_compactness. - Definitions of finite and strong execution-graph robustness (Def. 4.14) are given in
finitely_robustandstrongly_robustcorrespondingly. - The lifting of robustness onto the infinite execution (Theorem 4.15) is proved in
finitely2strongly. - The infinite robustness property for memory models considered in the paper (Corollary 4.16, excluding RC11) is proved in
program_robustness_models.
- The property of being a po|rf prefix (Def. 4.12) is formalized in
- We do not formalize the notion of thread fairness neither in an operational nor declarative sense. Instead, our
op_decl_def_equivproposition applies to any behavior (formalized as a set of events) without binding to a concrete program. The difference between a non-thread-fair and a thread-fair behavior of the same program in our presentation is simply that the former would lack some events presented in the latter.
- The proof of Theorem 5.3 stating a sufficient condition for loop termination is given in
src/termination/TerminationDecl.v, lemmainf_reads_latest. - For proofs of lock algorithms termination (progress for ticket lock) see:
- For spinlock (Theorem 5.4) -
src/termination/SpinlockTermination.v, theoremspinlock_client_terminates. - For ticket lock (Theorem 5.5) -
src/termination/TicketlockProgress.v, theoremticketlock_client_progress. - For MCS lock (Theorem 5.6, except for RC11) -
src/termination/HMCSTermination.v, theoremhmcs_client_terminates.
- For spinlock (Theorem 5.4) -
Our development relies on non-constructive axioms. Namely, we use excluded middle, functional extensionality and functional/relational choice which can be safely added to Coq logic.
To list axioms used to prove a theorem Thm execute the file with Thm in any proof editor, then execute Print Assumptions Thm.
During the proof compilation assumptions used to prove main statements are recorded in axioms_*.out files. Run print_axioms.sh script to view their content. This script filters out irrelevant output and only prints axioms.
We do not provide Coq formalization of claims from §4.3. Also, the formal proofs of Corollary 4.16 and Theorem 5.6 don't consider the RC11 case.
If you'd like to enhance the development, there are two immediate directions.
To extend our results to another memory model you'll need to:
- define its operational LTS along with the operational fairness condition;
- set its declarative consistency predicate;
- state and prove a theorem in
src/equivalence/Equivalence.vsimilar to existing ones. You'll also need to provide few auxiliary functions to create an instance of the generalop_decl_def_equivdefinition.
To verify some algorithm's liveness properties you'll need to do the following.
- Formalize an algorithm's execution graph as its threads' traces properties (e.g. see
src/termination/SpinlockTermination.v, definitionspinlock_client_execution). Note that an under-approximation may suffice (like in the spinlock formalization). - To state that the algorithm terminates you may require that its execution graph is finite. For expressing more complicated properties see e.g. the proof of ticket lock progress in
src/termination/TicketlockProgress.v, theoremticketlock_client_progress. - In our framework liveness properties are proved by contradiction: assuming that some thread's execution is infinite eventually allows us to apply
inf_reads_latestlemma and show that the graph is either not consistent or not fair.