1 theory Implementation |
1 theory Implementation |
2 imports PIPBasics |
2 imports PIPBasics |
3 begin |
3 begin |
4 |
4 |
|
5 |
|
6 (* |
|
7 The use of dependants has been abandoned. Through a series of lemma |
|
8 named xxx_alt_def, lemma originally expressed using dependants |
|
9 is now expressed in terms of RAG, tRAG and tG. |
|
10 *) |
|
11 |
5 text {* |
12 text {* |
6 |
13 |
7 This file contains lemmas used to guide the recalculation of current |
14 This file contains lemmas used to guide the recalculation of current |
8 precedence after every step of execution (or system operation, or event), |
15 precedence after every step of execution (or system operation, or event), |
9 which is the most tricky part in the implementation of PIP. |
16 which is the most tricky part in the implementation of PIP. |
10 |
17 |
11 Following convention, lemmas are grouped into locales corresponding to |
18 Following convention, lemmas are grouped into locales corresponding to |
12 system operations, each explained in a separate section. *} |
19 system operations, each explained in a separate section. To understand the relevant |
13 |
20 materials, one needs some acquaintance with locales, which are |
14 text {* |
21 used to as contexts for lemmas to situate, where lemmas with the same assumptions |
15 The following two lemmas are general about any valid system state, |
22 are grouped under the same locale. |
16 but are used in the derivation in more specific system operations. |
23 |
17 *} |
24 Locale @{text "valid_trace s"} assumes that @{text "s"} is a valid trace (or state) |
|
25 of PIP. Lemmas talking about general properties of valid states can be put under this |
|
26 locale. The locale @{text "valid_trace_e s e"} is an extension of @{text valid_trace} |
|
27 by introducing an event @{text e} and assuming @{text "e#s"} is also valid state. |
|
28 The purpose of @{text valid_trace_e} is to set a context to investigate |
|
29 one step execution of PIP, where @{text e} is a fixed but arbitrary |
|
30 action legitimate to happen under state @{text "s"}. General Properties about |
|
31 one step action of PIP are grouped under this locale. |
|
32 |
|
33 @{text "valid_trace_e"} is further extended to accommodate specific actions. For example, |
|
34 @{text "valid_trace_create s e th prio"} further assumes that the |
|
35 @{text "e"} action is @{text "Create th prio"}, and |
|
36 @{text "valid_trace_p s e th cs"} assumes that @{text "e"} is @{text "P th cs"}, etc. |
|
37 |
|
38 Since the recalculation of current precedence happens only when certain actions |
|
39 are taken, it is natural to put the lemmas about recalculation under the respective |
|
40 locales. In the following, each section corresponds one particular action of PIP, which, |
|
41 in turn, is developed under the locale corresponding to the specific action. |
|
42 |
|
43 By @{text cp_alt_def3}, the @{text cp}-value of one thread @{text th} is determined |
|
44 uniquely by static precedences of threads in its @{text "RAG"}-subtree |
|
45 (or @{text tRAG}-subtree, @{text "tG"}-subtree). Because of this, the decision where |
|
46 recalculation is needed is based on the change of @{text RAG} (@{text tRAG} or @{text tG}) |
|
47 as well the precedence of threads. Since most of PIP actions (except the @{text Set}-operation) |
|
48 only changes the formation of @{text RAG}, therefore, for non-@{text Set} operations, |
|
49 if the change of @{text RAG} does not affect the subtree |
|
50 of one thread, its @{text cp}-value may not change. |
|
51 |
|
52 In the following, the section corresponding to non-@{text Set} operations |
|
53 usually contain lemmas showing the subtrees of certain kind of threads are |
|
54 not changed. The proof of such lemmas is obvious based on the lemmas about the |
|
55 change of @{text RAG}, which have already been derived in theory @{text PIPBasics} |
|
56 all under the name @{text "RAG_es"} in the locale corresponding to different PIP |
|
57 operations. |
|
58 *} |
|
59 |
|
60 section {* The local recalculation principle for @{text cp}-value *} |
|
61 |
|
62 definition "cprecs Ths s = cp s ` Ths" |
18 |
63 |
19 context valid_trace |
64 context valid_trace |
20 begin |
65 begin |
21 |
66 |
22 lemma readys_root: |
67 text {* |
23 assumes "th \<in> readys s" |
68 To minimize the cost of the recalculation, we derived the following localized alternative |
24 shows "root (RAG s) (Th th)" |
69 definition of @{term cp}: |
25 unfolding root_def ancestors_def |
70 *} |
26 using readys_RAG assms |
71 |
27 by (metis Collect_empty_eq Domain.DomainI trancl_domain) |
72 lemma cp_rec_tG: |
28 |
73 "cp s th = Max (preceds {th} s \<union> cprecs (children (tG s) th) s)" |
29 lemma readys_in_no_subtree: |
74 proof - |
30 assumes "th \<in> readys s" |
75 have [simp]: "(cp s \<circ> the_thread \<circ> Th) = cp s" by (rule ext, simp) |
31 and "th' \<noteq> th" |
76 have [simp]: "(cp s \<circ> the_thread) ` children (tRAG s) (Th th) = |
32 shows "Th th \<notin> subtree (RAG s) (Th th')" |
77 cp s ` children (tG s) th" |
33 proof |
78 apply (unfold tRAG_def_tG) |
34 assume "Th th \<in> subtree (RAG s) (Th th')" |
79 apply (subst fmap_children) |
35 thus False |
80 apply (rule injI, simp) |
36 proof(cases rule:subtreeE) |
81 by (unfold image_comp, simp) |
37 case 1 |
82 have [simp]: "preceds {th} s = {the_preced s th}" |
38 with assms show ?thesis by auto |
83 by (unfold the_preced_def, simp) |
39 next |
84 show ?thesis |
40 case 2 |
85 by (unfold cp_rec cprecs_def, simp add:the_preced_def) |
41 with readys_root[OF assms(1)] |
86 qed |
42 show ?thesis by (auto simp:root_def) |
87 |
43 qed |
88 text {* |
44 qed |
89 According to this lemma, @{text cp}-value of one thread can be calculated by calling recursively |
|
90 the @{text cp} function on its @{text tG}-children. However, one thing to be noted is that |
|
91 the lemma also means the recursive call needs not to descend into lower levels if the |
|
92 @{text "cp"}-value of one child is not changed. In this way, the recalculation can be {\em localized} |
|
93 to those thread with changed @{text cp}-value. This is the reason why this lemma |
|
94 is called a {\em localized lemma}. |
|
95 *} |
45 |
96 |
46 end |
97 end |
47 |
98 |
48 section {* The @{term Set} operation *} |
99 section {* The @{term Set} operation *} |
49 |
100 |
108 qed |
162 qed |
109 thus ?thesis by (simp add:cp_alt_def) |
163 thus ?thesis by (simp add:cp_alt_def) |
110 qed |
164 qed |
111 |
165 |
112 text {* |
166 text {* |
113 The following lemma shows that @{term "th"} is not in the |
167 However, the following lemma shows that @{term "th"} is not in the |
114 sub-tree of any other thread. |
168 subtree of any thread except itself. |
115 *} |
169 *} |
116 lemma th_in_no_subtree: |
170 lemma th_in_no_subtree: |
117 assumes "th' \<noteq> th" |
171 assumes "th' \<noteq> th" |
118 shows "Th th \<notin> subtree (RAG s) (Th th')" |
172 shows "Th th \<notin> subtree (RAG s) (Th th')" |
119 proof - |
173 proof - |
120 from readys_in_no_subtree[OF th_ready_s assms(1)] |
174 from readys_in_no_subtree[OF th_ready_s assms(1)] |
121 show ?thesis by blast |
175 show ?thesis by blast |
122 qed |
176 qed |
123 |
177 |
124 text {* |
178 text {* |
125 By combining @{thm "eq_cp_pre"} and @{thm "th_in_no_subtree"}, |
179 Combining the above two lemmas, it is concluded that the |
126 it is obvious that the change of priority only affects the @{text "cp"}-value |
180 recalculation of @{text "cp"}-value is needed only on @{text th}. |
127 of the initiating thread @{text "th"}. |
181 *} |
128 *} |
182 |
129 lemma eq_cp: |
183 lemma eq_cp: |
130 assumes "th' \<noteq> th" |
184 assumes "th' \<noteq> th" |
131 shows "cp (e#s) th' = cp s th'" |
185 shows "cp (e#s) th' = cp s th'" |
132 by (rule eq_cp_pre[OF th_in_no_subtree[OF assms]]) |
186 by (rule eq_cp_pre[OF th_in_no_subtree[OF assms]]) |
133 |
187 |
|
188 text {* |
|
189 Under the local recalculation principle @{thm cp_rec_tG}, |
|
190 @{thm eq_cp} also means the recalculation of @{text cp} for @{text th} |
|
191 can be done locally by inspecting only @{text th} and its children. |
|
192 *} |
|
193 |
134 end |
194 end |
135 |
195 |
136 section {* The @{term V} operation *} |
196 section {* The @{term V} operation *} |
137 |
197 |
138 text {* |
198 text {* |
139 The following @{text "step_v_cps"} is the locale for @{text "V"}-operation. |
199 The following locale @{text "valid_trace_v"} is the locale for @{text "V"}-operation in |
|
200 general. The recalculation of @{text cp}-value needs to consider two more sub-case, each |
|
201 encapsulated into a sub-locale of @{text "valid_trace_v"}. But first, |
|
202 some general properties about the @{text V}-operation are derived: |
140 *} |
203 *} |
141 |
204 |
142 context valid_trace_v |
205 context valid_trace_v |
143 begin |
206 begin |
144 |
207 |
|
208 text {* |
|
209 Because @{text th} is running in state @{text s}, it does not in waiting of |
|
210 any resource, therefore, it has no ancestor in @{text "RAG s"}: |
|
211 *} |
145 lemma ancestors_th: "ancestors (RAG s) (Th th) = {}" |
212 lemma ancestors_th: "ancestors (RAG s) (Th th) = {}" |
146 proof - |
213 proof - |
147 from readys_root[OF th_ready_s] |
214 from readys_root[OF th_ready_s] |
148 show ?thesis |
215 show ?thesis |
149 by (unfold root_def, simp) |
216 by (unfold root_def, simp) |
150 qed |
217 qed |
151 |
218 |
|
219 text {* |
|
220 Since @{text th} is holding @{text cs} (the resource to be released by this @{text V}-operation), |
|
221 the edge @{text "(Cs cs, Th th)"} represents this fact. |
|
222 *} |
152 lemma edge_of_th: |
223 lemma edge_of_th: |
153 "(Cs cs, Th th) \<in> RAG s" |
224 "(Cs cs, Th th) \<in> RAG s" |
154 proof - |
225 proof - |
155 from holding_th_cs_s |
226 from holding_th_cs_s |
156 show ?thesis |
227 show ?thesis |
157 by (unfold s_RAG_def s_holding_abv, auto) |
228 by (unfold s_RAG_def s_holding_abv, auto) |
158 qed |
229 qed |
159 |
230 |
|
231 text {* |
|
232 Since @{text cs} is held by @{text th} which has no ancestors, |
|
233 @{text th} is the only ancestor of @{text cs}: |
|
234 *} |
160 lemma ancestors_cs: |
235 lemma ancestors_cs: |
161 "ancestors (RAG s) (Cs cs) = {Th th}" |
236 "ancestors (RAG s) (Cs cs) = {Th th}" |
162 proof - |
237 proof - |
163 have "ancestors (RAG s) (Cs cs) = ancestors (RAG s) (Th th) \<union> {Th th}" |
238 have "ancestors (RAG s) (Cs cs) = ancestors (RAG s) (Th th) \<union> {Th th}" |
164 by (rule forest_RAG.ancestors_accum[OF edge_of_th]) |
239 by (rule forest_RAG.ancestors_accum[OF edge_of_th]) |
165 from this[unfolded ancestors_th] show ?thesis by simp |
240 from this[unfolded ancestors_th] show ?thesis by simp |
166 qed |
241 qed |
167 |
242 |
168 end |
243 text {* |
169 |
244 As already said, all operations except @{text Set} may change precedence. |
170 text {* |
245 The following lemma confirms this fact of the @{text V}-operation: |
171 The following @{text "step_v_cps_nt"} is the sub-locale for @{text "V"}-operation, |
246 *} |
172 which represents the case when there is another thread @{text "th'"} |
247 lemma |
173 to take over the critical resource released by the initiating thread @{text "th"}. |
|
174 *} |
|
175 |
|
176 lemma (in valid_trace_v) |
|
177 the_preced_es: "the_preced (e#s) = the_preced s" |
248 the_preced_es: "the_preced (e#s) = the_preced s" |
178 proof |
249 proof |
179 fix th' |
250 fix th' |
180 show "the_preced (e # s) th' = the_preced s th'" |
251 show "the_preced (e # s) th' = the_preced s th'" |
181 by (unfold the_preced_def preced_def is_v, simp) |
252 by (unfold the_preced_def preced_def is_v, simp) |
182 qed |
253 qed |
183 |
254 |
|
255 end |
|
256 |
|
257 |
|
258 text {* |
|
259 The following sub-locale @{text "valid_trace_v_n"} |
|
260 deals with one of the sub-cases of @{text V}, which corresponds to the |
|
261 situation where there is another thread @{text "taker"} |
|
262 to take over the release resource @{text cs}. |
|
263 *} |
|
264 |
184 context valid_trace_v_n |
265 context valid_trace_v_n |
185 begin |
266 begin |
186 |
267 |
|
268 text {* |
|
269 The following lemma shows the two edges in @{text "RAG s"} which |
|
270 links @{text cs} with @{text taker} and @{text th} to form a chain. |
|
271 The existence of this chain set the stage for the @{text V}-operation |
|
272 in question to happen. |
|
273 *} |
187 lemma sub_RAGs': |
274 lemma sub_RAGs': |
188 "{(Cs cs, Th th), (Th taker, Cs cs)} \<subseteq> RAG s" |
275 "{(Cs cs, Th th), (Th taker, Cs cs)} \<subseteq> RAG s" |
189 using waiting_taker holding_th_cs_s |
276 using waiting_taker holding_th_cs_s |
190 by (unfold s_RAG_def, fold s_waiting_abv s_holding_abv, auto) |
277 by (unfold s_RAG_def, fold s_waiting_abv s_holding_abv, auto) |
191 |
278 |
|
279 text {* |
|
280 The following lemma shows that @{text taker} has only two the ancestors. |
|
281 The reason for this is very simple: The chain starting from @{text taker} |
|
282 stops at @{text th}, which, as shown by @{thm ancestors_th}, has no ancestor. |
|
283 *} |
192 lemma ancestors_th': |
284 lemma ancestors_th': |
193 "ancestors (RAG s) (Th taker) = {Th th, Cs cs}" |
285 "ancestors (RAG s) (Th taker) = {Th th, Cs cs}" |
194 proof - |
286 proof - |
195 have "ancestors (RAG s) (Th taker) = ancestors (RAG s) (Cs cs) \<union> {Cs cs}" |
287 have "ancestors (RAG s) (Th taker) = ancestors (RAG s) (Cs cs) \<union> {Cs cs}" |
196 proof(rule forest_RAG.ancestors_accum) |
288 proof(rule forest_RAG.ancestors_accum) |
197 from sub_RAGs' show "(Th taker, Cs cs) \<in> RAG s" by auto |
289 from sub_RAGs' show "(Th taker, Cs cs) \<in> RAG s" by auto |
198 qed |
290 qed |
199 thus ?thesis using ancestors_th ancestors_cs by auto |
291 thus ?thesis using ancestors_th ancestors_cs by auto |
200 qed |
292 qed |
201 |
293 |
|
294 text {* |
|
295 By composing several existing results, the following lemma |
|
296 make clear the change of @{text RAG} where there is a |
|
297 @{text taker} to take over the resource @{text cs}. |
|
298 More specifically, the lemma says the change of @{text RAG} |
|
299 is by first removing the chain linking @{text taker}, @{text cs} and |
|
300 @{text th} and then adding in one edge from @{text cs} to @{text taker}. |
|
301 The added edge represents acquisition of @{text cs} by @{text taker}. |
|
302 *} |
202 lemma RAG_s: |
303 lemma RAG_s: |
203 "RAG (e#s) = (RAG s - {(Cs cs, Th th), (Th taker, Cs cs)}) \<union> |
304 "RAG (e#s) = (RAG s - {(Cs cs, Th th), (Th taker, Cs cs)}) \<union> |
204 {(Cs cs, Th taker)}" |
305 {(Cs cs, Th taker)}" |
205 by (unfold RAG_es waiting_set_eq holding_set_eq, auto) |
306 by (unfold RAG_es waiting_set_eq holding_set_eq, auto) |
206 |
307 |
|
308 text {* |
|
309 The above lemma @{thm RAG_s} shows the effect of the @{text V}-operation |
|
310 on @{text RAG} is the removal of two edges followed by the addition of |
|
311 one edge. Based on this, the following lemma will show that |
|
312 the sub-trees of threads other than @{text th} and @{text taker} are unchanged. |
|
313 The intuition behind this is rather simple: the edges added and removed are not |
|
314 in these sub-trees. |
|
315 |
|
316 Formally, an edge is said to be outside of a sub-tree if its |
|
317 end point is. Note that when a set of edges are represented as a binary relation, the |
|
318 set of their end points is essentially range of the relation (formally defined |
|
319 as @{term Range}). Therefore, a set of edges (represented as a relation) |
|
320 are outside of a sub-tree if its @{text Range}-set does not intersect |
|
321 with the sub-tree. |
|
322 *} |
|
323 |
207 lemma subtree_kept: (* ddd *) |
324 lemma subtree_kept: (* ddd *) |
208 assumes "th1 \<notin> {th, taker}" |
325 assumes "th1 \<notin> {th, taker}" |
209 shows "subtree (RAG (e#s)) (Th th1) = |
326 shows "subtree (RAG (e#s)) (Th th1) = |
210 subtree (RAG s) (Th th1)" (is "_ = ?R") |
327 subtree (RAG s) (Th th1)" (is "_ = ?R") |
211 proof - |
328 proof - |
212 let ?RAG' = "(RAG s - {(Cs cs, Th th), (Th taker, Cs cs)})" |
329 let ?RAG' = "(RAG s - {(Cs cs, Th th), (Th taker, Cs cs)})" |
213 let ?RAG'' = "?RAG' \<union> {(Cs cs, Th taker)}" |
330 let ?RAG'' = "?RAG' \<union> {(Cs cs, Th taker)}" |
|
331 -- {* The first step is to show the deletion of edges does not change the sub-tree *} |
214 have "subtree ?RAG' (Th th1) = ?R" |
332 have "subtree ?RAG' (Th th1) = ?R" |
215 proof(rule subset_del_subtree_outside) |
333 proof(rule subset_del_subtree_outside) |
216 show "Range {(Cs cs, Th th), (Th taker, Cs cs)} \<inter> subtree (RAG s) (Th th1) = {}" |
334 show "Range {(Cs cs, Th th), (Th taker, Cs cs)} \<inter> subtree (RAG s) (Th th1) = {}" |
217 proof - |
335 proof - |
218 have "(Th th) \<notin> subtree (RAG s) (Th th1)" |
336 have "(Th th) \<notin> subtree (RAG s) (Th th1)" |
219 proof(rule subtree_refute) |
337 proof(rule subtree_refute) |
220 show "Th th1 \<notin> ancestors (RAG s) (Th th)" |
338 show "Th th1 \<notin> ancestors (RAG s) (Th th)" |
221 by (unfold ancestors_th, simp) |
339 by (unfold ancestors_th, simp) |
222 next |
340 next |
223 from assms show "Th th1 \<noteq> Th th" by simp |
341 from assms show "Th th1 \<noteq> Th th" by simp |
224 qed |
342 qed |
225 moreover have "(Cs cs) \<notin> subtree (RAG s) (Th th1)" |
343 moreover have "(Cs cs) \<notin> subtree (RAG s) (Th th1)" |
226 proof(rule subtree_refute) |
344 proof(rule subtree_refute) |
229 qed simp |
347 qed simp |
230 ultimately have "{Th th, Cs cs} \<inter> subtree (RAG s) (Th th1) = {}" by auto |
348 ultimately have "{Th th, Cs cs} \<inter> subtree (RAG s) (Th th1) = {}" by auto |
231 thus ?thesis by simp |
349 thus ?thesis by simp |
232 qed |
350 qed |
233 qed |
351 qed |
|
352 -- {* The second step is to show the addition of edges does not change the sub-tree *} |
234 moreover have "subtree ?RAG'' (Th th1) = subtree ?RAG' (Th th1)" |
353 moreover have "subtree ?RAG'' (Th th1) = subtree ?RAG' (Th th1)" |
235 proof(rule subtree_insert_next) |
354 proof(rule subset_insert_subtree_outside) |
236 show "Th taker \<notin> subtree (RAG s - {(Cs cs, Th th), (Th taker, Cs cs)}) (Th th1)" |
355 show "Range {(Cs cs, Th taker)} \<inter> |
237 proof(rule subtree_refute) |
356 subtree (RAG s - {(Cs cs, Th th), (Th taker, Cs cs)}) (Th th1) = {}" |
238 show "Th th1 \<notin> ancestors (RAG s - {(Cs cs, Th th), (Th taker, Cs cs)}) (Th taker)" |
357 proof - |
|
358 have "Th taker \<notin> subtree (RAG s - {(Cs cs, Th th), (Th taker, Cs cs)}) (Th th1)" |
|
359 proof(rule subtree_refute) |
|
360 show "Th th1 \<notin> ancestors (RAG s - {(Cs cs, Th th), (Th taker, Cs cs)}) (Th taker)" |
239 (is "_ \<notin> ?R") |
361 (is "_ \<notin> ?R") |
240 proof - |
362 proof - |
241 have "?R \<subseteq> ancestors (RAG s) (Th taker)" by (rule ancestors_mono, auto) |
363 have "?R \<subseteq> ancestors (RAG s) (Th taker)" by (rule ancestors_mono, auto) |
242 moreover have "Th th1 \<notin> ..." using ancestors_th' assms by simp |
364 moreover have "Th th1 \<notin> ..." using ancestors_th' assms by simp |
243 ultimately show ?thesis by auto |
365 ultimately show ?thesis by auto |
244 qed |
366 qed |
245 next |
367 next |
246 from assms show "Th th1 \<noteq> Th taker" by simp |
368 from assms show "Th th1 \<noteq> Th taker" by simp |
|
369 qed |
|
370 thus ?thesis by auto |
247 qed |
371 qed |
248 qed |
372 qed |
249 ultimately show ?thesis by (unfold RAG_s, simp) |
373 ultimately show ?thesis by (unfold RAG_s, simp) |
250 qed |
374 qed |
251 |
375 |
|
376 text {* |
|
377 The following lemma shows threads not involved in the @{text V}-operation (i.e. |
|
378 threads other than @{text th} and @{text taker}) do not need to do any @{text cp}-recalculation. |
|
379 The reason is simple: according to @{thm subtree_kept}, the sub-trees of such threads |
|
380 are not changed , additionally, since the @{text V}-operation does not change any precedence, |
|
381 the @{text "cp"}-value of such threads are not changed. |
|
382 *} |
252 lemma cp_kept: |
383 lemma cp_kept: |
253 assumes "th1 \<notin> {th, taker}" |
384 assumes "th1 \<notin> {th, taker}" |
254 shows "cp (e#s) th1 = cp s th1" |
385 shows "cp (e#s) th1 = cp s th1" |
255 by (unfold cp_alt_def the_preced_es subtree_kept[OF assms], simp) |
386 by (unfold cp_alt_def the_preced_es subtree_kept[OF assms], simp) |
256 |
387 |
|
388 text {* |
|
389 Lemma @{thm cp_kept} also means @{text cp}-recalculation is needed only for |
|
390 @{text th} and @{text taker}. The following lemmas are to ensure that |
|
391 the recalculation can done locally using {\em local recalculation principle}. |
|
392 Since @{text taker} and @{text th} are the only threads with changed @{text cp}-values |
|
393 and neither one can not be a child of the other, it can be concluded that |
|
394 neither of these two threads has children with changed @{text cp}-value. |
|
395 It means the recursive calls in @{thm cp_rec_tG} will not descend when recalculating |
|
396 the @{text cp}-values for @{text th} and @{text taker}. |
|
397 *} |
|
398 |
|
399 lemma "taker \<notin> children (tG (e#s)) th" |
|
400 by (metis children_subtree empty_iff in_mono neq_taker_th root_def set_mp |
|
401 subtree_ancestorsI taker_ready_es vat_es.root_readys_tG) |
|
402 |
|
403 |
|
404 lemma "th \<notin> children (tG (e#s)) taker" |
|
405 by (metis children_subtree empty_iff neq_taker_th root_def |
|
406 subsetD subtree_ancestorsI th_ready_es vat_es.root_readys_tG) |
|
407 |
|
408 |
257 end |
409 end |
258 |
410 |
259 |
411 text {* |
|
412 The following locale @{text valid_trace_v_e} deals with the second sub-case |
|
413 of @{text V}-operation, where there is no thread to take over the release |
|
414 resource @{text cs}. |
|
415 *} |
260 context valid_trace_v_e |
416 context valid_trace_v_e |
261 begin |
417 begin |
262 |
418 |
|
419 text {* |
|
420 Since no thread to take over @{text cs}, only the edge representing |
|
421 the holding of @{text cs} by @{text th} needs to be removed: |
|
422 *} |
263 lemma RAG_s: "RAG (e#s) = RAG s - {(Cs cs, Th th)}" |
423 lemma RAG_s: "RAG (e#s) = RAG s - {(Cs cs, Th th)}" |
264 by (unfold RAG_es waiting_set_eq holding_set_eq, simp) |
424 by (unfold RAG_es waiting_set_eq holding_set_eq, simp) |
265 |
425 |
|
426 text {* |
|
427 Since @{text th} has no ancestors, |
|
428 the removal of the holding edge only affects the sub-tree of @{text th}: |
|
429 *} |
266 lemma subtree_kept: |
430 lemma subtree_kept: |
267 assumes "th1 \<noteq> th" |
431 assumes "th1 \<noteq> th" |
268 shows "subtree (RAG (e#s)) (Th th1) = subtree (RAG s) (Th th1)" |
432 shows "subtree (RAG (e#s)) (Th th1) = subtree (RAG s) (Th th1)" |
269 proof(unfold RAG_s, rule subset_del_subtree_outside) |
433 proof(unfold RAG_s, rule subset_del_subtree_outside) |
270 show "Range {(Cs cs, Th th)} \<inter> subtree (RAG s) (Th th1) = {}" |
434 show "Range {(Cs cs, Th th)} \<inter> subtree (RAG s) (Th th1) = {}" |
319 |
505 |
320 lemma cp_kept_2: |
506 lemma cp_kept_2: |
321 shows "cp (e#s) th = cp s th" |
507 shows "cp (e#s) th = cp s th" |
322 by (unfold cp_alt_def subtree_th the_preced_es, auto) |
508 by (unfold cp_alt_def subtree_th the_preced_es, auto) |
323 |
509 |
|
510 text {* |
|
511 By combining @{thm cp_kept_1} and @{thm cp_kept_2}, it is shown that no @{text cp}-recalculation |
|
512 is needed at all for this sub-case of @{text V}-operation. |
|
513 *} |
324 lemma eq_cp: |
514 lemma eq_cp: |
325 shows "cp (e#s) th' = cp s th'" |
515 shows "cp (e#s) th' = cp s th'" |
326 using cp_kept_1 cp_kept_2 |
516 using cp_kept_1 cp_kept_2 |
327 by (cases "th' = th", auto) |
517 by (cases "th' = th", auto) |
328 |
518 |
329 end |
519 end |
330 |
520 |
331 |
521 section {* The @{term P} operation *} |
332 section {* The @{term P} operation *} |
522 |
|
523 text {* |
|
524 Like @{text V}-operation, the treatment of @{text P}-operation is also divided into |
|
525 tow sub-cases. If the requested resource is available, it is dealt with in |
|
526 sub-locale @{text valid_trace_p_h}, otherwise, it is dealt with |
|
527 in sub-locale @{text valid_trace_p_w}. |
|
528 *} |
|
529 |
|
530 text {* |
|
531 But first, the following base locale @{text valid_trace_p} contains |
|
532 some general properties of the @{text P}-operation: |
|
533 *} |
333 |
534 |
334 context valid_trace_p |
535 context valid_trace_p |
335 begin |
536 begin |
336 |
537 |
|
538 text {* |
|
539 The following lemma shows that @{text th} is a root in the |
|
540 @{text RAG} graph, which means @{text th} has no ancestors in the graph. |
|
541 The reason is that: since @{text th} is in running state, it is |
|
542 in ready state, which means it is not waiting for any resource, therefore, |
|
543 it has no outbound edge. |
|
544 *} |
337 lemma root_th: "root (RAG s) (Th th)" |
545 lemma root_th: "root (RAG s) (Th th)" |
338 by (simp add: ready_th_s readys_root) |
546 by (simp add: ready_th_s readys_root) |
339 |
547 |
|
548 text {* |
|
549 For the same reason as @{thm root_th}, @{text th} is not in |
|
550 the sub-tree of any thread other than @{text th}: |
|
551 *} |
340 lemma in_no_others_subtree: |
552 lemma in_no_others_subtree: |
341 assumes "th' \<noteq> th" |
553 assumes "th' \<noteq> th" |
342 shows "Th th \<notin> subtree (RAG s) (Th th')" |
554 shows "Th th \<notin> subtree (RAG s) (Th th')" |
343 proof |
555 proof |
344 assume "Th th \<in> subtree (RAG s) (Th th')" |
556 assume "Th th \<in> subtree (RAG s) (Th th')" |
350 case 2 |
562 case 2 |
351 with root_th show ?thesis by (auto simp:root_def) |
563 with root_th show ?thesis by (auto simp:root_def) |
352 qed |
564 qed |
353 qed |
565 qed |
354 |
566 |
|
567 text {* |
|
568 The following lemma confirms that the @{text P}-operation does not |
|
569 affect the precedence of any thread. |
|
570 *} |
355 lemma preced_kept: "the_preced (e#s) = the_preced s" |
571 lemma preced_kept: "the_preced (e#s) = the_preced s" |
356 proof |
572 proof |
357 fix th' |
573 fix th' |
358 show "the_preced (e # s) th' = the_preced s th'" |
574 show "the_preced (e # s) th' = the_preced s th'" |
359 by (unfold the_preced_def is_p preced_def, simp) |
575 by (unfold the_preced_def is_p preced_def, simp) |
360 qed |
576 qed |
361 |
577 |
362 end |
578 end |
363 |
579 |
|
580 text {* |
|
581 The following locale @{text valid_trace_p_h} deals with the |
|
582 sub-case of @{text P}-operation when the requested @{text cs} |
|
583 is available and @{text th} gets hold of it instantaneously with |
|
584 the @{text P}-operation. |
|
585 *} |
364 |
586 |
365 context valid_trace_p_h |
587 context valid_trace_p_h |
366 begin |
588 begin |
|
589 |
|
590 text {* |
|
591 According to @{thm RAG_es}, the only change to @{text RAG} by |
|
592 the @{text P}-operation is the addition of the edge @{text "(Cs cs, Th th)"}, |
|
593 representing the newly acquisition of @{text cs} by @{text th}. |
|
594 The following lemma shows that this newly added edge only change the sub-tree |
|
595 of @{text th}, the reason is that @{text th} is in no other sub-trees. |
|
596 *} |
367 |
597 |
368 lemma subtree_kept: |
598 lemma subtree_kept: |
369 assumes "th' \<noteq> th" |
599 assumes "th' \<noteq> th" |
370 shows "subtree (RAG (e#s)) (Th th') = subtree (RAG s) (Th th')" |
600 shows "subtree (RAG (e#s)) (Th th') = subtree (RAG s) (Th th')" |
371 proof(unfold RAG_es, rule subtree_insert_next) |
601 proof(unfold RAG_es, rule subtree_insert_next) |
372 from in_no_others_subtree[OF assms] |
602 from in_no_others_subtree[OF assms] |
373 show "Th th \<notin> subtree (RAG s) (Th th')" . |
603 show "Th th \<notin> subtree (RAG s) (Th th')" . |
374 qed |
604 qed |
375 |
605 |
|
606 text {* |
|
607 With both sub-tree and precdences unchanged, the @{text cp}-values of |
|
608 threads other than @{text th} are not changed. Therefore, the |
|
609 only recalculation of @{text cp}-value happens at @{text th}, and |
|
610 the recalculation can be done locally using the |
|
611 {\em local recalculation principle}, because the @{text cp}-values |
|
612 of its children are not changed. |
|
613 *} |
376 lemma cp_kept: |
614 lemma cp_kept: |
377 assumes "th' \<noteq> th" |
615 assumes "th' \<noteq> th" |
378 shows "cp (e#s) th' = cp s th'" |
616 shows "cp (e#s) th' = cp s th'" |
379 proof - |
617 proof - |
380 have "(the_preced (e#s) ` {th'a. Th th'a \<in> subtree (RAG (e#s)) (Th th')}) = |
618 have "(the_preced (e#s) ` {th'a. Th th'a \<in> subtree (RAG (e#s)) (Th th')}) = |
573 show ?thesis by metis |
843 show ?thesis by metis |
574 qed |
844 qed |
575 |
845 |
576 end |
846 end |
577 |
847 |
|
848 text {* |
|
849 The following locale deals with the @{text Create}-operation. |
|
850 *} |
|
851 |
578 section {* The @{term Create} operation *} |
852 section {* The @{term Create} operation *} |
579 |
853 |
580 context valid_trace_create |
854 context valid_trace_create |
581 begin |
855 begin |
582 |
856 |
|
857 text {* |
|
858 Since @{text Create}-operation does not change @{text RAG} (according to |
|
859 @{thm RAG_es}) and @{text tRAG} is determined uniquely by @{text RAG}, |
|
860 therefore, @{text tRAG} is not not changed by @{text Create} neither. |
|
861 *} |
583 lemma tRAG_kept: "tRAG (e#s) = tRAG s" |
862 lemma tRAG_kept: "tRAG (e#s) = tRAG s" |
584 by (unfold tRAG_alt_def RAG_es, auto) |
863 by (unfold tRAG_alt_def RAG_es, auto) |
585 |
864 |
|
865 lemma tG_kept: "tG (e#s) = tG s" |
|
866 by (unfold tG_def tRAG_kept, simp) |
|
867 |
|
868 text {* |
|
869 The following lemma shows that @{text th} is completely isolated |
|
870 from @{text RAG}. |
|
871 *} |
|
872 lemma th_not_in: "Th th \<notin> Field (tRAG s)" |
|
873 by (meson not_in_thread_isolated subsetCE tRAG_Field th_not_live_s) |
|
874 |
|
875 text {* |
|
876 Based on @{thm th_not_in}, it can be derived that @{text th} is also |
|
877 isolated from @{text RAG}. |
|
878 *} |
|
879 lemma th_not_in_tG: "th \<notin> Field (tG s)" |
|
880 using tG_threads th_not_live_s by blast |
|
881 |
|
882 |
|
883 text {* |
|
884 The @{text Create}-operation does not change the precedences |
|
885 of other threads excepting sets a the initial precedence for the |
|
886 thread being created (i.e. @{text th}). |
|
887 *} |
586 lemma preced_kept: |
888 lemma preced_kept: |
587 assumes "th' \<noteq> th" |
889 assumes "th' \<noteq> th" |
588 shows "the_preced (e#s) th' = the_preced s th'" |
890 shows "the_preced (e#s) th' = the_preced s th'" |
589 by (unfold the_preced_def preced_def is_create, insert assms, auto) |
891 by (unfold the_preced_def preced_def is_create, insert assms, auto) |
590 |
892 |
591 lemma th_not_in: "Th th \<notin> Field (tRAG s)" |
893 text {* |
592 by (meson not_in_thread_isolated subsetCE tRAG_Field th_not_live_s) |
894 The following lemma shows that the @{text cp}-values of |
593 |
895 all other threads need not be recalculated. The reason is twofold, first, |
|
896 since @{text tG} is not changed, sub-trees of these threads are not changed; |
|
897 second, the precedences of the threads in these sub-trees are not changed (because |
|
898 the only thread with a changed precedence is @{text th} and @{text th} is isolated |
|
899 from @{text tG}). |
|
900 *} |
594 lemma eq_cp: |
901 lemma eq_cp: |
595 assumes neq_th: "th' \<noteq> th" |
902 assumes neq_th: "th' \<noteq> th" |
596 shows "cp (e#s) th' = cp s th'" |
903 shows "cp (e#s) th' = cp s th'" |
597 proof - |
904 proof - |
598 have "(the_preced (e#s) \<circ> the_thread) ` subtree (tRAG (e#s)) (Th th') = |
905 have "(the_preced (e # s) ` subtree (tG (e # s)) th') = |
599 (the_preced s \<circ> the_thread) ` subtree (tRAG s) (Th th')" |
906 (the_preced s ` subtree (tG s) th')" |
600 proof(unfold tRAG_kept, rule f_image_eq) |
907 proof - |
601 fix a |
908 { fix a |
602 assume a_in: "a \<in> subtree (tRAG s) (Th th')" |
909 assume "a \<in> subtree (tG s) th'" |
603 then obtain th_a where eq_a: "a = Th th_a" |
910 with th_not_in_tG have "a \<noteq> th" |
604 proof(cases rule:subtreeE) |
911 by (metis ancestors_Field dm_tG_threads neq_th subtree_ancestorsI th_not_live_s) |
605 case 2 |
912 from preced_kept[OF this] |
606 from ancestors_Field[OF 2(2)] |
913 have "the_preced (e # s) a = the_preced s a" . |
607 and that show ?thesis by (unfold tRAG_alt_def, auto) |
914 } |
608 qed auto |
915 thus ?thesis by (unfold tG_kept, auto intro!:f_image_eq) |
609 have neq_th_a: "th_a \<noteq> th" |
916 qed |
610 proof - |
917 thus ?thesis by (unfold cp_alt_def2, simp) |
611 have "(Th th) \<notin> subtree (tRAG s) (Th th')" |
918 qed |
612 proof |
919 |
613 assume "Th th \<in> subtree (tRAG s) (Th th')" |
920 text {* |
614 thus False |
921 The following two lemmas deal with the @{text cp}-calculation of @{text th}. |
615 proof(cases rule:subtreeE) |
922 The first lemma @{text children_of_th} says @{text th} has no children. |
616 case 2 |
923 The reason is simple, @{text th} is isolated from @{text "RAG"} before the |
617 from ancestors_Field[OF this(2)] |
924 @{term Create}-operation and @{text Create} does not change @{text RAG}, so |
618 and th_not_in[unfolded Field_def] |
925 @{text th} keeps isolated after the operation. |
619 show ?thesis by auto |
926 *} |
620 qed (insert assms, auto) |
|
621 qed |
|
622 with a_in[unfolded eq_a] show ?thesis by auto |
|
623 qed |
|
624 from preced_kept[OF this] |
|
625 show "(the_preced (e#s) \<circ> the_thread) a = (the_preced s \<circ> the_thread) a" |
|
626 by (unfold eq_a, simp) |
|
627 qed |
|
628 thus ?thesis by (unfold cp_alt_def1, simp) |
|
629 qed |
|
630 |
927 |
631 lemma children_of_th: "RTree.children (tRAG (e#s)) (Th th) = {}" |
928 lemma children_of_th: "RTree.children (tRAG (e#s)) (Th th) = {}" |
632 proof - |
929 proof - |
633 { fix a |
930 { fix a |
634 assume "a \<in> RTree.children (tRAG (e#s)) (Th th)" |
931 assume "a \<in> RTree.children (tRAG (e#s)) (Th th)" |
636 with th_not_in have False |
933 with th_not_in have False |
637 by (unfold Field_def tRAG_kept, auto) |
934 by (unfold Field_def tRAG_kept, auto) |
638 } thus ?thesis by auto |
935 } thus ?thesis by auto |
639 qed |
936 qed |
640 |
937 |
|
938 text {* |
|
939 Now, since @{term th} has no children, by definition its @{text cp} value |
|
940 equals its precedence: |
|
941 *} |
641 lemma eq_cp_th: "cp (e#s) th = preced th (e#s)" |
942 lemma eq_cp_th: "cp (e#s) th = preced th (e#s)" |
642 by (unfold vat_es.cp_rec children_of_th, simp add:the_preced_def) |
943 by (unfold vat_es.cp_rec children_of_th, simp add:the_preced_def) |
643 |
944 |
644 end |
945 end |
645 |
946 |
646 |
947 text {* |
|
948 The following locale @{text valid_trace_exit} deals with the @{term Exit}-operation. |
|
949 *} |
647 context valid_trace_exit |
950 context valid_trace_exit |
648 begin |
951 begin |
|
952 |
|
953 text {* |
|
954 The treatment of @{text Exit} is very similar to @{text Create}. |
|
955 First, the precedences of threads other than @{text th} are not changed. |
|
956 *} |
649 |
957 |
650 lemma preced_kept: |
958 lemma preced_kept: |
651 assumes "th' \<noteq> th" |
959 assumes "th' \<noteq> th" |
652 shows "the_preced (e#s) th' = the_preced s th'" |
960 shows "the_preced (e#s) th' = the_preced s th'" |
653 using assms |
961 using assms |
654 by (unfold the_preced_def is_exit preced_def, simp) |
962 by (unfold the_preced_def is_exit preced_def, simp) |
655 |
963 |
|
964 text {* |
|
965 Second, @{term tRAG} is not changed by @{text Exit} either. |
|
966 *} |
656 lemma tRAG_kept: "tRAG (e#s) = tRAG s" |
967 lemma tRAG_kept: "tRAG (e#s) = tRAG s" |
657 by (unfold tRAG_alt_def RAG_es, auto) |
968 by (unfold tRAG_alt_def RAG_es, auto) |
|
969 |
|
970 text {* |
|
971 Since @{term tG} is defined in terms of @{term tRAG}, @{term tG} is not changed neither. |
|
972 *} |
|
973 lemma tG_kept: "tG (e#s) = tG s" |
|
974 by (unfold tG_def tRAG_kept, simp) |
658 |
975 |
659 lemma th_RAG: "Th th \<notin> Field (RAG s)" |
976 lemma th_RAG: "Th th \<notin> Field (RAG s)" |
660 proof - |
977 proof - |
661 have "Th th \<notin> Range (RAG s)" |
978 have "Th th \<notin> Range (RAG s)" |
662 proof |
979 proof |
675 th_not_live_es valid_trace.dm_RAG_threads vat_es.valid_trace_axioms by blast |
992 th_not_live_es valid_trace.dm_RAG_threads vat_es.valid_trace_axioms by blast |
676 qed |
993 qed |
677 ultimately show ?thesis by (auto simp:Field_def) |
994 ultimately show ?thesis by (auto simp:Field_def) |
678 qed |
995 qed |
679 |
996 |
|
997 |
680 lemma th_tRAG: "(Th th) \<notin> Field (tRAG s)" |
998 lemma th_tRAG: "(Th th) \<notin> Field (tRAG s)" |
681 using th_RAG tRAG_Field by auto |
999 using th_RAG tRAG_Field by auto |
682 |
1000 |
|
1001 |
|
1002 text {* |
|
1003 Based on @{thm th_RAG}, it can be derived that @{text th} is also |
|
1004 isolated from @{text tG}. |
|
1005 *} |
|
1006 lemma th_not_in_tG: "th \<notin> Field (tG s)" |
|
1007 using tG_kept vat_es.tG_threads by auto |
|
1008 |
|
1009 text {* |
|
1010 Because of @{thm preced_kept}, @{thm tG_kept} and @{thm th_tRAG}, |
|
1011 the @{text cp}-values of all other threads are not changed. |
|
1012 The reasoning is almost the same as that of @{term Create}: |
|
1013 *} |
683 lemma eq_cp: |
1014 lemma eq_cp: |
684 assumes neq_th: "th' \<noteq> th" |
1015 assumes neq_th: "th' \<noteq> th" |
685 shows "cp (e#s) th' = cp s th'" |
1016 shows "cp (e#s) th' = cp s th'" |
686 proof - |
1017 proof - |
687 have "(the_preced (e#s) \<circ> the_thread) ` subtree (tRAG (e#s)) (Th th') = |
1018 have "(the_preced (e # s) ` subtree (tG (e # s)) th') = |
688 (the_preced s \<circ> the_thread) ` subtree (tRAG s) (Th th')" |
1019 (the_preced s ` subtree (tG s) th')" |
689 proof(unfold tRAG_kept, rule f_image_eq) |
1020 proof - |
690 fix a |
1021 { fix a |
691 assume a_in: "a \<in> subtree (tRAG s) (Th th')" |
1022 assume "a \<in> subtree (tG s) th'" |
692 then obtain th_a where eq_a: "a = Th th_a" |
1023 with th_not_in_tG have "a \<noteq> th" |
693 proof(cases rule:subtreeE) |
1024 by (metis ex_in_conv neq_th root_def root_readys_tG subtree_ancestorsI th_ready_s) |
694 case 2 |
1025 from preced_kept[OF this] |
695 from ancestors_Field[OF 2(2)] |
1026 have "the_preced (e # s) a = the_preced s a" . |
696 and that show ?thesis by (unfold tRAG_alt_def, auto) |
1027 } |
697 qed auto |
1028 thus ?thesis by (unfold tG_kept, auto intro!:f_image_eq) |
698 have neq_th_a: "th_a \<noteq> th" |
1029 qed |
699 proof - |
1030 thus ?thesis by (unfold cp_alt_def2, simp) |
700 from readys_in_no_subtree[OF th_ready_s assms] |
|
701 have "(Th th) \<notin> subtree (RAG s) (Th th')" . |
|
702 with tRAG_subtree_RAG[of s "Th th'"] |
|
703 have "(Th th) \<notin> subtree (tRAG s) (Th th')" by auto |
|
704 with a_in[unfolded eq_a] show ?thesis by auto |
|
705 qed |
|
706 from preced_kept[OF this] |
|
707 show "(the_preced (e#s) \<circ> the_thread) a = (the_preced s \<circ> the_thread) a" |
|
708 by (unfold eq_a, simp) |
|
709 qed |
|
710 thus ?thesis by (unfold cp_alt_def1, simp) |
|
711 qed |
1031 qed |
712 |
1032 |
713 end |
1033 end |
714 |
1034 |
715 end |
1035 end |