# HG changeset patch # User Christian Urban # Date 1505999755 -3600 # Node ID b32b3bd99150e73b15985a6118b413a1918431d5 # Parent c3a42076b1648e44a2328031f02ec92912ad6d6c cleaned up diff -r c3a42076b164 -r b32b3bd99150 Attic/Test.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Attic/Test.thy Thu Sep 21 14:15:55 2017 +0100 @@ -0,0 +1,789 @@ +theory Test +imports Precedence_ord Graphs +begin + +type_synonym thread = nat -- {* Type for thread identifiers. *} +type_synonym priority = nat -- {* Type for priorities. *} +type_synonym cs = nat -- {* Type for critical sections (or resources). *} + +-- {* Schedulling Events *} + +datatype event = + Create thread priority +| Exit thread +| P thread cs +| V thread cs +| Set thread priority + +type_synonym state = "event list" + +fun threads :: "state \ thread set" + where + "threads [] = {}" +| "threads (Create th prio#s) = {th} \ threads s" +| "threads (Exit th # s) = (threads s) - {th}" +| "threads (_#s) = threads s" + +fun priority :: "thread \ state \ priority" + where + "priority th [] = 0" +| "priority th (Create th' prio#s) = (if th' = th then prio else priority th s)" +| "priority th (Set th' prio#s) = (if th' = th then prio else priority th s)" +| "priority th (_#s) = priority th s" + +fun last_set :: "thread \ state \ nat" + where + "last_set th [] = 0" +| "last_set th ((Create th' prio)#s) = (if (th = th') then length s else last_set th s)" +| "last_set th ((Set th' prio)#s) = (if (th = th') then length s else last_set th s)" +| "last_set th (_#s) = last_set th s" + + +definition preced :: "thread \ state \ precedence" + where "preced th s \ Prc (priority th s) (last_set th s)" + +abbreviation + "preceds s ths \ {preced th s | th. th \ ths}" + +definition + "holds wq th cs \ th \ set (wq cs) \ th = hd (wq cs)" + +definition + "waits wq th cs \ th \ set (wq cs) \ th \ hd (wq cs)" + +--{* Nodes in Resource Graph *} +datatype node = + Th "thread" +| Cs "cs" + +definition + "RAG wq \ {(Th th, Cs cs) | th cs. waits wq th cs} \ {(Cs cs, Th th) | cs th. holds wq th cs}" + +definition + "dependants wq th \ {th' . (Th th', Th th) \ (RAG wq)^+}" + +record schedule_state = + wq_fun :: "cs \ thread list" + cprec_fun :: "thread \ precedence" + +definition cpreced :: "(cs \ thread list) \ state \ thread \ precedence" + where + "cpreced wq s th \ Max ({preced th s} \ {preced th' s | th'. th' \ dependants wq th})" + +abbreviation + "all_unlocked \ \_::cs. ([]::thread list)" + +abbreviation + "initial_cprec \ \_::thread. Prc 0 0" + +abbreviation + "release qs \ case qs of + [] => [] + | (_ # qs) => SOME q. distinct q \ set q = set qs" + +lemma [simp]: + "(SOME q. distinct q \ q = []) = []" +by auto + +lemma [simp]: + "(x \ set (SOME q. distinct q \ set q = set p)) = (x \ set p)" +apply(rule iffI) +apply (metis (mono_tags, lifting) List.finite_set finite_distinct_list some_eq_ex)+ +done + +abbreviation + "next_to_run ths \ hd (SOME q::thread list. distinct q \ set q = set ths)" + + +fun schs :: "state \ schedule_state" + where + "schs [] = (| wq_fun = \ cs. [], cprec_fun = (\_. Prc 0 0) |)" +| "schs (Create th prio # s) = + (let wq = wq_fun (schs s) in + (|wq_fun = wq, cprec_fun = cpreced wq (Create th prio # s)|))" +| "schs (Exit th # s) = + (let wq = wq_fun (schs s) in + (|wq_fun = wq, cprec_fun = cpreced wq (Exit th # s)|))" +| "schs (Set th prio # s) = + (let wq = wq_fun (schs s) in + (|wq_fun = wq, cprec_fun = cpreced wq (Set th prio # s)|))" +| "schs (P th cs # s) = + (let wq = wq_fun (schs s) in + let new_wq = wq(cs := (wq cs @ [th])) in + (|wq_fun = new_wq, cprec_fun = cpreced new_wq (P th cs # s)|))" +| "schs (V th cs # s) = + (let wq = wq_fun (schs s) in + let new_wq = wq(cs := release (wq cs)) in + (|wq_fun = new_wq, cprec_fun = cpreced new_wq (V th cs # s)|))" + +definition wq :: "state \ cs \ thread list" + where "wq s = wq_fun (schs s)" + +definition cpreced2 :: "state \ thread \ precedence" + where "cpreced2 s \ cprec_fun (schs s)" + +abbreviation + "cpreceds2 s ths \ {cpreced2 s th | th. th \ ths}" + +definition + "holds2 s \ holds (wq_fun (schs s))" + +definition + "waits2 s \ waits (wq_fun (schs s))" + +definition + "RAG2 s \ RAG (wq_fun (schs s))" + +definition + "dependants2 s \ dependants (wq_fun (schs s))" + +(* ready -> is a thread that is not waiting for any resource *) +definition readys :: "state \ thread set" + where "readys s \ {th . th \ threads s \ (\ cs. \ waits2 s th cs)}" + +definition runing :: "state \ thread set" + where "runing s \ {th . th \ readys s \ cpreced2 s th = Max (cpreceds2 s (readys s))}" + +(* all resources a thread hols in a state *) +definition holding :: "state \ thread \ cs set" + where "holding s th \ {cs . holds2 s th cs}" + + +lemma exists_distinct: + obtains ys where "distinct ys" "set ys = set xs" +by (metis List.finite_set finite_distinct_list) + +lemma next_to_run_set [simp]: + "wts \ [] \ next_to_run wts \ set wts" +apply(rule exists_distinct[of wts]) +by (metis (mono_tags, lifting) hd_in_set set_empty some_eq_ex) + +lemma holding_RAG: + "holding s th = {cs . (Cs cs, Th th) \ RAG2 s}" +unfolding holding_def RAG2_def RAG_def +unfolding holds2_def holds_def waits_def +by auto + +inductive step :: "state \ event \ bool" + where + step_Create: "\th \ threads s\ \ step s (Create th prio)" +| step_Exit: "\th \ runing s; holding s th = {}\ \ step s (Exit th)" +| step_P: "\th \ runing s; (Cs cs, Th th) \ (RAG2 s)^+\ \ step s (P th cs)" +| step_V: "\th \ runing s; holds2 s th cs\ \ step s (V th cs)" +| step_Set: "\th \ runing s\ \ step s (Set th prio)" + +(* valid states *) +inductive vt :: "state \ bool" + where + vt_nil[intro]: "vt []" +| vt_cons[intro]: "\vt s; step s e\ \ vt (e#s)" + +lemma runing_ready: + shows "runing s \ readys s" + unfolding runing_def readys_def + by auto + +lemma readys_threads: + shows "readys s \ threads s" + unfolding readys_def + by auto + +lemma wq_threads: + assumes vt: "vt s" + and h: "th \ set (wq s cs)" + shows "th \ threads s" +using assms +apply(induct) +apply(simp add: wq_def) +apply(erule step.cases) +apply(auto simp add: wq_def Let_def holding_def holds2_def holds_def waits2_def runing_def readys_def) +apply(simp add: waits_def) +apply(auto simp add: waits_def split: if_splits)[1] +apply(auto split: if_splits) +apply(simp only: waits_def) +by (metis insert_iff set_simps(2)) + + + +lemma Domain_RAG_threads: + assumes vt: "vt s" + and in_dom: "(Th th) \ Domain (RAG2 s)" + shows "th \ threads s" +proof - + from in_dom obtain n where "(Th th, n) \ RAG2 s" by auto + then obtain cs where "n = Cs cs" "(Th th, Cs cs) \ RAG2 s" + unfolding RAG2_def RAG_def by auto + then have "th \ set (wq s cs)" + unfolding wq_def RAG_def RAG2_def waits_def by auto + with wq_threads [OF vt] show ?thesis . +qed + +lemma dependants_threads: + assumes vt: "vt s" + shows "dependants2 s th \ threads s" +proof + fix th1 + assume "th1 \ dependants2 s th" + then have h: "(Th th1, Th th) \ (RAG2 s)\<^sup>+" + unfolding dependants2_def dependants_def RAG2_def by simp + then have "Th th1 \ Domain ((RAG2 s)\<^sup>+)" unfolding Domain_def by auto + then have "Th th1 \ Domain (RAG2 s)" using trancl_domain by simp + then show "th1 \ threads s" using vt by (rule_tac Domain_RAG_threads) +qed + +lemma finite_threads: + assumes vt: "vt s" + shows "finite (threads s)" +using vt by (induct) (auto elim: step.cases) + + +section {* Distinctness of @{const wq} *} + +lemma wq_distinct_step: + assumes "step s e" "distinct (wq s cs)" + shows "distinct (wq (e # s) cs)" +using assms +unfolding wq_def +apply(erule_tac step.cases) +apply(auto simp add: RAG2_def RAG_def Let_def)[1] +apply(auto simp add: wq_def Let_def RAG2_def RAG_def holds_def runing_def waits2_def waits_def readys_def) +apply(auto split: list.split) +apply(rule someI2) +apply(auto) +done + +lemma wq_distinct: + assumes "vt s" + shows "distinct (wq s cs)" +using assms +apply(induct) +apply(simp add: wq_def) +apply(simp add: wq_distinct_step) +done + + +section {* Single_Valuedness of @{const waits2}, @{const holds2}, @{const RAG2} *} + +lemma waits2_unique: + assumes "vt s" + and "waits2 s th cs1" + and "waits2 s th cs2" + shows "cs1 = cs2" +using assms +apply(induct) +apply(simp add: waits2_def waits_def) +apply(erule step.cases) +apply(auto simp add: Let_def waits2_def waits_def holds_def RAG2_def RAG_def + readys_def runing_def split: if_splits) +apply (metis Nil_is_append_conv hd_append2 list.distinct(1) split_list) +apply (metis Nil_is_append_conv hd_append2 list.distinct(1) split_list) +apply (metis distinct.simps(2) distinct_length_2_or_more list.sel(1) wq_def wq_distinct) +by (metis (full_types, hide_lams) distinct.simps(2) distinct_length_2_or_more list.sel(1) wq_def wq_distinct) + +lemma single_valued_waits2: + assumes "vt s" + shows "single_valuedP (waits2 s)" +using assms +unfolding single_valued_def +by (simp add: Product_Type.Collect_case_prodD waits2_unique) + +lemma single_valued_holds2: + assumes "vt s" + shows "single_valuedP (\cs th. holds2 s th cs)" +unfolding single_valued_def holds2_def holds_def by simp + +lemma single_valued_RAG2: + assumes "vt s" + shows "single_valued (RAG2 s)" +using single_valued_waits2[OF assms] single_valued_holds2[OF assms] +unfolding RAG2_def RAG_def +apply(rule_tac single_valued_union) +unfolding holds2_def[symmetric] waits2_def[symmetric] +apply(rule single_valued_Collect) +apply(simp) +apply(simp add: inj_on_def) +apply(rule single_valued_Collect) +apply(simp) +apply(simp add: inj_on_def) +apply(auto) +done + + +section {* Properties of @{const RAG2} under events *} + +lemma RAG_Set [simp]: + shows "RAG2 (Set th prio # s) = RAG2 s" +unfolding RAG2_def +by (simp add: Let_def) + +lemma RAG_Create [simp]: + "RAG2 (Create th prio # s) = RAG2 s" +unfolding RAG2_def +by (simp add: Let_def) + +lemma RAG_Exit [simp]: + shows "RAG2 (Exit th # s) = RAG2 s" +unfolding RAG2_def +by (simp add: Let_def) + +lemma RAG_P1: + assumes "wq s cs = []" + shows "RAG2 (P th cs # s) \ RAG2 s \ {(Cs cs, Th th)}" +using assms +unfolding RAG2_def RAG_def wq_def Let_def waits_def holds_def +by (auto simp add: Let_def) + +lemma RAG_P2: + assumes "(Cs cs, Th th) \ (RAG2 s)\<^sup>+" "wq s cs \ []" + shows "RAG2 (P th cs # s) \ RAG2 s \ {(Th th, Cs cs)}" +using assms +unfolding RAG2_def RAG_def wq_def Let_def waits_def holds_def +by (auto simp add: Let_def) + + +lemma RAG_V1: +assumes vt: "wq s cs = [th]" +shows "RAG2 (V th cs # s) \ RAG2 s - {(Cs cs, Th th)}" +using assms +unfolding RAG2_def RAG_def waits_def holds_def wq_def +by (auto simp add: Let_def) + +lemma RAG_V2: +assumes vt:"vt s" "wq s cs = th # wts \ wts \ []" +shows "RAG2 (V th cs # s) \ + RAG2 s - {(Cs cs, Th th), (Th (next_to_run wts), Cs cs)} \ {(Cs cs, Th (next_to_run wts))}" +unfolding RAG2_def RAG_def waits_def holds_def +using assms wq_distinct[OF vt(1), of"cs"] +by (auto simp add: Let_def wq_def) + + + +section {* Acyclicity of @{const RAG2} *} + +lemma acyclic_RAG_step: + assumes vt: "vt s" + and stp: "step s e" + and ac: "acyclic (RAG2 s)" + shows "acyclic (RAG2 (e # s))" +using stp vt ac +proof (induct) + case (step_P th s cs) + have ac: "acyclic (RAG2 s)" by fact + have ds: "(Cs cs, Th th) \ (RAG2 s)\<^sup>+" by fact + { assume wq_empty: "wq s cs = []" -- "case waiting queue is empty" + then have "(Th th, Cs cs) \ (RAG2 s)\<^sup>+" + proof (rule_tac notI) + assume "(Th th, Cs cs) \ (RAG2 s)\<^sup>+" + then obtain x where "(x, Cs cs) \ RAG2 s" using tranclD2 by metis + with wq_empty show False by (auto simp: RAG2_def RAG_def wq_def waits_def) + qed + with ac have "acyclic (RAG2 s \ {(Cs cs, Th th)})" by simp + then have "acyclic (RAG2 (P th cs # s))" using RAG_P1[OF wq_empty] + by (rule acyclic_subset) + } + moreover + { assume wq_not_empty: "wq s cs \ []" -- "case waiting queue is not empty" + from ac ds + have "acyclic (RAG2 s \ {(Th th, Cs cs)})" by simp + then have "acyclic (RAG2 (P th cs # s))" using RAG_P2[OF ds wq_not_empty] + by (rule acyclic_subset) + } + ultimately show "acyclic (RAG2 (P th cs # s))" by metis +next + case (step_V th s cs) -- "case for release of a lock" + have vt: "vt s" by fact + have ac: "acyclic (RAG2 s)" by fact + have hd: "holds2 s th cs" by fact + from vt have wq_distinct:"distinct (wq s cs)" by (rule wq_distinct) + from hd have "th \ set (wq s cs)" "th = hd (wq s cs)" unfolding holds2_def holds_def wq_def by auto + then obtain wts where eq_wq: "wq s cs = th # wts" by (cases "wq s cs") (auto) + -- "case no thread present in the waiting queue to take over" + { assume "wts = []" + with eq_wq have "wq s cs = [th]" by simp + then have "RAG2 (V th cs # s) \ RAG2 s - {(Cs cs, Th th)}" by (rule RAG_V1) + moreover have "acyclic (RAG2 s - {(Cs cs, Th th)})" using ac by (auto intro: acyclic_subset) + ultimately + have "acyclic (RAG2 (V th cs # s))" by (auto intro: acyclic_subset) + } + moreover + -- "at least one thread present to take over" + { def nth \ "next_to_run wts" + assume wq_not_empty: "wts \ []" + have "waits2 s nth cs" + using eq_wq wq_not_empty wq_distinct + unfolding nth_def waits2_def waits_def wq_def[symmetric] by auto + then have cs_in_RAG: "(Th nth, Cs cs) \ RAG2 s" + unfolding RAG2_def RAG_def waits2_def by auto + have "RAG2 (V th cs # s) \ RAG2 s - {(Cs cs, Th th), (Th nth, Cs cs)} \ {(Cs cs, Th nth)}" + unfolding nth_def using vt wq_not_empty eq_wq by (rule_tac RAG_V2) (auto) + moreover + have "acyclic (RAG2 s - {(Cs cs, Th th), (Th nth, Cs cs)} \ {(Cs cs, Th nth)})" + proof - + have "acyclic (RAG2 s - {(Cs cs, Th th), (Th nth, Cs cs)})" using ac by (auto intro: acyclic_subset) + moreover + have "(Th nth, Cs cs) \ (RAG2 s - {(Cs cs, Th th), (Th nth, Cs cs)})\<^sup>+" + proof (rule notI) + assume "(Th nth, Cs cs) \ (RAG2 s - {(Cs cs, Th th), (Th nth, Cs cs)})\<^sup>+" + then obtain z where a: "(Th nth, z) \ (RAG2 s - {(Cs cs, Th th), (Th nth, Cs cs)})" + by (metis converse_tranclE) + then have "(Th nth, z) \ RAG2 s" by simp + then have "z = Cs cs" using cs_in_RAG single_valued_RAG2[OF vt] + by (simp add: single_valued_def) + then show "False" using a by simp + qed + ultimately + show "acyclic (RAG2 s - {(Cs cs, Th th), (Th nth, Cs cs)} \ {(Cs cs, Th nth) })" by simp + qed + ultimately have "acyclic (RAG2 (V th cs # s))" + by (rule_tac acyclic_subset) + } + ultimately show "acyclic (RAG2 (V th cs # s))" by metis +qed (simp_all) + + +lemma finite_RAG: + assumes "vt s" + shows "finite (RAG2 s)" +using assms +apply(induct) +apply(simp add: RAG2_def RAG_def waits_def holds_def) +apply(erule step.cases) +apply(auto) +apply(case_tac "wq sa cs = []") +apply(rule finite_subset) +apply(rule RAG_P1) +apply(simp) +apply(simp) +apply(rule finite_subset) +apply(rule RAG_P2) +apply(simp) +apply(simp) +apply(simp) +apply(subgoal_tac "\wts. wq sa cs = th # wts") +apply(erule exE) +apply(case_tac "wts = []") +apply(rule finite_subset) +apply(rule RAG_V1) +apply(simp) +apply(simp) +apply(rule finite_subset) +apply(rule RAG_V2) +apply(simp) +apply(simp) +apply(simp) +apply(subgoal_tac "th \ set (wq sa cs) \ th = hd (wq sa cs)") +apply(case_tac "wq sa cs") +apply(auto)[2] +apply(auto simp add: holds2_def holds_def wq_def) +done + + + +lemma dchain_unique: + assumes vt: "vt s" + and th1_d: "(n, Th th1) \ (RAG2 s)^+" + and th1_r: "th1 \ readys s" + and th2_d: "(n, Th th2) \ (RAG2 s)^+" + and th2_r: "th2 \ readys s" + shows "th1 = th2" +proof(rule ccontr) + assume neq: "th1 \ th2" + with single_valued_confluent2 [OF single_valued_RAG2 [OF vt]] th1_d th2_d + have "(Th th1, Th th2) \ (RAG2 s)\<^sup>+ \ (Th th2, Th th1) \ (RAG2 s)\<^sup>+" by auto + moreover + { assume "(Th th1, Th th2) \ (RAG2 s)\<^sup>+" + then obtain n where dd: "(Th th1, n) \ RAG2 s" by (metis converse_tranclE) + then obtain cs where eq_n: "n = Cs cs" + unfolding RAG2_def RAG_def by (case_tac n) (auto) + from dd eq_n have "th1 \ readys s" + unfolding RAG2_def RAG_def waits2_def readys_def by (auto) + with th1_r have "False" by auto + } + moreover + { assume "(Th th2, Th th1) \ (RAG2 s)\<^sup>+" + then obtain n where dd: "(Th th2, n) \ RAG2 s" by (metis converse_tranclE) + then obtain cs where eq_n: "n = Cs cs" + unfolding RAG2_def RAG_def by (case_tac n) (auto) + from dd eq_n have "th2 \ readys s" + unfolding RAG2_def RAG_def waits2_def readys_def by (auto) + with th2_r have "False" by auto + } + ultimately show "False" by metis +qed + +lemma cpreced2_cpreced: "cpreced2 s th = cpreced (wq s) s th" +unfolding cpreced2_def wq_def +apply(induct s rule: schs.induct) +apply(simp add: Let_def cpreced_def dependants_def RAG_def waits_def holds_def preced_def) +apply(simp add: Let_def) +apply(simp add: Let_def) +apply(simp add: Let_def) +apply(subst (2) schs.simps) +apply(simp add: Let_def) +apply(subst (2) schs.simps) +apply(simp add: Let_def) +done + +lemma cpreced_Exit: + shows "cpreced2 (Exit th # s) th' = cpreced2 s th'" +by (simp add: cpreced2_cpreced cpreced_def preced_def wq_def Let_def) + +lemma readys_Exit: + shows "readys (Exit th # s) = readys s - {th}" +by (auto simp add: readys_def waits2_def Let_def) + +lemma readys_Create: + shows "readys (Create th prio # s) \ {th} \ readys s" +apply (auto simp add: readys_def waits2_def Let_def waits_def) +done + +lemma readys_Set: + shows "readys (Set th prio # s) = readys s" +by (auto simp add: readys_def waits2_def Let_def) + + +lemma readys_P: + shows "readys (P th cs # s) \ readys s" +apply(auto simp add: readys_def waits2_def Let_def) +apply(simp add: waits_def) +apply(case_tac "csa = cs") +apply(simp) +apply(drule_tac x="cs" in spec) +apply(simp) +apply (metis hd_append2 in_set_insert insert_Nil list.sel(1)) +apply(drule_tac x="csa" in spec) +apply(simp) +done + +lemma readys_V: + shows "readys (V th cs # s) \ readys s \ set (wq s cs)" +apply(auto simp add: readys_def waits2_def waits_def Let_def wq_def) +done + + +fun the_th :: "node \ thread" + where "the_th (Th th) = th" + +lemma image_Collect2: + "f ` A = {f x | x. x \ A}" +apply(auto) +done + +lemma Collect_disj_eq2: + "{f x | x. x = y \ x \ A} = {f y} \ {f x | x. x \ A}" +by (auto) + +lemma last_set_lt: + "th \ threads s \ last_set th s < length s" + apply(induct rule: threads.induct) + apply(auto) + done + +lemma last_set_eq_iff: + assumes "th1 \ threads s" "th2 \ threads s" + shows "last_set th1 s = last_set th2 s \ th1 = th2" + using assms + apply(induct s rule: threads.induct) + apply(auto split:if_splits dest:last_set_lt) + done + +lemma preced_eq_iff: + assumes th_in1: "th1 \ threads s" + and th_in2: "th2 \ threads s" + shows "preced th1 s = preced th2 s \ th1 = th2" +using assms +by (auto simp add: preced_def last_set_eq_iff) + +lemma dm_RAG_threads: + assumes vt: "vt s" + and in_dom: "(Th th) \ Domain (RAG2 s)" + shows "th \ threads s" +proof - + from in_dom obtain n where a: "(Th th, n) \ RAG2 s" by auto + then obtain cs where "n = Cs cs" + unfolding RAG2_def RAG_def + by auto + then have "(Th th, Cs cs) \ RAG2 s" using a by simp + hence "th \ set (wq s cs)" + unfolding RAG2_def wq_def RAG_def waits_def + by (auto) + then show ?thesis + apply(rule_tac wq_threads) + apply(rule assms) + apply(simp) + done +qed + +lemma cpreced_eq_iff: + assumes "th1 \ readys s" "th2 \ readys s" "vt s" + shows "cpreced2 s th1 = cpreced2 s th2 \ th1 = th2" +proof + def S1\"({th1} \ dependants (wq s) th1)" + def S2\"({th2} \ dependants (wq s) th2)" + have fin: "finite ((the_th o fst) ` ((RAG (wq s))\<^sup>+))" + apply(rule) + apply(simp add: finite_trancl) + apply(simp add: wq_def) + apply(rule finite_RAG[simplified RAG2_def]) + apply(rule assms) + done + + from fin have h: "finite (preceds s S1)" "finite (preceds s S2)" + apply(simp_all add: S2_def S1_def Collect_disj_eq2 image_Collect[symmetric]) + apply(rule) + apply(simp add: dependants_def) + apply(rule rev_finite_subset) + apply(assumption) + apply(auto simp add: image_def)[1] + apply(metis fst_conv the_th.simps) + apply(rule) + apply(simp add: dependants_def) + apply(rule rev_finite_subset) + apply(assumption) + apply(auto simp add: image_def)[1] + apply(metis fst_conv the_th.simps) + done + moreover have "S1 \ {}" "S2 \ {}" by (simp_all add: S1_def S2_def) + then have "(preceds s S1) \ {}" "(preceds s S2) \ {}" by simp_all + ultimately have m: "Max (preceds s S1) \ (preceds s S1)" "Max (preceds s S2) \ (preceds s S2)" + apply(rule_tac [!] Max_in) + apply(simp_all) + done + + assume q: "cpreced2 s th1 = cpreced2 s th2" + then have eq_max: "Max (preceds s S1) = Max (preceds s S2)" + unfolding cpreced2_cpreced cpreced_def + apply(simp only: S1_def S2_def) + apply(simp add: Collect_disj_eq2) + done + + obtain th0 where th0_in: "th0 \ S1" "th0 \ S2" and + eq_f_th1: "preced th0 s = Max (preceds s S1)" + "preced th0 s = Max (preceds s S2)" + using m + apply(clarify) + apply(simp add: eq_max) + apply(subst (asm) (2) preced_eq_iff) + apply(insert assms(2))[1] + apply(simp add: S2_def) + apply(auto)[1] + apply (metis contra_subsetD readys_threads) + apply(simp add: dependants_def) + apply(subgoal_tac "Th tha \ Domain ((RAG2 s)^+)") + apply(simp add: trancl_domain) + apply (metis Domain_RAG_threads assms(3)) + apply(simp only: RAG2_def wq_def) + apply (metis Domain_iff) + apply(insert assms(1))[1] + apply(simp add: S1_def) + apply(auto)[1] + apply (metis contra_subsetD readys_threads) + apply(simp add: dependants_def) + apply(subgoal_tac "Th th \ Domain ((RAG2 s)^+)") + apply(simp add: trancl_domain) + apply (metis Domain_RAG_threads assms(3)) + apply(simp only: RAG2_def wq_def) + apply (metis Domain_iff) + apply(simp) + done + then show "th1 = th2" + apply - + apply(insert th0_in assms(1, 2))[1] + apply(simp add: S1_def S2_def) + apply(auto) + --"first case" + prefer 2 + apply(subgoal_tac "Th th2 \ Domain (RAG2 s)") + apply(subgoal_tac "\cs. (Th th2, Cs cs) \ RAG2 s") + apply(erule exE) + apply(simp add: runing_def RAG2_def RAG_def readys_def waits2_def)[1] + apply(auto simp add: RAG2_def RAG_def)[1] + apply(subgoal_tac "Th th2 \ Domain ((RAG2 s)^+)") + apply (metis trancl_domain) + apply(subgoal_tac "(Th th2, Th th1) \ (RAG2 s)^+") + apply (metis Domain_iff) + apply(simp add: dependants_def RAG2_def wq_def) + --"second case" + apply(subgoal_tac "Th th1 \ Domain (RAG2 s)") + apply(subgoal_tac "\cs. (Th th1, Cs cs) \ RAG2 s") + apply(erule exE) + apply(insert assms(1))[1] + apply(simp add: runing_def RAG2_def RAG_def readys_def waits2_def)[1] + apply(auto simp add: RAG2_def RAG_def)[1] + apply(subgoal_tac "Th th1 \ Domain ((RAG2 s)^+)") + apply (metis trancl_domain) + apply(subgoal_tac "(Th th1, Th th2) \ (RAG2 s)^+") + apply (metis Domain_iff) + apply(simp add: dependants_def RAG2_def wq_def) + --"third case" + apply(rule dchain_unique) + apply(rule assms(3)) + apply(simp add: dependants_def RAG2_def wq_def) + apply(simp) + apply(simp add: dependants_def RAG2_def wq_def) + apply(simp) + done +next + assume "th1 = th2" + then show "cpreced2 s th1 = cpreced2 s th2" by simp +qed + +lemma at_most_one_running: + assumes "vt s" + shows "card (runing s) \ 1" +proof (rule ccontr) + assume "\ card (runing s) \ 1" + then have "2 \ card (runing s)" by auto + moreover + have "finite (runing s)" + by (metis `\ card (runing s) \ 1` card_infinite le0) + ultimately obtain th1 th2 where a: + "th1 \ th2" "th1 \ runing s" "th2 \ runing s" + "cpreced2 s th1 = cpreced2 s th2" + apply(auto simp add: numerals card_le_Suc_iff runing_def) + apply(blast) + done + then have "th1 = th2" + apply(subst (asm) cpreced_eq_iff) + apply(auto intro: assms a) + apply (metis contra_subsetD runing_ready)+ + done + then show "False" using a(1) by auto +qed + + + + (* + obtain th0 where th0_in: "th0 \ S1 \ th0 \ S2" + and eq_f_th0: "preced th0 s = Max ((\th. preced th s) ` (S1 \ S2))" + proof - + from fin have h1: "finite ((\th. preced th s) ` (S1 \ S2))" + apply(simp only: S1_def S2_def) + apply(rule) + apply(rule) + apply(rule) + apply(simp add: dependants_def) + apply(rule rev_finite_subset) + apply(assumption) + apply(auto simp add: image_def) + apply (metis fst_conv the_th.simps) + done + moreover + have "S1 \ S2 \ {}" apply (simp add: S1_def S2_def) + apply(auto) + + done + then have h2: "((\th. preced th s) ` (S1 \ S2)) \ {}" by simp + ultimately have "Max ((\th. preced th s) ` (S1 \ S2)) \ ((\th. preced th s) ` (S1 \ S2))" + apply(rule Max_in) + done + then show ?thesis using that[intro] apply(auto) + + apply(erule_tac preced_unique) + done + qed + *) + +thm waits_def waits2_def + +end diff -r c3a42076b164 -r b32b3bd99150 ExtGG.ty --- a/ExtGG.ty Thu Sep 07 16:04:03 2017 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,922 +0,0 @@ -theory ExtGG -imports PrioG CpsG -begin - -text {* - The following two auxiliary lemmas are used to reason about @{term Max}. -*} -lemma image_Max_eqI: - assumes "finite B" - and "b \ B" - and "\ x \ B. f x \ f b" - shows "Max (f ` B) = f b" - using assms - using Max_eqI by blast - -lemma image_Max_subset: - assumes "finite A" - and "B \ A" - and "a \ B" - and "Max (f ` A) = f a" - shows "Max (f ` B) = f a" -proof(rule image_Max_eqI) - show "finite B" - using assms(1) assms(2) finite_subset by auto -next - show "a \ B" using assms by simp -next - show "\x\B. f x \ f a" - by (metis Max_ge assms(1) assms(2) assms(4) - finite_imageI image_eqI subsetCE) -qed - -text {* - The following locale @{text "highest_gen"} sets the basic context for our - investigation: supposing thread @{text th} holds the highest @{term cp}-value - in state @{text s}, which means the task for @{text th} is the - most urgent. We want to show that - @{text th} is treated correctly by PIP, which means - @{text th} will not be blocked unreasonably by other less urgent - threads. -*} -locale highest_gen = - fixes s th prio tm - assumes vt_s: "vt s" - and threads_s: "th \ threads s" - and highest: "preced th s = Max ((cp s)`threads s)" - -- {* The internal structure of @{term th}'s precedence is exposed:*} - and preced_th: "preced th s = Prc prio tm" - --- {* @{term s} is a valid trace, so it will inherit all results derived for - a valid trace: *} -sublocale highest_gen < vat_s: valid_trace "s" - by (unfold_locales, insert vt_s, simp) - -context highest_gen -begin - -text {* - @{term tm} is the time when the precedence of @{term th} is set, so - @{term tm} must be a valid moment index into @{term s}. -*} -lemma lt_tm: "tm < length s" - by (insert preced_tm_lt[OF threads_s preced_th], simp) - -text {* - Since @{term th} holds the highest precedence and @{text "cp"} - is the highest precedence of all threads in the sub-tree of - @{text "th"} and @{text th} is among these threads, - its @{term cp} must equal to its precedence: -*} -lemma eq_cp_s_th: "cp s th = preced th s" (is "?L = ?R") -proof - - have "?L \ ?R" - by (unfold highest, rule Max_ge, - auto simp:threads_s finite_threads) - moreover have "?R \ ?L" - by (unfold vat_s.cp_rec, rule Max_ge, - auto simp:the_preced_def vat_s.fsbttRAGs.finite_children) - ultimately show ?thesis by auto -qed - -(* ccc *) -lemma highest_cp_preced: "cp s th = Max ((\ th'. preced th' s) ` threads s)" - by (fold max_cp_eq, unfold eq_cp_s_th, insert highest, simp) - -lemma highest_preced_thread: "preced th s = Max ((\ th'. preced th' s) ` threads s)" - by (fold eq_cp_s_th, unfold highest_cp_preced, simp) - -lemma highest': "cp s th = Max (cp s ` threads s)" -proof - - from highest_cp_preced max_cp_eq[symmetric] - show ?thesis by simp -qed - -end - -locale extend_highest_gen = highest_gen + - fixes t - assumes vt_t: "vt (t@s)" - and create_low: "Create th' prio' \ set t \ prio' \ prio" - and set_diff_low: "Set th' prio' \ set t \ th' \ th \ prio' \ prio" - and exit_diff: "Exit th' \ set t \ th' \ th" - -sublocale extend_highest_gen < vat_t: valid_trace "t@s" - by (unfold_locales, insert vt_t, simp) - -lemma step_back_vt_app: - assumes vt_ts: "vt (t@s)" - shows "vt s" -proof - - from vt_ts show ?thesis - proof(induct t) - case Nil - from Nil show ?case by auto - next - case (Cons e t) - assume ih: " vt (t @ s) \ vt s" - and vt_et: "vt ((e # t) @ s)" - show ?case - proof(rule ih) - show "vt (t @ s)" - proof(rule step_back_vt) - from vt_et show "vt (e # t @ s)" by simp - qed - qed - qed -qed - - -locale red_extend_highest_gen = extend_highest_gen + - fixes i::nat - -sublocale red_extend_highest_gen < red_moment: extend_highest_gen "s" "th" "prio" "tm" "(moment i t)" - apply (insert extend_highest_gen_axioms, subst (asm) (1) moment_restm_s [of i t, symmetric]) - apply (unfold extend_highest_gen_def extend_highest_gen_axioms_def, clarsimp) - by (unfold highest_gen_def, auto dest:step_back_vt_app) - - -context extend_highest_gen -begin - - lemma ind [consumes 0, case_names Nil Cons, induct type]: - assumes - h0: "R []" - and h2: "\ e t. \vt (t@s); step (t@s) e; - extend_highest_gen s th prio tm t; - extend_highest_gen s th prio tm (e#t); R t\ \ R (e#t)" - shows "R t" -proof - - from vt_t extend_highest_gen_axioms show ?thesis - proof(induct t) - from h0 show "R []" . - next - case (Cons e t') - assume ih: "\vt (t' @ s); extend_highest_gen s th prio tm t'\ \ R t'" - and vt_e: "vt ((e # t') @ s)" - and et: "extend_highest_gen s th prio tm (e # t')" - from vt_e and step_back_step have stp: "step (t'@s) e" by auto - from vt_e and step_back_vt have vt_ts: "vt (t'@s)" by auto - show ?case - proof(rule h2 [OF vt_ts stp _ _ _ ]) - show "R t'" - proof(rule ih) - from et show ext': "extend_highest_gen s th prio tm t'" - by (unfold extend_highest_gen_def extend_highest_gen_axioms_def, auto dest:step_back_vt) - next - from vt_ts show "vt (t' @ s)" . - qed - next - from et show "extend_highest_gen s th prio tm (e # t')" . - next - from et show ext': "extend_highest_gen s th prio tm t'" - by (unfold extend_highest_gen_def extend_highest_gen_axioms_def, auto dest:step_back_vt) - qed - qed -qed - - -lemma th_kept: "th \ threads (t @ s) \ - preced th (t@s) = preced th s" (is "?Q t") -proof - - show ?thesis - proof(induct rule:ind) - case Nil - from threads_s - show ?case - by auto - next - case (Cons e t) - interpret h_e: extend_highest_gen _ _ _ _ "(e # t)" using Cons by auto - interpret h_t: extend_highest_gen _ _ _ _ t using Cons by auto - show ?case - proof(cases e) - case (Create thread prio) - show ?thesis - proof - - from Cons and Create have "step (t@s) (Create thread prio)" by auto - hence "th \ thread" - proof(cases) - case thread_create - with Cons show ?thesis by auto - qed - hence "preced th ((e # t) @ s) = preced th (t @ s)" - by (unfold Create, auto simp:preced_def) - moreover note Cons - ultimately show ?thesis - by (auto simp:Create) - qed - next - case (Exit thread) - from h_e.exit_diff and Exit - have neq_th: "thread \ th" by auto - with Cons - show ?thesis - by (unfold Exit, auto simp:preced_def) - next - case (P thread cs) - with Cons - show ?thesis - by (auto simp:P preced_def) - next - case (V thread cs) - with Cons - show ?thesis - by (auto simp:V preced_def) - next - case (Set thread prio') - show ?thesis - proof - - from h_e.set_diff_low and Set - have "th \ thread" by auto - hence "preced th ((e # t) @ s) = preced th (t @ s)" - by (unfold Set, auto simp:preced_def) - moreover note Cons - ultimately show ?thesis - by (auto simp:Set) - qed - qed - qed -qed - -text {* - According to @{thm th_kept}, thread @{text "th"} has its living status - and precedence kept along the way of @{text "t"}. The following lemma - shows that this preserved precedence of @{text "th"} remains as the highest - along the way of @{text "t"}. - - The proof goes by induction over @{text "t"} using the specialized - induction rule @{thm ind}, followed by case analysis of each possible - operations of PIP. All cases follow the same pattern rendered by the - generalized introduction rule @{thm "image_Max_eqI"}. - - The very essence is to show that precedences, no matter whether they are newly introduced - or modified, are always lower than the one held by @{term "th"}, - which by @{thm th_kept} is preserved along the way. -*} -lemma max_kept: "Max (the_preced (t @ s) ` (threads (t@s))) = preced th s" -proof(induct rule:ind) - case Nil - from highest_preced_thread - show ?case - by (unfold the_preced_def, simp) -next - case (Cons e t) - interpret h_e: extend_highest_gen _ _ _ _ "(e # t)" using Cons by auto - interpret h_t: extend_highest_gen _ _ _ _ t using Cons by auto - show ?case - proof(cases e) - case (Create thread prio') - show ?thesis (is "Max (?f ` ?A) = ?t") - proof - - -- {* The following is the common pattern of each branch of the case analysis. *} - -- {* The major part is to show that @{text "th"} holds the highest precedence: *} - have "Max (?f ` ?A) = ?f th" - proof(rule image_Max_eqI) - show "finite ?A" using h_e.finite_threads by auto - next - show "th \ ?A" using h_e.th_kept by auto - next - show "\x\?A. ?f x \ ?f th" - proof - fix x - assume "x \ ?A" - hence "x = thread \ x \ threads (t@s)" by (auto simp:Create) - thus "?f x \ ?f th" - proof - assume "x = thread" - thus ?thesis - apply (simp add:Create the_preced_def preced_def, fold preced_def) - using Create h_e.create_low h_t.th_kept lt_tm preced_leI2 preced_th by force - next - assume h: "x \ threads (t @ s)" - from Cons(2)[unfolded Create] - have "x \ thread" using h by (cases, auto) - hence "?f x = the_preced (t@s) x" - by (simp add:Create the_preced_def preced_def) - hence "?f x \ Max (the_preced (t@s) ` threads (t@s))" - by (simp add: h_t.finite_threads h) - also have "... = ?f th" - by (metis Cons.hyps(5) h_e.th_kept the_preced_def) - finally show ?thesis . - qed - qed - qed - -- {* The minor part is to show that the precedence of @{text "th"} - equals to preserved one, given by the foregoing lemma @{thm th_kept} *} - also have "... = ?t" using h_e.th_kept the_preced_def by auto - -- {* Then it follows trivially that the precedence preserved - for @{term "th"} remains the maximum of all living threads along the way. *} - finally show ?thesis . - qed - next - case (Exit thread) - show ?thesis (is "Max (?f ` ?A) = ?t") - proof - - have "Max (?f ` ?A) = ?f th" - proof(rule image_Max_eqI) - show "finite ?A" using h_e.finite_threads by auto - next - show "th \ ?A" using h_e.th_kept by auto - next - show "\x\?A. ?f x \ ?f th" - proof - fix x - assume "x \ ?A" - hence "x \ threads (t@s)" by (simp add: Exit) - hence "?f x \ Max (?f ` threads (t@s))" - by (simp add: h_t.finite_threads) - also have "... \ ?f th" - apply (simp add:Exit the_preced_def preced_def, fold preced_def) - using Cons.hyps(5) h_t.th_kept the_preced_def by auto - finally show "?f x \ ?f th" . - qed - qed - also have "... = ?t" using h_e.th_kept the_preced_def by auto - finally show ?thesis . - qed - next - case (P thread cs) - with Cons - show ?thesis by (auto simp:preced_def the_preced_def) - next - case (V thread cs) - with Cons - show ?thesis by (auto simp:preced_def the_preced_def) - next - case (Set thread prio') - show ?thesis (is "Max (?f ` ?A) = ?t") - proof - - have "Max (?f ` ?A) = ?f th" - proof(rule image_Max_eqI) - show "finite ?A" using h_e.finite_threads by auto - next - show "th \ ?A" using h_e.th_kept by auto - next - show "\x\?A. ?f x \ ?f th" - proof - fix x - assume h: "x \ ?A" - show "?f x \ ?f th" - proof(cases "x = thread") - case True - moreover have "the_preced (Set thread prio' # t @ s) thread \ the_preced (t @ s) th" - proof - - have "the_preced (t @ s) th = Prc prio tm" - using h_t.th_kept preced_th by (simp add:the_preced_def) - moreover have "prio' \ prio" using Set h_e.set_diff_low by auto - ultimately show ?thesis by (insert lt_tm, auto simp:the_preced_def preced_def) - qed - ultimately show ?thesis - by (unfold Set, simp add:the_preced_def preced_def) - next - case False - then have "?f x = the_preced (t@s) x" - by (simp add:the_preced_def preced_def Set) - also have "... \ Max (the_preced (t@s) ` threads (t@s))" - using Set h h_t.finite_threads by auto - also have "... = ?f th" by (metis Cons.hyps(5) h_e.th_kept the_preced_def) - finally show ?thesis . - qed - qed - qed - also have "... = ?t" using h_e.th_kept the_preced_def by auto - finally show ?thesis . - qed - qed -qed - -lemma max_preced: "preced th (t@s) = Max (the_preced (t@s) ` (threads (t@s)))" - by (insert th_kept max_kept, auto) - -text {* - The reason behind the following lemma is that: - Since @{term "cp"} is defined as the maximum precedence - of those threads contained in the sub-tree of node @{term "Th th"} - in @{term "RAG (t@s)"}, and all these threads are living threads, and - @{term "th"} is also among them, the maximum precedence of - them all must be the one for @{text "th"}. -*} -lemma th_cp_max_preced: - "cp (t@s) th = Max (the_preced (t@s) ` (threads (t@s)))" (is "?L = ?R") -proof - - let ?f = "the_preced (t@s)" - have "?L = ?f th" - proof(unfold cp_alt_def, rule image_Max_eqI) - show "finite {th'. Th th' \ subtree (RAG (t @ s)) (Th th)}" - proof - - have "{th'. Th th' \ subtree (RAG (t @ s)) (Th th)} = - the_thread ` {n . n \ subtree (RAG (t @ s)) (Th th) \ - (\ th'. n = Th th')}" - by (smt Collect_cong Setcompr_eq_image mem_Collect_eq the_thread.simps) - moreover have "finite ..." by (simp add: vat_t.fsbtRAGs.finite_subtree) - ultimately show ?thesis by simp - qed - next - show "th \ {th'. Th th' \ subtree (RAG (t @ s)) (Th th)}" - by (auto simp:subtree_def) - next - show "\x\{th'. Th th' \ subtree (RAG (t @ s)) (Th th)}. - the_preced (t @ s) x \ the_preced (t @ s) th" - proof - fix th' - assume "th' \ {th'. Th th' \ subtree (RAG (t @ s)) (Th th)}" - hence "Th th' \ subtree (RAG (t @ s)) (Th th)" by auto - moreover have "... \ Field (RAG (t @ s)) \ {Th th}" - by (meson subtree_Field) - ultimately have "Th th' \ ..." by auto - hence "th' \ threads (t@s)" - proof - assume "Th th' \ {Th th}" - thus ?thesis using th_kept by auto - next - assume "Th th' \ Field (RAG (t @ s))" - thus ?thesis using vat_t.not_in_thread_isolated by blast - qed - thus "the_preced (t @ s) th' \ the_preced (t @ s) th" - by (metis Max_ge finite_imageI finite_threads image_eqI - max_kept th_kept the_preced_def) - qed - qed - also have "... = ?R" by (simp add: max_preced the_preced_def) - finally show ?thesis . -qed - -lemma th_cp_max: "cp (t@s) th = Max (cp (t@s) ` threads (t@s))" - using max_cp_eq th_cp_max_preced the_preced_def vt_t by presburger - -lemma th_cp_preced: "cp (t@s) th = preced th s" - by (fold max_kept, unfold th_cp_max_preced, simp) - -lemma preced_less: - assumes th'_in: "th' \ threads s" - and neq_th': "th' \ th" - shows "preced th' s < preced th s" - using assms -by (metis Max.coboundedI finite_imageI highest not_le order.trans - preced_linorder rev_image_eqI threads_s vat_s.finite_threads - vat_s.le_cp) - -text {* - Counting of the number of @{term "P"} and @{term "V"} operations - is the cornerstone of a large number of the following proofs. - The reason is that this counting is quite easy to calculate and - convenient to use in the reasoning. - - The following lemma shows that the counting controls whether - a thread is running or not. -*} - -lemma pv_blocked_pre: - assumes th'_in: "th' \ threads (t@s)" - and neq_th': "th' \ th" - and eq_pv: "cntP (t@s) th' = cntV (t@s) th'" - shows "th' \ runing (t@s)" -proof - assume otherwise: "th' \ runing (t@s)" - show False - proof - - have "th' = th" - proof(rule preced_unique) - show "preced th' (t @ s) = preced th (t @ s)" (is "?L = ?R") - proof - - have "?L = cp (t@s) th'" - by (unfold cp_eq_cpreced cpreced_def count_eq_dependants[OF eq_pv], simp) - also have "... = cp (t @ s) th" using otherwise - by (metis (mono_tags, lifting) mem_Collect_eq - runing_def th_cp_max vat_t.max_cp_readys_threads) - also have "... = ?R" by (metis th_cp_preced th_kept) - finally show ?thesis . - qed - qed (auto simp: th'_in th_kept) - moreover have "th' \ th" using neq_th' . - ultimately show ?thesis by simp - qed -qed - -lemmas pv_blocked = pv_blocked_pre[folded detached_eq] - -lemma runing_precond_pre: - fixes th' - assumes th'_in: "th' \ threads s" - and eq_pv: "cntP s th' = cntV s th'" - and neq_th': "th' \ th" - shows "th' \ threads (t@s) \ - cntP (t@s) th' = cntV (t@s) th'" -proof(induct rule:ind) - case (Cons e t) - interpret vat_t: extend_highest_gen s th prio tm t using Cons by simp - interpret vat_e: extend_highest_gen s th prio tm "(e # t)" using Cons by simp - show ?case - proof(cases e) - case (P thread cs) - show ?thesis - proof - - have "cntP ((e # t) @ s) th' = cntV ((e # t) @ s) th'" - proof - - have "thread \ th'" - proof - - have "step (t@s) (P thread cs)" using Cons P by auto - thus ?thesis - proof(cases) - assume "thread \ runing (t@s)" - moreover have "th' \ runing (t@s)" using Cons(5) - by (metis neq_th' vat_t.pv_blocked_pre) - ultimately show ?thesis by auto - qed - qed with Cons show ?thesis - by (unfold P, simp add:cntP_def cntV_def count_def) - qed - moreover have "th' \ threads ((e # t) @ s)" using Cons by (unfold P, simp) - ultimately show ?thesis by auto - qed - next - case (V thread cs) - show ?thesis - proof - - have "cntP ((e # t) @ s) th' = cntV ((e # t) @ s) th'" - proof - - have "thread \ th'" - proof - - have "step (t@s) (V thread cs)" using Cons V by auto - thus ?thesis - proof(cases) - assume "thread \ runing (t@s)" - moreover have "th' \ runing (t@s)" using Cons(5) - by (metis neq_th' vat_t.pv_blocked_pre) - ultimately show ?thesis by auto - qed - qed with Cons show ?thesis - by (unfold V, simp add:cntP_def cntV_def count_def) - qed - moreover have "th' \ threads ((e # t) @ s)" using Cons by (unfold V, simp) - ultimately show ?thesis by auto - qed - next - case (Create thread prio') - show ?thesis - proof - - have "cntP ((e # t) @ s) th' = cntV ((e # t) @ s) th'" - proof - - have "thread \ th'" - proof - - have "step (t@s) (Create thread prio')" using Cons Create by auto - thus ?thesis using Cons(5) by (cases, auto) - qed with Cons show ?thesis - by (unfold Create, simp add:cntP_def cntV_def count_def) - qed - moreover have "th' \ threads ((e # t) @ s)" using Cons by (unfold Create, simp) - ultimately show ?thesis by auto - qed - next - case (Exit thread) - show ?thesis - proof - - have neq_thread: "thread \ th'" - proof - - have "step (t@s) (Exit thread)" using Cons Exit by auto - thus ?thesis apply (cases) using Cons(5) - by (metis neq_th' vat_t.pv_blocked_pre) - qed - hence "cntP ((e # t) @ s) th' = cntV ((e # t) @ s) th'" using Cons - by (unfold Exit, simp add:cntP_def cntV_def count_def) - moreover have "th' \ threads ((e # t) @ s)" using Cons neq_thread - by (unfold Exit, simp) - ultimately show ?thesis by auto - qed - next - case (Set thread prio') - with Cons - show ?thesis - by (auto simp:cntP_def cntV_def count_def) - qed -next - case Nil - with assms - show ?case by auto -qed - -text {* Changing counting balance to detachedness *} -lemmas runing_precond_pre_dtc = runing_precond_pre - [folded vat_t.detached_eq vat_s.detached_eq] - -lemma runing_precond: - fixes th' - assumes th'_in: "th' \ threads s" - and neq_th': "th' \ th" - and is_runing: "th' \ runing (t@s)" - shows "cntP s th' > cntV s th'" - using assms -proof - - have "cntP s th' \ cntV s th'" - by (metis is_runing neq_th' pv_blocked_pre runing_precond_pre th'_in) - moreover have "cntV s th' \ cntP s th'" using vat_s.cnp_cnv_cncs by auto - ultimately show ?thesis by auto -qed - -lemma moment_blocked_pre: - assumes neq_th': "th' \ th" - and th'_in: "th' \ threads ((moment i t)@s)" - and eq_pv: "cntP ((moment i t)@s) th' = cntV ((moment i t)@s) th'" - shows "cntP ((moment (i+j) t)@s) th' = cntV ((moment (i+j) t)@s) th' \ - th' \ threads ((moment (i+j) t)@s)" -proof - - interpret h_i: red_extend_highest_gen _ _ _ _ _ i - by (unfold_locales) - interpret h_j: red_extend_highest_gen _ _ _ _ _ "i+j" - by (unfold_locales) - interpret h: extend_highest_gen "((moment i t)@s)" th prio tm "moment j (restm i t)" - proof(unfold_locales) - show "vt (moment i t @ s)" by (metis h_i.vt_t) - next - show "th \ threads (moment i t @ s)" by (metis h_i.th_kept) - next - show "preced th (moment i t @ s) = - Max (cp (moment i t @ s) ` threads (moment i t @ s))" - by (metis h_i.th_cp_max h_i.th_cp_preced h_i.th_kept) - next - show "preced th (moment i t @ s) = Prc prio tm" by (metis h_i.th_kept preced_th) - next - show "vt (moment j (restm i t) @ moment i t @ s)" - using moment_plus_split by (metis add.commute append_assoc h_j.vt_t) - next - fix th' prio' - assume "Create th' prio' \ set (moment j (restm i t))" - thus "prio' \ prio" using assms - by (metis Un_iff add.commute h_j.create_low moment_plus_split set_append) - next - fix th' prio' - assume "Set th' prio' \ set (moment j (restm i t))" - thus "th' \ th \ prio' \ prio" - by (metis Un_iff add.commute h_j.set_diff_low moment_plus_split set_append) - next - fix th' - assume "Exit th' \ set (moment j (restm i t))" - thus "th' \ th" - by (metis Un_iff add.commute h_j.exit_diff moment_plus_split set_append) - qed - show ?thesis - by (metis add.commute append_assoc eq_pv h.runing_precond_pre - moment_plus_split neq_th' th'_in) -qed - -lemma moment_blocked_eqpv: - assumes neq_th': "th' \ th" - and th'_in: "th' \ threads ((moment i t)@s)" - and eq_pv: "cntP ((moment i t)@s) th' = cntV ((moment i t)@s) th'" - and le_ij: "i \ j" - shows "cntP ((moment j t)@s) th' = cntV ((moment j t)@s) th' \ - th' \ threads ((moment j t)@s) \ - th' \ runing ((moment j t)@s)" -proof - - from moment_blocked_pre [OF neq_th' th'_in eq_pv, of "j-i"] and le_ij - have h1: "cntP ((moment j t)@s) th' = cntV ((moment j t)@s) th'" - and h2: "th' \ threads ((moment j t)@s)" by auto - moreover have "th' \ runing ((moment j t)@s)" - proof - - interpret h: red_extend_highest_gen _ _ _ _ _ j by (unfold_locales) - show ?thesis - using h.pv_blocked_pre h1 h2 neq_th' by auto - qed - ultimately show ?thesis by auto -qed - -(* The foregoing two lemmas are preparation for this one, but - in long run can be combined. Maybe I am wrong. -*) -lemma moment_blocked: - assumes neq_th': "th' \ th" - and th'_in: "th' \ threads ((moment i t)@s)" - and dtc: "detached (moment i t @ s) th'" - and le_ij: "i \ j" - shows "detached (moment j t @ s) th' \ - th' \ threads ((moment j t)@s) \ - th' \ runing ((moment j t)@s)" -proof - - interpret h_i: red_extend_highest_gen _ _ _ _ _ i by (unfold_locales) - interpret h_j: red_extend_highest_gen _ _ _ _ _ j by (unfold_locales) - have cnt_i: "cntP (moment i t @ s) th' = cntV (moment i t @ s) th'" - by (metis dtc h_i.detached_elim) - from moment_blocked_eqpv[OF neq_th' th'_in cnt_i le_ij] - show ?thesis by (metis h_j.detached_intro) -qed - -lemma runing_preced_inversion: - assumes runing': "th' \ runing (t@s)" - shows "cp (t@s) th' = preced th s" (is "?L = ?R") -proof - - have "?L = Max (cp (t @ s) ` readys (t @ s))" using assms - by (unfold runing_def, auto) - also have "\ = ?R" - by (metis th_cp_max th_cp_preced vat_t.max_cp_readys_threads) - finally show ?thesis . -qed - -text {* - The situation when @{term "th"} is blocked is analyzed by the following lemmas. -*} - -text {* - The following lemmas shows the running thread @{text "th'"}, if it is different from - @{term th}, must be live at the very beginning. By the term {\em the very beginning}, - we mean the moment where the formal investigation starts, i.e. the moment (or state) - @{term s}. -*} - -lemma runing_inversion_0: - assumes neq_th': "th' \ th" - and runing': "th' \ runing (t@s)" - shows "th' \ threads s" -proof - - -- {* The proof is by contradiction: *} - { assume otherwise: "\ ?thesis" - have "th' \ runing (t @ s)" - proof - - -- {* Since @{term "th'"} is running at time @{term "t@s"}, so it exists that time. *} - have th'_in: "th' \ threads (t@s)" using runing' by (simp add:runing_def readys_def) - -- {* However, @{text "th'"} does not exist at very beginning. *} - have th'_notin: "th' \ threads (moment 0 t @ s)" using otherwise - by (metis append.simps(1) moment_zero) - -- {* Therefore, there must be a moment during @{text "t"}, when - @{text "th'"} came into being. *} - -- {* Let us suppose the moment being @{text "i"}: *} - from p_split_gen[OF th'_in th'_notin] - obtain i where lt_its: "i < length t" - and le_i: "0 \ i" - and pre: " th' \ threads (moment i t @ s)" (is "th' \ threads ?pre") - and post: "(\i'>i. th' \ threads (moment i' t @ s))" by (auto) - interpret h_i: red_extend_highest_gen _ _ _ _ _ i by (unfold_locales) - interpret h_i': red_extend_highest_gen _ _ _ _ _ "(Suc i)" by (unfold_locales) - from lt_its have "Suc i \ length t" by auto - -- {* Let us also suppose the event which makes this change is @{text e}: *} - from moment_head[OF this] obtain e where - eq_me: "moment (Suc i) t = e # moment i t" by blast - hence "vt (e # (moment i t @ s))" by (metis append_Cons h_i'.vt_t) - hence "PIP (moment i t @ s) e" by (cases, simp) - -- {* It can be derived that this event @{text "e"}, which - gives birth to @{term "th'"} must be a @{term "Create"}: *} - from create_pre[OF this, of th'] - obtain prio where eq_e: "e = Create th' prio" - by (metis append_Cons eq_me lessI post pre) - have h1: "th' \ threads (moment (Suc i) t @ s)" using post by auto - have h2: "cntP (moment (Suc i) t @ s) th' = cntV (moment (Suc i) t@ s) th'" - proof - - have "cntP (moment i t@s) th' = cntV (moment i t@s) th'" - by (metis h_i.cnp_cnv_eq pre) - thus ?thesis by (simp add:eq_me eq_e cntP_def cntV_def count_def) - qed - show ?thesis - using moment_blocked_eqpv [OF neq_th' h1 h2, of "length t"] lt_its moment_ge - by auto - qed - with `th' \ runing (t@s)` - have False by simp - } thus ?thesis by auto -qed - -text {* - The second lemma says, if the running thread @{text th'} is different from - @{term th}, then this @{text th'} must in the possession of some resources - at the very beginning. - - To ease the reasoning of resource possession of one particular thread, - we used two auxiliary functions @{term cntV} and @{term cntP}, - which are the counters of @{term P}-operations and - @{term V}-operations respectively. - If the number of @{term V}-operation is less than the number of - @{term "P"}-operations, the thread must have some unreleased resource. -*} - -lemma runing_inversion_1: (* ddd *) - assumes neq_th': "th' \ th" - and runing': "th' \ runing (t@s)" - -- {* thread @{term "th'"} is a live on in state @{term "s"} and - it has some unreleased resource. *} - shows "th' \ threads s \ cntV s th' < cntP s th'" -proof - - -- {* The proof is a simple composition of @{thm runing_inversion_0} and - @{thm runing_precond}: *} - -- {* By applying @{thm runing_inversion_0} to assumptions, - it can be shown that @{term th'} is live in state @{term s}: *} - have "th' \ threads s" using runing_inversion_0[OF assms(1,2)] . - -- {* Then the thesis is derived easily by applying @{thm runing_precond}: *} - with runing_precond [OF this neq_th' runing'] show ?thesis by simp -qed - -text {* - The following lemma is just a rephrasing of @{thm runing_inversion_1}: -*} -lemma runing_inversion_2: - assumes runing': "th' \ runing (t@s)" - shows "th' = th \ (th' \ th \ th' \ threads s \ cntV s th' < cntP s th')" -proof - - from runing_inversion_1[OF _ runing'] - show ?thesis by auto -qed - -lemma runing_inversion_3: - assumes runing': "th' \ runing (t@s)" - and neq_th: "th' \ th" - shows "th' \ threads s \ (cntV s th' < cntP s th' \ cp (t@s) th' = preced th s)" - by (metis neq_th runing' runing_inversion_2 runing_preced_inversion) - -lemma runing_inversion_4: - assumes runing': "th' \ runing (t@s)" - and neq_th: "th' \ th" - shows "th' \ threads s" - and "\detached s th'" - and "cp (t@s) th' = preced th s" - apply (metis neq_th runing' runing_inversion_2) - apply (metis neq_th pv_blocked runing' runing_inversion_2 runing_precond_pre_dtc) - by (metis neq_th runing' runing_inversion_3) - - -text {* - Suppose @{term th} is not running, it is first shown that - there is a path in RAG leading from node @{term th} to another thread @{text "th'"} - in the @{term readys}-set (So @{text "th'"} is an ancestor of @{term th}}). - - Now, since @{term readys}-set is non-empty, there must be - one in it which holds the highest @{term cp}-value, which, by definition, - is the @{term runing}-thread. However, we are going to show more: this running thread - is exactly @{term "th'"}. - *} -lemma th_blockedE: (* ddd *) - assumes "th \ runing (t@s)" - obtains th' where "Th th' \ ancestors (RAG (t @ s)) (Th th)" - "th' \ runing (t@s)" -proof - - -- {* According to @{thm vat_t.th_chain_to_ready}, either - @{term "th"} is in @{term "readys"} or there is path leading from it to - one thread in @{term "readys"}. *} - have "th \ readys (t @ s) \ (\th'. th' \ readys (t @ s) \ (Th th, Th th') \ (RAG (t @ s))\<^sup>+)" - using th_kept vat_t.th_chain_to_ready by auto - -- {* However, @{term th} can not be in @{term readys}, because otherwise, since - @{term th} holds the highest @{term cp}-value, it must be @{term "runing"}. *} - moreover have "th \ readys (t@s)" - using assms runing_def th_cp_max vat_t.max_cp_readys_threads by auto - -- {* So, there must be a path from @{term th} to another thread @{text "th'"} in - term @{term readys}: *} - ultimately obtain th' where th'_in: "th' \ readys (t@s)" - and dp: "(Th th, Th th') \ (RAG (t @ s))\<^sup>+" by auto - -- {* We are going to show that this @{term th'} is running. *} - have "th' \ runing (t@s)" - proof - - -- {* We only need to show that this @{term th'} holds the highest @{term cp}-value: *} - have "cp (t@s) th' = Max (cp (t@s) ` readys (t@s))" (is "?L = ?R") - proof - - have "?L = Max ((the_preced (t @ s) \ the_thread) ` subtree (tRAG (t @ s)) (Th th'))" - by (unfold cp_alt_def1, simp) - also have "... = (the_preced (t @ s) \ the_thread) (Th th)" - proof(rule image_Max_subset) - show "finite (Th ` (threads (t@s)))" by (simp add: vat_t.finite_threads) - next - show "subtree (tRAG (t @ s)) (Th th') \ Th ` threads (t @ s)" - by (metis Range.intros dp trancl_range vat_t.range_in vat_t.subtree_tRAG_thread) - next - show "Th th \ subtree (tRAG (t @ s)) (Th th')" using dp - by (unfold tRAG_subtree_eq, auto simp:subtree_def) - next - show "Max ((the_preced (t @ s) \ the_thread) ` Th ` threads (t @ s)) = - (the_preced (t @ s) \ the_thread) (Th th)" (is "Max ?L = _") - proof - - have "?L = the_preced (t @ s) ` threads (t @ s)" - by (unfold image_comp, rule image_cong, auto) - thus ?thesis using max_preced the_preced_def by auto - qed - qed - also have "... = ?R" - using th_cp_max th_cp_preced th_kept - the_preced_def vat_t.max_cp_readys_threads by auto - finally show ?thesis . - qed - -- {* Now, since @{term th'} holds the highest @{term cp} - and we have already show it is in @{term readys}, - it is @{term runing} by definition. *} - with `th' \ readys (t@s)` show ?thesis by (simp add: runing_def) - qed - -- {* It is easy to show @{term th'} is an ancestor of @{term th}: *} - moreover have "Th th' \ ancestors (RAG (t @ s)) (Th th)" - using `(Th th, Th th') \ (RAG (t @ s))\<^sup>+` by (auto simp:ancestors_def) - ultimately show ?thesis using that by metis -qed - -text {* - Now it is easy to see there is always a thread to run by case analysis - on whether thread @{term th} is running: if the answer is Yes, the - the running thread is obviously @{term th} itself; otherwise, the running - thread is the @{text th'} given by lemma @{thm th_blockedE}. -*} -lemma live: "runing (t@s) \ {}" -proof(cases "th \ runing (t@s)") - case True thus ?thesis by auto -next - case False - thus ?thesis using th_blockedE by auto -qed - -end -end - - - diff -r c3a42076b164 -r b32b3bd99150 Paper/ExtGG.ty --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Paper/ExtGG.ty Thu Sep 21 14:15:55 2017 +0100 @@ -0,0 +1,922 @@ +theory ExtGG +imports PrioG CpsG +begin + +text {* + The following two auxiliary lemmas are used to reason about @{term Max}. +*} +lemma image_Max_eqI: + assumes "finite B" + and "b \ B" + and "\ x \ B. f x \ f b" + shows "Max (f ` B) = f b" + using assms + using Max_eqI by blast + +lemma image_Max_subset: + assumes "finite A" + and "B \ A" + and "a \ B" + and "Max (f ` A) = f a" + shows "Max (f ` B) = f a" +proof(rule image_Max_eqI) + show "finite B" + using assms(1) assms(2) finite_subset by auto +next + show "a \ B" using assms by simp +next + show "\x\B. f x \ f a" + by (metis Max_ge assms(1) assms(2) assms(4) + finite_imageI image_eqI subsetCE) +qed + +text {* + The following locale @{text "highest_gen"} sets the basic context for our + investigation: supposing thread @{text th} holds the highest @{term cp}-value + in state @{text s}, which means the task for @{text th} is the + most urgent. We want to show that + @{text th} is treated correctly by PIP, which means + @{text th} will not be blocked unreasonably by other less urgent + threads. +*} +locale highest_gen = + fixes s th prio tm + assumes vt_s: "vt s" + and threads_s: "th \ threads s" + and highest: "preced th s = Max ((cp s)`threads s)" + -- {* The internal structure of @{term th}'s precedence is exposed:*} + and preced_th: "preced th s = Prc prio tm" + +-- {* @{term s} is a valid trace, so it will inherit all results derived for + a valid trace: *} +sublocale highest_gen < vat_s: valid_trace "s" + by (unfold_locales, insert vt_s, simp) + +context highest_gen +begin + +text {* + @{term tm} is the time when the precedence of @{term th} is set, so + @{term tm} must be a valid moment index into @{term s}. +*} +lemma lt_tm: "tm < length s" + by (insert preced_tm_lt[OF threads_s preced_th], simp) + +text {* + Since @{term th} holds the highest precedence and @{text "cp"} + is the highest precedence of all threads in the sub-tree of + @{text "th"} and @{text th} is among these threads, + its @{term cp} must equal to its precedence: +*} +lemma eq_cp_s_th: "cp s th = preced th s" (is "?L = ?R") +proof - + have "?L \ ?R" + by (unfold highest, rule Max_ge, + auto simp:threads_s finite_threads) + moreover have "?R \ ?L" + by (unfold vat_s.cp_rec, rule Max_ge, + auto simp:the_preced_def vat_s.fsbttRAGs.finite_children) + ultimately show ?thesis by auto +qed + +(* ccc *) +lemma highest_cp_preced: "cp s th = Max ((\ th'. preced th' s) ` threads s)" + by (fold max_cp_eq, unfold eq_cp_s_th, insert highest, simp) + +lemma highest_preced_thread: "preced th s = Max ((\ th'. preced th' s) ` threads s)" + by (fold eq_cp_s_th, unfold highest_cp_preced, simp) + +lemma highest': "cp s th = Max (cp s ` threads s)" +proof - + from highest_cp_preced max_cp_eq[symmetric] + show ?thesis by simp +qed + +end + +locale extend_highest_gen = highest_gen + + fixes t + assumes vt_t: "vt (t@s)" + and create_low: "Create th' prio' \ set t \ prio' \ prio" + and set_diff_low: "Set th' prio' \ set t \ th' \ th \ prio' \ prio" + and exit_diff: "Exit th' \ set t \ th' \ th" + +sublocale extend_highest_gen < vat_t: valid_trace "t@s" + by (unfold_locales, insert vt_t, simp) + +lemma step_back_vt_app: + assumes vt_ts: "vt (t@s)" + shows "vt s" +proof - + from vt_ts show ?thesis + proof(induct t) + case Nil + from Nil show ?case by auto + next + case (Cons e t) + assume ih: " vt (t @ s) \ vt s" + and vt_et: "vt ((e # t) @ s)" + show ?case + proof(rule ih) + show "vt (t @ s)" + proof(rule step_back_vt) + from vt_et show "vt (e # t @ s)" by simp + qed + qed + qed +qed + + +locale red_extend_highest_gen = extend_highest_gen + + fixes i::nat + +sublocale red_extend_highest_gen < red_moment: extend_highest_gen "s" "th" "prio" "tm" "(moment i t)" + apply (insert extend_highest_gen_axioms, subst (asm) (1) moment_restm_s [of i t, symmetric]) + apply (unfold extend_highest_gen_def extend_highest_gen_axioms_def, clarsimp) + by (unfold highest_gen_def, auto dest:step_back_vt_app) + + +context extend_highest_gen +begin + + lemma ind [consumes 0, case_names Nil Cons, induct type]: + assumes + h0: "R []" + and h2: "\ e t. \vt (t@s); step (t@s) e; + extend_highest_gen s th prio tm t; + extend_highest_gen s th prio tm (e#t); R t\ \ R (e#t)" + shows "R t" +proof - + from vt_t extend_highest_gen_axioms show ?thesis + proof(induct t) + from h0 show "R []" . + next + case (Cons e t') + assume ih: "\vt (t' @ s); extend_highest_gen s th prio tm t'\ \ R t'" + and vt_e: "vt ((e # t') @ s)" + and et: "extend_highest_gen s th prio tm (e # t')" + from vt_e and step_back_step have stp: "step (t'@s) e" by auto + from vt_e and step_back_vt have vt_ts: "vt (t'@s)" by auto + show ?case + proof(rule h2 [OF vt_ts stp _ _ _ ]) + show "R t'" + proof(rule ih) + from et show ext': "extend_highest_gen s th prio tm t'" + by (unfold extend_highest_gen_def extend_highest_gen_axioms_def, auto dest:step_back_vt) + next + from vt_ts show "vt (t' @ s)" . + qed + next + from et show "extend_highest_gen s th prio tm (e # t')" . + next + from et show ext': "extend_highest_gen s th prio tm t'" + by (unfold extend_highest_gen_def extend_highest_gen_axioms_def, auto dest:step_back_vt) + qed + qed +qed + + +lemma th_kept: "th \ threads (t @ s) \ + preced th (t@s) = preced th s" (is "?Q t") +proof - + show ?thesis + proof(induct rule:ind) + case Nil + from threads_s + show ?case + by auto + next + case (Cons e t) + interpret h_e: extend_highest_gen _ _ _ _ "(e # t)" using Cons by auto + interpret h_t: extend_highest_gen _ _ _ _ t using Cons by auto + show ?case + proof(cases e) + case (Create thread prio) + show ?thesis + proof - + from Cons and Create have "step (t@s) (Create thread prio)" by auto + hence "th \ thread" + proof(cases) + case thread_create + with Cons show ?thesis by auto + qed + hence "preced th ((e # t) @ s) = preced th (t @ s)" + by (unfold Create, auto simp:preced_def) + moreover note Cons + ultimately show ?thesis + by (auto simp:Create) + qed + next + case (Exit thread) + from h_e.exit_diff and Exit + have neq_th: "thread \ th" by auto + with Cons + show ?thesis + by (unfold Exit, auto simp:preced_def) + next + case (P thread cs) + with Cons + show ?thesis + by (auto simp:P preced_def) + next + case (V thread cs) + with Cons + show ?thesis + by (auto simp:V preced_def) + next + case (Set thread prio') + show ?thesis + proof - + from h_e.set_diff_low and Set + have "th \ thread" by auto + hence "preced th ((e # t) @ s) = preced th (t @ s)" + by (unfold Set, auto simp:preced_def) + moreover note Cons + ultimately show ?thesis + by (auto simp:Set) + qed + qed + qed +qed + +text {* + According to @{thm th_kept}, thread @{text "th"} has its living status + and precedence kept along the way of @{text "t"}. The following lemma + shows that this preserved precedence of @{text "th"} remains as the highest + along the way of @{text "t"}. + + The proof goes by induction over @{text "t"} using the specialized + induction rule @{thm ind}, followed by case analysis of each possible + operations of PIP. All cases follow the same pattern rendered by the + generalized introduction rule @{thm "image_Max_eqI"}. + + The very essence is to show that precedences, no matter whether they are newly introduced + or modified, are always lower than the one held by @{term "th"}, + which by @{thm th_kept} is preserved along the way. +*} +lemma max_kept: "Max (the_preced (t @ s) ` (threads (t@s))) = preced th s" +proof(induct rule:ind) + case Nil + from highest_preced_thread + show ?case + by (unfold the_preced_def, simp) +next + case (Cons e t) + interpret h_e: extend_highest_gen _ _ _ _ "(e # t)" using Cons by auto + interpret h_t: extend_highest_gen _ _ _ _ t using Cons by auto + show ?case + proof(cases e) + case (Create thread prio') + show ?thesis (is "Max (?f ` ?A) = ?t") + proof - + -- {* The following is the common pattern of each branch of the case analysis. *} + -- {* The major part is to show that @{text "th"} holds the highest precedence: *} + have "Max (?f ` ?A) = ?f th" + proof(rule image_Max_eqI) + show "finite ?A" using h_e.finite_threads by auto + next + show "th \ ?A" using h_e.th_kept by auto + next + show "\x\?A. ?f x \ ?f th" + proof + fix x + assume "x \ ?A" + hence "x = thread \ x \ threads (t@s)" by (auto simp:Create) + thus "?f x \ ?f th" + proof + assume "x = thread" + thus ?thesis + apply (simp add:Create the_preced_def preced_def, fold preced_def) + using Create h_e.create_low h_t.th_kept lt_tm preced_leI2 preced_th by force + next + assume h: "x \ threads (t @ s)" + from Cons(2)[unfolded Create] + have "x \ thread" using h by (cases, auto) + hence "?f x = the_preced (t@s) x" + by (simp add:Create the_preced_def preced_def) + hence "?f x \ Max (the_preced (t@s) ` threads (t@s))" + by (simp add: h_t.finite_threads h) + also have "... = ?f th" + by (metis Cons.hyps(5) h_e.th_kept the_preced_def) + finally show ?thesis . + qed + qed + qed + -- {* The minor part is to show that the precedence of @{text "th"} + equals to preserved one, given by the foregoing lemma @{thm th_kept} *} + also have "... = ?t" using h_e.th_kept the_preced_def by auto + -- {* Then it follows trivially that the precedence preserved + for @{term "th"} remains the maximum of all living threads along the way. *} + finally show ?thesis . + qed + next + case (Exit thread) + show ?thesis (is "Max (?f ` ?A) = ?t") + proof - + have "Max (?f ` ?A) = ?f th" + proof(rule image_Max_eqI) + show "finite ?A" using h_e.finite_threads by auto + next + show "th \ ?A" using h_e.th_kept by auto + next + show "\x\?A. ?f x \ ?f th" + proof + fix x + assume "x \ ?A" + hence "x \ threads (t@s)" by (simp add: Exit) + hence "?f x \ Max (?f ` threads (t@s))" + by (simp add: h_t.finite_threads) + also have "... \ ?f th" + apply (simp add:Exit the_preced_def preced_def, fold preced_def) + using Cons.hyps(5) h_t.th_kept the_preced_def by auto + finally show "?f x \ ?f th" . + qed + qed + also have "... = ?t" using h_e.th_kept the_preced_def by auto + finally show ?thesis . + qed + next + case (P thread cs) + with Cons + show ?thesis by (auto simp:preced_def the_preced_def) + next + case (V thread cs) + with Cons + show ?thesis by (auto simp:preced_def the_preced_def) + next + case (Set thread prio') + show ?thesis (is "Max (?f ` ?A) = ?t") + proof - + have "Max (?f ` ?A) = ?f th" + proof(rule image_Max_eqI) + show "finite ?A" using h_e.finite_threads by auto + next + show "th \ ?A" using h_e.th_kept by auto + next + show "\x\?A. ?f x \ ?f th" + proof + fix x + assume h: "x \ ?A" + show "?f x \ ?f th" + proof(cases "x = thread") + case True + moreover have "the_preced (Set thread prio' # t @ s) thread \ the_preced (t @ s) th" + proof - + have "the_preced (t @ s) th = Prc prio tm" + using h_t.th_kept preced_th by (simp add:the_preced_def) + moreover have "prio' \ prio" using Set h_e.set_diff_low by auto + ultimately show ?thesis by (insert lt_tm, auto simp:the_preced_def preced_def) + qed + ultimately show ?thesis + by (unfold Set, simp add:the_preced_def preced_def) + next + case False + then have "?f x = the_preced (t@s) x" + by (simp add:the_preced_def preced_def Set) + also have "... \ Max (the_preced (t@s) ` threads (t@s))" + using Set h h_t.finite_threads by auto + also have "... = ?f th" by (metis Cons.hyps(5) h_e.th_kept the_preced_def) + finally show ?thesis . + qed + qed + qed + also have "... = ?t" using h_e.th_kept the_preced_def by auto + finally show ?thesis . + qed + qed +qed + +lemma max_preced: "preced th (t@s) = Max (the_preced (t@s) ` (threads (t@s)))" + by (insert th_kept max_kept, auto) + +text {* + The reason behind the following lemma is that: + Since @{term "cp"} is defined as the maximum precedence + of those threads contained in the sub-tree of node @{term "Th th"} + in @{term "RAG (t@s)"}, and all these threads are living threads, and + @{term "th"} is also among them, the maximum precedence of + them all must be the one for @{text "th"}. +*} +lemma th_cp_max_preced: + "cp (t@s) th = Max (the_preced (t@s) ` (threads (t@s)))" (is "?L = ?R") +proof - + let ?f = "the_preced (t@s)" + have "?L = ?f th" + proof(unfold cp_alt_def, rule image_Max_eqI) + show "finite {th'. Th th' \ subtree (RAG (t @ s)) (Th th)}" + proof - + have "{th'. Th th' \ subtree (RAG (t @ s)) (Th th)} = + the_thread ` {n . n \ subtree (RAG (t @ s)) (Th th) \ + (\ th'. n = Th th')}" + by (smt Collect_cong Setcompr_eq_image mem_Collect_eq the_thread.simps) + moreover have "finite ..." by (simp add: vat_t.fsbtRAGs.finite_subtree) + ultimately show ?thesis by simp + qed + next + show "th \ {th'. Th th' \ subtree (RAG (t @ s)) (Th th)}" + by (auto simp:subtree_def) + next + show "\x\{th'. Th th' \ subtree (RAG (t @ s)) (Th th)}. + the_preced (t @ s) x \ the_preced (t @ s) th" + proof + fix th' + assume "th' \ {th'. Th th' \ subtree (RAG (t @ s)) (Th th)}" + hence "Th th' \ subtree (RAG (t @ s)) (Th th)" by auto + moreover have "... \ Field (RAG (t @ s)) \ {Th th}" + by (meson subtree_Field) + ultimately have "Th th' \ ..." by auto + hence "th' \ threads (t@s)" + proof + assume "Th th' \ {Th th}" + thus ?thesis using th_kept by auto + next + assume "Th th' \ Field (RAG (t @ s))" + thus ?thesis using vat_t.not_in_thread_isolated by blast + qed + thus "the_preced (t @ s) th' \ the_preced (t @ s) th" + by (metis Max_ge finite_imageI finite_threads image_eqI + max_kept th_kept the_preced_def) + qed + qed + also have "... = ?R" by (simp add: max_preced the_preced_def) + finally show ?thesis . +qed + +lemma th_cp_max: "cp (t@s) th = Max (cp (t@s) ` threads (t@s))" + using max_cp_eq th_cp_max_preced the_preced_def vt_t by presburger + +lemma th_cp_preced: "cp (t@s) th = preced th s" + by (fold max_kept, unfold th_cp_max_preced, simp) + +lemma preced_less: + assumes th'_in: "th' \ threads s" + and neq_th': "th' \ th" + shows "preced th' s < preced th s" + using assms +by (metis Max.coboundedI finite_imageI highest not_le order.trans + preced_linorder rev_image_eqI threads_s vat_s.finite_threads + vat_s.le_cp) + +text {* + Counting of the number of @{term "P"} and @{term "V"} operations + is the cornerstone of a large number of the following proofs. + The reason is that this counting is quite easy to calculate and + convenient to use in the reasoning. + + The following lemma shows that the counting controls whether + a thread is running or not. +*} + +lemma pv_blocked_pre: + assumes th'_in: "th' \ threads (t@s)" + and neq_th': "th' \ th" + and eq_pv: "cntP (t@s) th' = cntV (t@s) th'" + shows "th' \ runing (t@s)" +proof + assume otherwise: "th' \ runing (t@s)" + show False + proof - + have "th' = th" + proof(rule preced_unique) + show "preced th' (t @ s) = preced th (t @ s)" (is "?L = ?R") + proof - + have "?L = cp (t@s) th'" + by (unfold cp_eq_cpreced cpreced_def count_eq_dependants[OF eq_pv], simp) + also have "... = cp (t @ s) th" using otherwise + by (metis (mono_tags, lifting) mem_Collect_eq + runing_def th_cp_max vat_t.max_cp_readys_threads) + also have "... = ?R" by (metis th_cp_preced th_kept) + finally show ?thesis . + qed + qed (auto simp: th'_in th_kept) + moreover have "th' \ th" using neq_th' . + ultimately show ?thesis by simp + qed +qed + +lemmas pv_blocked = pv_blocked_pre[folded detached_eq] + +lemma runing_precond_pre: + fixes th' + assumes th'_in: "th' \ threads s" + and eq_pv: "cntP s th' = cntV s th'" + and neq_th': "th' \ th" + shows "th' \ threads (t@s) \ + cntP (t@s) th' = cntV (t@s) th'" +proof(induct rule:ind) + case (Cons e t) + interpret vat_t: extend_highest_gen s th prio tm t using Cons by simp + interpret vat_e: extend_highest_gen s th prio tm "(e # t)" using Cons by simp + show ?case + proof(cases e) + case (P thread cs) + show ?thesis + proof - + have "cntP ((e # t) @ s) th' = cntV ((e # t) @ s) th'" + proof - + have "thread \ th'" + proof - + have "step (t@s) (P thread cs)" using Cons P by auto + thus ?thesis + proof(cases) + assume "thread \ runing (t@s)" + moreover have "th' \ runing (t@s)" using Cons(5) + by (metis neq_th' vat_t.pv_blocked_pre) + ultimately show ?thesis by auto + qed + qed with Cons show ?thesis + by (unfold P, simp add:cntP_def cntV_def count_def) + qed + moreover have "th' \ threads ((e # t) @ s)" using Cons by (unfold P, simp) + ultimately show ?thesis by auto + qed + next + case (V thread cs) + show ?thesis + proof - + have "cntP ((e # t) @ s) th' = cntV ((e # t) @ s) th'" + proof - + have "thread \ th'" + proof - + have "step (t@s) (V thread cs)" using Cons V by auto + thus ?thesis + proof(cases) + assume "thread \ runing (t@s)" + moreover have "th' \ runing (t@s)" using Cons(5) + by (metis neq_th' vat_t.pv_blocked_pre) + ultimately show ?thesis by auto + qed + qed with Cons show ?thesis + by (unfold V, simp add:cntP_def cntV_def count_def) + qed + moreover have "th' \ threads ((e # t) @ s)" using Cons by (unfold V, simp) + ultimately show ?thesis by auto + qed + next + case (Create thread prio') + show ?thesis + proof - + have "cntP ((e # t) @ s) th' = cntV ((e # t) @ s) th'" + proof - + have "thread \ th'" + proof - + have "step (t@s) (Create thread prio')" using Cons Create by auto + thus ?thesis using Cons(5) by (cases, auto) + qed with Cons show ?thesis + by (unfold Create, simp add:cntP_def cntV_def count_def) + qed + moreover have "th' \ threads ((e # t) @ s)" using Cons by (unfold Create, simp) + ultimately show ?thesis by auto + qed + next + case (Exit thread) + show ?thesis + proof - + have neq_thread: "thread \ th'" + proof - + have "step (t@s) (Exit thread)" using Cons Exit by auto + thus ?thesis apply (cases) using Cons(5) + by (metis neq_th' vat_t.pv_blocked_pre) + qed + hence "cntP ((e # t) @ s) th' = cntV ((e # t) @ s) th'" using Cons + by (unfold Exit, simp add:cntP_def cntV_def count_def) + moreover have "th' \ threads ((e # t) @ s)" using Cons neq_thread + by (unfold Exit, simp) + ultimately show ?thesis by auto + qed + next + case (Set thread prio') + with Cons + show ?thesis + by (auto simp:cntP_def cntV_def count_def) + qed +next + case Nil + with assms + show ?case by auto +qed + +text {* Changing counting balance to detachedness *} +lemmas runing_precond_pre_dtc = runing_precond_pre + [folded vat_t.detached_eq vat_s.detached_eq] + +lemma runing_precond: + fixes th' + assumes th'_in: "th' \ threads s" + and neq_th': "th' \ th" + and is_runing: "th' \ runing (t@s)" + shows "cntP s th' > cntV s th'" + using assms +proof - + have "cntP s th' \ cntV s th'" + by (metis is_runing neq_th' pv_blocked_pre runing_precond_pre th'_in) + moreover have "cntV s th' \ cntP s th'" using vat_s.cnp_cnv_cncs by auto + ultimately show ?thesis by auto +qed + +lemma moment_blocked_pre: + assumes neq_th': "th' \ th" + and th'_in: "th' \ threads ((moment i t)@s)" + and eq_pv: "cntP ((moment i t)@s) th' = cntV ((moment i t)@s) th'" + shows "cntP ((moment (i+j) t)@s) th' = cntV ((moment (i+j) t)@s) th' \ + th' \ threads ((moment (i+j) t)@s)" +proof - + interpret h_i: red_extend_highest_gen _ _ _ _ _ i + by (unfold_locales) + interpret h_j: red_extend_highest_gen _ _ _ _ _ "i+j" + by (unfold_locales) + interpret h: extend_highest_gen "((moment i t)@s)" th prio tm "moment j (restm i t)" + proof(unfold_locales) + show "vt (moment i t @ s)" by (metis h_i.vt_t) + next + show "th \ threads (moment i t @ s)" by (metis h_i.th_kept) + next + show "preced th (moment i t @ s) = + Max (cp (moment i t @ s) ` threads (moment i t @ s))" + by (metis h_i.th_cp_max h_i.th_cp_preced h_i.th_kept) + next + show "preced th (moment i t @ s) = Prc prio tm" by (metis h_i.th_kept preced_th) + next + show "vt (moment j (restm i t) @ moment i t @ s)" + using moment_plus_split by (metis add.commute append_assoc h_j.vt_t) + next + fix th' prio' + assume "Create th' prio' \ set (moment j (restm i t))" + thus "prio' \ prio" using assms + by (metis Un_iff add.commute h_j.create_low moment_plus_split set_append) + next + fix th' prio' + assume "Set th' prio' \ set (moment j (restm i t))" + thus "th' \ th \ prio' \ prio" + by (metis Un_iff add.commute h_j.set_diff_low moment_plus_split set_append) + next + fix th' + assume "Exit th' \ set (moment j (restm i t))" + thus "th' \ th" + by (metis Un_iff add.commute h_j.exit_diff moment_plus_split set_append) + qed + show ?thesis + by (metis add.commute append_assoc eq_pv h.runing_precond_pre + moment_plus_split neq_th' th'_in) +qed + +lemma moment_blocked_eqpv: + assumes neq_th': "th' \ th" + and th'_in: "th' \ threads ((moment i t)@s)" + and eq_pv: "cntP ((moment i t)@s) th' = cntV ((moment i t)@s) th'" + and le_ij: "i \ j" + shows "cntP ((moment j t)@s) th' = cntV ((moment j t)@s) th' \ + th' \ threads ((moment j t)@s) \ + th' \ runing ((moment j t)@s)" +proof - + from moment_blocked_pre [OF neq_th' th'_in eq_pv, of "j-i"] and le_ij + have h1: "cntP ((moment j t)@s) th' = cntV ((moment j t)@s) th'" + and h2: "th' \ threads ((moment j t)@s)" by auto + moreover have "th' \ runing ((moment j t)@s)" + proof - + interpret h: red_extend_highest_gen _ _ _ _ _ j by (unfold_locales) + show ?thesis + using h.pv_blocked_pre h1 h2 neq_th' by auto + qed + ultimately show ?thesis by auto +qed + +(* The foregoing two lemmas are preparation for this one, but + in long run can be combined. Maybe I am wrong. +*) +lemma moment_blocked: + assumes neq_th': "th' \ th" + and th'_in: "th' \ threads ((moment i t)@s)" + and dtc: "detached (moment i t @ s) th'" + and le_ij: "i \ j" + shows "detached (moment j t @ s) th' \ + th' \ threads ((moment j t)@s) \ + th' \ runing ((moment j t)@s)" +proof - + interpret h_i: red_extend_highest_gen _ _ _ _ _ i by (unfold_locales) + interpret h_j: red_extend_highest_gen _ _ _ _ _ j by (unfold_locales) + have cnt_i: "cntP (moment i t @ s) th' = cntV (moment i t @ s) th'" + by (metis dtc h_i.detached_elim) + from moment_blocked_eqpv[OF neq_th' th'_in cnt_i le_ij] + show ?thesis by (metis h_j.detached_intro) +qed + +lemma runing_preced_inversion: + assumes runing': "th' \ runing (t@s)" + shows "cp (t@s) th' = preced th s" (is "?L = ?R") +proof - + have "?L = Max (cp (t @ s) ` readys (t @ s))" using assms + by (unfold runing_def, auto) + also have "\ = ?R" + by (metis th_cp_max th_cp_preced vat_t.max_cp_readys_threads) + finally show ?thesis . +qed + +text {* + The situation when @{term "th"} is blocked is analyzed by the following lemmas. +*} + +text {* + The following lemmas shows the running thread @{text "th'"}, if it is different from + @{term th}, must be live at the very beginning. By the term {\em the very beginning}, + we mean the moment where the formal investigation starts, i.e. the moment (or state) + @{term s}. +*} + +lemma runing_inversion_0: + assumes neq_th': "th' \ th" + and runing': "th' \ runing (t@s)" + shows "th' \ threads s" +proof - + -- {* The proof is by contradiction: *} + { assume otherwise: "\ ?thesis" + have "th' \ runing (t @ s)" + proof - + -- {* Since @{term "th'"} is running at time @{term "t@s"}, so it exists that time. *} + have th'_in: "th' \ threads (t@s)" using runing' by (simp add:runing_def readys_def) + -- {* However, @{text "th'"} does not exist at very beginning. *} + have th'_notin: "th' \ threads (moment 0 t @ s)" using otherwise + by (metis append.simps(1) moment_zero) + -- {* Therefore, there must be a moment during @{text "t"}, when + @{text "th'"} came into being. *} + -- {* Let us suppose the moment being @{text "i"}: *} + from p_split_gen[OF th'_in th'_notin] + obtain i where lt_its: "i < length t" + and le_i: "0 \ i" + and pre: " th' \ threads (moment i t @ s)" (is "th' \ threads ?pre") + and post: "(\i'>i. th' \ threads (moment i' t @ s))" by (auto) + interpret h_i: red_extend_highest_gen _ _ _ _ _ i by (unfold_locales) + interpret h_i': red_extend_highest_gen _ _ _ _ _ "(Suc i)" by (unfold_locales) + from lt_its have "Suc i \ length t" by auto + -- {* Let us also suppose the event which makes this change is @{text e}: *} + from moment_head[OF this] obtain e where + eq_me: "moment (Suc i) t = e # moment i t" by blast + hence "vt (e # (moment i t @ s))" by (metis append_Cons h_i'.vt_t) + hence "PIP (moment i t @ s) e" by (cases, simp) + -- {* It can be derived that this event @{text "e"}, which + gives birth to @{term "th'"} must be a @{term "Create"}: *} + from create_pre[OF this, of th'] + obtain prio where eq_e: "e = Create th' prio" + by (metis append_Cons eq_me lessI post pre) + have h1: "th' \ threads (moment (Suc i) t @ s)" using post by auto + have h2: "cntP (moment (Suc i) t @ s) th' = cntV (moment (Suc i) t@ s) th'" + proof - + have "cntP (moment i t@s) th' = cntV (moment i t@s) th'" + by (metis h_i.cnp_cnv_eq pre) + thus ?thesis by (simp add:eq_me eq_e cntP_def cntV_def count_def) + qed + show ?thesis + using moment_blocked_eqpv [OF neq_th' h1 h2, of "length t"] lt_its moment_ge + by auto + qed + with `th' \ runing (t@s)` + have False by simp + } thus ?thesis by auto +qed + +text {* + The second lemma says, if the running thread @{text th'} is different from + @{term th}, then this @{text th'} must in the possession of some resources + at the very beginning. + + To ease the reasoning of resource possession of one particular thread, + we used two auxiliary functions @{term cntV} and @{term cntP}, + which are the counters of @{term P}-operations and + @{term V}-operations respectively. + If the number of @{term V}-operation is less than the number of + @{term "P"}-operations, the thread must have some unreleased resource. +*} + +lemma runing_inversion_1: (* ddd *) + assumes neq_th': "th' \ th" + and runing': "th' \ runing (t@s)" + -- {* thread @{term "th'"} is a live on in state @{term "s"} and + it has some unreleased resource. *} + shows "th' \ threads s \ cntV s th' < cntP s th'" +proof - + -- {* The proof is a simple composition of @{thm runing_inversion_0} and + @{thm runing_precond}: *} + -- {* By applying @{thm runing_inversion_0} to assumptions, + it can be shown that @{term th'} is live in state @{term s}: *} + have "th' \ threads s" using runing_inversion_0[OF assms(1,2)] . + -- {* Then the thesis is derived easily by applying @{thm runing_precond}: *} + with runing_precond [OF this neq_th' runing'] show ?thesis by simp +qed + +text {* + The following lemma is just a rephrasing of @{thm runing_inversion_1}: +*} +lemma runing_inversion_2: + assumes runing': "th' \ runing (t@s)" + shows "th' = th \ (th' \ th \ th' \ threads s \ cntV s th' < cntP s th')" +proof - + from runing_inversion_1[OF _ runing'] + show ?thesis by auto +qed + +lemma runing_inversion_3: + assumes runing': "th' \ runing (t@s)" + and neq_th: "th' \ th" + shows "th' \ threads s \ (cntV s th' < cntP s th' \ cp (t@s) th' = preced th s)" + by (metis neq_th runing' runing_inversion_2 runing_preced_inversion) + +lemma runing_inversion_4: + assumes runing': "th' \ runing (t@s)" + and neq_th: "th' \ th" + shows "th' \ threads s" + and "\detached s th'" + and "cp (t@s) th' = preced th s" + apply (metis neq_th runing' runing_inversion_2) + apply (metis neq_th pv_blocked runing' runing_inversion_2 runing_precond_pre_dtc) + by (metis neq_th runing' runing_inversion_3) + + +text {* + Suppose @{term th} is not running, it is first shown that + there is a path in RAG leading from node @{term th} to another thread @{text "th'"} + in the @{term readys}-set (So @{text "th'"} is an ancestor of @{term th}}). + + Now, since @{term readys}-set is non-empty, there must be + one in it which holds the highest @{term cp}-value, which, by definition, + is the @{term runing}-thread. However, we are going to show more: this running thread + is exactly @{term "th'"}. + *} +lemma th_blockedE: (* ddd *) + assumes "th \ runing (t@s)" + obtains th' where "Th th' \ ancestors (RAG (t @ s)) (Th th)" + "th' \ runing (t@s)" +proof - + -- {* According to @{thm vat_t.th_chain_to_ready}, either + @{term "th"} is in @{term "readys"} or there is path leading from it to + one thread in @{term "readys"}. *} + have "th \ readys (t @ s) \ (\th'. th' \ readys (t @ s) \ (Th th, Th th') \ (RAG (t @ s))\<^sup>+)" + using th_kept vat_t.th_chain_to_ready by auto + -- {* However, @{term th} can not be in @{term readys}, because otherwise, since + @{term th} holds the highest @{term cp}-value, it must be @{term "runing"}. *} + moreover have "th \ readys (t@s)" + using assms runing_def th_cp_max vat_t.max_cp_readys_threads by auto + -- {* So, there must be a path from @{term th} to another thread @{text "th'"} in + term @{term readys}: *} + ultimately obtain th' where th'_in: "th' \ readys (t@s)" + and dp: "(Th th, Th th') \ (RAG (t @ s))\<^sup>+" by auto + -- {* We are going to show that this @{term th'} is running. *} + have "th' \ runing (t@s)" + proof - + -- {* We only need to show that this @{term th'} holds the highest @{term cp}-value: *} + have "cp (t@s) th' = Max (cp (t@s) ` readys (t@s))" (is "?L = ?R") + proof - + have "?L = Max ((the_preced (t @ s) \ the_thread) ` subtree (tRAG (t @ s)) (Th th'))" + by (unfold cp_alt_def1, simp) + also have "... = (the_preced (t @ s) \ the_thread) (Th th)" + proof(rule image_Max_subset) + show "finite (Th ` (threads (t@s)))" by (simp add: vat_t.finite_threads) + next + show "subtree (tRAG (t @ s)) (Th th') \ Th ` threads (t @ s)" + by (metis Range.intros dp trancl_range vat_t.range_in vat_t.subtree_tRAG_thread) + next + show "Th th \ subtree (tRAG (t @ s)) (Th th')" using dp + by (unfold tRAG_subtree_eq, auto simp:subtree_def) + next + show "Max ((the_preced (t @ s) \ the_thread) ` Th ` threads (t @ s)) = + (the_preced (t @ s) \ the_thread) (Th th)" (is "Max ?L = _") + proof - + have "?L = the_preced (t @ s) ` threads (t @ s)" + by (unfold image_comp, rule image_cong, auto) + thus ?thesis using max_preced the_preced_def by auto + qed + qed + also have "... = ?R" + using th_cp_max th_cp_preced th_kept + the_preced_def vat_t.max_cp_readys_threads by auto + finally show ?thesis . + qed + -- {* Now, since @{term th'} holds the highest @{term cp} + and we have already show it is in @{term readys}, + it is @{term runing} by definition. *} + with `th' \ readys (t@s)` show ?thesis by (simp add: runing_def) + qed + -- {* It is easy to show @{term th'} is an ancestor of @{term th}: *} + moreover have "Th th' \ ancestors (RAG (t @ s)) (Th th)" + using `(Th th, Th th') \ (RAG (t @ s))\<^sup>+` by (auto simp:ancestors_def) + ultimately show ?thesis using that by metis +qed + +text {* + Now it is easy to see there is always a thread to run by case analysis + on whether thread @{term th} is running: if the answer is Yes, the + the running thread is obviously @{term th} itself; otherwise, the running + thread is the @{text th'} given by lemma @{thm th_blockedE}. +*} +lemma live: "runing (t@s) \ {}" +proof(cases "th \ runing (t@s)") + case True thus ?thesis by auto +next + case False + thus ?thesis using th_blockedE by auto +qed + +end +end + + + diff -r c3a42076b164 -r b32b3bd99150 Test.thy --- a/Test.thy Thu Sep 07 16:04:03 2017 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,789 +0,0 @@ -theory Test -imports Precedence_ord Graphs -begin - -type_synonym thread = nat -- {* Type for thread identifiers. *} -type_synonym priority = nat -- {* Type for priorities. *} -type_synonym cs = nat -- {* Type for critical sections (or resources). *} - --- {* Schedulling Events *} - -datatype event = - Create thread priority -| Exit thread -| P thread cs -| V thread cs -| Set thread priority - -type_synonym state = "event list" - -fun threads :: "state \ thread set" - where - "threads [] = {}" -| "threads (Create th prio#s) = {th} \ threads s" -| "threads (Exit th # s) = (threads s) - {th}" -| "threads (_#s) = threads s" - -fun priority :: "thread \ state \ priority" - where - "priority th [] = 0" -| "priority th (Create th' prio#s) = (if th' = th then prio else priority th s)" -| "priority th (Set th' prio#s) = (if th' = th then prio else priority th s)" -| "priority th (_#s) = priority th s" - -fun last_set :: "thread \ state \ nat" - where - "last_set th [] = 0" -| "last_set th ((Create th' prio)#s) = (if (th = th') then length s else last_set th s)" -| "last_set th ((Set th' prio)#s) = (if (th = th') then length s else last_set th s)" -| "last_set th (_#s) = last_set th s" - - -definition preced :: "thread \ state \ precedence" - where "preced th s \ Prc (priority th s) (last_set th s)" - -abbreviation - "preceds s ths \ {preced th s | th. th \ ths}" - -definition - "holds wq th cs \ th \ set (wq cs) \ th = hd (wq cs)" - -definition - "waits wq th cs \ th \ set (wq cs) \ th \ hd (wq cs)" - ---{* Nodes in Resource Graph *} -datatype node = - Th "thread" -| Cs "cs" - -definition - "RAG wq \ {(Th th, Cs cs) | th cs. waits wq th cs} \ {(Cs cs, Th th) | cs th. holds wq th cs}" - -definition - "dependants wq th \ {th' . (Th th', Th th) \ (RAG wq)^+}" - -record schedule_state = - wq_fun :: "cs \ thread list" - cprec_fun :: "thread \ precedence" - -definition cpreced :: "(cs \ thread list) \ state \ thread \ precedence" - where - "cpreced wq s th \ Max ({preced th s} \ {preced th' s | th'. th' \ dependants wq th})" - -abbreviation - "all_unlocked \ \_::cs. ([]::thread list)" - -abbreviation - "initial_cprec \ \_::thread. Prc 0 0" - -abbreviation - "release qs \ case qs of - [] => [] - | (_ # qs) => SOME q. distinct q \ set q = set qs" - -lemma [simp]: - "(SOME q. distinct q \ q = []) = []" -by auto - -lemma [simp]: - "(x \ set (SOME q. distinct q \ set q = set p)) = (x \ set p)" -apply(rule iffI) -apply (metis (mono_tags, lifting) List.finite_set finite_distinct_list some_eq_ex)+ -done - -abbreviation - "next_to_run ths \ hd (SOME q::thread list. distinct q \ set q = set ths)" - - -fun schs :: "state \ schedule_state" - where - "schs [] = (| wq_fun = \ cs. [], cprec_fun = (\_. Prc 0 0) |)" -| "schs (Create th prio # s) = - (let wq = wq_fun (schs s) in - (|wq_fun = wq, cprec_fun = cpreced wq (Create th prio # s)|))" -| "schs (Exit th # s) = - (let wq = wq_fun (schs s) in - (|wq_fun = wq, cprec_fun = cpreced wq (Exit th # s)|))" -| "schs (Set th prio # s) = - (let wq = wq_fun (schs s) in - (|wq_fun = wq, cprec_fun = cpreced wq (Set th prio # s)|))" -| "schs (P th cs # s) = - (let wq = wq_fun (schs s) in - let new_wq = wq(cs := (wq cs @ [th])) in - (|wq_fun = new_wq, cprec_fun = cpreced new_wq (P th cs # s)|))" -| "schs (V th cs # s) = - (let wq = wq_fun (schs s) in - let new_wq = wq(cs := release (wq cs)) in - (|wq_fun = new_wq, cprec_fun = cpreced new_wq (V th cs # s)|))" - -definition wq :: "state \ cs \ thread list" - where "wq s = wq_fun (schs s)" - -definition cpreced2 :: "state \ thread \ precedence" - where "cpreced2 s \ cprec_fun (schs s)" - -abbreviation - "cpreceds2 s ths \ {cpreced2 s th | th. th \ ths}" - -definition - "holds2 s \ holds (wq_fun (schs s))" - -definition - "waits2 s \ waits (wq_fun (schs s))" - -definition - "RAG2 s \ RAG (wq_fun (schs s))" - -definition - "dependants2 s \ dependants (wq_fun (schs s))" - -(* ready -> is a thread that is not waiting for any resource *) -definition readys :: "state \ thread set" - where "readys s \ {th . th \ threads s \ (\ cs. \ waits2 s th cs)}" - -definition runing :: "state \ thread set" - where "runing s \ {th . th \ readys s \ cpreced2 s th = Max (cpreceds2 s (readys s))}" - -(* all resources a thread hols in a state *) -definition holding :: "state \ thread \ cs set" - where "holding s th \ {cs . holds2 s th cs}" - - -lemma exists_distinct: - obtains ys where "distinct ys" "set ys = set xs" -by (metis List.finite_set finite_distinct_list) - -lemma next_to_run_set [simp]: - "wts \ [] \ next_to_run wts \ set wts" -apply(rule exists_distinct[of wts]) -by (metis (mono_tags, lifting) hd_in_set set_empty some_eq_ex) - -lemma holding_RAG: - "holding s th = {cs . (Cs cs, Th th) \ RAG2 s}" -unfolding holding_def RAG2_def RAG_def -unfolding holds2_def holds_def waits_def -by auto - -inductive step :: "state \ event \ bool" - where - step_Create: "\th \ threads s\ \ step s (Create th prio)" -| step_Exit: "\th \ runing s; holding s th = {}\ \ step s (Exit th)" -| step_P: "\th \ runing s; (Cs cs, Th th) \ (RAG2 s)^+\ \ step s (P th cs)" -| step_V: "\th \ runing s; holds2 s th cs\ \ step s (V th cs)" -| step_Set: "\th \ runing s\ \ step s (Set th prio)" - -(* valid states *) -inductive vt :: "state \ bool" - where - vt_nil[intro]: "vt []" -| vt_cons[intro]: "\vt s; step s e\ \ vt (e#s)" - -lemma runing_ready: - shows "runing s \ readys s" - unfolding runing_def readys_def - by auto - -lemma readys_threads: - shows "readys s \ threads s" - unfolding readys_def - by auto - -lemma wq_threads: - assumes vt: "vt s" - and h: "th \ set (wq s cs)" - shows "th \ threads s" -using assms -apply(induct) -apply(simp add: wq_def) -apply(erule step.cases) -apply(auto simp add: wq_def Let_def holding_def holds2_def holds_def waits2_def runing_def readys_def) -apply(simp add: waits_def) -apply(auto simp add: waits_def split: if_splits)[1] -apply(auto split: if_splits) -apply(simp only: waits_def) -by (metis insert_iff set_simps(2)) - - - -lemma Domain_RAG_threads: - assumes vt: "vt s" - and in_dom: "(Th th) \ Domain (RAG2 s)" - shows "th \ threads s" -proof - - from in_dom obtain n where "(Th th, n) \ RAG2 s" by auto - then obtain cs where "n = Cs cs" "(Th th, Cs cs) \ RAG2 s" - unfolding RAG2_def RAG_def by auto - then have "th \ set (wq s cs)" - unfolding wq_def RAG_def RAG2_def waits_def by auto - with wq_threads [OF vt] show ?thesis . -qed - -lemma dependants_threads: - assumes vt: "vt s" - shows "dependants2 s th \ threads s" -proof - fix th1 - assume "th1 \ dependants2 s th" - then have h: "(Th th1, Th th) \ (RAG2 s)\<^sup>+" - unfolding dependants2_def dependants_def RAG2_def by simp - then have "Th th1 \ Domain ((RAG2 s)\<^sup>+)" unfolding Domain_def by auto - then have "Th th1 \ Domain (RAG2 s)" using trancl_domain by simp - then show "th1 \ threads s" using vt by (rule_tac Domain_RAG_threads) -qed - -lemma finite_threads: - assumes vt: "vt s" - shows "finite (threads s)" -using vt by (induct) (auto elim: step.cases) - - -section {* Distinctness of @{const wq} *} - -lemma wq_distinct_step: - assumes "step s e" "distinct (wq s cs)" - shows "distinct (wq (e # s) cs)" -using assms -unfolding wq_def -apply(erule_tac step.cases) -apply(auto simp add: RAG2_def RAG_def Let_def)[1] -apply(auto simp add: wq_def Let_def RAG2_def RAG_def holds_def runing_def waits2_def waits_def readys_def) -apply(auto split: list.split) -apply(rule someI2) -apply(auto) -done - -lemma wq_distinct: - assumes "vt s" - shows "distinct (wq s cs)" -using assms -apply(induct) -apply(simp add: wq_def) -apply(simp add: wq_distinct_step) -done - - -section {* Single_Valuedness of @{const waits2}, @{const holds2}, @{const RAG2} *} - -lemma waits2_unique: - assumes "vt s" - and "waits2 s th cs1" - and "waits2 s th cs2" - shows "cs1 = cs2" -using assms -apply(induct) -apply(simp add: waits2_def waits_def) -apply(erule step.cases) -apply(auto simp add: Let_def waits2_def waits_def holds_def RAG2_def RAG_def - readys_def runing_def split: if_splits) -apply (metis Nil_is_append_conv hd_append2 list.distinct(1) split_list) -apply (metis Nil_is_append_conv hd_append2 list.distinct(1) split_list) -apply (metis distinct.simps(2) distinct_length_2_or_more list.sel(1) wq_def wq_distinct) -by (metis (full_types, hide_lams) distinct.simps(2) distinct_length_2_or_more list.sel(1) wq_def wq_distinct) - -lemma single_valued_waits2: - assumes "vt s" - shows "single_valuedP (waits2 s)" -using assms -unfolding single_valued_def -by (simp add: Product_Type.Collect_case_prodD waits2_unique) - -lemma single_valued_holds2: - assumes "vt s" - shows "single_valuedP (\cs th. holds2 s th cs)" -unfolding single_valued_def holds2_def holds_def by simp - -lemma single_valued_RAG2: - assumes "vt s" - shows "single_valued (RAG2 s)" -using single_valued_waits2[OF assms] single_valued_holds2[OF assms] -unfolding RAG2_def RAG_def -apply(rule_tac single_valued_union) -unfolding holds2_def[symmetric] waits2_def[symmetric] -apply(rule single_valued_Collect) -apply(simp) -apply(simp add: inj_on_def) -apply(rule single_valued_Collect) -apply(simp) -apply(simp add: inj_on_def) -apply(auto) -done - - -section {* Properties of @{const RAG2} under events *} - -lemma RAG_Set [simp]: - shows "RAG2 (Set th prio # s) = RAG2 s" -unfolding RAG2_def -by (simp add: Let_def) - -lemma RAG_Create [simp]: - "RAG2 (Create th prio # s) = RAG2 s" -unfolding RAG2_def -by (simp add: Let_def) - -lemma RAG_Exit [simp]: - shows "RAG2 (Exit th # s) = RAG2 s" -unfolding RAG2_def -by (simp add: Let_def) - -lemma RAG_P1: - assumes "wq s cs = []" - shows "RAG2 (P th cs # s) \ RAG2 s \ {(Cs cs, Th th)}" -using assms -unfolding RAG2_def RAG_def wq_def Let_def waits_def holds_def -by (auto simp add: Let_def) - -lemma RAG_P2: - assumes "(Cs cs, Th th) \ (RAG2 s)\<^sup>+" "wq s cs \ []" - shows "RAG2 (P th cs # s) \ RAG2 s \ {(Th th, Cs cs)}" -using assms -unfolding RAG2_def RAG_def wq_def Let_def waits_def holds_def -by (auto simp add: Let_def) - - -lemma RAG_V1: -assumes vt: "wq s cs = [th]" -shows "RAG2 (V th cs # s) \ RAG2 s - {(Cs cs, Th th)}" -using assms -unfolding RAG2_def RAG_def waits_def holds_def wq_def -by (auto simp add: Let_def) - -lemma RAG_V2: -assumes vt:"vt s" "wq s cs = th # wts \ wts \ []" -shows "RAG2 (V th cs # s) \ - RAG2 s - {(Cs cs, Th th), (Th (next_to_run wts), Cs cs)} \ {(Cs cs, Th (next_to_run wts))}" -unfolding RAG2_def RAG_def waits_def holds_def -using assms wq_distinct[OF vt(1), of"cs"] -by (auto simp add: Let_def wq_def) - - - -section {* Acyclicity of @{const RAG2} *} - -lemma acyclic_RAG_step: - assumes vt: "vt s" - and stp: "step s e" - and ac: "acyclic (RAG2 s)" - shows "acyclic (RAG2 (e # s))" -using stp vt ac -proof (induct) - case (step_P th s cs) - have ac: "acyclic (RAG2 s)" by fact - have ds: "(Cs cs, Th th) \ (RAG2 s)\<^sup>+" by fact - { assume wq_empty: "wq s cs = []" -- "case waiting queue is empty" - then have "(Th th, Cs cs) \ (RAG2 s)\<^sup>+" - proof (rule_tac notI) - assume "(Th th, Cs cs) \ (RAG2 s)\<^sup>+" - then obtain x where "(x, Cs cs) \ RAG2 s" using tranclD2 by metis - with wq_empty show False by (auto simp: RAG2_def RAG_def wq_def waits_def) - qed - with ac have "acyclic (RAG2 s \ {(Cs cs, Th th)})" by simp - then have "acyclic (RAG2 (P th cs # s))" using RAG_P1[OF wq_empty] - by (rule acyclic_subset) - } - moreover - { assume wq_not_empty: "wq s cs \ []" -- "case waiting queue is not empty" - from ac ds - have "acyclic (RAG2 s \ {(Th th, Cs cs)})" by simp - then have "acyclic (RAG2 (P th cs # s))" using RAG_P2[OF ds wq_not_empty] - by (rule acyclic_subset) - } - ultimately show "acyclic (RAG2 (P th cs # s))" by metis -next - case (step_V th s cs) -- "case for release of a lock" - have vt: "vt s" by fact - have ac: "acyclic (RAG2 s)" by fact - have hd: "holds2 s th cs" by fact - from vt have wq_distinct:"distinct (wq s cs)" by (rule wq_distinct) - from hd have "th \ set (wq s cs)" "th = hd (wq s cs)" unfolding holds2_def holds_def wq_def by auto - then obtain wts where eq_wq: "wq s cs = th # wts" by (cases "wq s cs") (auto) - -- "case no thread present in the waiting queue to take over" - { assume "wts = []" - with eq_wq have "wq s cs = [th]" by simp - then have "RAG2 (V th cs # s) \ RAG2 s - {(Cs cs, Th th)}" by (rule RAG_V1) - moreover have "acyclic (RAG2 s - {(Cs cs, Th th)})" using ac by (auto intro: acyclic_subset) - ultimately - have "acyclic (RAG2 (V th cs # s))" by (auto intro: acyclic_subset) - } - moreover - -- "at least one thread present to take over" - { def nth \ "next_to_run wts" - assume wq_not_empty: "wts \ []" - have "waits2 s nth cs" - using eq_wq wq_not_empty wq_distinct - unfolding nth_def waits2_def waits_def wq_def[symmetric] by auto - then have cs_in_RAG: "(Th nth, Cs cs) \ RAG2 s" - unfolding RAG2_def RAG_def waits2_def by auto - have "RAG2 (V th cs # s) \ RAG2 s - {(Cs cs, Th th), (Th nth, Cs cs)} \ {(Cs cs, Th nth)}" - unfolding nth_def using vt wq_not_empty eq_wq by (rule_tac RAG_V2) (auto) - moreover - have "acyclic (RAG2 s - {(Cs cs, Th th), (Th nth, Cs cs)} \ {(Cs cs, Th nth)})" - proof - - have "acyclic (RAG2 s - {(Cs cs, Th th), (Th nth, Cs cs)})" using ac by (auto intro: acyclic_subset) - moreover - have "(Th nth, Cs cs) \ (RAG2 s - {(Cs cs, Th th), (Th nth, Cs cs)})\<^sup>+" - proof (rule notI) - assume "(Th nth, Cs cs) \ (RAG2 s - {(Cs cs, Th th), (Th nth, Cs cs)})\<^sup>+" - then obtain z where a: "(Th nth, z) \ (RAG2 s - {(Cs cs, Th th), (Th nth, Cs cs)})" - by (metis converse_tranclE) - then have "(Th nth, z) \ RAG2 s" by simp - then have "z = Cs cs" using cs_in_RAG single_valued_RAG2[OF vt] - by (simp add: single_valued_def) - then show "False" using a by simp - qed - ultimately - show "acyclic (RAG2 s - {(Cs cs, Th th), (Th nth, Cs cs)} \ {(Cs cs, Th nth) })" by simp - qed - ultimately have "acyclic (RAG2 (V th cs # s))" - by (rule_tac acyclic_subset) - } - ultimately show "acyclic (RAG2 (V th cs # s))" by metis -qed (simp_all) - - -lemma finite_RAG: - assumes "vt s" - shows "finite (RAG2 s)" -using assms -apply(induct) -apply(simp add: RAG2_def RAG_def waits_def holds_def) -apply(erule step.cases) -apply(auto) -apply(case_tac "wq sa cs = []") -apply(rule finite_subset) -apply(rule RAG_P1) -apply(simp) -apply(simp) -apply(rule finite_subset) -apply(rule RAG_P2) -apply(simp) -apply(simp) -apply(simp) -apply(subgoal_tac "\wts. wq sa cs = th # wts") -apply(erule exE) -apply(case_tac "wts = []") -apply(rule finite_subset) -apply(rule RAG_V1) -apply(simp) -apply(simp) -apply(rule finite_subset) -apply(rule RAG_V2) -apply(simp) -apply(simp) -apply(simp) -apply(subgoal_tac "th \ set (wq sa cs) \ th = hd (wq sa cs)") -apply(case_tac "wq sa cs") -apply(auto)[2] -apply(auto simp add: holds2_def holds_def wq_def) -done - - - -lemma dchain_unique: - assumes vt: "vt s" - and th1_d: "(n, Th th1) \ (RAG2 s)^+" - and th1_r: "th1 \ readys s" - and th2_d: "(n, Th th2) \ (RAG2 s)^+" - and th2_r: "th2 \ readys s" - shows "th1 = th2" -proof(rule ccontr) - assume neq: "th1 \ th2" - with single_valued_confluent2 [OF single_valued_RAG2 [OF vt]] th1_d th2_d - have "(Th th1, Th th2) \ (RAG2 s)\<^sup>+ \ (Th th2, Th th1) \ (RAG2 s)\<^sup>+" by auto - moreover - { assume "(Th th1, Th th2) \ (RAG2 s)\<^sup>+" - then obtain n where dd: "(Th th1, n) \ RAG2 s" by (metis converse_tranclE) - then obtain cs where eq_n: "n = Cs cs" - unfolding RAG2_def RAG_def by (case_tac n) (auto) - from dd eq_n have "th1 \ readys s" - unfolding RAG2_def RAG_def waits2_def readys_def by (auto) - with th1_r have "False" by auto - } - moreover - { assume "(Th th2, Th th1) \ (RAG2 s)\<^sup>+" - then obtain n where dd: "(Th th2, n) \ RAG2 s" by (metis converse_tranclE) - then obtain cs where eq_n: "n = Cs cs" - unfolding RAG2_def RAG_def by (case_tac n) (auto) - from dd eq_n have "th2 \ readys s" - unfolding RAG2_def RAG_def waits2_def readys_def by (auto) - with th2_r have "False" by auto - } - ultimately show "False" by metis -qed - -lemma cpreced2_cpreced: "cpreced2 s th = cpreced (wq s) s th" -unfolding cpreced2_def wq_def -apply(induct s rule: schs.induct) -apply(simp add: Let_def cpreced_def dependants_def RAG_def waits_def holds_def preced_def) -apply(simp add: Let_def) -apply(simp add: Let_def) -apply(simp add: Let_def) -apply(subst (2) schs.simps) -apply(simp add: Let_def) -apply(subst (2) schs.simps) -apply(simp add: Let_def) -done - -lemma cpreced_Exit: - shows "cpreced2 (Exit th # s) th' = cpreced2 s th'" -by (simp add: cpreced2_cpreced cpreced_def preced_def wq_def Let_def) - -lemma readys_Exit: - shows "readys (Exit th # s) = readys s - {th}" -by (auto simp add: readys_def waits2_def Let_def) - -lemma readys_Create: - shows "readys (Create th prio # s) \ {th} \ readys s" -apply (auto simp add: readys_def waits2_def Let_def waits_def) -done - -lemma readys_Set: - shows "readys (Set th prio # s) = readys s" -by (auto simp add: readys_def waits2_def Let_def) - - -lemma readys_P: - shows "readys (P th cs # s) \ readys s" -apply(auto simp add: readys_def waits2_def Let_def) -apply(simp add: waits_def) -apply(case_tac "csa = cs") -apply(simp) -apply(drule_tac x="cs" in spec) -apply(simp) -apply (metis hd_append2 in_set_insert insert_Nil list.sel(1)) -apply(drule_tac x="csa" in spec) -apply(simp) -done - -lemma readys_V: - shows "readys (V th cs # s) \ readys s \ set (wq s cs)" -apply(auto simp add: readys_def waits2_def waits_def Let_def wq_def) -done - - -fun the_th :: "node \ thread" - where "the_th (Th th) = th" - -lemma image_Collect2: - "f ` A = {f x | x. x \ A}" -apply(auto) -done - -lemma Collect_disj_eq2: - "{f x | x. x = y \ x \ A} = {f y} \ {f x | x. x \ A}" -by (auto) - -lemma last_set_lt: - "th \ threads s \ last_set th s < length s" - apply(induct rule: threads.induct) - apply(auto) - done - -lemma last_set_eq_iff: - assumes "th1 \ threads s" "th2 \ threads s" - shows "last_set th1 s = last_set th2 s \ th1 = th2" - using assms - apply(induct s rule: threads.induct) - apply(auto split:if_splits dest:last_set_lt) - done - -lemma preced_eq_iff: - assumes th_in1: "th1 \ threads s" - and th_in2: "th2 \ threads s" - shows "preced th1 s = preced th2 s \ th1 = th2" -using assms -by (auto simp add: preced_def last_set_eq_iff) - -lemma dm_RAG_threads: - assumes vt: "vt s" - and in_dom: "(Th th) \ Domain (RAG2 s)" - shows "th \ threads s" -proof - - from in_dom obtain n where a: "(Th th, n) \ RAG2 s" by auto - then obtain cs where "n = Cs cs" - unfolding RAG2_def RAG_def - by auto - then have "(Th th, Cs cs) \ RAG2 s" using a by simp - hence "th \ set (wq s cs)" - unfolding RAG2_def wq_def RAG_def waits_def - by (auto) - then show ?thesis - apply(rule_tac wq_threads) - apply(rule assms) - apply(simp) - done -qed - -lemma cpreced_eq_iff: - assumes "th1 \ readys s" "th2 \ readys s" "vt s" - shows "cpreced2 s th1 = cpreced2 s th2 \ th1 = th2" -proof - def S1\"({th1} \ dependants (wq s) th1)" - def S2\"({th2} \ dependants (wq s) th2)" - have fin: "finite ((the_th o fst) ` ((RAG (wq s))\<^sup>+))" - apply(rule) - apply(simp add: finite_trancl) - apply(simp add: wq_def) - apply(rule finite_RAG[simplified RAG2_def]) - apply(rule assms) - done - - from fin have h: "finite (preceds s S1)" "finite (preceds s S2)" - apply(simp_all add: S2_def S1_def Collect_disj_eq2 image_Collect[symmetric]) - apply(rule) - apply(simp add: dependants_def) - apply(rule rev_finite_subset) - apply(assumption) - apply(auto simp add: image_def)[1] - apply(metis fst_conv the_th.simps) - apply(rule) - apply(simp add: dependants_def) - apply(rule rev_finite_subset) - apply(assumption) - apply(auto simp add: image_def)[1] - apply(metis fst_conv the_th.simps) - done - moreover have "S1 \ {}" "S2 \ {}" by (simp_all add: S1_def S2_def) - then have "(preceds s S1) \ {}" "(preceds s S2) \ {}" by simp_all - ultimately have m: "Max (preceds s S1) \ (preceds s S1)" "Max (preceds s S2) \ (preceds s S2)" - apply(rule_tac [!] Max_in) - apply(simp_all) - done - - assume q: "cpreced2 s th1 = cpreced2 s th2" - then have eq_max: "Max (preceds s S1) = Max (preceds s S2)" - unfolding cpreced2_cpreced cpreced_def - apply(simp only: S1_def S2_def) - apply(simp add: Collect_disj_eq2) - done - - obtain th0 where th0_in: "th0 \ S1" "th0 \ S2" and - eq_f_th1: "preced th0 s = Max (preceds s S1)" - "preced th0 s = Max (preceds s S2)" - using m - apply(clarify) - apply(simp add: eq_max) - apply(subst (asm) (2) preced_eq_iff) - apply(insert assms(2))[1] - apply(simp add: S2_def) - apply(auto)[1] - apply (metis contra_subsetD readys_threads) - apply(simp add: dependants_def) - apply(subgoal_tac "Th tha \ Domain ((RAG2 s)^+)") - apply(simp add: trancl_domain) - apply (metis Domain_RAG_threads assms(3)) - apply(simp only: RAG2_def wq_def) - apply (metis Domain_iff) - apply(insert assms(1))[1] - apply(simp add: S1_def) - apply(auto)[1] - apply (metis contra_subsetD readys_threads) - apply(simp add: dependants_def) - apply(subgoal_tac "Th th \ Domain ((RAG2 s)^+)") - apply(simp add: trancl_domain) - apply (metis Domain_RAG_threads assms(3)) - apply(simp only: RAG2_def wq_def) - apply (metis Domain_iff) - apply(simp) - done - then show "th1 = th2" - apply - - apply(insert th0_in assms(1, 2))[1] - apply(simp add: S1_def S2_def) - apply(auto) - --"first case" - prefer 2 - apply(subgoal_tac "Th th2 \ Domain (RAG2 s)") - apply(subgoal_tac "\cs. (Th th2, Cs cs) \ RAG2 s") - apply(erule exE) - apply(simp add: runing_def RAG2_def RAG_def readys_def waits2_def)[1] - apply(auto simp add: RAG2_def RAG_def)[1] - apply(subgoal_tac "Th th2 \ Domain ((RAG2 s)^+)") - apply (metis trancl_domain) - apply(subgoal_tac "(Th th2, Th th1) \ (RAG2 s)^+") - apply (metis Domain_iff) - apply(simp add: dependants_def RAG2_def wq_def) - --"second case" - apply(subgoal_tac "Th th1 \ Domain (RAG2 s)") - apply(subgoal_tac "\cs. (Th th1, Cs cs) \ RAG2 s") - apply(erule exE) - apply(insert assms(1))[1] - apply(simp add: runing_def RAG2_def RAG_def readys_def waits2_def)[1] - apply(auto simp add: RAG2_def RAG_def)[1] - apply(subgoal_tac "Th th1 \ Domain ((RAG2 s)^+)") - apply (metis trancl_domain) - apply(subgoal_tac "(Th th1, Th th2) \ (RAG2 s)^+") - apply (metis Domain_iff) - apply(simp add: dependants_def RAG2_def wq_def) - --"third case" - apply(rule dchain_unique) - apply(rule assms(3)) - apply(simp add: dependants_def RAG2_def wq_def) - apply(simp) - apply(simp add: dependants_def RAG2_def wq_def) - apply(simp) - done -next - assume "th1 = th2" - then show "cpreced2 s th1 = cpreced2 s th2" by simp -qed - -lemma at_most_one_running: - assumes "vt s" - shows "card (runing s) \ 1" -proof (rule ccontr) - assume "\ card (runing s) \ 1" - then have "2 \ card (runing s)" by auto - moreover - have "finite (runing s)" - by (metis `\ card (runing s) \ 1` card_infinite le0) - ultimately obtain th1 th2 where a: - "th1 \ th2" "th1 \ runing s" "th2 \ runing s" - "cpreced2 s th1 = cpreced2 s th2" - apply(auto simp add: numerals card_le_Suc_iff runing_def) - apply(blast) - done - then have "th1 = th2" - apply(subst (asm) cpreced_eq_iff) - apply(auto intro: assms a) - apply (metis contra_subsetD runing_ready)+ - done - then show "False" using a(1) by auto -qed - - - - (* - obtain th0 where th0_in: "th0 \ S1 \ th0 \ S2" - and eq_f_th0: "preced th0 s = Max ((\th. preced th s) ` (S1 \ S2))" - proof - - from fin have h1: "finite ((\th. preced th s) ` (S1 \ S2))" - apply(simp only: S1_def S2_def) - apply(rule) - apply(rule) - apply(rule) - apply(simp add: dependants_def) - apply(rule rev_finite_subset) - apply(assumption) - apply(auto simp add: image_def) - apply (metis fst_conv the_th.simps) - done - moreover - have "S1 \ S2 \ {}" apply (simp add: S1_def S2_def) - apply(auto) - - done - then have h2: "((\th. preced th s) ` (S1 \ S2)) \ {}" by simp - ultimately have "Max ((\th. preced th s) ` (S1 \ S2)) \ ((\th. preced th s) ` (S1 \ S2))" - apply(rule Max_in) - done - then show ?thesis using that[intro] apply(auto) - - apply(erule_tac preced_unique) - done - qed - *) - -thm waits_def waits2_def - -end diff -r c3a42076b164 -r b32b3bd99150 draf.txt --- a/draf.txt Thu Sep 07 16:04:03 2017 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -There are low priority threads, -which do not hold any resources, -such thread will not block th. -Theorem 3 does not exclude such threads. - -There are resources, which are not held by any low prioirty threads, -such resources can not cause blockage of th neither. And similiary, -theorem 6 does not exlude them. - -Our one bound excudle them by using a different formaulation. - diff -r c3a42076b164 -r b32b3bd99150 red_1.thy --- a/red_1.thy Thu Sep 07 16:04:03 2017 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,359 +0,0 @@ -section {* - This file contains lemmas used to guide the recalculation of current precedence - after every system call (or system operation) -*} -theory CpsG -imports PrioG Max RTree -begin - - -definition "wRAG (s::state) = {(Th th, Cs cs) | th cs. waiting s th cs}" - -definition "hRAG (s::state) = {(Cs cs, Th th) | th cs. holding s th cs}" - -definition "tRAG s = wRAG s O hRAG s" - -definition "pairself f = (\(a, b). (f a, f b))" - -definition "rel_map f r = (pairself f ` r)" - -fun the_thread :: "node \ thread" where - "the_thread (Th th) = th" - -definition "tG s = rel_map the_thread (tRAG s)" - -locale pip = - fixes s - assumes vt: "vt s" - - -lemma RAG_split: "RAG s = (wRAG s \ hRAG s)" - by (unfold s_RAG_abv wRAG_def hRAG_def s_waiting_abv - s_holding_abv cs_RAG_def, auto) - -lemma relpow_mult: - "((r::'a rel) ^^ m) ^^ n = r ^^ (m*n)" -proof(induct n arbitrary:m) - case (Suc k m) - thus ?case (is "?L = ?R") - proof - - have h: "(m * k + m) = (m + m * k)" by auto - show ?thesis - apply (simp add:Suc relpow_add[symmetric]) - by (unfold h, simp) - qed -qed simp - -lemma compose_relpow_2: - assumes "r1 \ r" - and "r2 \ r" - shows "r1 O r2 \ r ^^ (2::nat)" -proof - - { fix a b - assume "(a, b) \ r1 O r2" - then obtain e where "(a, e) \ r1" "(e, b) \ r2" - by auto - with assms have "(a, e) \ r" "(e, b) \ r" by auto - hence "(a, b) \ r ^^ (Suc (Suc 0))" by auto - } thus ?thesis by (auto simp:numeral_2_eq_2) -qed - - -lemma acyclic_compose: - assumes "acyclic r" - and "r1 \ r" - and "r2 \ r" - shows "acyclic (r1 O r2)" -proof - - { fix a - assume "(a, a) \ (r1 O r2)^+" - from trancl_mono[OF this compose_relpow_2[OF assms(2, 3)]] - have "(a, a) \ (r ^^ 2) ^+" . - from trancl_power[THEN iffD1, OF this] - obtain n where h: "(a, a) \ (r ^^ 2) ^^ n" "n > 0" by blast - from this(1)[unfolded relpow_mult] have h2: "(a, a) \ r ^^ (2 * n)" . - have "(a, a) \ r^+" - proof(cases rule:trancl_power[THEN iffD2]) - from h(2) h2 show "\n>0. (a, a) \ r ^^ n" - by (rule_tac x = "2*n" in exI, auto) - qed - with assms have "False" by (auto simp:acyclic_def) - } thus ?thesis by (auto simp:acyclic_def) -qed - -lemma range_tRAG: "Range (tRAG s) \ {Th th | th. True}" -proof - - have "Range (wRAG s O hRAG s) \ {Th th |th. True}" (is "?L \ ?R") - proof - - have "?L \ Range (hRAG s)" by auto - also have "... \ ?R" - by (unfold hRAG_def, auto) - finally show ?thesis by auto - qed - thus ?thesis by (simp add:tRAG_def) -qed - -lemma domain_tRAG: "Domain (tRAG s) \ {Th th | th. True}" -proof - - have "Domain (wRAG s O hRAG s) \ {Th th |th. True}" (is "?L \ ?R") - proof - - have "?L \ Domain (wRAG s)" by auto - also have "... \ ?R" - by (unfold wRAG_def, auto) - finally show ?thesis by auto - qed - thus ?thesis by (simp add:tRAG_def) -qed - -lemma rel_mapE: - assumes "(a, b) \ rel_map f r" - obtains c d - where "(c, d) \ r" "(a, b) = (f c, f d)" - using assms - by (unfold rel_map_def pairself_def, auto) - -lemma rel_mapI: - assumes "(a, b) \ r" - and "c = f a" - and "d = f b" - shows "(c, d) \ rel_map f r" - using assms - by (unfold rel_map_def pairself_def, auto) - -lemma map_appendE: - assumes "map f zs = xs @ ys" - obtains xs' ys' - where "zs = xs' @ ys'" "xs = map f xs'" "ys = map f ys'" -proof - - have "\ xs' ys'. zs = xs' @ ys' \ xs = map f xs' \ ys = map f ys'" - using assms - proof(induct xs arbitrary:zs ys) - case (Nil zs ys) - thus ?case by auto - next - case (Cons x xs zs ys) - note h = this - show ?case - proof(cases zs) - case (Cons e es) - with h have eq_x: "map f es = xs @ ys" "x = f e" by auto - from h(1)[OF this(1)] - obtain xs' ys' where "es = xs' @ ys'" "xs = map f xs'" "ys = map f ys'" - by blast - with Cons eq_x - have "zs = (e#xs') @ ys' \ x # xs = map f (e#xs') \ ys = map f ys'" by auto - thus ?thesis by metis - qed (insert h, auto) - qed - thus ?thesis by (auto intro!:that) -qed - -lemma rel_map_mono: - assumes "r1 \ r2" - shows "rel_map f r1 \ rel_map f r2" - using assms - by (auto simp:rel_map_def pairself_def) - -lemma rel_map_compose [simp]: - shows "rel_map f1 (rel_map f2 r) = rel_map (f1 o f2) r" - by (auto simp:rel_map_def pairself_def) - -lemma edges_on_map: "edges_on (map f xs) = rel_map f (edges_on xs)" -proof - - { fix a b - assume "(a, b) \ edges_on (map f xs)" - then obtain l1 l2 where eq_map: "map f xs = l1 @ [a, b] @ l2" - by (unfold edges_on_def, auto) - hence "(a, b) \ rel_map f (edges_on xs)" - by (auto elim!:map_appendE intro!:rel_mapI simp:edges_on_def) - } moreover { - fix a b - assume "(a, b) \ rel_map f (edges_on xs)" - then obtain c d where - h: "(c, d) \ edges_on xs" "(a, b) = (f c, f d)" - by (elim rel_mapE, auto) - then obtain l1 l2 where - eq_xs: "xs = l1 @ [c, d] @ l2" - by (auto simp:edges_on_def) - hence eq_map: "map f xs = map f l1 @ [f c, f d] @ map f l2" by auto - have "(a, b) \ edges_on (map f xs)" - proof - - from h(2) have "[f c, f d] = [a, b]" by simp - from eq_map[unfolded this] show ?thesis by (auto simp:edges_on_def) - qed - } ultimately show ?thesis by auto -qed - -lemma plus_rpath: - assumes "(a, b) \ r^+" - obtains xs where "rpath r a xs b" "xs \ []" -proof - - from assms obtain m where h: "(a, m) \ r" "(m, b) \ r^*" - by (auto dest!:tranclD) - from star_rpath[OF this(2)] obtain xs where "rpath r m xs b" by auto - from rstepI[OF h(1) this] have "rpath r a (m # xs) b" . - from that[OF this] show ?thesis by auto -qed - -lemma edges_on_unfold: - "edges_on (a # b # xs) = {(a, b)} \ edges_on (b # xs)" (is "?L = ?R") -proof - - { fix c d - assume "(c, d) \ ?L" - then obtain l1 l2 where h: "(a # b # xs) = l1 @ [c, d] @ l2" - by (auto simp:edges_on_def) - have "(c, d) \ ?R" - proof(cases "l1") - case Nil - with h have "(c, d) = (a, b)" by auto - thus ?thesis by auto - next - case (Cons e es) - from h[unfolded this] have "b#xs = es@[c, d]@l2" by auto - thus ?thesis by (auto simp:edges_on_def) - qed - } moreover - { fix c d - assume "(c, d) \ ?R" - moreover have "(a, b) \ ?L" - proof - - have "(a # b # xs) = []@[a,b]@xs" by simp - hence "\ l1 l2. (a # b # xs) = l1@[a,b]@l2" by auto - thus ?thesis by (unfold edges_on_def, simp) - qed - moreover { - assume "(c, d) \ edges_on (b#xs)" - then obtain l1 l2 where "b#xs = l1@[c, d]@l2" by (unfold edges_on_def, auto) - hence "a#b#xs = (a#l1)@[c,d]@l2" by simp - hence "\ l1 l2. (a # b # xs) = l1@[c,d]@l2" by metis - hence "(c,d) \ ?L" by (unfold edges_on_def, simp) - } - ultimately have "(c, d) \ ?L" by auto - } ultimately show ?thesis by auto -qed - -lemma edges_on_rpathI: - assumes "edges_on (a#xs@[b]) \ r" - shows "rpath r a (xs@[b]) b" - using assms -proof(induct xs arbitrary: a b) - case Nil - moreover have "(a, b) \ edges_on (a # [] @ [b])" - by (unfold edges_on_def, auto) - ultimately have "(a, b) \ r" by auto - thus ?case by auto -next - case (Cons x xs a b) - from this(2) have "edges_on (x # xs @ [b]) \ r" by (simp add:edges_on_unfold) - from Cons(1)[OF this] have " rpath r x (xs @ [b]) b" . - moreover from Cons(2) have "(a, x) \ r" by (auto simp:edges_on_unfold) - ultimately show ?case by (auto intro!:rstepI) -qed - -lemma image_id: - assumes "\ x. x \ A \ f x = x" - shows "f ` A = A" - using assms by (auto simp:image_def) - -lemma rel_map_inv_id: - assumes "inj_on f ((Domain r) \ (Range r))" - shows "(rel_map (inv_into ((Domain r) \ (Range r)) f \ f) r) = r" -proof - - let ?f = "(inv_into (Domain r \ Range r) f \ f)" - { - fix a b - assume h0: "(a, b) \ r" - have "pairself ?f (a, b) = (a, b)" - proof - - from assms h0 have "?f a = a" by (auto intro:inv_into_f_f) - moreover have "?f b = b" - by (insert h0, simp, intro inv_into_f_f[OF assms], auto intro!:RangeI) - ultimately show ?thesis by (auto simp:pairself_def) - qed - } thus ?thesis by (unfold rel_map_def, intro image_id, case_tac x, auto) -qed - -lemma rel_map_acyclic: - assumes "acyclic r" - and "inj_on f ((Domain r) \ (Range r))" - shows "acyclic (rel_map f r)" -proof - - let ?D = "Domain r \ Range r" - { fix a - assume "(a, a) \ (rel_map f r)^+" - from plus_rpath[OF this] - obtain xs where rp: "rpath (rel_map f r) a xs a" "xs \ []" by auto - from rpath_nnl_lastE[OF this] obtain xs' where eq_xs: "xs = xs'@[a]" by auto - from rpath_edges_on[OF rp(1)] - have h: "edges_on (a # xs) \ rel_map f r" . - from edges_on_map[of "inv_into ?D f" "a#xs"] - have "edges_on (map (inv_into ?D f) (a # xs)) = rel_map (inv_into ?D f) (edges_on (a # xs))" . - with rel_map_mono[OF h, of "inv_into ?D f"] - have "edges_on (map (inv_into ?D f) (a # xs)) \ rel_map ((inv_into ?D f) o f) r" by simp - from this[unfolded eq_xs] - have subr: "edges_on (map (inv_into ?D f) (a # xs' @ [a])) \ rel_map (inv_into ?D f \ f) r" . - have "(map (inv_into ?D f) (a # xs' @ [a])) = (inv_into ?D f a) # map (inv_into ?D f) xs' @ [inv_into ?D f a]" - by simp - from edges_on_rpathI[OF subr[unfolded this]] - have "rpath (rel_map (inv_into ?D f \ f) r) - (inv_into ?D f a) (map (inv_into ?D f) xs' @ [inv_into ?D f a]) (inv_into ?D f a)" . - hence "(inv_into ?D f a, inv_into ?D f a) \ (rel_map (inv_into ?D f \ f) r)^+" - by (rule rpath_plus, simp) - moreover have "(rel_map (inv_into ?D f \ f) r) = r" by (rule rel_map_inv_id[OF assms(2)]) - moreover note assms(1) - ultimately have False by (unfold acyclic_def, auto) - } thus ?thesis by (auto simp:acyclic_def) -qed - -context pip -begin - -interpretation rtree_RAG: rtree "RAG s" -proof - show "single_valued (RAG s)" - by (unfold single_valued_def, auto intro: unique_RAG[OF vt]) - - show "acyclic (RAG s)" - by (rule acyclic_RAG[OF vt]) -qed - -lemma sgv_wRAG: - shows "single_valued (wRAG s)" - using waiting_unique[OF vt] - by (unfold single_valued_def wRAG_def, auto) - -lemma sgv_hRAG: - shows "single_valued (hRAG s)" - using held_unique - by (unfold single_valued_def hRAG_def, auto) - -lemma sgv_tRAG: shows "single_valued (tRAG s)" - by (unfold tRAG_def, rule Relation.single_valued_relcomp, - insert sgv_hRAG sgv_wRAG, auto) - -lemma acyclic_hRAG: - shows "acyclic (hRAG s)" - by (rule acyclic_subset[OF acyclic_RAG[OF vt]], insert RAG_split, auto) - -lemma acyclic_wRAG: - shows "acyclic (wRAG s)" - by (rule acyclic_subset[OF acyclic_RAG[OF vt]], insert RAG_split, auto) - -lemma acyclic_tRAG: - shows "acyclic (tRAG s)" - by (unfold tRAG_def, rule acyclic_compose[OF acyclic_RAG[OF vt]], - unfold RAG_split, auto) - -lemma acyclic_tG: - shows "acyclic (tG s)" -proof(unfold tG_def, rule rel_map_acyclic[OF acyclic_tRAG]) - show "inj_on the_thread (Domain (tRAG s) \ Range (tRAG s))" - proof(rule subset_inj_on) - show " inj_on the_thread {Th th |th. True}" by (unfold inj_on_def, auto) - next - from domain_tRAG range_tRAG - show " Domain (tRAG s) \ Range (tRAG s) \ {Th th |th. True}" by auto - qed -qed - -end