163 The Priority Inheritance Protocol, short PIP, is a scheduling |
165 The Priority Inheritance Protocol, short PIP, is a scheduling |
164 algorithm for a single-processor system.\footnote{We shall come back |
166 algorithm for a single-processor system.\footnote{We shall come back |
165 later to the case of PIP on multi-processor systems.} Our model of |
167 later to the case of PIP on multi-processor systems.} Our model of |
166 PIP is based on Paulson's inductive approach to protocol |
168 PIP is based on Paulson's inductive approach to protocol |
167 verification \cite{Paulson98}, where the \emph{state} of a system is |
169 verification \cite{Paulson98}, where the \emph{state} of a system is |
168 given by a list of events that happened so far. \emph{Events} in PIP fall |
170 given by a list of events that happened so far. \emph{Events} of PIP fall |
169 into five categories defined as the datatype: |
171 into five categories defined as the datatype: |
170 |
172 |
171 \begin{isabelle}\ \ \ \ \ %%% |
173 \begin{isabelle}\ \ \ \ \ %%% |
172 \mbox{\begin{tabular}{r@ {\hspace{2mm}}c@ {\hspace{2mm}}l@ {\hspace{7mm}}l} |
174 \mbox{\begin{tabular}{r@ {\hspace{2mm}}c@ {\hspace{2mm}}l@ {\hspace{7mm}}l} |
173 \isacommand{datatype} event |
175 \isacommand{datatype} event |
182 \noindent |
184 \noindent |
183 whereby threads, priorities and (critical) resources are represented |
185 whereby threads, priorities and (critical) resources are represented |
184 as natural numbers. The event @{term Set} models the situation that |
186 as natural numbers. The event @{term Set} models the situation that |
185 a thread obtains a new priority given by the programmer or |
187 a thread obtains a new priority given by the programmer or |
186 user (for example via the {\tt nice} utility under UNIX). As in Paulson's work, we |
188 user (for example via the {\tt nice} utility under UNIX). As in Paulson's work, we |
187 need to define functions that allow one to make some observations |
189 need to define functions that allow us to make some observations |
188 about states. One, called @{term threads}, calculates the set of |
190 about states. One, called @{term threads}, calculates the set of |
189 ``live'' threads that we have seen so far: |
191 ``live'' threads that we have seen so far: |
190 |
192 |
191 \begin{isabelle}\ \ \ \ \ %%% |
193 \begin{isabelle}\ \ \ \ \ %%% |
192 \mbox{\begin{tabular}{lcl} |
194 \mbox{\begin{tabular}{lcl} |
254 this choice would translate to a quite natural FIFO-scheduling of processes with |
256 this choice would translate to a quite natural FIFO-scheduling of processes with |
255 the same priority. |
257 the same priority. |
256 |
258 |
257 Next, we introduce the concept of \emph{waiting queues}. They are |
259 Next, we introduce the concept of \emph{waiting queues}. They are |
258 lists of threads associated with every resource. The first thread in |
260 lists of threads associated with every resource. The first thread in |
259 this list (the head, or short @{term hd}) is chosen to be the one |
261 this list (i.e.~the head, or short @{term hd}) is chosen to be the one |
260 that is in possession of the |
262 that is in possession of the |
261 ``lock'' of the corresponding resource. We model waiting queues as |
263 ``lock'' of the corresponding resource. We model waiting queues as |
262 functions, below abbreviated as @{text wq}. They take a resource as |
264 functions, below abbreviated as @{text wq}. They take a resource as |
263 argument and return a list of threads. This allows us to define |
265 argument and return a list of threads. This allows us to define |
264 when a thread \emph{holds}, respectively \emph{waits} for, a |
266 when a thread \emph{holds}, respectively \emph{waits} for, a |
312 \node (A) at (0,0) [draw, rounded corners=1mm, rectangle, very thick] {@{text "th\<^isub>0"}}; |
314 \node (A) at (0,0) [draw, rounded corners=1mm, rectangle, very thick] {@{text "th\<^isub>0"}}; |
313 \node (B) at (2,0) [draw, circle, very thick, inner sep=0.4mm] {@{text "cs\<^isub>1"}}; |
315 \node (B) at (2,0) [draw, circle, very thick, inner sep=0.4mm] {@{text "cs\<^isub>1"}}; |
314 \node (C) at (4,0.7) [draw, rounded corners=1mm, rectangle, very thick] {@{text "th\<^isub>1"}}; |
316 \node (C) at (4,0.7) [draw, rounded corners=1mm, rectangle, very thick] {@{text "th\<^isub>1"}}; |
315 \node (D) at (4,-0.7) [draw, rounded corners=1mm, rectangle, very thick] {@{text "th\<^isub>2"}}; |
317 \node (D) at (4,-0.7) [draw, rounded corners=1mm, rectangle, very thick] {@{text "th\<^isub>2"}}; |
316 \node (E) at (6,-0.7) [draw, circle, very thick, inner sep=0.4mm] {@{text "cs\<^isub>2"}}; |
318 \node (E) at (6,-0.7) [draw, circle, very thick, inner sep=0.4mm] {@{text "cs\<^isub>2"}}; |
|
319 \node (E1) at (6, 0.2) [draw, circle, very thick, inner sep=0.4mm] {@{text "cs\<^isub>3"}}; |
317 \node (F) at (8,-0.7) [draw, rounded corners=1mm, rectangle, very thick] {@{text "th\<^isub>3"}}; |
320 \node (F) at (8,-0.7) [draw, rounded corners=1mm, rectangle, very thick] {@{text "th\<^isub>3"}}; |
318 |
321 |
319 \draw [->,line width=0.6mm] (A) to node [pos=0.45,sloped,above=-0.5mm] {\fnt{}holding} (B); |
322 \draw [->,line width=0.6mm] (A) to node [pos=0.45,sloped,above=-0.5mm] {\fnt{}holding} (B); |
320 \draw [->,line width=0.6mm] (C) to node [pos=0.4,sloped,above=-0.5mm] {\fnt{}waiting} (B); |
323 \draw [->,line width=0.6mm] (C) to node [pos=0.4,sloped,above=-0.5mm] {\fnt{}waiting} (B); |
321 \draw [->,line width=0.6mm] (D) to node [pos=0.4,sloped,above=-0.5mm] {\fnt{}waiting} (B); |
324 \draw [->,line width=0.6mm] (D) to node [pos=0.4,sloped,below=-0.5mm] {\fnt{}waiting} (B); |
322 \draw [->,line width=0.6mm] (D) to node [pos=0.45,sloped,above=-0.5mm] {\fnt{}holding} (E); |
325 \draw [->,line width=0.6mm] (D) to node [pos=0.45,sloped,below=-0.5mm] {\fnt{}holding} (E); |
323 \draw [->,line width=0.6mm] (F) to node [pos=0.45,sloped,above=-0.5mm] {\fnt{}waiting} (E); |
326 \draw [->,line width=0.6mm] (D) to node [pos=0.45,sloped,above=-0.5mm] {\fnt{}holding} (E1); |
|
327 \draw [->,line width=0.6mm] (F) to node [pos=0.45,sloped,below=-0.5mm] {\fnt{}waiting} (E); |
324 \end{tikzpicture} |
328 \end{tikzpicture} |
325 \end{center} |
329 \end{center} |
326 |
330 |
327 \noindent |
331 \noindent |
328 The use of relations for representing RAGs allows us to conveniently define |
332 The use of relations for representing RAGs allows us to conveniently define |
333 \end{isabelle} |
337 \end{isabelle} |
334 |
338 |
335 \noindent |
339 \noindent |
336 This definition needs to account for all threads that wait for a thread to |
340 This definition needs to account for all threads that wait for a thread to |
337 release a resource. This means we need to include threads that transitively |
341 release a resource. This means we need to include threads that transitively |
338 wait for a resource being released (in the picture above this means also @{text "th\<^isub>3"}, |
342 wait for a resource being released (in the picture above this means the dependants |
339 which cannot make any progress unless @{text "th\<^isub>2"} makes progress which |
343 of @{text "th\<^isub>0"} are @{text "th\<^isub>1"} and @{text "th\<^isub>2"}, but also @{text "th\<^isub>3"}, |
340 in turn needs to wait for @{text "th\<^isub>1"}). If there is a circle in a RAG, then clearly |
344 which cannot make any progress unless @{text "th\<^isub>2"} makes progress, which |
|
345 in turn needs to wait for @{text "th\<^isub>1"} to finish). If there is a circle in a RAG, then clearly |
341 we have a deadlock. Therefore when a thread requests a resource, |
346 we have a deadlock. Therefore when a thread requests a resource, |
342 we must ensure that the resulting RAG is not not circular. |
347 we must ensure that the resulting RAG is not circular. |
343 |
348 |
344 Next we introduce the notion of the \emph{current precedence} for a thread @{text th} in a |
349 Next we introduce the notion of the \emph{current precedence} of a thread @{text th} in a |
345 state @{text s}, which is defined as |
350 state @{text s}. It is defined as |
346 |
351 |
347 \begin{isabelle}\ \ \ \ \ %%% |
352 \begin{isabelle}\ \ \ \ \ %%% |
348 @{thm cpreced_def2} |
353 @{thm cpreced_def2}\numbered{permprops} |
349 \end{isabelle} |
354 \end{isabelle} |
350 |
355 |
351 \noindent |
356 \noindent |
352 While the precedence @{term prec} of a thread is determined by the programmer |
357 While the precedence @{term prec} of a thread is determined by the programmer |
353 (for example when the thread is |
358 (for example when the thread is |
357 processes that are dependants of @{text th}. Since the notion @{term "dependants"} is |
362 processes that are dependants of @{text th}. Since the notion @{term "dependants"} is |
358 defined as the transitive closure of all dependent threads, we deal correctly with the |
363 defined as the transitive closure of all dependent threads, we deal correctly with the |
359 problem in the algorithm by Sha et al.~\cite{Sha90} where a priority of a thread is |
364 problem in the algorithm by Sha et al.~\cite{Sha90} where a priority of a thread is |
360 lowered prematurely. |
365 lowered prematurely. |
361 |
366 |
362 The next function, called @{term schs}, defines the behaviour of the scheduler. It is defined |
367 The next function, called @{term schs}, defines the behaviour of the scheduler. It will be defined |
363 by recursion on the state (a list of events); @{term "schs"} takes a state as argument |
368 by recursion on the state (a list of events); @{term "schs"} returns a \emph{schedule state}, which |
364 and returns a \emph{schedule state}, which we define as a record consisting of two |
369 we represent as a record consisting of two |
365 functions: |
370 functions: |
366 |
371 |
367 \begin{isabelle}\ \ \ \ \ %%% |
372 \begin{isabelle}\ \ \ \ \ %%% |
368 @{text "\<lparr>wq_fun, cprec_fun\<rparr>"} |
373 @{text "\<lparr>wq_fun, cprec_fun\<rparr>"} |
369 \end{isabelle} |
374 \end{isabelle} |
370 |
375 |
371 \noindent |
376 \noindent |
372 The first is a waiting queue function (that is takes a @{text "cs"} and returns the |
377 The first function is a waiting queue function (that is takes a @{text "cs"} and returns the |
373 corresponding list of threads that wait for it), the second is a function that takes |
378 corresponding list of threads that wait for it), the second is a function that takes |
374 a thread and returns its current precedence (see ???). We have the usual getter and |
379 a thread and returns its current precedence (see ???). We assume the usual getter and |
375 setter methods for such records. |
380 setter methods for such records. |
376 |
381 |
377 In the initial state, the scheduler starts with all resources unlocked and the |
382 In the initial state, the scheduler starts with all resources unlocked and the |
378 precedence of every thread is initialised with @{term "Prc 0 0"}. Therefore |
383 current precedence of every thread is initialised with @{term "Prc 0 0"}; that means |
|
384 @{abbrev initial_cprec}. Therefore |
379 we have |
385 we have |
380 |
386 |
381 \begin{isabelle}\ \ \ \ \ %%% |
387 \begin{isabelle}\ \ \ \ \ %%% |
382 \begin{tabular}{@ {}l} |
388 \begin{tabular}{@ {}l} |
383 @{thm (lhs) schs.simps(1)} @{text "\<equiv>"}\\ |
389 @{thm (lhs) schs.simps(1)} @{text "\<equiv>"}\\ |
386 \end{isabelle} |
392 \end{isabelle} |
387 |
393 |
388 \noindent |
394 \noindent |
389 The cases for @{term Create}, @{term Exit} and @{term Set} are also straightforward: |
395 The cases for @{term Create}, @{term Exit} and @{term Set} are also straightforward: |
390 we calculate the waiting queue function of the (previous) state @{text s}; |
396 we calculate the waiting queue function of the (previous) state @{text s}; |
391 this waiting queue function @{text wq} is unchanged in the next schedule state; |
397 this waiting queue function @{text wq} is unchanged in the next schedule state---because |
|
398 none of these events lock or release any resources; |
392 for calculating the next @{term "cprec_fun"}, we use @{text wq} and the function |
399 for calculating the next @{term "cprec_fun"}, we use @{text wq} and the function |
393 @{term cpreced}. This gives the following three clauses: |
400 @{term cpreced}. This gives the following three clauses for @{term schs}: |
394 |
401 |
395 \begin{isabelle}\ \ \ \ \ %%% |
402 \begin{isabelle}\ \ \ \ \ %%% |
396 \begin{tabular}{@ {}l} |
403 \begin{tabular}{@ {}l} |
397 @{thm (lhs) schs.simps(2)} @{text "\<equiv>"}\\ |
404 @{thm (lhs) schs.simps(2)} @{text "\<equiv>"}\\ |
398 \hspace{5mm}@{text "let"} @{text "wq = wq_fun (schs s)"} @{text "in"}\\ |
405 \hspace{5mm}@{text "let"} @{text "wq = wq_fun (schs s)"} @{text "in"}\\ |
399 \hspace{8mm}@{term "(|wq_fun = wq\<iota>, cprec_fun = cpreced wq\<iota> (Create th prio # s)|)"}\\ |
406 \hspace{8mm}@{term "(|wq_fun = wq\<iota>, cprec_fun = cpreced wq\<iota> (Create th prio # s)|)"}\smallskip\\ |
400 @{thm (lhs) schs.simps(3)} @{text "\<equiv>"}\\ |
407 @{thm (lhs) schs.simps(3)} @{text "\<equiv>"}\\ |
401 \hspace{5mm}@{text "let"} @{text "wq = wq_fun (schs s)"} @{text "in"}\\ |
408 \hspace{5mm}@{text "let"} @{text "wq = wq_fun (schs s)"} @{text "in"}\\ |
402 \hspace{8mm}@{term "(|wq_fun = wq\<iota>, cprec_fun = cpreced wq\<iota> (Exit th # s)|)"}\smallskip\\ |
409 \hspace{8mm}@{term "(|wq_fun = wq\<iota>, cprec_fun = cpreced wq\<iota> (Exit th # s)|)"}\smallskip\\ |
403 @{thm (lhs) schs.simps(4)} @{text "\<equiv>"}\\ |
410 @{thm (lhs) schs.simps(4)} @{text "\<equiv>"}\\ |
404 \hspace{5mm}@{text "let"} @{text "wq = wq_fun (schs s)"} @{text "in"}\\ |
411 \hspace{5mm}@{text "let"} @{text "wq = wq_fun (schs s)"} @{text "in"}\\ |
421 \hspace{8mm}@{term "(|wq_fun = new_wq, cprec_fun = cpreced new_wq (P th cs # s)|)"} |
428 \hspace{8mm}@{term "(|wq_fun = new_wq, cprec_fun = cpreced new_wq (P th cs # s)|)"} |
422 \end{tabular} |
429 \end{tabular} |
423 \end{isabelle} |
430 \end{isabelle} |
424 |
431 |
425 \noindent |
432 \noindent |
426 The case for @{term V} is similar, except that we need to update the waiting queue function |
433 The clause for event @{term V} is similar, except that we need to update the waiting queue function |
427 so that the thread that possessed the lock is eliminated. For this we use |
434 so that the thread that possessed the lock is deleted from the corresponding thread list. For this we use |
428 the auxiliary function @{term release}. A simple version of @{term release} would |
435 the auxiliary function @{term release}. A simple version of @{term release} would |
429 just delete this thread and return the rest like so |
436 just delete this thread and return the rest, namely |
430 |
437 |
431 \begin{isabelle}\ \ \ \ \ %%% |
438 \begin{isabelle}\ \ \ \ \ %%% |
432 \begin{tabular}{@ {}lcl} |
439 \begin{tabular}{@ {}lcl} |
433 @{term "release []"} & @{text "\<equiv>"} & @{term "[]"}\\ |
440 @{term "release []"} & @{text "\<equiv>"} & @{term "[]"}\\ |
434 @{term "release (DUMMY # qs)"} & @{text "\<equiv>"} & @{term "qs"}\\ |
441 @{term "release (DUMMY # qs)"} & @{text "\<equiv>"} & @{term "qs"}\\ |
435 \end{tabular} |
442 \end{tabular} |
436 \end{isabelle} |
443 \end{isabelle} |
437 |
444 |
438 \noindent |
445 \noindent |
439 However in practice often the thread with the highest precedence will get the |
446 In practice, however, often the thread with the highest precedence will get the |
440 lock next. We have implemented this choice, but later found out that the choice |
447 lock next. We have implemented this choice, but later found out that the choice |
441 about which thread is chosen next is actually irrelevant for the correctness of PIP. |
448 about which thread is chosen next is actually irrelevant for the correctness of PIP. |
442 Therefore we prove the stronger result where @{term release} is defined as |
449 Therefore we prove the stronger result where @{term release} is defined as |
443 |
450 |
444 \begin{isabelle}\ \ \ \ \ %%% |
451 \begin{isabelle}\ \ \ \ \ %%% |
448 \end{tabular} |
455 \end{tabular} |
449 \end{isabelle} |
456 \end{isabelle} |
450 |
457 |
451 \noindent |
458 \noindent |
452 @{text "SOME"} stands for Hilbert's epsilon and implements an arbitrary |
459 @{text "SOME"} stands for Hilbert's epsilon and implements an arbitrary |
453 choice for the next waiting list, it just has to be a distinct list and |
460 choice for the next waiting list. It just has to be a list of distinctive threads and |
454 contain the same elements as @{text "qs"}. This gives for @{term V} and @{term schs} the clause: |
461 contain the same elements as @{text "qs"}. This gives for @{term V} the clause: |
455 |
462 |
456 \begin{isabelle}\ \ \ \ \ %%% |
463 \begin{isabelle}\ \ \ \ \ %%% |
457 \begin{tabular}{@ {}l} |
464 \begin{tabular}{@ {}l} |
458 @{thm (lhs) schs.simps(6)} @{text "\<equiv>"}\\ |
465 @{thm (lhs) schs.simps(6)} @{text "\<equiv>"}\\ |
459 \hspace{5mm}@{text "let"} @{text "wq = wq_fun (schs s)"} @{text "in"}\\ |
466 \hspace{5mm}@{text "let"} @{text "wq = wq_fun (schs s)"} @{text "in"}\\ |
460 \hspace{5mm}@{text "let"} @{text "new_wq = release (wq cs)"} @{text "in"}\\ |
467 \hspace{5mm}@{text "let"} @{text "new_wq = release (wq cs)"} @{text "in"}\\ |
461 \hspace{8mm}@{term "(|wq_fun = new_wq, cprec_fun = cpreced new_wq (V th cs # s)|)"} |
468 \hspace{8mm}@{term "(|wq_fun = new_wq, cprec_fun = cpreced new_wq (V th cs # s)|)"} |
462 \end{tabular} |
469 \end{tabular} |
463 \end{isabelle} |
470 \end{isabelle} |
464 |
471 |
465 |
472 Having the scheduler function @{term schs} at our disposal, we can ``lift'' the notions |
466 TODO |
473 @{term waiting}, @{term holding} @{term depend} and @{term cp} such that they only depend |
467 |
474 on states. |
468 \begin{isabelle}\ \ \ \ \ %%% |
475 |
469 \begin{tabular}{@ {}l} |
476 \begin{isabelle}\ \ \ \ \ %%% |
470 @{thm s_depend_def}\\ |
477 \begin{tabular}{@ {}rcl} |
|
478 @{thm (lhs) s_holding_abv} & @{text "\<equiv>"} & @{thm (rhs) s_holding_abv}\\ |
|
479 @{thm (lhs) s_waiting_abv} & @{text "\<equiv>"} & @{thm (rhs) s_waiting_abv}\\ |
|
480 @{thm (lhs) s_depend_abv} & @{text "\<equiv>"} & @{thm (rhs) s_depend_abv}\\ |
|
481 @{thm (lhs) cp_def} & @{text "\<equiv>"} & @{thm (rhs) cp_def} |
471 \end{tabular} |
482 \end{tabular} |
472 \end{isabelle} |
483 \end{isabelle} |
|
484 |
|
485 \noindent |
|
486 With them we can introduce the notion of threads being @{term readys} (i.e.~threads |
|
487 that do not wait for any resource) and the running thread. |
473 |
488 |
474 \begin{isabelle}\ \ \ \ \ %%% |
489 \begin{isabelle}\ \ \ \ \ %%% |
475 \begin{tabular}{@ {}l} |
490 \begin{tabular}{@ {}l} |
476 @{thm readys_def}\\ |
491 @{thm readys_def}\\ |
477 \end{tabular} |
|
478 \end{isabelle} |
|
479 |
|
480 \begin{isabelle}\ \ \ \ \ %%% |
|
481 \begin{tabular}{@ {}l} |
|
482 @{thm runing_def}\\ |
492 @{thm runing_def}\\ |
483 \end{tabular} |
493 \end{tabular} |
484 \end{isabelle} |
494 \end{isabelle} |
485 |
495 |
486 |
496 \noindent |
487 resources |
497 Note that in the initial case, that is where the list of events is empty, the set |
488 |
498 @{term threads} is empty and therefore there is no thread ready nor a running. |
489 done: threads not done: running |
499 If there is one or more threads ready, then there can only be \emph{one} thread |
490 |
500 running, namely the one whose current precedence is equal to the maximum of all ready |
491 step relation: |
501 threads. We can also define the set of resources that are locked by a thread in a |
|
502 given state. |
|
503 |
|
504 \begin{isabelle}\ \ \ \ \ %%% |
|
505 @{thm holdents_def} |
|
506 \end{isabelle} |
|
507 |
|
508 \noindent |
|
509 These resources are given by the holding edges in the RAG. |
|
510 |
|
511 Finally we can define what a \emph{valid state} is. For example we cannot exptect to |
|
512 be able to exit a thread, if it was not created yet. These validity constraints |
|
513 are characterised by the inductive predicate @{term "step"} by the following five |
|
514 inference rules relating a state and an event that can happen next. |
492 |
515 |
493 \begin{center} |
516 \begin{center} |
494 \begin{tabular}{c} |
517 \begin{tabular}{c} |
495 @{thm[mode=Rule] thread_create[where thread=th]}\hspace{1cm} |
518 @{thm[mode=Rule] thread_create[where thread=th]}\hspace{1cm} |
496 @{thm[mode=Rule] thread_exit[where thread=th]}\medskip\\ |
519 @{thm[mode=Rule] thread_exit[where thread=th]} |
497 |
520 \end{tabular} |
498 @{thm[mode=Rule] thread_set[where thread=th]}\medskip\\ |
521 \end{center} |
|
522 |
|
523 \noindent |
|
524 The first rule states that a thread can only be created, if it does not yet exists. |
|
525 Similarly, the second rule states that a thread can only be terminated if it was |
|
526 running and does not lock any resources anymore. The event @{text Set} can happen |
|
527 if the corresponding thread is running. |
|
528 |
|
529 \begin{center} |
|
530 @{thm[mode=Rule] thread_set[where thread=th]} |
|
531 \end{center} |
|
532 |
|
533 \noindent |
|
534 If a thread wants to lock a resource, then the thread needs to be running and |
|
535 also we have to make sure that the resource lock doe not lead to a cycle in the |
|
536 RAG. Similarly, if a thread wants to release a lock on a resource, then it must |
|
537 be running and in the possession of that lock. This is formally given by the |
|
538 last two inference rules of @{term step}. |
|
539 |
|
540 \begin{center} |
|
541 \begin{tabular}{c} |
499 @{thm[mode=Rule] thread_P[where thread=th]}\medskip\\ |
542 @{thm[mode=Rule] thread_P[where thread=th]}\medskip\\ |
500 @{thm[mode=Rule] thread_V[where thread=th]}\\ |
543 @{thm[mode=Rule] thread_V[where thread=th]}\\ |
501 \end{tabular} |
544 \end{tabular} |
502 \end{center} |
545 \end{center} |
503 |
546 |
504 valid state: |
547 \noindent |
|
548 A valid state of PIP can then be conveniently be defined as follows: |
505 |
549 |
506 \begin{center} |
550 \begin{center} |
507 \begin{tabular}{c} |
551 \begin{tabular}{c} |
508 @{thm[mode=Axiom] vt_nil[where cs=step]}\hspace{1cm} |
552 @{thm[mode=Axiom] vt_nil}\hspace{1cm} |
509 @{thm[mode=Rule] vt_cons[where cs=step]} |
553 @{thm[mode=Rule] vt_cons} |
510 \end{tabular} |
554 \end{tabular} |
511 \end{center} |
555 \end{center} |
512 |
556 |
513 |
557 \noindent |
514 To define events, the identifiers of {\em threads}, |
558 This completes our formal model of PIP. In the next section we present |
515 {\em priority} and {\em critical resources } (abbreviated as @{text "cs"}) |
559 properties that show our version of PIP is correct. |
516 need to be represented. All three are represetned using standard |
|
517 Isabelle/HOL type @{typ "nat"}: |
|
518 *} |
560 *} |
|
561 |
|
562 section {* Correctness Proof *} |
|
563 |
|
564 text {* TO DO *} |
|
565 |
|
566 section {* Properties for an Implementation *} |
|
567 |
|
568 text {* TO DO *} |
|
569 |
|
570 section {* Conclusion *} |
|
571 |
|
572 text {* TO DO *} |
519 |
573 |
520 text {* |
574 text {* |
521 \bigskip |
575 \bigskip |
522 The priority inversion phenomenon was first published in |
576 The priority inversion phenomenon was first published in |
523 \cite{Lampson80}. The two protocols widely used to eliminate |
577 \cite{Lampson80}. The two protocols widely used to eliminate |