(* 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.

(* Specifications: *)
Lemma Empty_inj : forall i, vint i = Empty -> repable_signed i -> i = -1.
Lemma repable_buf : forall a, -1 <= a < B -> repable_signed a.
Lemma list_join_minus : forall l (sh : share) shs sh1 sh2 (Hl : Zlength l = Zlength shs) (Hall : sepalg_list.list_join sh shs sh1) (Hsome : sepalg_list.list_join sh (map snd (filter fst (combine l shs))) sh2), sepalg_list.list_join sh2 (map snd (filter (fun '(b, _) => negb b) (combine l shs))) sh1.
Lemma fold_right_emp : forall l (Hemp : Forall (eq emp) l), fold_right sepcon emp l = emp.
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.
Lemma prev_taken_cons : forall r w h, prev_taken (AE r w :: h) = if eq_dec w Empty then prev_taken h else fst (find_read h (vint 1)).
Lemma find_read_pos : forall d h, d <> Empty -> fst (find_read h d) <> Empty.