diff --git a/_CoqProject b/_CoqProject
index c03b2e2b60c556cb12f90154d5edf63677a55baa..40b8f4c2427315a9c93ef79f8e2293e301700f56 100644
--- a/_CoqProject
+++ b/_CoqProject
@@ -66,6 +66,7 @@ theories/typing/lib/refcell/ref.v
 theories/typing/lib/rwlock/rwlock.v
 theories/typing/lib/rwlock/rwlockreadguard.v
 theories/typing/lib/rwlock/rwlockwriteguard.v
+theories/typing/lib/rwlock/rwlock_code.v
 theories/typing/examples/get_x.v
 theories/typing/examples/rebor.v
 theories/typing/examples/unbox.v
diff --git a/theories/typing/lib/rwlock/rwlock.v b/theories/typing/lib/rwlock/rwlock.v
index 1f3d82f33571f3890fef68c3d4b542cc18e537ac..145efd265caf5bd351e3bc8428b1733fb38be2ed 100644
--- a/theories/typing/lib/rwlock/rwlock.v
+++ b/theories/typing/lib/rwlock/rwlock.v
@@ -142,6 +142,21 @@ Section rwlock_inv.
       apply Qcplus_le_mono_r, Qp_ge_0.
   Qed.
 
+  Lemma rwown_update_write γs :
+    let st' : rwlock_st := Some (inl ()) in
+    rwown γs (main_st None) -∗ rwown γs (sub_st None)
+    ==∗ rwown γs (main_st st') ∗ rwown γs (sub_st st') ∗ rwown γs writing_st.
+  Proof.
+    iIntros (st') "m s".
+    rewrite bi.sep_assoc -rwown_st_global_main_sub -embed_sep -own_op pair_op right_id.
+    iDestruct (rwown_st_global_main_sub with "[$m $s]") as "ms".
+    iMod (own_update (A:=rwlockR) with "ms") as "$"; [|done].
+    apply prod_update; simpl; [|by apply rwown_agree_update].
+    apply auth_update_alloc.
+    rewrite (_: Some (Cinl (Excl ())) = Some (Cinl (Excl ())) ⋅ ε);
+              [by apply op_local_update_discrete|by rewrite right_id_L].
+  Qed.
+
   (* GPS protocol definitions *)
   Definition rwlock_interp
     (γs: gname) (α : lft) (tyO: vProp) (tyS: lft → vProp)
diff --git a/theories/typing/lib/rwlock/rwlock_code.v b/theories/typing/lib/rwlock/rwlock_code.v
index 844b24f17cc8fa22e377a576c30f1f88c40cee09..da353f3f4394408c0166dff6294a6cd830d40d12 100644
--- a/theories/typing/lib/rwlock/rwlock_code.v
+++ b/theories/typing/lib/rwlock/rwlock_code.v
@@ -8,6 +8,20 @@ From lrust.typing.lib.rwlock Require Import rwlock rwlockreadguard rwlockwritegu
 From gpfsl.gps Require Import middleware.
 Set Default Proof Using "Type".
 
+(** SYNCHRONIZATION CONDITIONS of rwlock *)
+(*  ---> stands for Release-Acquire synchronization.
+  write_unlock  --->  read_lock
+  read_unlock   --->  read_lock
+  read_unlock   --->  write_lock
+
+  This leads to the following C11 implementation:
+  - write_unlock uses a release write
+  - read_lock uses an acquire CAS
+  - write_lock uses an acquire CAS
+  - read_unlock uses a release CAS
+    TODO: check if read_unlock can be a relaxed CAS, due to the release sequence
+    or read-only accesses? *)
+
 Section rwlock_functions.
   Context `{typeG Σ, rwlockG Σ}.
 
@@ -332,37 +346,75 @@ Section rwlock_functions.
     iIntros (x' tid) "#LFT #HE Hna HL Hk HT". simpl_subst.
     rewrite 2!tctx_interp_cons tctx_interp_singleton !tctx_hasty_val.
     iDestruct "HT" as "(Hx & Hx' & Hr)". destruct x' as [[|lx|]|]; try done.
-    iDestruct "Hx'" as (β γ) "#[Hαβ Hinv]".
+    iDestruct "Hx'" as (β) "#[Hαβ Hinv]".
+    iDestruct "Hinv" as (γ γs tyO tyS) "((EqO & EqS & PP) & Hinv)".
+    iDestruct "PP" as (vP) "PP".
     iMod (lctx_lft_alive_tok α with "HE HL") as (qα) "(Hα & HL & Hclose)"; [solve_typing..|].
     iMod (lft_incl_acc with "Hαβ Hα") as (qβ) "[Hβtok Hclose']". done.
-    wp_bind (CAS _ _ _).
-    iMod (at_bor_acc_tok with "LFT Hinv Hβtok") as "[INV Hclose'']"; try done.
-    iDestruct "INV" as (st) "(Hlx & >Hownst & Hst)". destruct st.
-    - iApply (wp_cas_int_fail with "Hlx"). by destruct c as [|[[]]|].
-      iNext. iIntros "Hlx".
-      iMod ("Hclose''" with "[Hlx Hownst Hst]") as "Hβtok"; first by iExists _; iFrame.
+    wp_bind (CAS _ _ _ _ _ _).
+    iMod (at_bor_acc with "LFT Hinv Hβtok") as (Vb) "[INV Hclose'']"; try done.
+    iDestruct (rwlock_proto_inv_split with "INV") as "[mst INV]".
+    iDestruct (bi.later_exist_2 with "mst") as ">mst".
+    set Q : () → vProp Σ :=
+      (λ _, (∃ st, rwown γs (main_st st) ∗ rwown γs (sub_st st)) ∗
+             &{β}tyO ∗ rwown γs writing_st)%I.
+    set R : () → lit → vProp Σ := (λ _ _, True)%I.
+    set P : vProp Σ := ((∃ st, rwown γs (main_st st)))%I.
+    iMod (rel_True_intro True%I tid with "[//]") as "#rTrue".
+    iApply (GPS_PPRaw_CAS_int_simple (rwlock_interp γs β tyO tyS) _ _ _ _ _
+                  0 #(-1) () P Q R _ _ Vb with "[$PP $INV mst rTrue]");
+      [solve_ndisj|by left|done|by right|by left|iSplitL ""; last iSplitL ""|..].
+    { iIntros "!> !>" (???). by iApply rwlock_interp_comparable. }
+    { iIntros "!> !>" (???). by iApply rwlock_interp_duplicable. }
+    { simpl. iSplitL ""; last first.
+      { rewrite -{2}(bi.True_sep' P).
+        iApply (rel_sep_objectively with "[$rTrue mst]"). iModIntro. by iFrame. }
+      iNext. rewrite -(bi.True_sep' (∀ _ : (), _)%I).
+      iApply (rel_sep_objectively with "[$rTrue]"). iModIntro.
+      iIntros ([] _). iSplit; [|by iIntros (?) "_ _"].
+      iDestruct 1 as (st) "mst".
+      iDestruct 1 as (st') "[Eqst INT]". iDestruct "Eqst" as %Eqst.
+      destruct st' as [[[]|[[ν q] n]]|]; [by inversion Eqst..|].
+      iDestruct "INT" as "[sst Hst]".
+      iDestruct 1 as (?) "[_ #Share]". iExists (). iSplitL ""; [done|].
+      iDestruct (rwown_main_sub_agree with "mst sst") as %Eqst2. subst st.
+      set st': rwlock_st := Some (inl ()).
+      iMod (rwown_update_write γs with "mst sst") as "(mst'&sst'&wst)".
+      iModIntro. iFrame "Hst wst". iSplitR ""; [iExists _; by iFrame|].
+      iSplitL ""; iExists st'; [done|by iFrame "Share"]. }
+
+    iNext. simpl.
+    iIntros (b v' [])
+            "(INV & _ &[([%%] & _ & mst & Hβ & wst) | ([% Neq] & _ & _ & P)])".
+    - subst b v'. iDestruct "mst" as (st2) "[mst sst]".
+      iMod ("Hclose''" with "[mst INV]") as "Hβtok".
+      { iIntros "Vb'". iDestruct ("INV" with "Vb'") as "$". by iExists st2. }
       iMod ("Hclose'" with "Hβtok") as "Hα". iMod ("Hclose" with "Hα HL") as "HL".
       iModIntro. wp_case.
-      iApply (type_type _ _ _
-              [ x ◁ box (&shr{α}(rwlock ty)); r ◁ box (uninit 2) ]
-              with "[] LFT HE Hna HL Hk"); first last.
-      { rewrite tctx_interp_cons tctx_interp_singleton !tctx_hasty_val. iFrame. }
-      iApply (type_sum_unit (option $ rwlockwriteguard α ty));
-        [solve_typing..|]; first last.
-      rewrite /option /=. iApply type_jump; solve_typing.
-    - iApply (wp_cas_int_suc with "Hlx"). iIntros "!> Hlx".
-      iMod (own_update with "Hownst") as "[Hownst ?]".
-      { by eapply auth_update_alloc, (op_local_update_discrete _ _ writing_st). }
-      iMod ("Hclose''" with "[Hlx Hownst]") as "Hβtok". { iExists _. iFrame. }
-      iModIntro. wp_case. iMod ("Hclose'" with "Hβtok") as "Hα".
-      iMod ("Hclose" with "Hα HL") as "HL".
       iApply (type_type  _ _ _
                    [ x ◁ box (&shr{α}(rwlock ty)); r ◁ box (uninit 2);
                      #lx ◁ rwlockwriteguard α ty]
               with "[] LFT HE Hna HL Hk"); first last.
       { rewrite 2!tctx_interp_cons tctx_interp_singleton !tctx_hasty_val
-                tctx_hasty_val' //. iFrame.  iExists _, _. iFrame "∗#". }
+                tctx_hasty_val' //. iFrame "Hx Hr".
+        iExists γs, β. iSplitL "Hβ"; [by iApply (bor_iff with "[$EqO] Hβ")|].
+        iFrame "Hαβ wst". iSplitL "sst"; [by iExists st2|].
+        iExists _,_,_. iFrame "EqO EqS Hinv". by iExists _. }
       iApply (type_sum_assign (option $ rwlockwriteguard α ty)); [solve_typing..|].
       simpl. iApply type_jump; solve_typing.
+    - subst b.
+      iDestruct (rel_exist with "P") as (st') "mst".
+      iDestruct (rel_embed_elim with "mst") as "mst".
+      iMod ("Hclose''" with "[INV mst]") as "Hβtok".
+      { iIntros "Vb'". iDestruct ("INV" with "Vb'") as "$". by iExists _. }
+      iMod ("Hclose'" with "Hβtok") as "Hα". iMod ("Hclose" with "Hα HL") as "HL".
+      iModIntro. wp_case.
+      iApply (type_type _ _ _
+              [ x ◁ box (&shr{α}(rwlock ty)); r ◁ box (uninit 2) ]
+              with "[] LFT HE Hna HL Hk"); first last.
+      { rewrite tctx_interp_cons tctx_interp_singleton !tctx_hasty_val. iFrame. }
+      iApply (type_sum_unit (option $ rwlockwriteguard α ty));
+        [solve_typing..|]; first last.
+      rewrite /option /=. iApply type_jump; solve_typing.
   Qed.
 End rwlock_functions.
diff --git a/theories/typing/lib/rwlock/rwlockwriteguard.v b/theories/typing/lib/rwlock/rwlockwriteguard.v
index ad3d3ff839ea5f2ab39151fb81240a2723d15ea3..daa5c4e64c45ccfcb7daa1e6f327cb52105b9996 100644
--- a/theories/typing/lib/rwlock/rwlockwriteguard.v
+++ b/theories/typing/lib/rwlock/rwlockwriteguard.v
@@ -23,7 +23,7 @@ Section rwlockwriteguard.
          match vl return _ with
          | [ #(LitLoc l) ] =>
            ∃ γs β, &{β}((l +ₗ 1) ↦∗: ty.(ty_own) tid) ∗
-             α ⊑ β ∗ rwown γs writing_st ∗
+             α ⊑ β ∗ rwown γs writing_st ∗ (∃ st, rwown γs (sub_st st)) ∗
              (∃ γ tyO tyS, rwlock_proto_lc l γ tyO tyS tid ty ∗
                     &at{β,rwlockN}(rwlock_proto_inv l γ γs β tyO tyS))
          | _ => False
@@ -84,8 +84,8 @@ Section rwlockwriteguard.
     iIntros "!# #HE". iDestruct ("Hα" with "HE") as "Hα1α2".
     iDestruct ("Hty" with "HE") as "(%&#Ho&#Hs)". iSplit; [done|iSplit; iAlways].
     - iIntros (tid [|[[]|][]]) "H"; try done.
-      iDestruct "H" as (γs β) "(Hb & #H⊑ & Hown & Hinv)".
-      iExists γs, β. iFrame "Hown". iSplit; last iSplit.
+      iDestruct "H" as (γs β) "(Hb & #H⊑ & Hown & Hsst & Hinv)".
+      iExists γs, β. iFrame "Hown Hsst". iSplit; last iSplit.
       + iApply bor_iff; last done.
         iIntros "!>!#". iSplit; iIntros "H"; iDestruct "H" as (vl) "[??]";
         iExists vl; iFrame; by iApply "Ho".