(* PERSONAL MEM: Is the contents of the global memory, with the juice of a single thread and the Cur that corresponds to that juice.*)
Definition acc_coh:= fun m phi pr => @max_acc_coh_acc_coh m phi (max_coh pr).
Definition personal_mem {m phi} (pr : mem_cohere' m phi) : juicy_mem:=
mkJuicyMem
(@juicyRestrict phi m (acc_coh pr))
phi
(juicyRestrictContentCoh (acc_coh pr) (cont_coh pr))
(juicyRestrictAccCoh (acc_coh pr))
(juicyRestrictMaxCoh (acc_coh pr) (max_coh pr))
(juicyRestrictAllocCoh (acc_coh pr) (all_coh pr)).
Definition juicy_sem := (FSem.F _ _ JuicyFSem.t) _ the_sem.
(* Definition juicy_step := (FSem.step _ _ JuicyFSem.t) _ _ the_sem. *)
Program Definition first_phi (tp : thread_pool) : rmap := (@getThreadR _ _ _ 0%nat tp _).
Next Obligation.
unfold OrdinalPool.containsThread.
destruct num_threads.
simpl.
ssromega.
Defined.
Program Definition level_tp (tp : thread_pool) := level (first_phi tp).
Definition tp_level_is_above n tp :=
(forall i (cnti : containsThread tp i), le n (level (getThreadR cnti))) /\
(forall i phi, lockRes(resources:=LocksAndResources) tp i = Some (Some phi) -> le n (level phi)).
Definition tp_level_is n tp :=
(forall i (cnti : containsThread tp i), level (getThreadR cnti) = n) /\
(forall i phi, lockRes(resources:=LocksAndResources) tp i = Some (Some phi) -> level phi = n).
(* Lemma mem_compatible_same_level tp m : mem_compatible tp m -> tp_level_is (level_tp tp) tp.  Definition cnt_from_ordinal tp : forall i : ordinal (pos.n (num_threads tp)), containsThread tp i. intros [i pr]; apply pr. Defined.  Definition age_tp_to (k : nat) (tp : thread_pool) : thread_pool := match tp with mk n pool maps lset => mk n pool ((age_to k) oo maps) (AMap.map (option_map (age_to k)) lset) end.  Lemma level_age_tp_to tp k : tp_level_is_above k tp -> tp_level_is k (age_tp_to k tp).  Lemma map_compose {A B C} (g : A -> B) (f : B -> C) l : map (f oo g) l = map f (map g l).  Lemma join_list_age_to k l Phi : le k (level Phi) -> join_list l Phi -> join_list (map (age_to k) l) (age_to k Phi).  Lemma join_list'_age_to k (l : list (option res)) (Phi : option res) : (match Phi with None => Logic.True | Some phi => le k (level phi) end) -> join_list' l Phi -> join_list' (map (option_map (age_to k)) l) (option_map (age_to k) Phi).  Lemma join_all_age_to k tp Phi : le k (level Phi) -> join_all tp Phi -> join_all (age_tp_to k tp) (age_to k Phi).  Lemma perm_of_age rm age loc : perm_of_res (age_to age rm @ loc) = perm_of_res (rm @ loc).  Lemma perm_of_age_lock rm age loc : perm_of_res_lock (age_to age rm @ loc) = perm_of_res_lock (rm @ loc).  Lemma almost_empty_perm: forall rm, res_predicates.almost_empty rm -> forall loc, Mem.perm_order'' (Some Nonempty) (perm_of_res (rm @ loc)).  Lemma cnt_age {js i age} : containsThread (age_tp_to age js) i -> containsThread js i.  Lemma cnt_age' {js i age} : containsThread js i -> containsThread (age_tp_to age js) i.  Lemma age_getThreadCode: forall i tp age cnt cnt', @getThreadC _ _ _ i tp cnt = @getThreadC _ _ _ i (age_tp_to age tp) cnt'.  Inductive juicy_step  {tid0 tp m} (cnt: containsThread tp tid0) (Hcompatible: mem_compatible tp m) : thread_pool -> mem -> list mem_event -> Prop := | step_juicy : forall (tp':thread_pool) c jm jm' m' (c' : C), forall (Hpersonal_perm: personal_mem (thread_mem_compatible Hcompatible cnt) = jm) (Hinv : invariant tp) (Hthread: getThreadC cnt = Krun c) (Hcorestep: corestep juicy_sem c jm c' jm') (Htp': tp' = @updThread _ _ _ tid0 (age_tp_to (level jm') tp) (cnt_age' cnt) (Krun c') (m_phi jm')) (Hm': m_dry jm' = m'), juicy_step  cnt Hcompatible tp' m' [::].  Definition pack_res_inv (R: pred rmap) := SomeP rmaps.Mpred (fun _ => R) .  Definition lock_at_least sh R phi b ofs := forall i, 0 <= i < LKSIZE -> exists sh' rsh', join_sub sh sh' /\ phi@(b,ofs+i) = YES sh' rsh' (LK LKSIZE i) (pack_res_inv R).   Notation Kblocked := (threadPool.Kblocked). Open Scope Z_scope. Inductive syncStep' {isCoarse: bool} {tid0 tp m} (cnt0:containsThread tp tid0)(Hcompat:mem_compatible tp m): thread_pool -> mem -> sync_event -> Prop := | step_acquire : forall (tp' tp'' tp''':thread_pool) c m0 m1 b ofs d_phi phi phi' m' pmap_tid', forall (Hinv : invariant tp) (Hthread: getThreadC cnt0 = Kblocked c) (Hat_external: at_external the_sem c m = Some (LOCK, Vptr b ofs::nil)) (Hcompatible: mem_compatible tp m) (*Hpersonal_perm: personal_mem cnt0 Hcompatible = jm*)
(Hpersonal_juice: getThreadR cnt0 = phi)
(sh:Share.t)(R:pred rmap)
(HJcanwrite: lock_at_least sh R phi b (Ptrofs.intval ofs))
(Hrestrict_map0: juicyRestrict_locks
(mem_compat_thread_max_cohere Hcompat cnt0) = m0)
(Hload: Mem.load Mint32 m0 b (Ptrofs.intval ofs) = Some (Vint Int.one))
(*Hrestrict_pmap: permissions.restrPermMap (mem_compatible_locks_ltwritable Hcompatible) = m1*)
(Hset_perm: setPermBlock (Some Writable)
b (Ptrofs.intval ofs) (juice2Perm_locks phi m) LKSIZE_nat = pmap_tid')
(Hlt': permMapLt pmap_tid' (getMaxPerm m))
(* This following condition is not needed: It should follow from the mem_compat statement... somehow... *)
(Hrestrict_pmap: restrPermMap Hlt' = m1)
(Hstore: Mem.store Mint32 m1 b (Ptrofs.intval ofs) (Vint Int.zero) = Some m')
(His_unlocked: lockRes tp (b, Ptrofs.intval ofs) = SSome d_phi )
(Hadd_lock_res: join phi d_phi phi')
(Htp': tp' = updThread cnt0 (Kresume c Vundef) phi')
(Htp'': tp'' = updLockSet tp' (b, Ptrofs.intval ofs) None )
(Htp''': tp''' = age_tp_to (level phi - 1)%coq_nat tp''),
syncStep' cnt0 Hcompat tp''' m' (acquire (b, Ptrofs.intval ofs) None)
| step_release :
forall  (tp' tp'' tp''':thread_pool) c m0 m1 b ofs  (phi d_phi :rmap) (R: pred rmap) phi' m' pmap_tid',
forall
(Hinv : invariant tp)
(Hthread: getThreadC cnt0 = Kblocked c)
(Hat_external: at_external the_sem c m =
Some (UNLOCK, Vptr b ofs::nil))
(Hcompatible: mem_compatible tp m)
(* Hpersonal_perm: personal_mem cnt0 Hcompatible = jm *)
(Hpersonal_juice: getThreadR cnt0 = phi)
(sh:Share.t)
(HJcanwrite: lock_at_least sh R phi b (Ptrofs.intval ofs))
(Hrestrict_map0: juicyRestrict_locks
(mem_compat_thread_max_cohere Hcompat cnt0) = m0)
(Hload: Mem.load Mint32 m0 b (Ptrofs.intval ofs) = Some (Vint Int.zero))
(*Hrestrict_pmap: permissions.restrPermMap (mem_compatible_locks_ltwritable Hcompatible) = m1*)
(Hset_perm: setPermBlock (Some Writable)
b (Ptrofs.intval ofs) (juice2Perm_locks phi m) LKSIZE_nat = pmap_tid')
(Hlt': permMapLt pmap_tid' (getMaxPerm m))
(* This following condition is not needed: It should follow from the mem_compat statement... somehow... *)
(Hrestrict_pmap: restrPermMap Hlt' = m1)
(Hstore: Mem.store Mint32 m1 b (Ptrofs.intval ofs) (Vint Int.one) = Some m')
(His_locked: lockRes tp (b, Ptrofs.intval ofs) = SNone )
(Hsat_lock_inv: R (age_by 1 d_phi))
(Hrem_lock_res: join d_phi phi' phi)
(Htp': tp' = updThread cnt0 (Kresume c Vundef) phi')
(Htp'': tp'' =
updLockSet tp' (b, Ptrofs.intval ofs) (Some d_phi))
(Htp''': tp''' = age_tp_to (level phi - 1)%coq_nat tp''),
syncStep' cnt0 Hcompat tp''' m' (release (b, Ptrofs.intval ofs) None)
| step_create :
forall  (tp_upd tp':thread_pool) c vf arg jm (d_phi phi': rmap) b ofs (* P Q *),
forall
(Hinv : invariant tp)
(Hthread: getThreadC cnt0 = Kblocked c)
(Hat_external: at_external the_sem c m =
Some (CREATE, vf::arg::nil))
(Harg: Val.inject (Mem.flat_inj (Mem.nextblock m)) arg arg)
(Hfun_sepc: vf = Vptr b ofs)
(Hcompatible: mem_compatible tp m)
(Hpersonal_perm:
personal_mem (thread_mem_compatible Hcompatible cnt0) = jm)
(Hrem_fun_res: join d_phi phi' (m_phi jm))
(Htp': tp_upd = updThread cnt0 (Kresume c Vundef) phi')
(Htp'': tp' = age_tp_to (level (m_phi jm) - 1)%coq_nat (addThread tp_upd vf arg d_phi)),
syncStep' cnt0 Hcompat tp' m (spawn (b, Ptrofs.intval ofs) None None)
| step_mklock :
forall  (tp' tp'': thread_pool)  jm c b ofs R ,
let: phi := m_phi jm in
forall
phi' m'
(Hinv : invariant tp)
(Hthread: getThreadC cnt0 = Kblocked c)
(Hat_external: at_external the_sem c m =
Some (MKLOCK, Vptr b ofs::nil))
(Hcompatible: mem_compatible tp m)
(*Hright_juice:  m = m_dry jm*)
(Hpersonal_perm:
personal_mem (thread_mem_compatible Hcompatible cnt0) = jm)
(Hpersonal_juice: getThreadR cnt0 = phi)
(*Check I have the right permission to mklock and the right value (i.e. 0) *)
(*Haccess: address_mapsto LKCHUNK (Vint Int.zero) sh Share.top (b, Ptrofs.intval ofs) phi*)
(Hstore:
Mem.store Mint32 (m_dry jm) b (Ptrofs.intval ofs) (Vint Int.zero) = Some m')
(* [Hrmap] replaced: [Hct], [Hlock], [Hj_forward] and [levphi']. This says that phi and phi' coincide everywhere except in adr_range, and specifies how phi and phi' should differ in adr_range (in particular, they have equal shares, pointwise) *)
(Hrmap : rmap_makelock phi phi' (b, Ptrofs.unsigned ofs) R LKSIZE)
(Htp': tp' = updThread cnt0 (Kresume c Vundef) phi')
(Htp'': tp'' = age_tp_to (level phi - 1)%coq_nat
(updLockSet tp' (b, Ptrofs.intval ofs) None )),
syncStep' cnt0 Hcompat tp'' m' (mklock (b, Ptrofs.intval ofs))
| step_freelock :
forall  (tp' tp'': thread_pool) c b ofs phi R phi',
forall
(Hinv : invariant tp)
(Hthread: getThreadC cnt0 = Kblocked c)
(Hat_external: at_external the_sem c m =
Some (FREE_LOCK, Vptr b ofs::nil))
(Hcompatible: mem_compatible tp m)
(Hpersonal_juice: getThreadR cnt0 = phi)
(*First check the lock is acquired:*)
(His_acq: lockRes tp (b, (Ptrofs.intval ofs)) = SNone)
(*Relation between rmaps:*)
(Hrmap : rmap_freelock phi phi' m (b, Ptrofs.unsigned ofs) R LKSIZE)
(Htp': tp' = updThread cnt0 (Kresume c Vundef) phi')
(Htp'': tp'' = age_tp_to (level phi - 1)%coq_nat
(remLockSet tp' (b, Ptrofs.intval ofs) )),
syncStep' cnt0 Hcompat  tp'' m (freelock (b, Ptrofs.intval ofs))
| step_acqfail :
forall  c b ofs jm m1,
let: phi := m_phi jm in
forall
(Hinv : invariant tp)
(Hthread: getThreadC cnt0 = Kblocked c)
(Hat_external: at_external the_sem c m =
Some (LOCK, Vptr b ofs::nil))
(Hcompatible: mem_compatible tp m)
(Hpersonal_perm:
personal_mem (thread_mem_compatible Hcompatible cnt0) = jm)
(Hrestrict_map: juicyRestrict_locks
(mem_compat_thread_max_cohere Hcompat cnt0) = m1)
(sh:Share.t) (R:pred rmap)
(HJcanwrite: lock_at_least sh R phi b (Ptrofs.intval ofs))
(Hload: Mem.load Mint32 m1 b (Ptrofs.intval ofs) = Some (Vint Int.zero)),
syncStep' cnt0 Hcompat tp m (failacq (b,Ptrofs.intval ofs)).
Definition threadStep : forall {tid0 ms m},
containsThread ms tid0 -> mem_compatible ms m ->
thread_pool -> mem -> list mem_event -> Prop:=
@juicy_step.

(* Specifications: *)
Lemma threadStep_at_Krun:
forall i tp m cnt cmpt tp' m' tr,
@threadStep i tp m cnt cmpt tp' m' tr ->
(exists q, @getThreadC _ _ _ i tp cnt = Krun q).
Lemma threadStep_equal_run:
forall i tp m cnt cmpt tp' m' tr,
@threadStep i tp m cnt cmpt tp' m' tr ->
forall j,
(exists cntj q, @getThreadC _ _ _ j tp cntj = Krun q) <->
(exists cntj' q', @getThreadC _ _ _ j tp' cntj' = Krun q').