Definition int_op e :=
match e with
| Load v | Store v => tc_val tint v
| CAS r c w => tc_val tint r /\ tc_val tint c /\ tc_val tint w
end.
(* Once set, a key is never reset. *)
Definition k_R (h : list hist_el) (v : val) := !!(Forall int_op h /\
forall e, In e h -> value_of e <> vint 0 -> v = value_of e) && emp.
Definition v_R (h : list hist_el) (v : val) := emp.
Definition atomic_entry sh p := !!(field_compatible tentry [] p) && EX lkey : val, EX lval : val,
field_at sh tentry [StructField _lkey] lkey p *
atomic_loc sh lkey (field_address tentry [StructField _key] p) (vint 0) Tsh k_R *
field_at sh tentry [StructField _lvalue] lval p *
atomic_loc sh lval (field_address tentry [StructField _value] p) (vint 0) Tsh v_R.
(* Can we comprehend the per-entry histories into a broader history? *)
Definition failed_CAS k (a b : hist * hist) := exists t r, Forall (fun x => fst x < t)%nat (fst a) /\
fst b = fst a ++ [(t, CAS (Vint r) (vint 0) (vint k))] /\
r <> Int.zero /\ r <> Int.repr k /\ snd b = snd a /\
(let v := value_of_hist (fst a) in v <> vint 0 -> v = Vint r).
Definition wf_hists h l := Forall (fun x => ordered_hist (fst x) /\ ordered_hist (snd x) /\
Forall int_op (map snd (fst x)) /\ Forall int_op (map snd (snd x))) h /\ 0 <= l <= Zlength h /\
Forall (fun x => value_of_hist (fst x) <> vint 0) (sublist 0 l h) /\
Forall (fun x => value_of_hist (fst x) = vint 0) (sublist l (Zlength h) h).
Definition make_int v := match v with Vint i => Int.signed i | _ => 0 end.

Lemma make_map_nil : forall h, Forall (fun x => value_of_hist (fst x) = vint 0) h -> make_map h = [].
Definition set_item_trace (h : list (hist * hist)) k v i h' := 0 <= i < Zlength h /\
Forall2 (failed_CAS k) (sublist 0 i h) (sublist 0 i h') /\
(let '(hk, hv) := Znth i h ([], []) in exists t r tv, Forall (fun x => fst x < t)%nat hk /\
Forall (fun x => fst x < tv)%nat hv /\
Znth i h' ([], []) = (hk ++ [(t, CAS r (vint 0) (vint k))], hv ++ [(tv, Store (vint v))]) /\
(r = vint 0 \/ r = vint k) /\ (let v := value_of_hist hk in v <> vint 0 -> v = r)) /\
sublist (i + 1) (Zlength h) h = sublist (i + 1) (Zlength h') h'.