Instance CompSpecs : compspecs. make_compspecs prog. Defined.
Definition Vprog : varspecs. mk_varspecs prog. Defined.
Definition acquire_spec := DECLARE _acquire acquire_spec.
Definition release_spec := DECLARE _release release_spec.
Definition makelock_spec := DECLARE _makelock (makelock_spec _).
Definition freelock_spec := DECLARE _freelock (freelock_spec _).
Definition spawn_spec := DECLARE _spawn spawn_spec.
Definition freelock2_spec := DECLARE _freelock2 (freelock2_spec _).
Definition release2_spec := DECLARE _release2 release2_spec.
Notation sum := (fold_right Z.add 0).
Definition cptr_lock_inv lg ctr := EX z : Z, data_at Ews tuint (Vint (Int.repr z)) ctr *
EX lv : list Z, !!(z = sum lv) && iter_sepcon2 (fun g v => ghost_var gsh1 v g) lg lv.
Definition init_ctr_spec :=
DECLARE _init_ctr
WITH N : Z, gv: globals
PRE [ ]
PROP  (0 <= N)
LOCAL (gvars gv)
SEP   (data_at_ Ews tuint (gv _ctr); data_at_ Ews tlock (gv _ctr_lock))
POST [ tvoid ]
EX lg : list gname,
PROP (Zlength lg = N)
LOCAL ()
SEP (lock_inv Ews (gv _ctr_lock) (cptr_lock_inv lg (gv _ctr));
iter_sepcon (ghost_var gsh2 0) lg).
Definition dest_ctr_spec :=
DECLARE _dest_ctr
WITH lg : list gname, lv : list Z, gv: globals
PRE [ ]
PROP  ()
LOCAL (gvars gv)
SEP   (lock_inv Ews (gv _ctr_lock) (cptr_lock_inv lg (gv _ctr));
iter_sepcon2 (fun g v => ghost_var gsh2 v g) lg lv)
POST [ tvoid ]
PROP ()
LOCAL ()
SEP (data_at Ews tuint (vint (sum lv)) (gv _ctr);
data_at_ Ews tlock (gv _ctr_lock)).
Definition incr_spec :=
DECLARE _incr
WITH sh : share, lg : list gname, i : Z, n : Z, gv: globals
PRE [ ]
PROP  (readable_share sh; 0 <= i < Zlength lg)
LOCAL (gvars gv)
SEP   (lock_inv sh (gv _ctr_lock) (cptr_lock_inv lg (gv _ctr)); ghost_var gsh2 n (Znth i lg))
POST [ tvoid ]
PROP ()
LOCAL ()
SEP (lock_inv sh (gv _ctr_lock) (cptr_lock_inv lg (gv _ctr)); ghost_var gsh2 (n+1) (Znth i lg)).
Definition thread_lock_R sh lg i ctr lockc :=
lock_inv sh lockc (cptr_lock_inv lg ctr) * ghost_var gsh2 1 (Znth i lg).
Definition thread_lock_inv tsh sh lg i ctr lockc lockt :=
selflock (thread_lock_R sh lg i ctr lockc) tsh lockt.
Definition thread_func_spec :=
DECLARE _thread_func
WITH y : val, x : share * share * list gname * Z * val * globals
PRE [ _args OF (tptr tvoid) ]
let '(tsh, sh, lg, i, l, gv) := x in
PROP  (readable_share tsh; readable_share sh; 0 <= i < Zlength lg)
LOCAL (temp _args y; gvars gv)
SEP   (lock_inv sh (gv _ctr_lock) (cptr_lock_inv lg (gv _ctr));
ghost_var gsh2 0 (Znth i lg);
lock_inv tsh y (thread_lock_inv tsh sh lg i (gv _ctr) (gv _ctr_lock) y))
POST [ tptr tvoid ]
PROP ()
LOCAL ()
SEP ().
Definition main_spec :=
DECLARE _main
WITH gv : globals
PRE  [] main_pre prog tt nil gv
POST [ tint ] main_post prog nil gv.
Definition Gprog : funspecs := ltac:(with_library prog [acquire_spec; release_spec; release2_spec; makelock_spec;
freelock_spec; freelock2_spec; spawn_spec; init_ctr_spec; dest_ctr_spec; incr_spec; thread_func_spec; main_spec]).
Hint Resolve ctr_inv_exclusive.
Hint Resolve thread_inv_exclusive.

Lemma upd_Znth_sum: forall l i n, 0 <= i < Zlength l ->
sum (upd_Znth i l n) = sum l + n - Znth i l.