(*(* Steps to linearizability: A single thread sees a sequence of reads and writes. The join of a collection of sequences of reads and writes, if consistent, is equivalent to a sequence of reads and writes. *)
Fixpoint do_op h1 op h2 :=
match op with
| Read v vals => Z.testbit v 0 = false /\ exists failvs, Forall repable_signed failvs /\
add_events (fst h1) (make_loads (failvs ++ [v; v])) (fst h2) /\ exists loops,
forall i, 0 <= i < 8 -> exists fails, Zlength fails = loops /\
add_events (Znth i (snd h1) []) (make_loads (fails ++ [Znth i vals 0])) (Znth i (snd h2) [])
| Write v vals =>
add_events (fst h1) [Load (vint v); Store (vint (Z.lor v 1)); Store (vint (v + 2))] (fst h2) /\
forall i, 0 <= i < 8 -> add_events (Znth i (snd h1) []) [Store (vint (Znth i vals 0))] (Znth i (snd h2) [])
end.
Inductive do_ops h : list lin_op -> hist * list hist -> Prop :=
| do_ops_nil : do_ops h [] h
| do_ops_cons : forall a la h' h'' (Hh' : do_op h a h') (Hh'' : do_ops h' la h''), do_ops h (a :: la) h''.

(* For now, we're relying on there being only one writer. *)
Lemma full_hist_writes : forall w lr v (Hv : full_hist' (concat (w :: lr)) v) (Hw : NoDup (map fst w))
(Hr : Forall (fun h => exists lv, map snd h = make_loads lv) lr), full_hist' w v.