Set Bullet Behavior "Strict Subproofs".
(* standard VST prelude *)
Instance CompSpecs : compspecs. make_compspecs prog. Defined.
Instance CompSpecs_Preserve: change_composite_env verif_atomic_exchange.CompSpecs CompSpecs.
make_cs_preserve verif_atomic_exchange.CompSpecs CompSpecs.
Defined.
Definition Vprog : varspecs. mk_varspecs prog. Defined.
(* import funspecs from concurrency library *)
Definition release_spec := DECLARE _release release_spec.
Definition makelock_spec := DECLARE _makelock (makelock_spec _).
Definition spawn_spec := DECLARE _spawn spawn_spec.
(* utility function specs *)
Definition surely_malloc_spec :=
DECLARE _surely_malloc
WITH t:type, gv: globals
PRE [ _n OF tuint ]
PROP (0 <= sizeof t <= Int.max_unsigned;
complete_legal_cosu_type t = true;
natural_aligned natural_alignment t = true)
LOCAL (temp _n (Vint (Int.repr (sizeof t))); gvars gv)
SEP (mem_mgr gv)
POST [ tptr tvoid ] EX p:_,
PROP ()
LOCAL (temp ret_temp p)
SEP (mem_mgr gv; malloc_token Ews t p * data_at_ Ews t p).
Definition memset_spec :=
DECLARE _memset
WITH sh : share, t : type, p : val, c : Z, n : Z
PRE [ _s OF tptr tvoid, _c OF tint, _n OF tuint ]
PROP (writable_share sh; sizeof t = (4 * n)%Z; align_compatible tint p)
LOCAL (temp _s p; temp _c (vint c); temp _n (vint (4 * n)%Z))
SEP (data_at_ sh t p)
POST [ tptr tvoid ]
PROP ()
LOCAL (temp ret_temp p)
SEP (data_at sh (tarray tint n) (repeat (vint c) (Z.to_nat n)) p).
Definition N := 3.
Definition B := N + 2.
Definition tbuffer := Tstruct _buffer noattr.
Definition Empty := vint (-1).
(* operations on histories *)
Fixpoint find_read h d :=
match h with
| [] => (d, [])
| AE r w :: rest => if eq_dec w Empty then if eq_dec r Empty then find_read rest d
else (r, rest) else find_read rest d
end.
Definition last_two_reads h := let '(b1, rest) := find_read h (vint 1) in (b1, fst (find_read rest (vint 1))).
Fixpoint find_write h d :=
match h with
| [] => (d, [])
| AE r w :: rest => if eq_dec w Empty then find_write rest d else (w, rest)
end.
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)).
(* This is the invariant for the location buffers comm[N]. *)
(* The ghost variables are the last value read, the last value written, and the last value read before the last write (i.e., last_taken). The first is updated by the reader, the rest by the writer. *)
Definition comm_R bufs sh gsh g0 g1 g2 h v := EX b : Z, EX b1 : Z, EX b2 : Z,
!!(v = vint b /\ -1 <= b < B /\
Forall (fun a => match a with AE v1 v2 =>
exists r w, v1 = vint r /\ v2 = vint w /\ -1 <= r < B /\ -1 <= w < B end) h /\
last_two_reads (rev h) = (vint b1, vint b2) /\ repable_signed b1 /\ repable_signed b2) &&
ghost_var gsh (vint b1) g0 * ghost_var gsh (last_write (rev h)) g1 *
ghost_var gsh (prev_taken (rev h)) g2 *
if eq_dec b (-1) then EX v : Z, data_at sh tbuffer (vint v) (Znth b2 bufs)
else EX v : Z, data_at sh tbuffer (vint v) (Znth b bufs).
Definition comm_loc lsh lock comm g g0 g1 g2 bufs sh gsh :=
AE_loc lsh lock comm g (vint 0) (comm_R bufs sh gsh g0 g1 g2).
Definition Ish := Share.comp Ews.

Lemma Ews_Ish_join : sepalg.join Ews Ish Tsh.