(* standard VST prelude *)
Instance CompSpecs : compspecs.Definition Vprog : varspecs.(* import funspecs from concurrency library *)
Definition spawn_spec := DECLARE _spawn spawn_spec.Definition load_SC_spec := DECLARE _load_SC load_SC_spec.Definition store_SC_spec := DECLARE _store_SC store_SC_spec.Definition AEX_SC_spec := DECLARE _atomic_exchange_SC AEX_SC_spec.Definition N := 3.Definition B := N + 2.Definition tbuffer := Tstruct _buffer noattr.Definition Empty := vint (-1).Definition last_two_reads h := let '(b1, rest) := find_read h (vint 1) in (b1, fst (find_read rest (vint 1))).Definition prev_taken h := fst (find_read (snd (find_write h (vint 0))) (vint 1)).Definition last_write h := fst (find_write h (vint 0)).(* The ghost_hist assertion is held by the thread, while the resource invariant is part of the
   global invariant. *)
(* The share ownership here is purely "defensive", modeling the fact that no one will write to a
   data buffer that is held by a good reader. *)

Notation hist := (list (nat * AE_hist_el)).Definition comm_loc good lsh comm g g0 g1 g2 bufs sh gsh h :=
  invariant (comm_inv good comm bufs sh g g0 g1 g2 gsh) * ghost_hist lsh (h : hist) g.Definition latest_read (h : hist) v :=
  (* initial condition *)
  (Forall (fun x => let '(_, AE r w) := x in w = Empty ->
    match r with Vint i => Int.signed i < 0 \/ Int.signed i >= B | _ => True end) h /\ v = 1) \/
  0 <= v < B /\ exists n, In (n, AE (vint v) Empty) h /\
  Forall (fun x => let '(m, AE r w) := x in w = Empty -> forall v', r = vint v' -> 0 <= v' < B ->
    (m <= n)%nat) h.

Lemma last_two_reads_cons : forall r w h, last_two_reads (AE r w :: h) = if eq_dec w Empty then if eq_dec r Empty then last_two_reads h else (r, fst (last_two_reads h)) else last_two_reads h.