Set Bullet Behavior "Strict Subproofs".
(* standard VST prelude *)
Instance CompSpecs : compspecs. make_compspecs prog. Defined.
Definition Vprog : varspecs. mk_varspecs prog. Defined.
(* import funspecs from concurrency library *)
Definition acquire_spec := DECLARE _acquire acquire_spec.
Definition release_spec := DECLARE _release release_spec.
(* encoding a lock invariant in terms of an atomic exchange invariant *)
Definition lock_R R (h : list AE_hist_el) v := EX z : Z, !!(repable_signed z /\ v = vint z) &&
(weak_precise_mpred R && emp) * (weak_positive_mpred R && emp) * if eq_dec z 0 then R else emp.
Definition my_lock sh l p g R := EX h : hist, AE_loc sh l p g (vint 1) (lock_R R) h.
Notation "'TYPE' A 'WITH'  x1 : t1 , x2 : t2 , x3 : t3 , x4 : t4 , x5 : t5 'PRE'  [ u , .. , v ] P 'POST' [ tz ] Q" :=
(mk_funspec ((cons u%formals .. (cons v%formals nil) ..), tz) cc_default A
(fun (ts: list Type) (x: t1*t2*t3*t4*t5) =>
match x with (x1,x2,x3,x4,x5) => P%assert end)
(fun (ts: list Type) (x: t1*t2*t3*t4*t5) =>
match x with (x1,x2,x3,x4,x5) => Q%assert end) _ _)
(at level 200, x1 at level 0, x2 at level 0, x3 at level 0, x4 at level 0, x5 at level 0,
P at level 100, Q at level 100).
Definition lock_sig := (ProdType (ConstType (share * val * val * val)) Mpred).
(* funspecs for acquire and release *)
Program Definition my_acquire_spec :=
DECLARE _my_acquire TYPE lock_sig
WITH sh : share, l : val, p : val, g : val, R : mpred
PRE [ _l OF tptr tint, _ll OF tptr (Tstruct _lock_t noattr) ]
PROP (readable_share sh)
LOCAL (temp _l p; temp _ll l)
SEP (my_lock sh l p g R)
POST [ tvoid ]
PROP ()
LOCAL ()
SEP (my_lock sh l p g R; R).
Next Obligation.
Next Obligation.
Program Definition my_release_spec :=
DECLARE _my_release TYPE lock_sig
WITH sh : share, l : val, p : val, g : val, R : mpred
PRE [ _l OF tptr tint, _ll OF tptr (Tstruct _lock_t noattr) ]
PROP (readable_share sh)
LOCAL (temp _l p; temp _ll l)
SEP (my_lock sh l p g R; R)
POST [ tvoid ]
PROP ()
LOCAL ()
SEP (my_lock sh l p g R).
Next Obligation.
Next Obligation.
Definition Gprog : funspecs := ltac:(with_library prog [acquire_spec; release_spec; atomic_exchange_spec;
my_acquire_spec; my_release_spec]).
(* proofs of correctnes of the lock functions *)

Lemma body_my_release : semax_body Vprog Gprog f_my_release my_release_spec.