Up to index of Isabelle/HOL/JinjaThreads
theory FWProgress(* Title: JinjaThreads/Framework/FWProgress.thy Author: Andreas Lochbihler *) header {* \isaheader{Progress theorem for the multithreaded semantics} *} theory FWProgress imports FWDeadlock FWWellformSem begin locale preserve_deadlocked = final_thread_wf + preserve_lock_behav begin lemma redT_deadlocked_subset: assumes Red': "start_state -\<triangleright>ttas->* s" and Red: "s -t\<triangleright>ta-> s'" and t'dead: "deadlocked s t'" shows "deadlocked s' t'" proof - from Red have tndead: "¬ deadlocked s t" by(auto dest: red_no_deadlock) with t'dead have t't: "t' ≠ t" by auto obtain las tas cas was obs where ta: "ta = (las, tas, cas, was, obs)" by (cases ta) obtain ls ts m ws where s [simp]: "s = (ls, (ts, m), ws)" by (cases s, auto) obtain ls' ts' m' ws' where s' [simp]: "s' = (ls', (ts', m'), ws')" by (cases s', auto) with s Red have "〈ls, (ts, m), ws〉 -t\<triangleright>ta-> 〈ls', (ts', m'), ws'〉" by simp thus "deadlocked s' t'" proof(cases rule: redT_elims4) case (normal x x' ta') with ta s s' Red have red: "〈x, m〉 -ta'-> 〈x', m'〉" and est: "ts t = ⌊(x, no_wait_locks)⌋" and lot: "lock_ok_las ls t las" and cct: "thread_oks ts tas" and cdt: "cond_action_oks (ls, (ts, m), ws) t cas" and wst: "ws t = None" and ws': "ws' = redT_updWs ws t was" and es': "ts' = redT_updTs ts \<lbrace>ta\<rbrace>t(t \<mapsto> (x', redT_updLns ls t no_wait_locks \<lbrace>ta\<rbrace>l))" and ls': "ls' = redT_updLs ls t las" and [simp]: "ta = observable_ta_of ta'" by auto from red have "¬ final x" by(auto dest: final_no_red) with tndead est s est wst have nafe: "¬ all_final_except s (deadlocked s)" by(fastsimp simp add: all_final_except_def not_final_thread_iff) from t'dead show ?thesis proof(coinduct) case (deadlocked t'') note t''dead = this with Red have t''t: "t'' ≠ t" by(auto dest: red_no_deadlock) from t''dead show ?case proof(cases rule: deadlocked_elims) case (lock X) hence est'': "ts t'' = ⌊(X, no_wait_locks)⌋" and msE: "〈X, m〉 \<wrong>" and csexdead: "∀LT. 〈X, m〉 LT \<wrong> --> (∃t'. (deadlocked s t' ∨ final_thread s t') ∧ (∃lt ∈ LT. must_wait s t'' lt t'))" by auto from t''t Red est'' s s' have es't'': "ts' t'' = ⌊(X, no_wait_locks)⌋" by(auto elim!: redT_ts_Some_inv) note es't'' moreover from msE obtain X' M' ta where red': "〈X, m〉 -ta-> 〈X', M'〉" by(auto elim: must_syncE) let ?LT = "collect_locks \<lbrace>ta\<rbrace>l <+> {t. Join t ∈ set \<lbrace>ta\<rbrace>c}" from red' have csLT: "〈X, m〉 ?LT \<wrong>" by(auto intro: can_syncI) with csexdead[rule_format] have "?LT ≠ {}" by auto with est'' csLT have msE': "〈X, m'〉 \<wrong>" by(rule can_lock_preserved[OF Red' Red, simplified]) moreover { fix LT assume clL'': "〈X, m'〉 LT \<wrong>" with clL'' est'' have "∃LT'⊆LT. 〈X, m〉 LT' \<wrong>" by - (rule can_lock_devreserp[OF Red' Red, simplified shr_conv s], auto) then obtain LT' where clL': "〈X, m〉 LT' \<wrong>" and LL': "LT' ⊆ LT" by blast with csexdead obtain t' lt where t'dead: "deadlocked s t' ∨ final_thread s t'" and lt: "lt ∈ LT" and mw: "must_wait s t'' lt t'" by blast from t'dead Red s have tt': "t ≠ t'" by(auto dest: red_no_deadlock final_no_redT elim: final_threadE) from mw have "must_wait s' t'' lt t'" proof(induct rule: must_wait_elims) case (lock l) from lot have "lock_actions_ok (lsf l) t (lasf l)" by(simp add: lock_ok_las_def) with tt' ls' `has_lock ((locks s)f l) t'` have hl't': "has_lock (ls'f l) t'" by(auto) with `lt = Inl l` `t' ≠ t''` show ?thesis by auto next case thread note nftt' = `not_final_thread s t'` from tt' t'dead Red cct es' ta have ts't': "ts' t' = ts t'" by(auto elim!: deadlocked_thread_exists final_threadE intro: redT_updTs_Some simp add: observable_ta_of_def) from nftt' have "thr s t' ≠ None" by(auto) with nftt' t'dead have "deadlocked s t'" by(simp add: not_final_thread_final_thread_conv[symmetric]) hence "not_final_thread s' t'" proof(induct rule: deadlocked_elims) case (lock x'') from `〈x'', shr s〉 \<wrong>` have "¬ final x''" by(auto elim: must_syncE) with `thr s t' = ⌊(x'', no_wait_locks)⌋` ts't' show ?thesis by(auto intro: not_final_thread.intros) next case (wait x'' ln'' w'') from `¬ final x` est `all_final_except s (deadlocked s)` wst have "deadlocked s t" by(fastsimp dest: all_final_exceptD simp add: not_final_thread_iff) with Red have False by(auto dest: red_no_deadlock) thus ?thesis .. next case (acquire x'' ln'' l'' T'') from `thr s t' = ⌊(x'', ln'')⌋` `0 < ln''f l''` ts't' show ?thesis by(auto intro: not_final_thread.intros) qed with `lt = Inr t'` show ?thesis by auto qed moreover { assume "final_thread s t'" from t'dead have "thr s t' ≠ None" by(auto elim: deadlocked_elims final_threadE) then obtain x' ln' where tst': "thr s t' = ⌊(x', ln')⌋" by auto with `final_thread s t'` have "final x'" and "wset s t' = None" and [simp]: "ln' = no_wait_locks" by(auto elim: final_threadE) with red have "x ≠ x'" by(auto dest: final_no_red) with est tst' have "t ≠ t'" by auto with Red cct es' tst' ta have "thr s' t' = ⌊(x', ln')⌋" by(auto intro: redT_updTs_Some simp add: observable_ta_of_def) moreover from Red ws' `t ≠ t'` `wset s t' = None` have "ws' t' = None" by(auto simp: redT_updWs_None_implies_None) ultimately have "final_thread s' t'" using tst' `final x'` by(auto simp add: final_thread_def) } ultimately have "((deadlocked s t' ∨ deadlocked s' t') ∨ final_thread s' t') ∧ (∃lt ∈ LT. must_wait s' t'' lt t')" using t'dead `lt ∈ LT` by blast hence "∃t'. ((deadlocked s t' ∨ deadlocked s' t') ∨ final_thread s' t') ∧ (∃lt ∈ LT. must_wait s' t'' lt t')" by blast } moreover have "ws' t'' = None" using ws' t''t `wset s t'' = None` by(auto intro: redT_updWs_None_implies_None) ultimately show ?thesis by(auto) next case (wait x ln w) from `all_final_except s (deadlocked s)` nafe have False by simp thus ?thesis by simp next case (acquire X ln l T) from t''t Red `thr s t'' = ⌊(X, ln)⌋` s s' have es't'': "ts' t'' = ⌊(X, ln)⌋" by(auto elim!: redT_ts_Some_inv) moreover from `deadlocked s T ∨ final_thread s T` have "T ≠ t" proof(rule disjE) assume "deadlocked s T" with Red show ?thesis by(auto dest: red_no_deadlock) next assume "final_thread s T" with Red show ?thesis by(auto dest!: final_no_redT simp add: final_thread_def) qed with Red `has_lock ((locks s)f l) T` have "has_lock ((locks s')f l) T" by(simp add: redT_has_lock_inv) moreover from ws' `T ≠ t` have wset: "ws T = None ==> ws' T = None" by(auto intro: redT_updWs_None_implies_None) { fix x assume "thr s T = ⌊(x, no_wait_locks)⌋" with `T ≠ t` Red es' cct est ta have "thr s' T = ⌊(x, no_wait_locks)⌋" by(auto intro: redT_updTs_Some simp add: observable_ta_of_def) } moreover hence "final_thread s T ==> final_thread s' T" by(auto simp add: final_thread_def intro: wset) ultimately show ?thesis using `0 < lnf l` `t'' ≠ T` `deadlocked s T ∨ final_thread s T` apply - apply(rule disjI2) apply(rule disjI2) apply(auto) done qed qed next case (acquire x ln n) note [simp] = `ta = (λf [], [], [], [], ReacquireLocks ln)` `ws' = ws` `m' = m` note ts' = `ts' = ts(t \<mapsto> (x, no_wait_locks))` note ls' = `ls' = acquire_all ls t ln` note tst = `ts t = ⌊(x, ln)⌋` from t'dead show ?thesis proof(coinduct) case (deadlocked t'') note t''dead = this with Red have t''t: "t'' ≠ t" by(auto dest: red_no_deadlock) from t''dead show ?case proof(cases rule: deadlocked_elims) case (lock X) hence clnml: "!!LT. 〈X, shr s〉 LT \<wrong> ==> ∃t'. (deadlocked s t' ∨ final_thread s t') ∧ (∃lt ∈ LT. must_wait s t'' lt t')" by blast note tst'' = `thr s t'' = ⌊(X, no_wait_locks)⌋` with ts' t''t have ts't'': "thr s' t'' = ⌊(X, no_wait_locks)⌋" by simp moreover { fix LT assume "〈X, shr s'〉 LT \<wrong>" hence "〈X, shr s〉 LT \<wrong>" by simp then obtain T lt where Tdead: "deadlocked s T ∨ final_thread s T" and "lt ∈ LT" and hlnft: "must_wait s t'' lt T" by(blast dest: clnml) from Tdead tst ts' have "deadlocked s T ∨ final_thread s' T" by(clarsimp simp add: final_thread_def) hence "(deadlocked s T ∨ deadlocked s' T) ∨ final_thread s' T" by blast moreover from hlnft have "must_wait s' t'' lt T" proof(induct rule: must_wait_elims) case (lock l') from `has_lock ((locks s)f l') T` ls' have "has_lock ((locks s')f l') T" by(auto intro: has_lock_has_lock_acquire_locks) with `T ≠ t''` `lt = Inl l'` show ?thesis by auto next case thread from Tdead have "ts T ≠ None" by(auto elim: deadlocked_elims final_threadE) moreover from Tdead have "T ≠ t" proof(rule disjE) assume "deadlocked s T" with Red show ?thesis by(auto dest: red_no_deadlock) next assume "final_thread s T" with `0 < lnf n` tst show ?thesis by(auto simp add: final_thread_def) qed ultimately have "not_final_thread s' T" using `not_final_thread s T` ts' by(auto simp add: not_final_thread_iff) with `lt = Inr T` show ?thesis by auto qed ultimately have "∃T. ((deadlocked s T ∨ deadlocked s' T) ∨ final_thread s' T) ∧ (∃lt ∈ LT. must_wait s' t'' lt T)" using `lt ∈ LT` by blast } moreover from `wset s t'' = None` have "wset s' t'' = None" by simp ultimately show ?thesis using `thr s t'' = ⌊(X, no_wait_locks)⌋` `〈X, shr s〉 \<wrong>` by fastsimp next case (wait X LN w) from `wset s t'' = ⌊w⌋` `ws t = None` have "t'' ≠ t" by auto have "all_final_except (ls', (ts(t \<mapsto> (x, no_wait_locks)), m), ws) (deadlocked s)" proof(rule all_final_exceptI) fix T assume "not_final_thread (ls', (ts(t \<mapsto> (x, no_wait_locks)), m), ws) T" hence "not_final_thread s T" using `ws t = None` `ts t = ⌊(x, ln)⌋` by(auto simp add: not_final_thread_iff split: split_if_asm) with `all_final_except s (deadlocked s)` `ts t = ⌊(x, ln)⌋` show "deadlocked s T" by -(erule all_final_exceptD) qed hence "all_final_except s' (deadlocked s)" by(simp add: ts') have "all_final_except s' (λx. deadlocked s x ∨ deadlocked s' x)" by(blast intro: all_final_except_mono[rule_format, OF _ `all_final_except s' (deadlocked s)`]) with t''t `thr s t'' = ⌊(X, LN)⌋` `wset s t'' = ⌊w⌋` ts' show ?thesis by-(rule disjI2, rule disjI1, simp) next case (acquire X LN l T) from `thr s t'' = ⌊(X, LN)⌋` t''t ts' have "thr s' t'' = ⌊(X, LN)⌋" by(simp) moreover from `deadlocked s T ∨ final_thread s T` ts' tst have "deadlocked s T ∨ final_thread s' T" by(clarsimp simp add: final_thread_def) moreover from `has_lock ((locks s)f l) T` ls' have "has_lock ((locks s')f l) T" by(auto intro: has_lock_has_lock_acquire_locks) ultimately show ?thesis using `0 < LNf l` `t'' ≠ T` by blast qed qed qed qed lemma RedT_deadlocked_subset: "[| start_state -\<triangleright>tta->* s; deadlocked start_state t' |] ==> deadlocked s t'" apply(induct rule: RedT_induct') apply(assumption) by(insert can_lock_preserved can_lock_devreserp)(rule redT_deadlocked_subset) end locale progress = final_thread_wf final r + wf_progress final r start_state + wf_red final r start_state for final :: "'x => bool" and r :: "('l,'t,'x,'m,'w,'o) semantics" and start_state :: "('l,'t,'x,'m,'w) state" + fixes deadlock :: "('l,'t,'x,'m,'w) state => bool" assumes waiting_deadlock: "[| start_state -\<triangleright>ttas->* s; not_final_thread s t; !!t x LT. [| thr s t = ⌊(x, no_wait_locks)⌋; ¬ final x; wset s t = None; 〈x, shr s〉 LT \<wrong> |] ==> ∃t'. ∃lt ∈ LT. must_wait s t lt t'; !!t x ln l. [| thr s t = ⌊(x, ln)⌋; wset s t = None; lnf l > 0 |] ==> ∃l'. lnf l' > 0 ∧ ¬ may_lock ((locks s)f l') t |] ==> deadlock s" begin lemma redT_progress: assumes Red: "start_state -\<triangleright>ttas->* s" assumes nfine: "not_final_thread s t" and ndead: "¬ deadlock s" shows "∃t' ta' s'. s -t'\<triangleright>ta'-> s'" proof - from ndead have "∃t x ln l. thr s t = ⌊(x, ln)⌋ ∧ wset s t = None ∧ (ln = no_wait_locks ∧ ¬ final x ∧ (∃LT. 〈x, shr s〉 LT \<wrong> ∧ (∀t'. ∀lt ∈ LT. ¬ must_wait s t lt t')) ∨ lnf l > 0 ∧ (∀l. lnf l > 0 --> may_lock ((locks s)f l) t))" apply - apply(erule contrapos_np) apply(rule waiting_deadlock[OF Red nfine]) by(blast)+ then obtain t x ln l where "thr s t = ⌊(x, ln)⌋" and "wset s t = None" and a: "(ln = no_wait_locks ∧ ¬ final x ∧ (∃LT. 〈x, shr s〉 LT \<wrong> ∧ (∀t'. ∀lt ∈ LT. ¬ must_wait s t lt t')) ∨ lnf l > 0 ∧ (∀l. lnf l > 0 --> may_lock ((locks s)f l) t))" by blast obtain ls ts m ws where s [simp]: "s = (ls, (ts, m), ws)" by (cases s, auto) note conform = wf_red[OF Red, simplified] from `thr s t = ⌊(x, ln)⌋` have tst: "ts t = ⌊(x, ln)⌋" by simp from s a have a: "(ln = no_wait_locks ∧ ¬ final x ∧ (∃LT. 〈x, m〉 LT \<wrong> ∧ (∀t'. ∀lt ∈ LT. ¬ must_wait s t lt t')) ∨ lnf l > 0 ∧ (∀l. lnf l > 0 --> may_lock (lsf l) t))" by simp thus ?thesis proof(rule disjE) assume "ln = no_wait_locks ∧ ¬ final x ∧ (∃LT. 〈x, m〉 LT \<wrong> ∧ (∀t'. ∀lt∈LT. ¬ must_wait s t lt t'))" then obtain LT where [simp]: "ln = no_wait_locks" and nfine': "¬ final x" and cl': "〈x, m〉 LT \<wrong>" and mw: "!!t' lt. lt∈LT ==> ¬ must_wait s t lt t'" by blast from `thr s t = ⌊(x, ln)⌋` nfine' obtain x'' m'' ta' where red: "〈x, m〉 -ta'-> 〈x'', m''〉" by(auto intro: wf_progressE[OF Red]) from cl' have "∃ta''' x''' m'''. 〈x, m〉 -ta'''-> 〈x''', m'''〉 ∧ LT = collect_locks \<lbrace>ta'''\<rbrace>l <+> {t. Join t ∈ set \<lbrace>ta'''\<rbrace>c}" by (fastsimp elim!: can_syncE) then obtain ta''' x''' m''' where red'': "〈x, m〉 -ta'''-> 〈x''', m'''〉" and L: "LT = collect_locks \<lbrace>ta'''\<rbrace>l <+> {t. Join t ∈ set \<lbrace>ta'''\<rbrace>c}" by blast from tst[simplified] red'' obtain ta'' x'' m'' where red': "〈x, m〉 -ta''-> 〈x'', m''〉" and cct: "thread_oks ts \<lbrace>ta''\<rbrace>t" and lot: "lock_ok_las' ls t \<lbrace>ta''\<rbrace>l" and collect: "collect_locks' \<lbrace>ta''\<rbrace>l ⊆ collect_locks \<lbrace>ta'''\<rbrace>l" and cao: "cond_action_oks' (ls, (ts, m), ws) t \<lbrace>ta'''\<rbrace>c" and join: "collect_cond_actions \<lbrace>ta''\<rbrace>c ⊆ collect_cond_actions \<lbrace>ta'''\<rbrace>c" by -(rule wf_redE[OF Red], auto) { fix l assume "Inl l ∈ LT" hence "∀t'. ¬ must_wait s t (Inl l) t'" by-(rule allI mw)+ hence "∀t'. t ≠ t' --> ¬ has_lock (lsf l) t'" by(fastsimp) hence "may_lock (lsf l) t" by-(rule classical, auto simp add: not_may_lock_conv) } note mayl = this { fix t' assume t'LT: "Inr t' ∈ LT" hence "¬ not_final_thread s t' ∧ t' ≠ t" proof(cases "t' = t") case False with t'LT mw L show ?thesis by(auto) next case True with tst mw[OF t'LT, of t] nfine' L have False by(auto intro!: must_wait.intros simp add: not_final_thread_iff) thus ?thesis .. qed } note mayj = this from collect L mayl have "∀l∈collect_locks' \<lbrace>ta''\<rbrace>l. may_lock (lsf l) t" by auto with lot have "!!l. l ∈ collect_locks \<lbrace>ta''\<rbrace>l ==> may_lock (lsf l) t" by - (rule lock_ok_las'_collect_locks'_may_lock) with lot have "lock_ok_las ls t \<lbrace>ta''\<rbrace>l" by -(rule lock_ok_las'_collect_locks_lock_ok_las) moreover from mayj join L have "cond_action_oks (ls, (ts, m), ws) t \<lbrace>ta''\<rbrace>c" by(fastsimp intro: may_join_cond_action_oks) moreover note red' cct tst `wset s t = None` ultimately show ?thesis by(fastsimp intro: redT_normal) next assume "0 < lnf l ∧ (∀l. 0 < lnf l --> may_lock (lsf l) t)" hence "0 < lnf l" "!!l. 0 < lnf l ==> may_lock (lsf l) t" by(auto) hence "may_acquire_all ls t ln" by(auto intro: may_acquire_allI) with tst `wset s t = None` `0 < lnf l` show ?thesis by(fastsimp intro: redT_acquire) qed qed end lemma (in final_thread_wf) lock_thread_ok_must_wait_thread_exists: "[| lock_thread_ok (locks s) (thr s); must_wait s t lt t' |] ==> thr s t' ≠ None" by(auto dest: lock_thread_okD elim!: must_wait_elims) lemma (in final_thread_wf) progress_deadlock: assumes wf_progress: "wf_progress final r start_state" and wf_red: "wf_red final r start_state" shows "progress final r start_state deadlock" proof(rule progress.intro[OF final_thread_wf_axioms wf_progress wf_red progress_axioms.intro]) fix ttas s t assume Red: "start_state -\<triangleright>ttas->* s" and tst: "not_final_thread s t" and normal: "!!t x LT. [|thr s t = ⌊(x, no_wait_locks)⌋; ¬ final x; wset s t = None; 〈x, shr s〉 LT \<wrong> |] ==> ∃t'. ∃lt∈LT. must_wait s t lt t'" and acquire: "!!t x ln l. [|thr s t = ⌊(x, ln)⌋; wset s t = None; 0 < lnf l|] ==> ∃l'. 0 < lnf l' ∧ ¬ may_lock ((locks s)f l') t" have lok: "lock_thread_ok (locks s) (thr s)" by(rule multithreaded_start.preserves_lock_thread_ok[OF wf_progress.axioms(1)[OF wf_progress] Red]) with Red tst normal acquire show "deadlock s" by-(rule all_waiting_implies_deadlock, (blast dest: lock_thread_ok_must_wait_thread_exists[OF lok] intro: must_syncI[OF wf_progress.wf_progress[OF wf_progress]])+) qed lemmas (in final_thread_wf) progress_deadlocked'_aux = progress_deadlock[unfolded deadlock_eq_deadlocked'] lemmas (in final_thread_wf) progress_deadlocked' = progress_deadlocked'_aux end