68 -- {* Finished thread is removed: *} |
69 -- {* Finished thread is removed: *} |
69 "threads (Exit thread # s) = (threads s) - {thread}" | |
70 "threads (Exit thread # s) = (threads s) - {thread}" | |
70 -- {* Other kind of events does not affect the value of @{text "threads"}: *} |
71 -- {* Other kind of events does not affect the value of @{text "threads"}: *} |
71 "threads (e#s) = threads s" |
72 "threads (e#s) = threads s" |
72 |
73 |
73 text {* \noindent |
74 text {* |
74 Functions such as @{text "threads"}, which extract information out of system states, are called |
75 \noindent |
75 {\em observing functions}. A series of observing functions will be defined in the sequel in order to |
76 The function @{text "threads"} defined above is one of |
76 model the protocol. |
77 the so called {\em observation function}s which forms |
77 Observing function @{text "priority"} calculates |
78 the very basis of Paulson's inductive protocol verification method. |
78 the {\em original priority} of thread @{text "th"} in state @{text "s"}, expressed as |
79 Each observation function {\em observes} one particular aspect (or attribute) |
79 : @{text "priority th s" }. The {\em original priority} is the priority |
80 of the system. For example, the attribute observed by @{text "threads s"} |
|
81 is the set of threads living in state @{text "s"}. |
|
82 The protocol being modelled |
|
83 The decision made the protocol being modelled is based on the {\em observation}s |
|
84 returned by {\em observation function}s. Since {\observation function}s forms |
|
85 the very basis on which Paulson's inductive method is based, there will be |
|
86 a lot of such observation functions introduced in the following. In fact, any function |
|
87 which takes event list as argument is a {\em observation function}. |
|
88 *} |
|
89 |
|
90 text {* \noindent |
|
91 Observation @{text "priority th s"} is |
|
92 the {\em original priority} of thread @{text "th"} in state @{text "s"}. |
|
93 The {\em original priority} is the priority |
80 assigned to a thread when it is created or when it is reset by system call |
94 assigned to a thread when it is created or when it is reset by system call |
81 @{text "Set thread priority"}. |
95 (represented by event @{text "Set thread priority"}). |
82 *} |
96 *} |
83 |
97 |
84 fun priority :: "thread \<Rightarrow> state \<Rightarrow> priority" |
98 fun priority :: "thread \<Rightarrow> state \<Rightarrow> priority" |
85 where |
99 where |
86 -- {* @{text "0"} is assigned to threads which have never been created: *} |
100 -- {* @{text "0"} is assigned to threads which have never been created: *} |
91 (if thread' = thread then prio else priority thread s)" | |
105 (if thread' = thread then prio else priority thread s)" | |
92 "priority thread (e#s) = priority thread s" |
106 "priority thread (e#s) = priority thread s" |
93 |
107 |
94 text {* |
108 text {* |
95 \noindent |
109 \noindent |
96 In the following, |
110 Observation @{text "last_set th s"} is the last time when the priority of thread @{text "th"} is set, |
97 @{text "last_set th s"} is the last time when the priority of thread @{text "th"} is set, |
|
98 observed from state @{text "s"}. |
111 observed from state @{text "s"}. |
99 The time in the system is measured by the number of events happened so far since the very beginning. |
112 The time in the system is measured by the number of events happened so far since the very beginning. |
100 *} |
113 *} |
101 fun last_set :: "thread \<Rightarrow> state \<Rightarrow> nat" |
114 fun last_set :: "thread \<Rightarrow> state \<Rightarrow> nat" |
102 where |
115 where |
175 \end{minipage} |
188 \end{minipage} |
176 *} |
189 *} |
177 cs_dependants_def: |
190 cs_dependants_def: |
178 "dependants (wq::cs \<Rightarrow> thread list) th \<equiv> {th' . (Th th', Th th) \<in> (RAG wq)^+}" |
191 "dependants (wq::cs \<Rightarrow> thread list) th \<equiv> {th' . (Th th', Th th) \<in> (RAG wq)^+}" |
179 |
192 |
180 text {* |
|
181 The data structure used by the operating system for scheduling is referred to as |
|
182 {\em schedule state}. It is represented as a record consisting of |
|
183 a function assigning waiting queue to resources |
|
184 (to be used as the @{text "wq"} argument in @{text "holding"}, @{text "waiting"} |
|
185 and @{text "RAG"}, etc) and a function assigning precedence to threads: |
|
186 *} |
|
187 |
|
188 record schedule_state = |
|
189 wq_fun :: "cs \<Rightarrow> thread list" -- {* The function assigning waiting queue. *} |
|
190 cprec_fun :: "thread \<Rightarrow> precedence" -- {* The function assigning precedence. *} |
|
191 |
193 |
192 text {* \noindent |
194 text {* \noindent |
193 The following |
195 The following |
194 @{text "cpreced s th"} gives the {\em current precedence} of thread @{text "th"} under |
196 @{text "cpreced s th"} gives the {\em current precedence} of thread @{text "th"} under |
195 state @{text "s"}. The definition of @{text "cpreced"} reflects the basic idea of |
197 state @{text "s"}. The definition of @{text "cpreced"} reflects the basic idea of |
201 *} |
203 *} |
202 |
204 |
203 definition cpreced :: "(cs \<Rightarrow> thread list) \<Rightarrow> state \<Rightarrow> thread \<Rightarrow> precedence" |
205 definition cpreced :: "(cs \<Rightarrow> thread list) \<Rightarrow> state \<Rightarrow> thread \<Rightarrow> precedence" |
204 where "cpreced wq s = (\<lambda>th. Max ((\<lambda>th'. preced th' s) ` ({th} \<union> dependants wq th)))" |
206 where "cpreced wq s = (\<lambda>th. Max ((\<lambda>th'. preced th' s) ` ({th} \<union> dependants wq th)))" |
205 |
207 |
|
208 text {* |
|
209 Notice that the current precedence (@{text "cpreced"}) of one thread @{text "th"} can be boosted |
|
210 (becoming larger than its own precedence) by those threads in |
|
211 the @{text "dependants wq th"}-set. If one thread get boosted, we say |
|
212 it inherits the priority (or, more precisely, the precedence) of |
|
213 its dependants. This is how the word "Inheritance" in |
|
214 Priority Inheritance Protocol comes. |
|
215 *} |
|
216 |
206 (*<*) |
217 (*<*) |
207 lemma |
218 lemma |
208 cpreced_def2: |
219 cpreced_def2: |
209 "cpreced wq s th \<equiv> Max ({preced th s} \<union> {preced th' s | th'. th' \<in> dependants wq th})" |
220 "cpreced wq s th \<equiv> Max ({preced th s} \<union> {preced th' s | th'. th' \<in> dependants wq th})" |
210 unfolding cpreced_def image_def |
221 unfolding cpreced_def image_def |
211 apply(rule eq_reflection) |
222 apply(rule eq_reflection) |
212 apply(rule_tac f="Max" in arg_cong) |
223 apply(rule_tac f="Max" in arg_cong) |
213 by (auto) |
224 by (auto) |
214 (*>*) |
225 (*>*) |
215 |
226 |
216 (* |
|
217 abbreviation |
|
218 "all_unlocked \<equiv> \<lambda>_::cs. ([]::thread list)" |
|
219 |
|
220 abbreviation |
|
221 "initial_cprec \<equiv> \<lambda>_::thread. Prc 0 0" |
|
222 *) |
|
223 |
227 |
224 text {* \noindent |
228 text {* \noindent |
225 Assuming @{text "qs"} be the waiting queue of a critical resource, |
229 Assuming @{text "qs"} be the waiting queue of a critical resource, |
226 the following abbreviation "release qs" is the waiting queue after the thread |
230 the following abbreviation "release qs" is the waiting queue after the thread |
227 holding the resource (which is thread at the head of @{text "qs"}) released |
231 holding the resource (which is thread at the head of @{text "qs"}) released |
240 from common sense that the thread who comes the earliest should take over. |
244 from common sense that the thread who comes the earliest should take over. |
241 The intention of this definition is to show that the choice of which thread to take over the |
245 The intention of this definition is to show that the choice of which thread to take over the |
242 release resource does not affect the correctness of the PIP protocol. |
246 release resource does not affect the correctness of the PIP protocol. |
243 *} |
247 *} |
244 |
248 |
245 (* ccc *) |
249 text {* |
246 |
250 The data structure used by the operating system for scheduling is referred to as |
247 text {* \noindent |
251 {\em schedule state}. It is represented as a record consisting of |
248 The following function @{text "schs"} is used to calculate the schedule state @{text "schs s"} |
252 a function assigning waiting queue to resources |
249 out of the current system state @{text "s"}. |
253 (to be used as the @{text "wq"} argument in @{text "holding"}, @{text "waiting"} |
250 It is the central function to model Priority Inheritance: |
254 and @{text "RAG"}, etc) and a function assigning precedence to threads: |
|
255 *} |
|
256 |
|
257 record schedule_state = |
|
258 wq_fun :: "cs \<Rightarrow> thread list" -- {* The function assigning waiting queue. *} |
|
259 cprec_fun :: "thread \<Rightarrow> precedence" -- {* The function assigning precedence. *} |
|
260 |
|
261 text {* \noindent |
|
262 The following two abbreviations (@{text "all_unlocked"} and @{text "initial_cprec"}) |
|
263 are used to set the initial values of the @{text "wq_fun"} @{text "cprec_fun"} fields |
|
264 respectively of the @{text "schedule_state"} record by the following function @{text "sch"}, |
|
265 which is used to calculate the system's {\em schedule state}. |
|
266 |
|
267 Since there is no thread at the very beginning to make request, all critical resources |
|
268 are free (or unlocked). This status is represented by the abbreviation |
|
269 @{text "all_unlocked"}. |
|
270 *} |
|
271 abbreviation |
|
272 "all_unlocked \<equiv> \<lambda>_::cs. ([]::thread list)" |
|
273 |
|
274 |
|
275 text {* \noindent |
|
276 The initial current precedence for a thread can be anything, because there is no thread then. |
|
277 We simply assume every thread has precedence @{text "Prc 0 0"}. |
|
278 *} |
|
279 |
|
280 abbreviation |
|
281 "initial_cprec \<equiv> \<lambda>_::thread. Prc 0 0" |
|
282 |
|
283 |
|
284 text {* \noindent |
|
285 The following function @{text "schs"} is used to calculate the system's schedule state @{text "schs s"} |
|
286 out of the current system state @{text "s"}. It is the central function to model Priority Inheritance: |
251 *} |
287 *} |
252 fun schs :: "state \<Rightarrow> schedule_state" |
288 fun schs :: "state \<Rightarrow> schedule_state" |
253 where |
289 where |
254 "schs [] = (| wq_fun = \<lambda> cs. [], cprec_fun = (\<lambda>_. Prc 0 0) |)" | |
290 -- {* |
|
291 \begin{minipage}{0.9\textwidth} |
|
292 Setting the initial value of the @{text "schedule_state"} record (see the explanations above). |
|
293 \end{minipage} |
|
294 *} |
|
295 "schs [] = (| wq_fun = all_unlocked, cprec_fun = initial_cprec |)" | |
255 |
296 |
256 -- {* |
297 -- {* |
257 \begin{minipage}{0.9\textwidth} |
298 \begin{minipage}{0.9\textwidth} |
258 \begin{enumerate} |
299 \begin{enumerate} |
259 \item @{text "ps"} is the schedule state of last moment. |
300 \item @{text "ps"} is the schedule state of last moment. |
274 \end{enumerate} |
315 \end{enumerate} |
275 \item @{text "ncp"} is new precedence function, it is calculated from the newly updated waiting queue |
316 \item @{text "ncp"} is new precedence function, it is calculated from the newly updated waiting queue |
276 function. The RAGency of precedence function on waiting queue function is the reason to |
317 function. The RAGency of precedence function on waiting queue function is the reason to |
277 put them in the same record so that they can evolve together. |
318 put them in the same record so that they can evolve together. |
278 \end{enumerate} |
319 \end{enumerate} |
|
320 |
|
321 |
|
322 The calculation of @{text "cprec_fun"} depends on the value of @{text "wq_fun"}. |
|
323 Therefore, in the following cases, @{text "wq_fun"} is always calculated first, in |
|
324 the name of @{text "wq"} (if @{text "wq_fun"} is not changed |
|
325 by the happening event) or @{text "new_wq"} (if the value of @{text "wq_fun"} is changed). |
279 \end{minipage} |
326 \end{minipage} |
280 *} |
327 *} |
281 "schs (Create th prio # s) = |
328 "schs (Create th prio # s) = |
282 (let wq = wq_fun (schs s) in |
329 (let wq = wq_fun (schs s) in |
283 (|wq_fun = wq, cprec_fun = cpreced wq (Create th prio # s)|))" |
330 (|wq_fun = wq, cprec_fun = cpreced wq (Create th prio # s)|))" |
285 (let wq = wq_fun (schs s) in |
332 (let wq = wq_fun (schs s) in |
286 (|wq_fun = wq, cprec_fun = cpreced wq (Exit th # s)|))" |
333 (|wq_fun = wq, cprec_fun = cpreced wq (Exit th # s)|))" |
287 | "schs (Set th prio # s) = |
334 | "schs (Set th prio # s) = |
288 (let wq = wq_fun (schs s) in |
335 (let wq = wq_fun (schs s) in |
289 (|wq_fun = wq, cprec_fun = cpreced wq (Set th prio # s)|))" |
336 (|wq_fun = wq, cprec_fun = cpreced wq (Set th prio # s)|))" |
|
337 -- {* |
|
338 \begin{minipage}{0.9\textwidth} |
|
339 Different from the forth coming cases, the @{text "wq_fun"} field of the schedule state |
|
340 is changed. So, the new value is calculated first, in the name of @{text "new_wq"}. |
|
341 \end{minipage} |
|
342 *} |
290 | "schs (P th cs # s) = |
343 | "schs (P th cs # s) = |
291 (let wq = wq_fun (schs s) in |
344 (let wq = wq_fun (schs s) in |
292 let new_wq = wq(cs := (wq cs @ [th])) in |
345 let new_wq = wq(cs := (wq cs @ [th])) in |
293 (|wq_fun = new_wq, cprec_fun = cpreced new_wq (P th cs # s)|))" |
346 (|wq_fun = new_wq, cprec_fun = cpreced new_wq (P th cs # s)|))" |
294 | "schs (V th cs # s) = |
347 | "schs (V th cs # s) = |
381 definition readys :: "state \<Rightarrow> thread set" |
434 definition readys :: "state \<Rightarrow> thread set" |
382 where "readys s \<equiv> {th . th \<in> threads s \<and> (\<forall> cs. \<not> waiting s th cs)}" |
435 where "readys s \<equiv> {th . th \<in> threads s \<and> (\<forall> cs. \<not> waiting s th cs)}" |
383 |
436 |
384 text {* \noindent |
437 text {* \noindent |
385 The following function @{text "runing"} calculates the set of running thread, which is the ready |
438 The following function @{text "runing"} calculates the set of running thread, which is the ready |
386 thread with the highest precedence. |
439 thread with the highest precedence. |
387 *} |
440 *} |
388 definition runing :: "state \<Rightarrow> thread set" |
441 definition runing :: "state \<Rightarrow> thread set" |
389 where "runing s \<equiv> {th . th \<in> readys s \<and> cp s th = Max ((cp s) ` (readys s))}" |
442 where "runing s \<equiv> {th . th \<in> readys s \<and> cp s th = Max ((cp s) ` (readys s))}" |
|
443 |
|
444 text {* \noindent |
|
445 Notice that the definition of @{text "running"} reflects the preemptive scheduling strategy, |
|
446 because, if the @{text "running"}-thread (the one in @{text "runing"} set) |
|
447 lowered its precedence by resetting its own priority to a lower |
|
448 one, it will lose its status of being the max in @{text "ready"}-set and be superseded. |
|
449 *} |
390 |
450 |
391 text {* \noindent |
451 text {* \noindent |
392 The following function @{text "holdents s th"} returns the set of resources held by thread |
452 The following function @{text "holdents s th"} returns the set of resources held by thread |
393 @{text "th"} in state @{text "s"}. |
453 @{text "th"} in state @{text "s"}. |
394 *} |
454 *} |
402 unfolding s_holding_abv |
462 unfolding s_holding_abv |
403 unfolding wq_def |
463 unfolding wq_def |
404 by (simp) |
464 by (simp) |
405 |
465 |
406 text {* \noindent |
466 text {* \noindent |
407 @{text "cntCS s th"} returns the number of resources held by thread @{text "th"} in |
467 Observation @{text "cntCS s th"} returns the number of resources held by thread @{text "th"} in |
408 state @{text "s"}: |
468 state @{text "s"}: |
409 *} |
469 *} |
410 definition cntCS :: "state \<Rightarrow> thread \<Rightarrow> nat" |
470 definition cntCS :: "state \<Rightarrow> thread \<Rightarrow> nat" |
411 where "cntCS s th = card (holdents s th)" |
471 where "cntCS s th = card (holdents s th)" |
412 |
472 |
413 text {* \noindent |
473 text {* \noindent |
414 The fact that event @{text "e"} is eligible to happen next in state @{text "s"} |
474 According to the convention of Paulson's inductive method, |
|
475 the decision made by a protocol that event @{text "e"} is eligible to happen next under state @{text "s"} |
415 is expressed as @{text "step s e"}. The predicate @{text "step"} is inductively defined as |
476 is expressed as @{text "step s e"}. The predicate @{text "step"} is inductively defined as |
416 follows: |
477 follows (notice how the decision is based on the {\em observation function}s |
|
478 defined above, and also notice how a complicated protocol is modeled by a few simple |
|
479 observations, and how such a kind of simplicity gives rise to improved trust on |
|
480 faithfulness): |
417 *} |
481 *} |
418 inductive step :: "state \<Rightarrow> event \<Rightarrow> bool" |
482 inductive step :: "state \<Rightarrow> event \<Rightarrow> bool" |
419 where |
483 where |
420 -- {* |
484 -- {* |
421 A thread can be created if it is not a live thread: |
485 A thread can be created if it is not a live thread: |
441 if it is running and holding that resource: |
505 if it is running and holding that resource: |
442 \end{minipage} |
506 \end{minipage} |
443 *} |
507 *} |
444 thread_V: "\<lbrakk>thread \<in> runing s; holding s thread cs\<rbrakk> \<Longrightarrow> step s (V thread cs)" | |
508 thread_V: "\<lbrakk>thread \<in> runing s; holding s thread cs\<rbrakk> \<Longrightarrow> step s (V thread cs)" | |
445 -- {* |
509 -- {* |
446 A thread can adjust its own priority as long as it is current running: |
510 \begin{minipage}{0.9\textwidth} |
|
511 A thread can adjust its own priority as long as it is current running. |
|
512 With the resetting of one thread's priority, its precedence may change. |
|
513 If this change lowered the precedence, according to the definition of @{text "running"} |
|
514 function, |
|
515 \end{minipage} |
447 *} |
516 *} |
448 thread_set: "\<lbrakk>thread \<in> runing s\<rbrakk> \<Longrightarrow> step s (Set thread prio)" |
517 thread_set: "\<lbrakk>thread \<in> runing s\<rbrakk> \<Longrightarrow> step s (Set thread prio)" |
449 |
518 |
450 text {* \noindent |
519 text {* |
451 With predicate @{text "step"}, the fact that @{text "s"} is a legal state in |
520 In Paulson's inductive method, every protocol is defined by such a @{text "step"} |
452 Priority Inheritance protocol can be expressed as: @{text "vt step s"}, where |
521 predicate. For instance, the predicate @{text "step"} given above |
|
522 defines the PIP protocol. So, it can also be called "PIP". |
|
523 *} |
|
524 |
|
525 abbreviation |
|
526 "PIP \<equiv> step" |
|
527 |
|
528 |
|
529 text {* \noindent |
|
530 For any protocol defined by a @{text "step"} predicate, |
|
531 the fact that @{text "s"} is a legal state in |
|
532 the protocol is expressed as: @{text "vt step s"}, where |
453 the predicate @{text "vt"} can be defined as the following: |
533 the predicate @{text "vt"} can be defined as the following: |
454 *} |
534 *} |
455 inductive vt :: "state \<Rightarrow> bool" |
535 inductive vt :: "state \<Rightarrow> bool" |
456 where |
536 where |
457 -- {* Empty list @{text "[]"} is a legal state in any protocol:*} |
537 -- {* Empty list @{text "[]"} is a legal state in any protocol:*} |
458 vt_nil[intro]: "vt []" | |
538 vt_nil[intro]: "vt []" | |
459 -- {* |
539 -- {* |
460 \begin{minipage}{0.9\textwidth} |
540 \begin{minipage}{0.9\textwidth} |
461 If @{text "s"} a legal state, and event @{text "e"} is eligible to happen |
541 If @{text "s"} a legal state of the protocol defined by predicate @{text "step"}, |
462 in state @{text "s"}, then @{text "e#s"} is a legal state as well: |
542 and event @{text "e"} is allowed to happen under state @{text "s"} by the protocol |
|
543 predicate @{text "step"}, then @{text "e#s"} is a new legal state rendered by the |
|
544 happening of @{text "e"}: |
463 \end{minipage} |
545 \end{minipage} |
464 *} |
546 *} |
465 vt_cons[intro]: "\<lbrakk>vt s; step s e\<rbrakk> \<Longrightarrow> vt (e#s)" |
547 vt_cons[intro]: "\<lbrakk>vt s; step s e\<rbrakk> \<Longrightarrow> vt (e#s)" |
466 |
548 |
467 text {* \noindent |
549 text {* \noindent |
468 It is easy to see that the definition of @{text "vt"} is generic. It can be applied to |
550 It is easy to see that the definition of @{text "vt"} is generic. It can be applied to |
469 any step predicate to get the set of legal states. |
551 any specific protocol specified by a @{text "step"}-predicate to get the set of |
470 *} |
552 legal states of that particular protocol. |
471 |
553 *} |
472 text {* \noindent |
554 |
473 The following two functions @{text "the_cs"} and @{text "the_th"} are used to extract |
555 text {* |
|
556 The following are two very basic properties of @{text "vt"}. |
|
557 *} |
|
558 |
|
559 lemma step_back_vt: "vt (e#s) \<Longrightarrow> vt s" |
|
560 by(ind_cases "vt (e#s)", simp) |
|
561 |
|
562 lemma step_back_step: "vt (e#s) \<Longrightarrow> step s e" |
|
563 by(ind_cases "vt (e#s)", simp) |
|
564 |
|
565 text {* \noindent |
|
566 The following two auxiliary functions @{text "the_cs"} and @{text "the_th"} are used to extract |
474 critical resource and thread respectively out of RAG nodes. |
567 critical resource and thread respectively out of RAG nodes. |
475 *} |
568 *} |
476 fun the_cs :: "node \<Rightarrow> cs" |
569 fun the_cs :: "node \<Rightarrow> cs" |
477 where "the_cs (Cs cs) = cs" |
570 where "the_cs (Cs cs) = cs" |
478 |
571 |
481 |
574 |
482 text {* \noindent |
575 text {* \noindent |
483 The following predicate @{text "next_th"} describe the next thread to |
576 The following predicate @{text "next_th"} describe the next thread to |
484 take over when a critical resource is released. In @{text "next_th s th cs t"}, |
577 take over when a critical resource is released. In @{text "next_th s th cs t"}, |
485 @{text "th"} is the thread to release, @{text "t"} is the one to take over. |
578 @{text "th"} is the thread to release, @{text "t"} is the one to take over. |
|
579 Notice how this definition is backed up by the @{text "release"} function and its use |
|
580 in the @{text "V"}-branch of @{text "schs"} function. This @{text "next_th"} function |
|
581 is not needed for the execution of PIP. It is introduced as an auxiliary function |
|
582 to state lemmas. The correctness of this definition will be confirmed by |
|
583 lemmas @{text "step_v_hold_inv"}, @{text " step_v_wait_inv"}, |
|
584 @{text "step_v_get_hold"} and @{text "step_v_not_wait"}. |
486 *} |
585 *} |
487 definition next_th:: "state \<Rightarrow> thread \<Rightarrow> cs \<Rightarrow> thread \<Rightarrow> bool" |
586 definition next_th:: "state \<Rightarrow> thread \<Rightarrow> cs \<Rightarrow> thread \<Rightarrow> bool" |
488 where "next_th s th cs t = (\<exists> rest. wq s cs = th#rest \<and> rest \<noteq> [] \<and> |
587 where "next_th s th cs t = (\<exists> rest. wq s cs = th#rest \<and> rest \<noteq> [] \<and> |
489 t = hd (SOME q. distinct q \<and> set q = set rest))" |
588 t = hd (SOME q. distinct q \<and> set q = set rest))" |
490 |
589 |
491 text {* \noindent |
590 text {* \noindent |
492 The function @{text "count Q l"} is used to count the occurrence of situation @{text "Q"} |
591 The aux function @{text "count Q l"} is used to count the occurrence of situation @{text "Q"} |
493 in list @{text "l"}: |
592 in list @{text "l"}: |
494 *} |
593 *} |
495 definition count :: "('a \<Rightarrow> bool) \<Rightarrow> 'a list \<Rightarrow> nat" |
594 definition count :: "('a \<Rightarrow> bool) \<Rightarrow> 'a list \<Rightarrow> nat" |
496 where "count Q l = length (filter Q l)" |
595 where "count Q l = length (filter Q l)" |
497 |
596 |
498 text {* \noindent |
597 text {* \noindent |
499 The following @{text "cntP s"} returns the number of operation @{text "P"} happened |
598 The following observation @{text "cntP s"} returns the number of operation @{text "P"} happened |
500 before reaching state @{text "s"}. |
599 before reaching state @{text "s"}. |
501 *} |
600 *} |
502 definition cntP :: "state \<Rightarrow> thread \<Rightarrow> nat" |
601 definition cntP :: "state \<Rightarrow> thread \<Rightarrow> nat" |
503 where "cntP s th = count (\<lambda> e. \<exists> cs. e = P th cs) s" |
602 where "cntP s th = count (\<lambda> e. \<exists> cs. e = P th cs) s" |
504 |
603 |
505 text {* \noindent |
604 text {* \noindent |
506 The following @{text "cntV s"} returns the number of operation @{text "V"} happened |
605 The following observation @{text "cntV s"} returns the number of operation @{text "V"} happened |
507 before reaching state @{text "s"}. |
606 before reaching state @{text "s"}. |
508 *} |
607 *} |
509 definition cntV :: "state \<Rightarrow> thread \<Rightarrow> nat" |
608 definition cntV :: "state \<Rightarrow> thread \<Rightarrow> nat" |
510 where "cntV s th = count (\<lambda> e. \<exists> cs. e = V th cs) s" |
609 where "cntV s th = count (\<lambda> e. \<exists> cs. e = V th cs) s" |
511 (*<*) |
610 (*<*) |