From 647edceca038974b85a3aa1843ece23a116f3ea9 Mon Sep 17 00:00:00 2001
From: Zhen Zhang <izgzhen@gmail.com>
Date: Tue, 11 Oct 2016 15:24:58 +0200
Subject: [PATCH] Pull dependencies back

---
 Makefile.coq  |  27 +++---
 _CoqProject   |   6 +-
 atomic.v      | 147 ++++++++++++++++++++++++++++++
 atomic_pair.v |   4 +-
 atomic_sync.v |   3 +-
 flat.v        |  10 +-
 misc.v        | 248 ++++++++++++++++++++++++++++++++++++++++++++++++++
 pair_cas.v    |   2 +-
 simple_sync.v |   4 +-
 treiber.v     | 205 ++++++++++++++++++++++++++++++++++++++++-
 10 files changed, 620 insertions(+), 36 deletions(-)
 create mode 100644 atomic.v
 create mode 100644 misc.v

diff --git a/Makefile.coq b/Makefile.coq
index 154f355..5f758bc 100644
--- a/Makefile.coq
+++ b/Makefile.coq
@@ -50,11 +50,11 @@ vo_to_obj = $(addsuffix .o,\
 ##########################
 
 COQLIBS?=\
-  -Q "." flatcomb
+  -Q "." iris_atomic
 COQCHKLIBS?=\
-  -R "." flatcomb
+  -R "." iris_atomic
 COQDOCLIBS?=\
-  -R "." flatcomb
+  -R "." iris_atomic
 
 ##########################
 #                        #
@@ -96,12 +96,13 @@ endif
 #                    #
 ######################
 
-VFILES:=simple_sync.v\
-  pair_cas.v\
+VFILES:=atomic.v\
+  simple_sync.v\
   flat.v\
   atomic_pair.v\
   atomic_sync.v\
-  treiber.v
+  treiber.v\
+  misc.v
 
 ifneq ($(filter-out archclean clean cleanall printenv,$(MAKECMDGOALS)),)
 -include $(addsuffix .d,$(VFILES))
@@ -191,22 +192,22 @@ userinstall:
 
 install:
 	cd "." && for i in $(VOFILES) $(VFILES) $(GLOBFILES) $(NATIVEFILES) $(CMOFILES) $(CMIFILES) $(CMAFILES); do \
-	 install -d "`dirname "$(DSTROOT)"$(COQLIBINSTALL)/flatcomb/$$i`"; \
-	 install -m 0644 $$i "$(DSTROOT)"$(COQLIBINSTALL)/flatcomb/$$i; \
+	 install -d "`dirname "$(DSTROOT)"$(COQLIBINSTALL)/iris_atomic/$$i`"; \
+	 install -m 0644 $$i "$(DSTROOT)"$(COQLIBINSTALL)/iris_atomic/$$i; \
 	done
 
 install-doc:
-	install -d "$(DSTROOT)"$(COQDOCINSTALL)/flatcomb/html
+	install -d "$(DSTROOT)"$(COQDOCINSTALL)/iris_atomic/html
 	for i in html/*; do \
-	 install -m 0644 $$i "$(DSTROOT)"$(COQDOCINSTALL)/flatcomb/$$i;\
+	 install -m 0644 $$i "$(DSTROOT)"$(COQDOCINSTALL)/iris_atomic/$$i;\
 	done
 
 uninstall_me.sh: Makefile
 	echo '#!/bin/sh' > $@
-	printf 'cd "$${DSTROOT}"$(COQLIBINSTALL)/flatcomb && rm -f $(VOFILES) $(VFILES) $(GLOBFILES) $(NATIVEFILES) $(CMOFILES) $(CMIFILES) $(CMAFILES) && find . -type d -and -empty -delete\ncd "$${DSTROOT}"$(COQLIBINSTALL) && find "flatcomb" -maxdepth 0 -and -empty -exec rmdir -p \{\} \;\n' >> "$@"
-	printf 'cd "$${DSTROOT}"$(COQDOCINSTALL)/flatcomb \\\n' >> "$@"
+	printf 'cd "$${DSTROOT}"$(COQLIBINSTALL)/iris_atomic && rm -f $(VOFILES) $(VFILES) $(GLOBFILES) $(NATIVEFILES) $(CMOFILES) $(CMIFILES) $(CMAFILES) && find . -type d -and -empty -delete\ncd "$${DSTROOT}"$(COQLIBINSTALL) && find "iris_atomic" -maxdepth 0 -and -empty -exec rmdir -p \{\} \;\n' >> "$@"
+	printf 'cd "$${DSTROOT}"$(COQDOCINSTALL)/iris_atomic \\\n' >> "$@"
 	printf '&& rm -f $(shell find "html" -maxdepth 1 -and -type f -print)\n' >> "$@"
-	printf 'cd "$${DSTROOT}"$(COQDOCINSTALL) && find flatcomb/html -maxdepth 0 -and -empty -exec rmdir -p \{\} \;\n' >> "$@"
+	printf 'cd "$${DSTROOT}"$(COQDOCINSTALL) && find iris_atomic/html -maxdepth 0 -and -empty -exec rmdir -p \{\} \;\n' >> "$@"
 	chmod +x $@
 
 uninstall: uninstall_me.sh
diff --git a/_CoqProject b/_CoqProject
index 5905c1f..0282886 100644
--- a/_CoqProject
+++ b/_CoqProject
@@ -1,8 +1,8 @@
--Q . flatcomb
+-Q . iris_atomic
+atomic.v
 simple_sync.v
-pair_cas.v
 flat.v
 atomic_pair.v
 atomic_sync.v
 treiber.v
-
+misc.v
diff --git a/atomic.v b/atomic.v
new file mode 100644
index 0000000..0b978ba
--- /dev/null
+++ b/atomic.v
@@ -0,0 +1,147 @@
+From iris.program_logic Require Export hoare weakestpre pviewshifts ownership.
+From iris.algebra Require Import upred_big_op.
+From iris.prelude Require Export coPset.
+From iris.proofmode Require Import tactics.
+Import uPred.
+
+Section atomic.
+  Context `{irisG Λ Σ} {A: Type}.
+
+  (* logically atomic triple: <x, α> e @ E_i, E_o <v, β x v> *)
+  Definition atomic_triple
+             (α: A → iProp Σ)
+             (β: A → val _ → iProp Σ)
+             (Ei Eo: coPset)
+             (e: expr _) : iProp Σ :=
+    (∀ P Q, (P ={Eo, Ei}=> ∃ x:A,
+                                α x ★
+                                ((α x ={Ei, Eo}=★ P) ∧
+                                 (∀ v, β x v ={Ei, Eo}=★ Q x v))
+            ) -★ {{ P }} e @ ⊤ {{ v, (∃ x: A, Q x v) }})%I.
+
+  (* Weakest-pre version of the above one. Also weaker in some sense *)
+  Definition atomic_triple_wp
+             (α: A → iProp Σ)
+             (β: A → val _ → iProp Σ)
+             (Ei Eo: coPset)
+             (e: expr _) : iProp Σ :=
+    (∀ P Q, (P ={Eo, Ei}=> ∃ x,
+                              α x ★
+                              ((α x ={Ei, Eo}=★ P) ∧
+                               (∀ v, β x v ={Ei, Eo}=★ Q x v))
+            ) -★ P -★ WP e @ ⊤ {{ v, (∃ x, Q x v) }})%I.
+
+  Lemma atomic_triple_weaken α β Ei Eo e:
+    atomic_triple α β Ei Eo e ⊢ atomic_triple_wp α β Ei Eo e.
+  Proof.
+    iIntros "H". iIntros (P Q) "Hvs Hp".
+    by iApply ("H" $! P Q with "Hvs").
+  Qed.
+
+  Arguments atomic_triple {_} _ _ _ _.
+End atomic.
+
+From iris.heap_lang Require Export lang proofmode notation.
+
+Section incr.
+  Context `{!heapG Σ} (N : namespace).
+
+  Definition incr: val :=
+    rec: "incr" "l" :=
+       let: "oldv" := !"l" in
+       if: CAS "l" "oldv" ("oldv" + #1)
+         then "oldv" (* return old value if success *)
+         else "incr" "l".
+
+  Global Opaque incr.
+
+  (* TODO: Can we have a more WP-style definition and avoid the equality? *)
+  Definition incr_triple (l: loc) :=
+    atomic_triple (fun (v: Z) => l ↦ #v)%I
+                  (fun v ret => ret = #v ★ l ↦ #(v + 1))%I
+                  (nclose heapN)
+                  ⊤
+                  (incr #l).
+
+  Lemma incr_atomic_spec: ∀ (l: loc), heapN ⊥ N → heap_ctx ⊢ incr_triple l.
+  Proof.
+    iIntros (l HN) "#?".
+    rewrite /incr_triple.
+    rewrite /atomic_triple.
+    iIntros (P Q) "#Hvs".
+    iLöb as "IH".
+    iIntros "!# HP".
+    wp_rec.
+    wp_bind (! _)%E.
+    iVs ("Hvs" with "HP") as (x) "[Hl [Hvs' _]]".
+    wp_load.
+    iVs ("Hvs'" with "Hl") as "HP".
+    iVsIntro. wp_let. wp_bind (CAS _ _ _). wp_op.
+    iVs ("Hvs" with "HP") as (x') "[Hl Hvs']".
+    destruct (decide (x = x')).
+    - subst.
+      iDestruct "Hvs'" as "[_ Hvs']".
+      iSpecialize ("Hvs'" $! #x').
+      wp_cas_suc.
+      iVs ("Hvs'" with "[Hl]") as "HQ"; first by iFrame.
+      iVsIntro. wp_if. iVsIntro. by iExists x'.
+    - iDestruct "Hvs'" as "[Hvs' _]".
+      wp_cas_fail.
+      iVs ("Hvs'" with "[Hl]") as "HP"; first by iFrame.
+      iVsIntro. wp_if. by iApply "IH".
+  Qed.
+End incr.
+
+From iris.heap_lang.lib Require Import par.
+
+Section user.
+  Context `{!heapG Σ, !spawnG Σ} (N : namespace).
+
+  Definition incr_2 : val :=
+    λ: "x",
+       let: "l" := ref "x" in
+       incr "l" || incr "l";;
+       !"l".
+
+  (* prove that incr is safe w.r.t. data race. TODO: prove a stronger post-condition *)
+  Lemma incr_2_safe:
+    ∀ (x: Z), heapN ⊥ N -> heap_ctx ⊢ WP incr_2 #x {{ _, True }}.
+  Proof.
+    iIntros (x HN) "#Hh".
+    rewrite /incr_2.
+    wp_let.
+    wp_alloc l as "Hl".
+    iVs (inv_alloc N _ (∃x':Z, l ↦ #x')%I with "[Hl]") as "#?"; first eauto.
+    wp_let.
+    wp_bind (_ || _)%E.
+    iApply (wp_par (λ _, True%I) (λ _, True%I)).
+    iFrame "Hh".
+    (* prove worker triple *)
+    iDestruct (incr_atomic_spec N l with "Hh") as "Hincr"=>//.
+    rewrite /incr_triple /atomic_triple.
+    iSpecialize ("Hincr"  $! True%I (fun _ _ => True%I) with "[]").
+    - iIntros "!# _".
+      (* open the invariant *)
+      iInv N as (x') ">Hl'" "Hclose".
+      (* mask magic *)
+      iApply pvs_intro'.
+      { apply ndisj_subseteq_difference; auto. }
+      iIntros "Hvs".
+      iExists x'.
+      iFrame "Hl'".
+      iSplit.
+      + (* provide a way to rollback *)
+        iIntros "Hl'".
+        iVs "Hvs". iVs ("Hclose" with "[Hl']"); eauto.
+      + (* provide a way to commit *)
+        iIntros (v) "[Heq Hl']".
+        iVs "Hvs". iVs ("Hclose" with "[Hl']"); eauto.
+    - iDestruct "Hincr" as "#HIncr".
+      iSplitL; [|iSplitL]; try (iApply wp_wand_r;iSplitL; [by iApply "HIncr"|auto]).
+      iIntros (v1 v2) "_ !>".
+      wp_seq.
+      iInv N as (x') ">Hl" "Hclose".
+      wp_load.
+      iApply "Hclose". eauto.
+  Qed.
+End user.
diff --git a/atomic_pair.v b/atomic_pair.v
index 9a6cca2..73b8fba 100644
--- a/atomic_pair.v
+++ b/atomic_pair.v
@@ -2,10 +2,8 @@ From iris.program_logic Require Export weakestpre hoare.
 From iris.heap_lang Require Export lang.
 From iris.heap_lang Require Import proofmode notation.
 From iris.heap_lang.lib Require Import spin_lock.
-From iris.tests Require Import atomic.
 From iris.algebra Require Import dec_agree frac.
-From iris.program_logic Require Import auth.
-From flatcomb Require Import sync.
+From iris_atomic Require Import atomic sync.
 Import uPred.
 
 Section atomic_pair.
diff --git a/atomic_sync.v b/atomic_sync.v
index c5f6f9d..89df35f 100644
--- a/atomic_sync.v
+++ b/atomic_sync.v
@@ -2,9 +2,8 @@ From iris.program_logic Require Export weakestpre hoare.
 From iris.heap_lang Require Export lang.
 From iris.heap_lang Require Import proofmode notation.
 From iris.heap_lang.lib Require Import spin_lock.
-From iris.tests Require Import atomic misc.
 From iris.algebra Require Import dec_agree frac.
-From iris.program_logic Require Import auth.
+From iris_atomic Require Import atomic misc.
 
 Definition syncR := prodR fracR (dec_agreeR val).
 Class syncG Σ := sync_tokG :> inG Σ syncR.
diff --git a/flat.v b/flat.v
index 2cacbfa..ad4504b 100644
--- a/flat.v
+++ b/flat.v
@@ -1,10 +1,9 @@
-From iris.program_logic Require Export auth weakestpre saved_prop.
+From iris.program_logic Require Export weakestpre saved_prop.
 From iris.heap_lang Require Export lang.
 From iris.heap_lang Require Import proofmode notation.
 From iris.heap_lang.lib Require Import spin_lock.
-From iris.algebra Require Import upred frac agree excl dec_agree upred_big_op gset gmap.
-From iris.tests Require Import misc atomic treiber_stack.
-Require Import flatcomb.atomic_sync.
+From iris.algebra Require Import auth upred frac agree excl dec_agree upred_big_op gset gmap.
+From iris_atomic Require Import misc atomic treiber atomic_sync.
 
 Definition doOp : val :=
   λ: "f" "p",
@@ -168,8 +167,7 @@ Section proof.
       iDestruct (evmap_alloc _ _ _ m p (γx, γ1, γ3, γ4, γq) with "[Hm]") as "==>[Hm1 Hm2]"=>//.
       iDestruct "Hl" as "[Hl1 Hl2]".
       iVs ("Hclose" with "[HRm Hm1 Hl1 Hrs]").
-      + iNext. iFrame. iExists ({[p := (1%Qp, DecAgree (γx, γ1, γ3, γ4, γq))]} ⋅ m). iFrame.
-        rewrite <-(insert_singleton_op m)=>//.
+      + iNext. iFrame. iExists (<[p := (1%Qp, DecAgree (γx, γ1, γ3, γ4, γq))]> m). iFrame.
         iDestruct (big_sepM_insert _ m with "[-]") as "H"=>//.
         iSplitL "Hl1"; last by iAssumption. eauto.
       + iDestruct (pack_ev with "Hm2") as "Hev".
diff --git a/misc.v b/misc.v
new file mode 100644
index 0000000..3a373dc
--- /dev/null
+++ b/misc.v
@@ -0,0 +1,248 @@
+From iris.program_logic Require Export weakestpre.
+From iris.heap_lang Require Export lang.
+From iris.heap_lang Require Import proofmode notation.
+From iris.algebra Require Import auth frac gmap dec_agree upred_big_op.
+From iris.prelude Require Import countable.
+Import uPred.
+
+Section lemmas.
+  Lemma op_some: ∀ {A: cmraT} (a b: A), Some a ⋅ Some b = Some (a ⋅ b).
+  Proof. done. Qed.
+
+  Lemma invalid_plus: ∀ (q: Qp), ¬ ✓ (1 + q)%Qp.
+  Proof.
+    intros q H.
+    apply (Qp_not_plus_q_ge_1 q).
+    done.
+  Qed.
+
+  Lemma pair_l_frac_update (g g': val):
+    ((1 / 2)%Qp, DecAgree g) â‹… ((1 / 2)%Qp, DecAgree g) ~~> ((1 / 2)%Qp, DecAgree g') â‹… ((1 / 2)%Qp, DecAgree g').
+  Proof.
+    repeat rewrite pair_op dec_agree_idemp.
+    rewrite frac_op' Qp_div_2.
+    eapply cmra_update_exclusive.
+    done.
+  Qed.
+  
+  Lemma pair_l_frac_op (p q: Qp) (g g': val):
+    (((p, DecAgree g') â‹… (q, DecAgree g'))) ~~> ((p + q)%Qp, DecAgree g').
+  Proof. by rewrite pair_op dec_agree_idemp frac_op'. Qed.
+
+  Lemma pair_l_frac_op' (p q: Qp) (g g': val):
+     ((p + q)%Qp, DecAgree g') ~~> (((p, DecAgree g') â‹… (q, DecAgree g'))).
+  Proof. by rewrite pair_op dec_agree_idemp frac_op'. Qed.
+
+  Lemma pair_l_frac_op_1' (g g': val):
+     (1%Qp, DecAgree g') ~~> (((1/2)%Qp, DecAgree g') â‹… ((1/2)%Qp, DecAgree g')).
+  Proof. by rewrite pair_op dec_agree_idemp frac_op' Qp_div_2. Qed.
+  
+End lemmas.
+
+Section excl.
+  Context `{!inG Σ (exclR unitC)}.
+  Lemma excl_falso γ Q':
+    own γ (Excl ()) ★ own γ (Excl ()) ⊢ Q'.
+  Proof.
+    iIntros "[Ho1 Ho2]". iCombine "Ho1" "Ho2" as "Ho".
+    iExFalso. by iDestruct (own_valid with "Ho") as "%".
+  Qed.
+End excl.
+
+Section pair.
+  Context `{EqDecision A, !inG Σ (prodR fracR (dec_agreeR A))}.
+  
+  Lemma m_frag_agree γm (q1 q2: Qp) (a1 a2: A):
+    own γm (q1, DecAgree a1) ★ own γm (q2, DecAgree a2)
+    ⊢ |=r=> own γm ((q1 + q2)%Qp, DecAgree a1) ★ (a1 = a2).
+  Proof.
+    iIntros "[Ho Ho']".
+    destruct (decide (a1 = a2)) as [->|Hneq].
+    - iSplitL=>//.
+      iCombine "Ho" "Ho'" as "Ho".
+      iDestruct (own_update with "Ho") as "?"; last by iAssumption.
+      by rewrite pair_op frac_op' dec_agree_idemp.
+    - iCombine "Ho" "Ho'" as "Ho".
+      iDestruct (own_valid with "Ho") as %Hvalid.
+      exfalso. destruct Hvalid as [_ Hvalid].
+      simpl in Hvalid. apply dec_agree_op_inv in Hvalid. inversion Hvalid. subst. auto.
+  Qed.
+End pair.
+
+Section evidence.  
+  Context (K A: Type) `{Countable K, EqDecision A}.
+  Definition evkR := prodR fracR (dec_agreeR A).
+  Definition evmapR := gmapUR K evkR.
+  Definition evidenceR := authR evmapR.
+  Class evidenceG Σ := EvidenceG { evidence_G :> inG Σ evidenceR }.
+  Definition evidenceΣ : gFunctors := #[ GFunctor (constRF evidenceR) ].
+
+  Instance subG_evidenceΣ {Σ} : subG evidenceΣ Σ → evidenceG Σ.
+  Proof. intros [?%subG_inG _]%subG_inv. split; apply _. Qed.
+
+  Lemma map_agree_eq m m' (hd: K) (p q: Qp) (x y: A):
+    m !! hd = Some (p, DecAgree y) →
+    m = {[hd := (q, DecAgree x)]} ⋅ m' → x = y.
+  Proof.
+    intros H1 H2.
+    destruct (decide (x = y)) as [->|Hneq]=>//.
+    exfalso.
+    subst. rewrite lookup_op lookup_singleton in H1.
+    destruct (m' !! hd) as [[b [c|]]|] eqn:Heqn; rewrite Heqn in H1; inversion H1=>//.
+    destruct (decide (x = c)) as [->|Hneq3]=>//.
+    - rewrite dec_agree_idemp in H3. by inversion H3.
+    - rewrite dec_agree_ne in H3=>//.
+  Qed.
+
+  Lemma map_agree_somebot m m' (hd: K) (p q: Qp) (x: A):
+    m !! hd = Some (p, DecAgreeBot) → m' !! hd = None →
+    m = {[hd := (q, DecAgree x)]} ⋅ m' → False.
+  Proof.
+    intros H1 H2 H3. subst. rewrite lookup_op lookup_singleton in H1.
+    destruct (m' !! hd) as [[b [c|]]|] eqn:Heqn; rewrite Heqn in H1; inversion H1=>//.
+  Qed.
+
+  Lemma map_agree_none m m' (hd: K) (q: Qp) (x: A):
+    m !! hd = None → m = {[hd := (q, DecAgree x)]} ⋅ m' → False.
+  Proof.
+    intros H1 H2. subst. rewrite lookup_op lookup_singleton in H1.
+    destruct (m' !! hd)=>//.
+  Qed.
+
+  Context `{!inG Σ (authR evmapR)}.
+
+  Definition ev γm (k : K) (v: A) := (∃ q, own γm (◯ {[ k := (q, DecAgree v) ]}))%I.
+
+  Lemma evmap_alloc γm m k v:
+    m !! k = None →
+    own γm (● m) ⊢ |=r=> own γm (● (<[ k := (1%Qp, DecAgree v) ]> m) ⋅ ◯ {[ k := (1%Qp, DecAgree v) ]}).
+  Proof.
+    iIntros (?) "Hm".
+    iDestruct (own_update with "Hm") as "?"; last by iAssumption.
+    apply auth_update_alloc, alloc_local_update=>//.
+  Qed.
+  
+  Lemma map_agree_none' γm m hd x:
+    m !! hd = None →
+    own γm (● m) ★ ev γm hd x ⊢ False.
+  Proof.
+    iIntros (?) "[Hom Hev]". iDestruct "Hev" as (?) "Hfrag".
+    iCombine "Hom" "Hfrag" as "Hauth".
+    iDestruct (own_valid γm (● m ⋅ ◯ {[hd := (_, DecAgree x)]})
+               with "[Hauth]") as %Hvalid=>//.
+    iPureIntro.
+    apply auth_valid_discrete_2 in Hvalid as [[af Compose%leibniz_equiv_iff] Valid].
+    eapply (map_agree_none m)=>//.
+  Qed.
+  
+  Lemma map_agree_eq' γm m hd p x agy:
+    m !! hd = Some (p, agy) →
+    own γm (● m) ★ ev γm hd x ⊢ own γm (● m) ★ ev γm hd x ★ DecAgree x = agy.
+  Proof.
+    iIntros (?) "[Hom Hev]". iDestruct "Hev" as (?) "Hfrag".
+    iCombine "Hom" "Hfrag" as "Hauth".
+    iDestruct (own_valid γm (● m ⋅ ◯ {[hd := (_, DecAgree x)]})
+               with "[Hauth]") as %Hvalid=>//.
+    apply auth_valid_discrete_2 in Hvalid as [[af Compose%leibniz_equiv_iff] Valid].
+    destruct agy as [y|].
+    - iDestruct "Hauth" as "[? ?]". iFrame. iSplitL.
+      { rewrite /ev. eauto. }
+      iPureIntro. destruct (decide (x = y)); try by subst.
+      exfalso. apply n. eapply (map_agree_eq m)=>//. (* XXX: Why it is uPred M *)
+    - iAssert (✓ m)%I as "H"=>//. rewrite (gmap_validI m).
+      iDestruct ("H" $! hd) as "%".
+      exfalso. subst. rewrite H0 in H2.
+      by destruct H2 as [? ?].
+  Qed.
+
+  Lemma pack_ev γm k v q:
+    own γm (◯ {[ k := (q, DecAgree v) ]}) ⊢ ev γm k v.
+  Proof. iIntros "?". rewrite /ev. eauto. Qed.
+  
+  Lemma dup_ev γm hd y:
+    ev γm hd y ⊢ |=r=> ev γm hd y ★ ev γm hd y.
+  Proof.
+    rewrite /ev. iIntros "Hev". iDestruct "Hev" as (q) "Hev".
+    iAssert (|=r=> own γm (◯ {[hd := ((q/2)%Qp, DecAgree y)]} ⋅
+                           â—¯ {[hd := ((q/2)%Qp, DecAgree y)]}))%I with "[Hev]" as "==>[Hev1 Hev2]".
+    { iDestruct (own_update with "Hev") as "?"; last by iAssumption.
+      rewrite <- auth_frag_op.
+      by rewrite op_singleton pair_op dec_agree_idemp  frac_op' Qp_div_2. }
+    iSplitL "Hev1"; eauto.
+  Qed.
+
+  Lemma evmap_frag_agree_split γm p q1 q2 (a1 a2: A):
+    own γm (◯ {[p := (q1, DecAgree a1)]}) ★
+    own γm (◯ {[p := (q2, DecAgree a2)]})
+    ⊢ |=r=> own γm (◯ {[p := (q1, DecAgree a1)]}) ★
+            own γm (◯ {[p := (q2, DecAgree a1)]}) ★ (a1 = a2).
+  Proof.
+    iIntros "[Ho Ho']".
+    destruct (decide (a1 = a2)) as [->|Hneq].
+    - by iFrame.
+    - iCombine "Ho" "Ho'" as "Ho".
+      iDestruct (own_valid with "Ho") as %Hvalid.
+      exfalso. rewrite <-(@auth_frag_op evmapR) in Hvalid.
+      rewrite op_singleton in Hvalid.
+      apply auth_valid_discrete in Hvalid. simpl in Hvalid.
+      apply singleton_valid in Hvalid.
+      destruct Hvalid as [_ Hvalid].
+      apply dec_agree_op_inv in Hvalid. inversion Hvalid. subst. auto.
+  Qed.
+
+  Lemma evmap_frag_agree γm p q1 q2 (a1 a2: A):
+    own γm (◯ {[p := (q1, DecAgree a1)]}) ★
+    own γm (◯ {[p := (q2, DecAgree a2)]})
+    ⊢ |=r=> own γm (◯ {[p := ((q1 + q2)%Qp, DecAgree a1)]}) ★ (a1 = a2).
+  Proof.
+    iIntros "Hos".
+    iDestruct (evmap_frag_agree_split with "Hos") as "==>[Ho1 [Ho2 %]]".
+    iCombine "Ho1" "Ho2" as "Ho". iSplitL; auto.
+    iDestruct (own_update with "Ho") as "?"; last by iAssumption.
+    rewrite <-(@auth_frag_op evmapR {[p := (q1, DecAgree a1)]} {[p := (q2, DecAgree a1)]}).
+    by rewrite op_singleton pair_op frac_op' dec_agree_idemp.
+  Qed.
+
+  Lemma ev_agree γm k v1 v2:
+    ev γm k v1 ★ ev γm k v2 ⊢ |=r=> ev γm k v1 ★ ev γm k v1 ★ v1 = v2.
+  Proof.
+    iIntros "[Hev1 Hev2]".
+    iDestruct "Hev1" as (?) "Hev1". iDestruct "Hev2" as (?) "Hev2".
+    iDestruct (evmap_frag_agree_split with "[-]") as "==>[Hev1 [Hev2 %]]"; first iFrame.
+    subst. iSplitL "Hev1"; rewrite /ev; eauto.
+  Qed.
+
+End evidence.
+
+Section heap_extra.
+  Context `{heapG Σ}.
+
+  Lemma bogus_heap p (q1 q2: Qp) a b:
+    ~((q1 + q2)%Qp ≤ 1%Qp)%Qc →
+    heap_ctx ★ p ↦{q1} a ★ p ↦{q2} b ⊢ False.
+  Proof.
+    iIntros (?) "(#Hh & Hp1 & Hp2)".
+    iCombine "Hp1" "Hp2" as "Hp".
+    iDestruct (heap_mapsto_op_1 with "Hp") as "[_ Hp]".
+    rewrite heap_mapsto_eq. iDestruct (own_valid with "Hp") as %H'.
+    apply singleton_valid in H'. by destruct H' as [H' _].
+  Qed.
+  
+End heap_extra.
+
+Section big_op_later.
+  Context {M : ucmraT}.
+  Context `{Countable K} {A : Type}.
+  Implicit Types m : gmap K A.
+  Implicit Types Φ Ψ : K → A → uPred M. 
+
+  Lemma big_sepM_delete_later Φ m i x :
+    m !! i = Some x →
+    ▷ ([★ map] k↦y ∈ m, Φ k y) ⊣⊢ ▷ Φ i x ★ ▷ [★ map] k↦y ∈ delete i m, Φ k y.
+  Proof. intros ?. rewrite big_sepM_delete=>//. apply later_sep. Qed.
+
+  Lemma big_sepM_insert_later Φ m i x :
+    m !! i = None →
+    ▷ ([★ map] k↦y ∈ <[i:=x]> m, Φ k y) ⊣⊢ ▷ Φ i x ★ ▷ [★ map] k↦y ∈ m, Φ k y.
+  Proof. intros ?. rewrite big_sepM_insert=>//. apply later_sep. Qed.
+End big_op_later.
diff --git a/pair_cas.v b/pair_cas.v
index aa7b1ff..5ab3cd7 100644
--- a/pair_cas.v
+++ b/pair_cas.v
@@ -3,7 +3,7 @@ From iris.heap_lang Require Export lang.
 From iris.heap_lang Require Import proofmode notation.
 From iris.heap_lang.lib Require Import spin_lock.
 From iris.algebra Require Import excl.
-From flatcomb Require Import sync.
+Require Import iris_atomic.atomic_sync.
 Import uPred.
 
 (* CAS, load and store to pair of locations *)
diff --git a/simple_sync.v b/simple_sync.v
index de70675..d9859bb 100644
--- a/simple_sync.v
+++ b/simple_sync.v
@@ -2,10 +2,8 @@ From iris.program_logic Require Export weakestpre hoare.
 From iris.heap_lang Require Export lang.
 From iris.heap_lang Require Import proofmode notation.
 From iris.heap_lang.lib Require Import spin_lock.
-From iris.tests Require Import atomic misc.
 From iris.algebra Require Import dec_agree frac.
-From iris.program_logic Require Import auth.
-From flatcomb Require Import atomic_sync.
+From iris_atomic Require Import atomic atomic_sync.
 Import uPred.
 
 Definition mk_sync: val :=
diff --git a/treiber.v b/treiber.v
index c2cbe7c..82dc587 100644
--- a/treiber.v
+++ b/treiber.v
@@ -1,9 +1,204 @@
 From iris.program_logic Require Export weakestpre.
 From iris.heap_lang Require Export lang.
 From iris.heap_lang Require Import proofmode notation.
-From iris.algebra Require Import upred gmap dec_agree upred_big_op.
-From iris.program_logic Require Import auth.
-From iris.tests Require Import treiber_stack atomic misc.
+From iris.algebra Require Import auth upred gmap dec_agree upred_big_op.
+From iris_atomic Require Import atomic misc.
+
+Definition new_stack: val := λ: <>, ref (ref NONE).
+
+Definition push: val :=
+  rec: "push" "s" "x" :=
+      let: "hd" := !"s" in
+      let: "s'" := ref SOME ("x", "hd") in
+      if: CAS "s" "hd" "s'"
+        then #()
+        else "push" "s" "x".
+
+Definition pop: val :=
+  rec: "pop" "s" :=
+      let: "hd" := !"s" in
+      match: !"hd" with
+        SOME "cell" =>
+        if: CAS "s" "hd" (Snd "cell")
+          then SOME (Fst "cell")
+          else "pop" "s"
+      | NONE => NONE
+      end.
+
+Definition iter: val :=
+  rec: "iter" "hd" "f" :=
+      match: !"hd" with
+        NONE => #()
+      | SOME "cell" => "f" (Fst "cell") ;; "iter" (Snd "cell") "f"
+      end.
+
+Global Opaque new_stack push pop iter.
+
+Section proof.
+  Context `{!heapG Σ} (N: namespace).
+
+  Fixpoint is_list (hd: loc) (xs: list val) : iProp Σ :=
+    match xs with
+    | [] => (∃ q, hd ↦{ q } NONEV)%I
+    | x :: xs => (∃ (hd': loc) q, hd ↦{ q } SOMEV (x, #hd') ★ is_list hd' xs)%I
+    end.
+
+  Lemma dup_is_list : ∀ xs hd,
+    heap_ctx ★ is_list hd xs ⊢ is_list hd xs ★ is_list hd xs.
+  Proof.
+    induction xs as [|y xs' IHxs'].
+    - iIntros (hd) "(#? & Hs)".
+      simpl. iDestruct "Hs" as (q) "[Hhd Hhd']". iSplitL "Hhd"; eauto.
+    - iIntros (hd) "(#? & Hs)". simpl.
+      iDestruct "Hs" as (hd' q) "([Hhd Hhd'] & Hs')".
+      iDestruct (IHxs' with "[Hs']") as "[Hs1 Hs2]"; first by iFrame.
+      iSplitL "Hhd Hs1"; iExists hd', (q / 2)%Qp; by iFrame.
+  Qed.
+
+  Lemma uniq_is_list:
+    ∀ xs ys hd, heap_ctx ★ is_list hd xs ★ is_list hd ys ⊢ xs = ys.
+  Proof.
+    induction xs as [|x xs' IHxs'].
+    - induction ys as [|y ys' IHys'].
+      + auto.
+      + iIntros (hd) "(#? & Hxs & Hys)".
+        simpl. iDestruct "Hys" as (hd' ?) "(Hhd & Hys')".
+        iExFalso. iDestruct "Hxs" as (?) "Hhd'".
+        iDestruct (heap_mapsto_op_1 with "[Hhd Hhd']") as "[% _]".
+        { iSplitL "Hhd"; done. }
+        done.
+    - induction ys as [|y ys' IHys'].
+      + iIntros (hd) "(#? & Hxs & Hys)".
+        simpl.
+        iExFalso. iDestruct "Hxs" as (? ?) "(Hhd & _)".
+        iDestruct "Hys" as (?) "Hhd'".
+        iDestruct (heap_mapsto_op_1 with "[Hhd Hhd']") as "[% _]".
+        { iSplitL "Hhd"; done. }
+        done.
+      + iIntros (hd) "(#? & Hxs & Hys)".
+        simpl. iDestruct "Hxs" as (? ?) "(Hhd & Hxs')".
+        iDestruct "Hys" as (? ?) "(Hhd' & Hys')".
+        iDestruct (heap_mapsto_op_1 with "[Hhd Hhd']") as "[% _]".
+        { iSplitL "Hhd"; done. }
+        inversion H3. (* FIXME: name *)
+        subst. iDestruct (IHxs' with "[Hxs' Hys']") as "%"; first by iFrame.
+        by subst.
+  Qed.
+
+  Definition is_stack (s: loc) xs: iProp Σ := (∃ hd: loc, s ↦ #hd ★ is_list hd xs)%I.
+
+  Global Instance is_list_timeless xs hd: TimelessP (is_list hd xs).
+  Proof. generalize hd. induction xs; apply _. Qed.
+
+  Global Instance is_stack_timeless xs hd: TimelessP (is_stack hd xs).
+  Proof. generalize hd. induction xs; apply _. Qed.
+
+  Lemma new_stack_spec:
+    ∀ (Φ: val → iProp Σ),
+      heapN ⊥ N →
+      heap_ctx ★ (∀ s, is_stack s [] -★ Φ #s) ⊢ WP new_stack #() {{ Φ }}.
+  Proof.
+    iIntros (Φ HN) "[#Hh HΦ]". wp_seq.
+    wp_bind (ref NONE)%E. wp_alloc l as "Hl".
+    wp_alloc l' as "Hl'".
+    iApply "HΦ". rewrite /is_stack. iExists l.
+    iFrame. by iExists 1%Qp.
+  Qed.
+
+  Definition push_triple (s: loc) (x: val) :=
+    atomic_triple (fun xs_hd: list val * loc =>
+                     let '(xs, hd) := xs_hd in s ↦ #hd ★ is_list hd xs)%I
+                  (fun xs_hd ret =>
+                     let '(xs, hd) := xs_hd in 
+                     ∃ hd': loc,
+                       ret = #() ★ s ↦ #hd' ★ hd' ↦ SOMEV (x, #hd) ★ is_list hd xs)%I
+                  (nclose heapN)
+                  ⊤
+                  (push #s x).
+  
+  Lemma push_atomic_spec (s: loc) (x: val) :
+    heapN ⊥ N → heap_ctx ⊢ push_triple s x.
+  Proof.
+    iIntros (HN) "#?". rewrite /push_triple /atomic_triple.
+    iIntros (P Q) "#Hvs".
+    iLöb as "IH". iIntros "!# HP". wp_rec.
+    wp_let. wp_bind (! _)%E.
+    iVs ("Hvs" with "HP") as ([xs hd]) "[[Hs Hhd] [Hvs' _]]".
+    wp_load. iVs ("Hvs'" with "[Hs Hhd]") as "HP"; first by iFrame.
+    iVsIntro. wp_let. wp_alloc l as "Hl". wp_let.
+    wp_bind (CAS _ _ _)%E.
+    iVs ("Hvs" with "HP") as ([xs' hd']) "[[Hs Hhd'] Hvs']".
+    destruct (decide (hd = hd')) as [->|Hneq].
+    * wp_cas_suc. iDestruct "Hvs'" as "[_ Hvs']".
+      iVs ("Hvs'" $! #() with "[-]") as "HQ".
+      { iExists l. iSplitR; first done. by iFrame. }
+      iVsIntro. wp_if. iVsIntro. eauto.
+    * wp_cas_fail.
+      iDestruct "Hvs'" as "[Hvs' _]".
+      iVs ("Hvs'" with "[-]") as "HP"; first by iFrame.
+      iVsIntro. wp_if. by iApply "IH".
+  Qed.
+
+  Definition pop_triple (s: loc) :=
+    atomic_triple (fun xs_hd: list val * loc =>
+                     let '(xs, hd) := xs_hd in s ↦ #hd ★ is_list hd xs)%I
+                  (fun xs_hd ret =>
+                     let '(xs, hd) := xs_hd in
+                     (ret = NONEV ★ xs = [] ★ s ↦ #hd ★ is_list hd []) ∨
+                     (∃ x q (hd': loc) xs', hd ↦{q} SOMEV (x, #hd') ★ ret = SOMEV x ★
+                                            xs = x :: xs' ★ s ↦ #hd' ★ is_list hd' xs'))%I
+                  (nclose heapN)
+                  ⊤
+                  (pop #s).
+
+  Lemma pop_atomic_spec (s: loc):
+    heapN ⊥ N → heap_ctx ⊢ pop_triple s.
+  Proof.
+    iIntros (HN) "#?".
+    rewrite /pop_triple /atomic_triple.
+    iIntros (P Q) "#Hvs".
+    iLöb as "IH". iIntros "!# HP". wp_rec.
+    wp_bind (! _)%E.
+    iVs ("Hvs" with "HP") as ([xs hd]) "[[Hs Hhd] Hvs']".
+    destruct xs as [|y' xs'].
+    - simpl. wp_load. iDestruct "Hvs'" as "[_ Hvs']".
+      iDestruct "Hhd" as (q) "[Hhd Hhd']".
+      iVs ("Hvs'" $! NONEV with "[-Hhd]") as "HQ".
+      { iLeft. iSplit=>//. iSplit=>//. iFrame. eauto. }
+      iVsIntro. wp_let. wp_load. wp_match.
+      iVsIntro. eauto.
+    - simpl. iDestruct "Hhd" as (hd' q) "([[Hhd1 Hhd2] Hhd'] & Hxs')".
+      iDestruct (dup_is_list with "[Hxs']") as "[Hxs1 Hxs2]"; first by iFrame.
+      wp_load. iDestruct "Hvs'" as "[Hvs' _]".
+      iVs ("Hvs'" with "[-Hhd1 Hhd2 Hxs1]") as "HP".
+      { iFrame. iExists hd', (q / 2)%Qp. by iFrame. }
+      iVsIntro. wp_let. wp_load. wp_match. wp_proj.
+      wp_bind (CAS _ _ _). iVs ("Hvs" with "HP") as ([xs hd'']) "[[Hs Hhd''] Hvs']".
+      destruct (decide (hd = hd'')) as [->|Hneq].
+      + wp_cas_suc. iDestruct "Hvs'" as "[_ Hvs']".
+        iVs ("Hvs'" $! (SOMEV y') with "[-]") as "HQ".
+        { iRight. iExists y', (q / 2 / 2)%Qp, hd', xs'.
+          destruct xs as [|x' xs''].
+          - simpl. iDestruct "Hhd''" as (?) "H".
+            iExFalso. iDestruct (heap_mapsto_op_1 with "[Hhd1 H]") as "[% _]".
+            { iSplitL "Hhd1"; done. }
+            done.
+          - simpl. iDestruct "Hhd''" as (hd''' ?) "(Hhd'' & Hxs'')".
+            iDestruct (heap_mapsto_op_1 with "[Hhd1 Hhd'']") as "[% _]".
+            { iSplitL "Hhd1"; done. }
+            inversion H0. (* FIXME: bad naming *) subst.
+            iDestruct (uniq_is_list with "[Hxs1 Hxs'']") as "%"; first by iFrame. subst.
+            repeat (iSplitR "Hxs1 Hs"; first done).
+            iFrame. }
+        iVsIntro. wp_if. wp_proj. eauto.
+      + wp_cas_fail. iDestruct "Hvs'" as "[Hvs' _]".
+        iVs ("Hvs'" with "[-]") as "HP"; first by iFrame.
+        iVsIntro. wp_if. by iApply "IH".
+  Qed.
+
+End proof.
+
+
 
 Section defs.
   Context `{heapG Σ, !evidenceG loc val Σ} (N: namespace).
@@ -174,8 +369,7 @@ Lemma new_stack_spec' Φ RI:
             { rewrite /ev. eauto. }
             iFrame.
             iDestruct (big_sepM_insert_later (perR R) m) as "H"=>//.
-            rewrite (insert_singleton_op m)=>//.
-            iExists ({[hd' := (1%Qp, DecAgree x)]} â‹… m).
+            iExists (<[hd' := (1%Qp, DecAgree x)]> m).
             iFrame. iApply "H". iFrame. iExists x.
             iFrame. rewrite /allocated. iSplitR "Hhd'1"; auto.
           }
@@ -222,3 +416,4 @@ Lemma new_stack_spec' Φ RI:
   Qed.
 
 End proofs.
+
-- 
GitLab