prio/Paper/Paper.thy
changeset 325 163cd8034e5b
parent 324 41e4b331ce08
child 326 8f256104e4f3
equal deleted inserted replaced
324:41e4b331ce08 325:163cd8034e5b
    25   dependents ("dependants") and
    25   dependents ("dependants") and
    26   cp ("cprec") and
    26   cp ("cprec") and
    27   holdents ("resources") and
    27   holdents ("resources") and
    28   original_priority ("priority") and
    28   original_priority ("priority") and
    29   DUMMY  ("\<^raw:\mbox{$\_\!\_$}>")
    29   DUMMY  ("\<^raw:\mbox{$\_\!\_$}>")
       
    30 
       
    31 abbreviation
       
    32  "detached s th \<equiv> cntP s th = cntV s th"
    30 (*>*)
    33 (*>*)
    31 
    34 
    32 section {* Introduction *}
    35 section {* Introduction *}
    33 
    36 
    34 text {*
    37 text {*
   590 section {* The Correctness Proof *}
   593 section {* The Correctness Proof *}
   591 
   594 
   592 (*<*)
   595 (*<*)
   593 context extend_highest_gen
   596 context extend_highest_gen
   594 begin
   597 begin
   595 print_locale extend_highest_gen
       
   596 thm extend_highest_gen_def
       
   597 thm extend_highest_gen_axioms_def
       
   598 thm highest_gen_def
       
   599 (*>*)
   598 (*>*)
   600 text {* 
   599 text {* 
   601   Sha et al.~\cite[Theorem 6]{Sha90} state their correctness criterion
   600   Sha et al.~\cite[Theorem 6]{Sha90} state their correctness criterion
   602   for PIP in terms of the number of critical resources: if there are
   601   for PIP in terms of the number of critical resources: if there are
   603   @{text m} critical resources, then a blocked job with high priority
   602   @{text m} critical resources, then a blocked job with high priority
   697   finite bound does not guarantee absence of indefinite Priority
   696   finite bound does not guarantee absence of indefinite Priority
   698   Inversion. For this we further have to assume that every thread
   697   Inversion. For this we further have to assume that every thread
   699   gives up its resources after a finite amount of time. We found that
   698   gives up its resources after a finite amount of time. We found that
   700   this assumption is awkward to formalise in our model. Therefore we
   699   this assumption is awkward to formalise in our model. Therefore we
   701   leave it out and let the programmer assume the responsibility to
   700   leave it out and let the programmer assume the responsibility to
   702   program threads in such a benign manner. In this detail, we do not
   701   program threads in such a benign manner (in addition to causeing no 
       
   702   circularity in the @{text RAG}). In this detail, we do not
   703   make any progress in comparison with the work by Sha et al.
   703   make any progress in comparison with the work by Sha et al.
   704 
   704 
   705   In what follows we will describe properties of PIP that allow us to prove 
   705   In what follows we will describe properties of PIP that allow us to prove 
   706   Theorem~\ref{mainthm}. It is relatively easily to see that
   706   Theorem~\ref{mainthm} and, when instructive, briefly describe our argument. 
       
   707   It is relatively easily to see that
   707 
   708 
   708   \begin{isabelle}\ \ \ \ \ %%%
   709   \begin{isabelle}\ \ \ \ \ %%%
   709   \begin{tabular}{@ {}l}
   710   \begin{tabular}{@ {}l}
   710   @{text "running s \<subseteq> ready s \<subseteq> threads s"}\\
   711   @{text "running s \<subseteq> ready s \<subseteq> threads s"}\\
   711   @{thm[mode=IfThen]  finite_threads}
   712   @{thm[mode=IfThen]  finite_threads}
   712   \end{tabular}
   713   \end{tabular}
   713   \end{isabelle}
   714   \end{isabelle}
   714 
   715 
   715   \noindent
   716   \noindent
   716   where the second property is by induction of @{term vt}. The next three
   717   whereby the second property is by induction of @{term vt}. The next three
   717   properties are 
   718   properties are 
   718 
   719 
   719   \begin{isabelle}\ \ \ \ \ %%%
   720   \begin{isabelle}\ \ \ \ \ %%%
   720   \begin{tabular}{@ {}l}
   721   \begin{tabular}{@ {}l}
   721   @{thm[mode=IfThen] waiting_unique[of _ _ "cs\<^isub>1" "cs\<^isub>2"]}\\
   722   @{thm[mode=IfThen] waiting_unique[of _ _ "cs\<^isub>1" "cs\<^isub>2"]}\\
   723   @{thm[mode=IfThen] runing_unique[of _ "th\<^isub>1" "th\<^isub>2"]}
   724   @{thm[mode=IfThen] runing_unique[of _ "th\<^isub>1" "th\<^isub>2"]}
   724   \end{tabular}
   725   \end{tabular}
   725   \end{isabelle}
   726   \end{isabelle}
   726 
   727 
   727   \noindent
   728   \noindent
   728   The first one states that every waiting thread can only wait for a single
   729   The first property states that every waiting thread can only wait for a single
   729   resource (because it gets suspended after requesting that resource and having
   730   resource (because it gets suspended after requesting that resource); the second 
   730   to wait for it); the second that every resource can only be held by a single thread; 
   731   that every resource can only be held by a single thread; 
   731   the third property establishes that in every given valid state, there is
   732   the third property establishes that in every given valid state, there is
   732   at most one running thread. We can also show the following properties 
   733   at most one running thread. We can also show the following properties 
   733   about the RAG in @{text "s"}.
   734   about the @{term RAG} in @{text "s"}.
   734 
   735 
   735   \begin{isabelle}\ \ \ \ \ %%%
   736   \begin{isabelle}\ \ \ \ \ %%%
   736   \begin{tabular}{@ {}l}
   737   \begin{tabular}{@ {}l}
   737   @{text If}~@{thm (prem 1) acyclic_depend}~@{text "then"}:\\
   738   @{text If}~@{thm (prem 1) acyclic_depend}~@{text "then"}:\\
   738   \hspace{5mm}@{thm (concl) acyclic_depend},
   739   \hspace{5mm}@{thm (concl) acyclic_depend},
   739   @{thm (concl) finite_depend} and
   740   @{thm (concl) finite_depend} and
   740   @{thm (concl) wf_dep_converse},\\
   741   @{thm (concl) wf_dep_converse},\\
   741   \hspace{5mm}@{text "if"}~@{thm (prem 2) dm_depend_threads}~@{text "then"}~@{thm (concl) dm_depend_threads}\\
   742   \hspace{5mm}@{text "if"}~@{thm (prem 2) dm_depend_threads}~@{text "then"}~@{thm (concl) dm_depend_threads}
   742   \hspace{5mm}@{text "if"}~@{thm (prem 2) range_in}~@{text "then"}~@{thm (concl) range_in}
   743   and\\
   743   \end{tabular}
   744   \hspace{5mm}@{text "if"}~@{thm (prem 2) range_in}~@{text "then"}~@{thm (concl) range_in}.
   744   \end{isabelle}
   745   \end{tabular}
   745 
   746   \end{isabelle}
   746   TODO
   747 
   747 
   748   \noindent
   748   \noindent
   749   The acyclicity property follow from how we restricted the events in
   749   The following lemmas show how RAG is changed with the execution of events:
   750   @{text step}; similarly the finiteness and well-foundedness property.
   750   \begin{enumerate}
   751   The last two properties establish that every thread in a @{text "RAG"}
   751   \item Execution of @{term "Set"} does not change RAG (@{text "depend_set_unchanged"}):
   752   (either holding or waiting for a resource) is a live thread.
   752     @{thm[display] depend_set_unchanged}
   753 
   753   \item Execution of @{term "Create"} does not change RAG (@{text "depend_create_unchanged"}):
   754   To state the key lemma in our proof, it will be convenient to introduce the notion
   754     @{thm[display] depend_create_unchanged}
   755   of a \emph{detached} thread in a state, that is one which does not hold any
   755   \item Execution of @{term "Exit"} does not change RAG (@{text "depend_exit_unchanged"}):
   756   critical resource nor requests one. 
   756     @{thm[display] depend_exit_unchanged}
   757 
   757   \item Execution of @{term "P"} (@{text "step_depend_p"}):
   758   \begin{lemma}\label{mainlem}
   758     @{thm[display] step_depend_p}
   759   Given the assumptions about states @{text "s"} and @{text "s' @ s"},
   759   \item Execution of @{term "V"} (@{text "step_depend_v"}):
   760   the thread @{text th} and the events in @{text "s'"},
   760     @{thm[display] step_depend_v}
   761   if @{term "th' \<in> treads (s' @ s)"}, @{text "th' \<noteq> th"} and @{text "detached (s' @ s) th'"}\\
   761   \end{enumerate}
   762   then @{text "th' \<notin> running (s' @ s)"}.
   762   *}
   763   \end{lemma}
   763 
   764 
   764 text {* \noindent
   765   \noindent
   765   These properties are used to derive the following important results about RAG:
   766   The point of this lemma is that a thread different from @{text th} (which has the highest
   766   \begin{enumerate}
   767   precedence in @{text s}) not holding any resource cannot be running 
   767   \item RAG is loop free (@{text "acyclic_depend"}):
   768   in the state @{text "s' @ s"}.
   768   @{thm [display] acyclic_depend}
   769 
   769   \item RAGs are finite (@{text "finite_depend"}):
   770   \begin{proof}
   770   @{thm [display] finite_depend}
   771   Since thread @{text "th'"} does not hold any resource, no thread can depend on it. 
   771   \item Reverse paths in RAG are well founded (@{text "wf_dep_converse"}):
   772   Therefore its current precedence @{term "cp (s' @ s) th'"} equals its own precedence
   772   @{thm [display] wf_dep_converse}
   773   @{term "prec th' (s' @ s)"}. Since @{text "th"} has the highest precedence in the 
   773   \item The dependence relation represented by RAG has a tree structure (@{text "unique_depend"}):
   774   state @{text "(s' @ s)"} and precedences are distinct among threads, we have
   774   @{thm [display] unique_depend[of _ _ "n\<^isub>1" "n\<^isub>2"]}
   775   @{term "prec th' (s' @s ) < prec th (s' @ s)"}. From this 
   775   \item All threads in RAG are living threads 
   776   we have @{term "cp (s' @ s) th' < prec th (s' @ s)"}.
   776     (@{text "dm_depend_threads"} and @{text "range_in"}):
   777   Since @{text "prec th (s' @ s)"} is already the highest 
   777     @{thm [display] dm_depend_threads range_in}
   778   @{term "cp (s' @ s) th"} can not be higher than this and can not be lower either (by 
   778   \end{enumerate}
   779   definition of @{term "cp"}). Consequently, we have @{term "prec th (s' @ s) = cp (s' @ s) th"}.
   779   *}
   780   Finally we have @{term "cp (s' @ s) th' < cp (s' @ s) th"}.
   780 
   781   By defintion of @{text "running"}, @{text "th'"} can not be running in state
   781 text {* \noindent
   782   @{text "s' @ s"}, as we had to show.\qed
       
   783   \end{proof}
       
   784 
       
   785   \noindent
       
   786   Since @{text "th'"} is not able to run at state @{text "s' @ s"}, it is not able to 
       
   787   issue a {text "P"} or @{text "V"} event. Therefore if @{text "s' @ s"} is extended
       
   788   one step further, @{text "th'"} still cannot hold any resource. The situation will 
       
   789   not change in further extensions as long as @{text "th"} holds the highest precedence.
       
   790 
       
   791 
   782   The following lemmas show how every node in RAG can be chased to ready threads:
   792   The following lemmas show how every node in RAG can be chased to ready threads:
   783   \begin{enumerate}
   793   \begin{enumerate}
   784   \item Every node in RAG can be chased to a ready thread (@{text "chain_building"}):
   794   \item Every node in RAG can be chased to a ready thread (@{text "chain_building"}):
   785     @{thm [display] chain_building[rule_format]}
   795     @{thm [display] chain_building[rule_format]}
   786   \item The ready thread chased to is unique (@{text "dchain_unique"}):
   796   \item The ready thread chased to is unique (@{text "dchain_unique"}):
   787     @{thm [display] dchain_unique[of _ _ "th\<^isub>1" "th\<^isub>2"]}
   797     @{thm [display] dchain_unique[of _ _ "th\<^isub>1" "th\<^isub>2"]}
   788   \end{enumerate}
   798   \end{enumerate}
   789   *}
   799   *}
   790 
   800 
   791 text {* \noindent
       
   792   Properties about @{term "next_th"}:
       
   793   \begin{enumerate}
       
   794   \item The thread taking over is different from the thread which is releasing
       
   795   (@{text "next_th_neq"}):
       
   796   @{thm [display] next_th_neq}
       
   797   \item The thread taking over is unique
       
   798   (@{text "next_th_unique"}):
       
   799   @{thm [display] next_th_unique[of _ _ _ "th\<^isub>1" "th\<^isub>2"]}  
       
   800   \end{enumerate}
       
   801   *}
       
   802 
   801 
   803 text {* \noindent
   802 text {* \noindent
   804   Some deeper results about the system:
   803   Some deeper results about the system:
   805   \begin{enumerate}
   804   \begin{enumerate}
   806   \item The maximum of @{term "cp"} and @{term "preced"} are equal (@{text "max_cp_eq"}):
   805   \item The maximum of @{term "cp"} and @{term "preced"} are equal (@{text "max_cp_eq"}):
   831   \item When the number of @{text "P"} equals the number of @{text "V"}, the relevant 
   830   \item When the number of @{text "P"} equals the number of @{text "V"}, the relevant 
   832     thread does not hold any critical resource, therefore no thread can depend on it
   831     thread does not hold any critical resource, therefore no thread can depend on it
   833     (@{text "count_eq_dependents"}):
   832     (@{text "count_eq_dependents"}):
   834     @{thm [display] count_eq_dependents}
   833     @{thm [display] count_eq_dependents}
   835   \end{enumerate}
   834   \end{enumerate}
       
   835 
       
   836 
       
   837   @{thm[display] live}
   836 *}
   838 *}
   837 
   839 
   838 (*<*)
       
   839 end
       
   840 (*>*)
       
   841 
       
   842 subsection {* Proof idea *}
   840 subsection {* Proof idea *}
   843 
       
   844 (*<*)
       
   845 context extend_highest_gen
       
   846 begin
       
   847 print_locale extend_highest_gen
       
   848 thm extend_highest_gen_def
       
   849 thm extend_highest_gen_axioms_def
       
   850 thm highest_gen_def
       
   851 (*>*)
       
   852 
   841 
   853 text {*
   842 text {*
   854 The reason that only threads which already held some resoures
   843 The reason that only threads which already held some resoures
   855 can be runing and block @{text "th"} is that if , otherwise, one thread 
   844 can be runing and block @{text "th"} is that if , otherwise, one thread 
   856 does not hold any resource, it may never have its prioirty raised
   845 does not hold any resource, it may never have its prioirty raised
   867   if a thread releases all its resources at some moment in @{text "t"}, after that, 
   856   if a thread releases all its resources at some moment in @{text "t"}, after that, 
   868   it may never get a change to run. If every thread releases its resource in finite duration,
   857   it may never get a change to run. If every thread releases its resource in finite duration,
   869   then after a while, only thread @{text "th"} is left running. This shows how indefinite 
   858   then after a while, only thread @{text "th"} is left running. This shows how indefinite 
   870   priority inversion can be avoided. 
   859   priority inversion can be avoided. 
   871 
   860 
   872   So, the key of the proof is to establish the correctness of @{text "moment_blocked"}.
       
   873   We are going to show how this lemma is proved. At the heart of this proof, is 
       
   874   lemma @{text "pv_blocked"}:
       
   875   @{thm [display] pv_blocked}
       
   876   This lemma says: for any @{text "s"}-extension {text "t"}, if thread @{text "th'"}
       
   877   does not hold any resource, it can not be running at @{text "t@s"}.
       
   878 
       
   879 
       
   880   \noindent Proof: 
       
   881   \begin{enumerate}
       
   882   \item Since thread @{text "th'"} does not hold any resource, no thread may depend on it, 
       
   883     so its current precedence @{text "cp (t@s) th'"} equals to its own precedence
       
   884    @{text "preced th' (t@s)"}.  \label{arg_1}
       
   885   \item Since @{text "th"} has the highest precedence in the system and 
       
   886     precedences are distinct among threads, we have
       
   887     @{text "preced th' (t@s) < preced th (t@s)"}. From this and item \ref{arg_1}, 
       
   888     we have @{text "cp (t@s) th' < preced th (t@s)"}.
       
   889   \item Since @{text "preced th (t@s)"} is already the highest in the system, 
       
   890     @{text "cp (t@s) th"} can not be higher than this and can not be lower neither (by 
       
   891     the definition of @{text "cp"}), we have @{text "preced th (t@s) = cp (t@s) th"}.
       
   892   \item Finally we have @{text "cp (t@s) th' < cp (t@s) th"}.
       
   893   \item By defintion of @{text "running"}, @{text "th'"} can not be runing at 
       
   894     @{text "t@s"}.
       
   895   \end{enumerate}
       
   896   Since @{text "th'"} is not able to run at state @{text "t@s"}, it is not able to 
       
   897   make either {text "P"} or @{text "V"} action, so if @{text "t@s"} is extended
       
   898   one step further, @{text "th'"} still does not hold any resource. 
       
   899   The situation will not unchanged in further extensions as long as 
       
   900   @{text "th"} holds the highest precedence. Since this @{text "t"} is arbitarily chosen 
       
   901   except being constrained by predicate @{text "extend_highest_gen"} and 
       
   902   this predicate has the property that if it holds for @{text "t"}, it also holds
       
   903   for any moment @{text "i"} inside @{text "t"}, as shown by lemma @{text "red_moment"}:
       
   904 @{thm [display] "extend_highest_gen.red_moment"}
       
   905   so @{text "pv_blocked"} can be applied to any @{text "moment i t"}. 
       
   906   From this, lemma @{text "moment_blocked"} follows.
       
   907 *}
   861 *}
   908 
   862 
   909 (*<*)
       
   910 end
       
   911 (*>*)
       
   912 
       
   913 
       
   914 section {* Properties for an Implementation\label{implement} *}
       
   915 
       
   916 text {*
       
   917   While a formal correctness proof for our model of PIP is certainly
       
   918   attractive (especially in light of the flawed proof by Sha et
       
   919   al.~\cite{Sha90}), we found that the formalisation can even help us
       
   920   with efficiently implementing PIP.
       
   921 
       
   922   For example Baker complained that calculating the current precedence
       
   923   in PIP is quite ``heavy weight'' in Linux (see the Introduction).
       
   924   In our model of PIP the current precedence of a thread in a state s
       
   925   depends on all its dependants---a ``global'' transitive notion,
       
   926   which is indeed heavy weight (see Def.~shown in \eqref{cpreced}).
       
   927   We can however improve upon this. For this let us define the notion
       
   928   of @{term children} of a thread @{text th} in a state @{text s} as
       
   929 
       
   930   \begin{isabelle}\ \ \ \ \ %%%
       
   931   \begin{tabular}{@ {}l}
       
   932   @{thm children_def2}
       
   933   \end{tabular}
       
   934   \end{isabelle}
       
   935 
       
   936   \noindent
       
   937   where a child is a thread that is one ``hop'' away from the tread
       
   938   @{text th} in the @{term RAG} (and waiting for @{text th} to release
       
   939   a resource). We can prove that
       
   940 
       
   941   \begin{lemma}\label{childrenlem}
       
   942   @{text "If"} @{thm (prem 1) cp_rec} @{text "then"}
       
   943   \begin{center}
       
   944   @{thm (concl) cp_rec}.
       
   945   \end{center}
       
   946   \end{lemma}
       
   947   
       
   948   \noindent
       
   949   That means the current precedence of a thread @{text th} can be
       
   950   computed locally by considering only the children of @{text th}. In
       
   951   effect, it only needs to be recomputed for @{text th} when one of
       
   952   its children changes its current precedence.  Once the current 
       
   953   precedence is computed in this more efficient manner, the selection
       
   954   of the thread with highest precedence from a set of ready threads is
       
   955   a standard scheduling operation implemented in most operating
       
   956   systems.
       
   957 
       
   958   Of course the main implementation work for PIP involves the
       
   959   scheduler and coding how it should react to events.  Below we
       
   960   outline how our formalisation guides this implementation for each
       
   961   kind of event.\smallskip
       
   962 *}
       
   963 
       
   964 (*<*)
       
   965 context step_create_cps
       
   966 begin
       
   967 (*>*)
       
   968 text {*
       
   969   \noindent
       
   970   \colorbox{mygrey}{@{term "Create th prio"}:} We assume that the current state @{text s'} and 
       
   971   the next state @{term "s \<equiv> Create th prio#s'"} are both valid (meaning the event
       
   972   is allowed to occur). In this situation we can show that
       
   973 
       
   974   \begin{isabelle}\ \ \ \ \ %%%
       
   975   \begin{tabular}{@ {}l}
       
   976   @{thm eq_dep},\\
       
   977   @{thm eq_cp_th}, and\\
       
   978   @{thm[mode=IfThen] eq_cp}
       
   979   \end{tabular}
       
   980   \end{isabelle}
       
   981 
       
   982   \noindent
       
   983   This means we do not have recalculate the @{text RAG} and also none of the
       
   984   current precedences of the other threads. The current precedence of the created
       
   985   thread @{text th} is just its precedence, namely the pair @{term "(prio, length (s::event list))"}.
       
   986   \smallskip
       
   987   *}
       
   988 (*<*)
       
   989 end
       
   990 context step_exit_cps
       
   991 begin
       
   992 (*>*)
       
   993 text {*
       
   994   \noindent
       
   995   \colorbox{mygrey}{@{term "Exit th"}:} We again assume that the current state @{text s'} and 
       
   996   the next state @{term "s \<equiv> Exit th#s'"} are both valid. We can show that
       
   997 
       
   998   \begin{isabelle}\ \ \ \ \ %%%
       
   999   \begin{tabular}{@ {}l}
       
  1000   @{thm eq_dep}, and\\
       
  1001   @{thm[mode=IfThen] eq_cp}
       
  1002   \end{tabular}
       
  1003   \end{isabelle}
       
  1004 
       
  1005   \noindent
       
  1006   This means again we do not have to recalculate the @{text RAG} and
       
  1007   also not the current precedences for the other threads. Since @{term th} is not
       
  1008   alive anymore in state @{term "s"}, there is no need to calculate its
       
  1009   current precedence.
       
  1010   \smallskip
       
  1011 *}
       
  1012 (*<*)
       
  1013 end
       
  1014 context step_set_cps
       
  1015 begin
       
  1016 (*>*)
       
  1017 text {*
       
  1018   \noindent
       
  1019   \colorbox{mygrey}{@{term "Set th prio"}:} We assume that @{text s'} and 
       
  1020   @{term "s \<equiv> Set th prio#s'"} are both valid. We can show that
       
  1021 
       
  1022   \begin{isabelle}\ \ \ \ \ %%%
       
  1023   \begin{tabular}{@ {}l}
       
  1024   @{thm[mode=IfThen] eq_dep}, and\\
       
  1025   @{thm[mode=IfThen] eq_cp}
       
  1026   \end{tabular}
       
  1027   \end{isabelle}
       
  1028 
       
  1029   \noindent
       
  1030   The first property is again telling us we do not need to change the @{text RAG}. The second
       
  1031   however states that only threads that are \emph{not} dependants of @{text th} have their
       
  1032   current precedence unchanged. For the others we have to recalculate the current
       
  1033   precedence. To do this we can start from @{term "th"} 
       
  1034   and follow the @{term "depend"}-chains to recompute the @{term "cp"} of every 
       
  1035   thread encountered on the way using Lemma~\ref{childrenlem}. Since the @{term "depend"}
       
  1036   is loop free, this procedure will always stop. The following two lemmas show, however, 
       
  1037   that this procedure can actually stop often earlier without having to consider all
       
  1038   dependants.
       
  1039 
       
  1040   \begin{isabelle}\ \ \ \ \ %%%
       
  1041   \begin{tabular}{@ {}l}
       
  1042   @{thm[mode=IfThen] eq_up_self}\\
       
  1043   @{text "If"} @{thm (prem 1) eq_up}, @{thm (prem 2) eq_up} and @{thm (prem 3) eq_up}\\
       
  1044   @{text "then"} @{thm (concl) eq_up}.
       
  1045   \end{tabular}
       
  1046   \end{isabelle}
       
  1047 
       
  1048   \noindent
       
  1049   The first states that if the current precedence of @{text th} is unchanged,
       
  1050   then the procedure can stop immediately (all dependent threads have their @{term cp}-value unchanged).
       
  1051   The second states that if an intermediate @{term cp}-value does not change, then
       
  1052   the procedure can also stop, because none of its dependent threads will
       
  1053   have their current precedence changed.
       
  1054   \smallskip
       
  1055   *}
       
  1056 (*<*)
       
  1057 end
       
  1058 context step_v_cps_nt
       
  1059 begin
       
  1060 (*>*)
       
  1061 text {*
       
  1062   \noindent
       
  1063   \colorbox{mygrey}{@{term "V th cs"}:} We assume that @{text s'} and 
       
  1064   @{term "s \<equiv> V th cs#s'"} are both valid. We have to consider two
       
  1065   subcases: one where there is a thread to ``take over'' the released
       
  1066   resource @{text cs}, and one where there is not. Let us consider them
       
  1067   in turn. Suppose in state @{text s}, the thread @{text th'} takes over
       
  1068   resource @{text cs} from thread @{text th}. We can show
       
  1069 
       
  1070 
       
  1071   \begin{isabelle}\ \ \ \ \ %%%
       
  1072   @{thm depend_s}
       
  1073   \end{isabelle}
       
  1074   
       
  1075   \noindent
       
  1076   which shows how the @{text RAG} needs to be changed. This also suggests
       
  1077   how the current precedences need to be recalculated. For threads that are
       
  1078   not @{text "th"} and @{text "th'"} nothing needs to be changed, since we
       
  1079   can show
       
  1080 
       
  1081   \begin{isabelle}\ \ \ \ \ %%%
       
  1082   @{thm[mode=IfThen] cp_kept}
       
  1083   \end{isabelle}
       
  1084   
       
  1085   \noindent
       
  1086   For @{text th} and @{text th'} we need to use Lemma~\ref{childrenlem} to
       
  1087   recalculate their current prcedence since their children have changed. *}(*<*)end context step_v_cps_nnt begin (*>*)text {*
       
  1088   \noindent
       
  1089   In the other case where there is no thread that takes over @{text cs}, we can show how
       
  1090   to recalculate the @{text RAG} and also show that no current precedence needs
       
  1091   to be recalculated.
       
  1092 
       
  1093   \begin{isabelle}\ \ \ \ \ %%%
       
  1094   \begin{tabular}{@ {}l}
       
  1095   @{thm depend_s}\\
       
  1096   @{thm eq_cp}
       
  1097   \end{tabular}
       
  1098   \end{isabelle}
       
  1099   *}
       
  1100 (*<*)
       
  1101 end
       
  1102 context step_P_cps_e
       
  1103 begin
       
  1104 (*>*)
       
  1105 
       
  1106 text {*
       
  1107   \noindent
       
  1108   \colorbox{mygrey}{@{term "P th cs"}:} We assume that @{text s'} and 
       
  1109   @{term "s \<equiv> P th cs#s'"} are both valid. We again have to analyse two subcases, namely
       
  1110   the one where @{text cs} is locked, and where it is not. We treat the second case
       
  1111   first by showing that
       
  1112   
       
  1113   \begin{isabelle}\ \ \ \ \ %%%
       
  1114   \begin{tabular}{@ {}l}
       
  1115   @{thm depend_s}\\
       
  1116   @{thm eq_cp}
       
  1117   \end{tabular}
       
  1118   \end{isabelle}
       
  1119 
       
  1120   \noindent
       
  1121   This means we do not need to add a holding edge to the @{text RAG} and no
       
  1122   current precedence needs to be recalculated.*}(*<*)end context step_P_cps_ne begin(*>*) text {*
       
  1123   \noindent
       
  1124   In the second case we know that resouce @{text cs} is locked. We can show that
       
  1125   
       
  1126   \begin{isabelle}\ \ \ \ \ %%%
       
  1127   \begin{tabular}{@ {}l}
       
  1128   @{thm depend_s}\\
       
  1129   @{thm[mode=IfThen] eq_cp}
       
  1130   \end{tabular}
       
  1131   \end{isabelle}
       
  1132 
       
  1133   \noindent
       
  1134   That means we have to add a waiting edge to the @{text RAG}. Furthermore
       
  1135   the current precedence for all threads that are not dependants of @{text th}
       
  1136   are unchanged. For the others we need to follow the edges 
       
  1137   in the @{text RAG} and recompute the @{term "cp"}. However, like in the 
       
  1138   @case of {text Set}, this operation can stop often earlier, namely when intermediate
       
  1139   values do not change.
       
  1140   *}
       
  1141 (*<*)
       
  1142 end
       
  1143 (*>*)
       
  1144 text {*
       
  1145   \noindent
       
  1146   A pleasing result of our formalisation is that the properties in
       
  1147   this section closely inform an implementation of PIP:  Whether the
       
  1148   @{text RAG} needs to be reconfigured or current precedences need to
       
  1149   recalculated for an event is given by a lemma we proved.
       
  1150 *}
       
  1151 
       
  1152 section {* Conclusion *}
       
  1153 
       
  1154 text {* 
       
  1155   The Priority Inheritance Protocol (PIP) is a classic textbook
       
  1156   algorithm used in real-time operating systems in order to avoid the problem of
       
  1157   Priority Inversion.  Although classic and widely used, PIP does have
       
  1158   its faults: for example it does not prevent deadlocks in cases where threads
       
  1159   have circular lock dependencies.
       
  1160 
       
  1161   We had two goals in mind with our formalisation of PIP: One is to
       
  1162   make the notions in the correctness proof by Sha et al.~\cite{Sha90}
       
  1163   precise so that they can be processed by a theorem prover. The reason is
       
  1164   that a mechanically checked proof avoids the flaws that crept into their
       
  1165   informal reasoning. We achieved this goal: The correctness of PIP now
       
  1166   only hinges on the assumptions behind our formal model. The reasoning, which is
       
  1167   sometimes quite intricate and tedious, has been checked beyond any
       
  1168   reasonable doubt by Isabelle/HOL. We can also confirm that Paulson's
       
  1169   inductive method for protocol verification~\cite{Paulson98} is quite
       
  1170   suitable for our formal model and proof. The traditional application
       
  1171   area of this method is security protocols.  The only other
       
  1172   application of Paulson's method we know of outside this area is
       
  1173   \cite{Wang09}.
       
  1174 
       
  1175   The second goal of our formalisation is to provide a specification for actually
       
  1176   implementing PIP. Textbooks, for example \cite[Section 5.6.5]{Vahalia96},
       
  1177   explain how to use various implementations of PIP and abstractly
       
  1178   discuss their properties, but surprisingly lack most details for a
       
  1179   programmer who wants to implement PIP.  That this is an issue in practice is illustrated by the
       
  1180   email from Baker we cited in the Introduction. We achieved also this
       
  1181   goal: The formalisation gives the first author enough data to enable
       
  1182   his undergraduate students to implement PIP (as part of their OS course)
       
  1183   on top of PINTOS, a small operating system for teaching
       
  1184   purposes. A byproduct of our formalisation effort is that nearly all
       
  1185   design choices for the PIP scheduler are backed up with a proved
       
  1186   lemma. We were also able to establish the property that the choice of
       
  1187   the next thread which takes over a lock is irrelevant for the correctness
       
  1188   of PIP. Earlier model checking approaches which verified implementations
       
  1189   of PIP \cite{Faria08,Jahier09,Wellings07} cannot
       
  1190   provide this kind of ``deep understanding'' about the principles behind 
       
  1191   PIP and its correctness.
       
  1192 
       
  1193   PIP is a scheduling algorithm for single-processor systems. We are
       
  1194   now living in a multi-processor world. So the question naturally
       
  1195   arises whether PIP has any relevance in such a world beyond
       
  1196   teaching. Priority Inversion certainly occurs also in
       
  1197   multi-processor systems.  However, the surprising answer, according
       
  1198   to \cite{Steinberg10}, is that except for one unsatisfactory
       
  1199   proposal nobody has a good idea for how PIP should be modified to
       
  1200   work correctly on multi-processor systems. The difficulties become
       
  1201   clear when considering that locking and releasing a resource always
       
  1202   requires a small amount of time. If processes work independently,
       
  1203   then a low priority process can ``steal'' in such an unguarded
       
  1204   moment a lock for a resource that was supposed allow a high-priority
       
  1205   process to run next. Thus the problem of Priority Inversion is not
       
  1206   really prevented. It seems difficult to design a PIP-algorithm with
       
  1207   a meaningful correctness property on a multi-processor systems where
       
  1208   processes work independently.  We can imagine PIP to be of use in
       
  1209   situations where processes are \emph{not} independent, but
       
  1210   coordinated via a master process that distributes work over some
       
  1211   slave processes. However, a formal investigation of this is beyond
       
  1212   the scope of this paper.  We are not aware of any proofs in this
       
  1213   area, not even informal ones.
       
  1214 
       
  1215   The most closely related work to ours is the formal verification in
       
  1216   PVS for Priority Ceiling done by Dutertre \cite{dutertre99b}. His formalisation
       
  1217   consists of 407 lemmas and 2500 lines of ``specification'' (we do not
       
  1218   know whether this includes also code for proofs).  Our formalisation
       
  1219   consists of around 210 lemmas and overall 6950 lines of readable Isabelle/Isar
       
  1220   code with a few apply-scripts interspersed. The formal model of PIP
       
  1221   is 385 lines long; the formal correctness proof 3800 lines. Some auxiliary
       
  1222   definitions and proofs took 770 lines of code. The properties relevant
       
  1223   for an implementation took 2000 lines.  Our code can be downloaded from
       
  1224   ...
       
  1225 
       
  1226   \bibliographystyle{plain}
       
  1227   \bibliography{root}
       
  1228 *}
       
  1229 
       
  1230 section {* Key properties \label{extension} *}
   863 section {* Key properties \label{extension} *}
  1231 
   864 
  1232 (*<*)
       
  1233 context extend_highest_gen
       
  1234 begin
       
  1235 (*>*)
       
  1236 
       
  1237 text {*
       
  1238   The essential of {\em Priority Inheritance} is to avoid indefinite priority inversion. For this 
       
  1239   purpose, we need to investigate what happens after one thread takes the highest precedence. 
       
  1240   A locale is used to describe such a situation, which assumes:
       
  1241   \begin{enumerate}
       
  1242   \item @{term "s"} is a valid state (@{text "vt_s"}):
       
  1243     @{thm  vt_s}.
       
  1244   \item @{term "th"} is a living thread in @{term "s"} (@{text "threads_s"}):
       
  1245     @{thm threads_s}.
       
  1246   \item @{term "th"} has the highest precedence in @{term "s"} (@{text "highest"}):
       
  1247     @{thm highest}.
       
  1248   \item The precedence of @{term "th"} is @{term "Prc prio tm"} (@{text "preced_th"}):
       
  1249     @{thm preced_th}.
       
  1250   \end{enumerate}
       
  1251   *}
       
  1252 
       
  1253 text {* \noindent
       
  1254   Under these assumptions, some basic priority can be derived for @{term "th"}:
       
  1255   \begin{enumerate}
       
  1256   \item The current precedence of @{term "th"} equals its own precedence (@{text "eq_cp_s_th"}):
       
  1257     @{thm [display] eq_cp_s_th}
       
  1258   \item The current precedence of @{term "th"} is the highest precedence in 
       
  1259     the system (@{text "highest_cp_preced"}):
       
  1260     @{thm [display] highest_cp_preced}
       
  1261   \item The precedence of @{term "th"} is the highest precedence 
       
  1262     in the system (@{text "highest_preced_thread"}):
       
  1263     @{thm [display] highest_preced_thread}
       
  1264   \item The current precedence of @{term "th"} is the highest current precedence 
       
  1265     in the system (@{text "highest'"}):
       
  1266     @{thm [display] highest'}
       
  1267   \end{enumerate}
       
  1268   *}
       
  1269 
       
  1270 text {* \noindent
       
  1271   To analysis what happens after state @{term "s"} a sub-locale is defined, which 
       
  1272   assumes:
       
  1273   \begin{enumerate}
       
  1274   \item @{term "t"} is a valid extension of @{term "s"} (@{text "vt_t"}): @{thm vt_t}.
       
  1275   \item Any thread created in @{term "t"} has priority no higher than @{term "prio"}, therefore
       
  1276     its precedence can not be higher than @{term "th"},  therefore
       
  1277     @{term "th"} remain to be the one with the highest precedence
       
  1278     (@{text "create_low"}):
       
  1279     @{thm [display] create_low}
       
  1280   \item Any adjustment of priority in 
       
  1281     @{term "t"} does not happen to @{term "th"} and 
       
  1282     the priority set is no higher than @{term "prio"}, therefore
       
  1283     @{term "th"} remain to be the one with the highest precedence (@{text "set_diff_low"}):
       
  1284     @{thm [display] set_diff_low}
       
  1285   \item Since we are investigating what happens to @{term "th"}, it is assumed 
       
  1286     @{term "th"} does not exit during @{term "t"} (@{text "exit_diff"}):
       
  1287     @{thm [display] exit_diff}
       
  1288   \end{enumerate}
       
  1289 *}
       
  1290 
   865 
  1291 text {* \noindent
   866 text {* \noindent
  1292   All these assumptions are put into a predicate @{term "extend_highest_gen"}. 
   867   All these assumptions are put into a predicate @{term "extend_highest_gen"}. 
  1293   It can be proved that @{term "extend_highest_gen"} holds 
   868   It can be proved that @{term "extend_highest_gen"} holds 
  1294   for any moment @{text "i"} in it @{term "t"} (@{text "red_moment"}):
   869   for any moment @{text "i"} in it @{term "t"} (@{text "red_moment"}):
  1341   then.
   916   then.
  1342   *}
   917   *}
  1343 
   918 
  1344 (*<*)
   919 (*<*)
  1345 end
   920 end
  1346 
   921 (*>*)
       
   922 
       
   923 section {* Properties for an Implementation\label{implement} *}
       
   924 
       
   925 text {*
       
   926   While a formal correctness proof for our model of PIP is certainly
       
   927   attractive (especially in light of the flawed proof by Sha et
       
   928   al.~\cite{Sha90}), we found that the formalisation can even help us
       
   929   with efficiently implementing PIP.
       
   930 
       
   931   For example Baker complained that calculating the current precedence
       
   932   in PIP is quite ``heavy weight'' in Linux (see the Introduction).
       
   933   In our model of PIP the current precedence of a thread in a state s
       
   934   depends on all its dependants---a ``global'' transitive notion,
       
   935   which is indeed heavy weight (see Def.~shown in \eqref{cpreced}).
       
   936   We can however improve upon this. For this let us define the notion
       
   937   of @{term children} of a thread @{text th} in a state @{text s} as
       
   938 
       
   939   \begin{isabelle}\ \ \ \ \ %%%
       
   940   \begin{tabular}{@ {}l}
       
   941   @{thm children_def2}
       
   942   \end{tabular}
       
   943   \end{isabelle}
       
   944 
       
   945   \noindent
       
   946   where a child is a thread that is one ``hop'' away from the tread
       
   947   @{text th} in the @{term RAG} (and waiting for @{text th} to release
       
   948   a resource). We can prove that
       
   949 
       
   950   \begin{lemma}\label{childrenlem}
       
   951   @{text "If"} @{thm (prem 1) cp_rec} @{text "then"}
       
   952   \begin{center}
       
   953   @{thm (concl) cp_rec}.
       
   954   \end{center}
       
   955   \end{lemma}
       
   956   
       
   957   \noindent
       
   958   That means the current precedence of a thread @{text th} can be
       
   959   computed locally by considering only the children of @{text th}. In
       
   960   effect, it only needs to be recomputed for @{text th} when one of
       
   961   its children changes its current precedence.  Once the current 
       
   962   precedence is computed in this more efficient manner, the selection
       
   963   of the thread with highest precedence from a set of ready threads is
       
   964   a standard scheduling operation implemented in most operating
       
   965   systems.
       
   966 
       
   967   Of course the main implementation work for PIP involves the
       
   968   scheduler and coding how it should react to events.  Below we
       
   969   outline how our formalisation guides this implementation for each
       
   970   kind of event.\smallskip
       
   971 *}
       
   972 
       
   973 (*<*)
       
   974 context step_create_cps
       
   975 begin
       
   976 (*>*)
       
   977 text {*
       
   978   \noindent
       
   979   \colorbox{mygrey}{@{term "Create th prio"}:} We assume that the current state @{text s'} and 
       
   980   the next state @{term "s \<equiv> Create th prio#s'"} are both valid (meaning the event
       
   981   is allowed to occur). In this situation we can show that
       
   982 
       
   983   \begin{isabelle}\ \ \ \ \ %%%
       
   984   \begin{tabular}{@ {}l}
       
   985   @{thm eq_dep},\\
       
   986   @{thm eq_cp_th}, and\\
       
   987   @{thm[mode=IfThen] eq_cp}
       
   988   \end{tabular}
       
   989   \end{isabelle}
       
   990 
       
   991   \noindent
       
   992   This means we do not have recalculate the @{text RAG} and also none of the
       
   993   current precedences of the other threads. The current precedence of the created
       
   994   thread @{text th} is just its precedence, namely the pair @{term "(prio, length (s::event list))"}.
       
   995   \smallskip
       
   996   *}
       
   997 (*<*)
       
   998 end
       
   999 context step_exit_cps
       
  1000 begin
       
  1001 (*>*)
       
  1002 text {*
       
  1003   \noindent
       
  1004   \colorbox{mygrey}{@{term "Exit th"}:} We again assume that the current state @{text s'} and 
       
  1005   the next state @{term "s \<equiv> Exit th#s'"} are both valid. We can show that
       
  1006 
       
  1007   \begin{isabelle}\ \ \ \ \ %%%
       
  1008   \begin{tabular}{@ {}l}
       
  1009   @{thm eq_dep}, and\\
       
  1010   @{thm[mode=IfThen] eq_cp}
       
  1011   \end{tabular}
       
  1012   \end{isabelle}
       
  1013 
       
  1014   \noindent
       
  1015   This means again we do not have to recalculate the @{text RAG} and
       
  1016   also not the current precedences for the other threads. Since @{term th} is not
       
  1017   alive anymore in state @{term "s"}, there is no need to calculate its
       
  1018   current precedence.
       
  1019   \smallskip
       
  1020 *}
       
  1021 (*<*)
       
  1022 end
       
  1023 context step_set_cps
       
  1024 begin
       
  1025 (*>*)
       
  1026 text {*
       
  1027   \noindent
       
  1028   \colorbox{mygrey}{@{term "Set th prio"}:} We assume that @{text s'} and 
       
  1029   @{term "s \<equiv> Set th prio#s'"} are both valid. We can show that
       
  1030 
       
  1031   \begin{isabelle}\ \ \ \ \ %%%
       
  1032   \begin{tabular}{@ {}l}
       
  1033   @{thm[mode=IfThen] eq_dep}, and\\
       
  1034   @{thm[mode=IfThen] eq_cp}
       
  1035   \end{tabular}
       
  1036   \end{isabelle}
       
  1037 
       
  1038   \noindent
       
  1039   The first property is again telling us we do not need to change the @{text RAG}. The second
       
  1040   however states that only threads that are \emph{not} dependants of @{text th} have their
       
  1041   current precedence unchanged. For the others we have to recalculate the current
       
  1042   precedence. To do this we can start from @{term "th"} 
       
  1043   and follow the @{term "depend"}-chains to recompute the @{term "cp"} of every 
       
  1044   thread encountered on the way using Lemma~\ref{childrenlem}. Since the @{term "depend"}
       
  1045   is loop free, this procedure will always stop. The following two lemmas show, however, 
       
  1046   that this procedure can actually stop often earlier without having to consider all
       
  1047   dependants.
       
  1048 
       
  1049   \begin{isabelle}\ \ \ \ \ %%%
       
  1050   \begin{tabular}{@ {}l}
       
  1051   @{thm[mode=IfThen] eq_up_self}\\
       
  1052   @{text "If"} @{thm (prem 1) eq_up}, @{thm (prem 2) eq_up} and @{thm (prem 3) eq_up}\\
       
  1053   @{text "then"} @{thm (concl) eq_up}.
       
  1054   \end{tabular}
       
  1055   \end{isabelle}
       
  1056 
       
  1057   \noindent
       
  1058   The first states that if the current precedence of @{text th} is unchanged,
       
  1059   then the procedure can stop immediately (all dependent threads have their @{term cp}-value unchanged).
       
  1060   The second states that if an intermediate @{term cp}-value does not change, then
       
  1061   the procedure can also stop, because none of its dependent threads will
       
  1062   have their current precedence changed.
       
  1063   \smallskip
       
  1064   *}
       
  1065 (*<*)
       
  1066 end
       
  1067 context step_v_cps_nt
       
  1068 begin
       
  1069 (*>*)
       
  1070 text {*
       
  1071   \noindent
       
  1072   \colorbox{mygrey}{@{term "V th cs"}:} We assume that @{text s'} and 
       
  1073   @{term "s \<equiv> V th cs#s'"} are both valid. We have to consider two
       
  1074   subcases: one where there is a thread to ``take over'' the released
       
  1075   resource @{text cs}, and one where there is not. Let us consider them
       
  1076   in turn. Suppose in state @{text s}, the thread @{text th'} takes over
       
  1077   resource @{text cs} from thread @{text th}. We can show
       
  1078 
       
  1079 
       
  1080   \begin{isabelle}\ \ \ \ \ %%%
       
  1081   @{thm depend_s}
       
  1082   \end{isabelle}
       
  1083   
       
  1084   \noindent
       
  1085   which shows how the @{text RAG} needs to be changed. This also suggests
       
  1086   how the current precedences need to be recalculated. For threads that are
       
  1087   not @{text "th"} and @{text "th'"} nothing needs to be changed, since we
       
  1088   can show
       
  1089 
       
  1090   \begin{isabelle}\ \ \ \ \ %%%
       
  1091   @{thm[mode=IfThen] cp_kept}
       
  1092   \end{isabelle}
       
  1093   
       
  1094   \noindent
       
  1095   For @{text th} and @{text th'} we need to use Lemma~\ref{childrenlem} to
       
  1096   recalculate their current prcedence since their children have changed. *}(*<*)end context step_v_cps_nnt begin (*>*)text {*
       
  1097   \noindent
       
  1098   In the other case where there is no thread that takes over @{text cs}, we can show how
       
  1099   to recalculate the @{text RAG} and also show that no current precedence needs
       
  1100   to be recalculated.
       
  1101 
       
  1102   \begin{isabelle}\ \ \ \ \ %%%
       
  1103   \begin{tabular}{@ {}l}
       
  1104   @{thm depend_s}\\
       
  1105   @{thm eq_cp}
       
  1106   \end{tabular}
       
  1107   \end{isabelle}
       
  1108   *}
       
  1109 (*<*)
       
  1110 end
       
  1111 context step_P_cps_e
       
  1112 begin
       
  1113 (*>*)
       
  1114 
       
  1115 text {*
       
  1116   \noindent
       
  1117   \colorbox{mygrey}{@{term "P th cs"}:} We assume that @{text s'} and 
       
  1118   @{term "s \<equiv> P th cs#s'"} are both valid. We again have to analyse two subcases, namely
       
  1119   the one where @{text cs} is locked, and where it is not. We treat the second case
       
  1120   first by showing that
       
  1121   
       
  1122   \begin{isabelle}\ \ \ \ \ %%%
       
  1123   \begin{tabular}{@ {}l}
       
  1124   @{thm depend_s}\\
       
  1125   @{thm eq_cp}
       
  1126   \end{tabular}
       
  1127   \end{isabelle}
       
  1128 
       
  1129   \noindent
       
  1130   This means we do not need to add a holding edge to the @{text RAG} and no
       
  1131   current precedence needs to be recalculated.*}(*<*)end context step_P_cps_ne begin(*>*) text {*
       
  1132   \noindent
       
  1133   In the second case we know that resouce @{text cs} is locked. We can show that
       
  1134   
       
  1135   \begin{isabelle}\ \ \ \ \ %%%
       
  1136   \begin{tabular}{@ {}l}
       
  1137   @{thm depend_s}\\
       
  1138   @{thm[mode=IfThen] eq_cp}
       
  1139   \end{tabular}
       
  1140   \end{isabelle}
       
  1141 
       
  1142   \noindent
       
  1143   That means we have to add a waiting edge to the @{text RAG}. Furthermore
       
  1144   the current precedence for all threads that are not dependants of @{text th}
       
  1145   are unchanged. For the others we need to follow the edges 
       
  1146   in the @{text RAG} and recompute the @{term "cp"}. However, like in the 
       
  1147   @case of {text Set}, this operation can stop often earlier, namely when intermediate
       
  1148   values do not change.
       
  1149   *}
       
  1150 (*<*)
  1347 end
  1151 end
  1348 (*>*)
  1152 (*>*)
       
  1153 text {*
       
  1154   \noindent
       
  1155   A pleasing result of our formalisation is that the properties in
       
  1156   this section closely inform an implementation of PIP:  Whether the
       
  1157   @{text RAG} needs to be reconfigured or current precedences need to
       
  1158   recalculated for an event is given by a lemma we proved.
       
  1159 *}
       
  1160 
       
  1161 section {* Conclusion *}
       
  1162 
       
  1163 text {* 
       
  1164   The Priority Inheritance Protocol (PIP) is a classic textbook
       
  1165   algorithm used in real-time operating systems in order to avoid the problem of
       
  1166   Priority Inversion.  Although classic and widely used, PIP does have
       
  1167   its faults: for example it does not prevent deadlocks in cases where threads
       
  1168   have circular lock dependencies.
       
  1169 
       
  1170   We had two goals in mind with our formalisation of PIP: One is to
       
  1171   make the notions in the correctness proof by Sha et al.~\cite{Sha90}
       
  1172   precise so that they can be processed by a theorem prover. The reason is
       
  1173   that a mechanically checked proof avoids the flaws that crept into their
       
  1174   informal reasoning. We achieved this goal: The correctness of PIP now
       
  1175   only hinges on the assumptions behind our formal model. The reasoning, which is
       
  1176   sometimes quite intricate and tedious, has been checked beyond any
       
  1177   reasonable doubt by Isabelle/HOL. We can also confirm that Paulson's
       
  1178   inductive method for protocol verification~\cite{Paulson98} is quite
       
  1179   suitable for our formal model and proof. The traditional application
       
  1180   area of this method is security protocols.  The only other
       
  1181   application of Paulson's method we know of outside this area is
       
  1182   \cite{Wang09}.
       
  1183 
       
  1184   The second goal of our formalisation is to provide a specification for actually
       
  1185   implementing PIP. Textbooks, for example \cite[Section 5.6.5]{Vahalia96},
       
  1186   explain how to use various implementations of PIP and abstractly
       
  1187   discuss their properties, but surprisingly lack most details for a
       
  1188   programmer who wants to implement PIP.  That this is an issue in practice is illustrated by the
       
  1189   email from Baker we cited in the Introduction. We achieved also this
       
  1190   goal: The formalisation gives the first author enough data to enable
       
  1191   his undergraduate students to implement PIP (as part of their OS course)
       
  1192   on top of PINTOS, a small operating system for teaching
       
  1193   purposes. A byproduct of our formalisation effort is that nearly all
       
  1194   design choices for the PIP scheduler are backed up with a proved
       
  1195   lemma. We were also able to establish the property that the choice of
       
  1196   the next thread which takes over a lock is irrelevant for the correctness
       
  1197   of PIP. Earlier model checking approaches which verified implementations
       
  1198   of PIP \cite{Faria08,Jahier09,Wellings07} cannot
       
  1199   provide this kind of ``deep understanding'' about the principles behind 
       
  1200   PIP and its correctness.
       
  1201 
       
  1202   PIP is a scheduling algorithm for single-processor systems. We are
       
  1203   now living in a multi-processor world. So the question naturally
       
  1204   arises whether PIP has any relevance in such a world beyond
       
  1205   teaching. Priority Inversion certainly occurs also in
       
  1206   multi-processor systems.  However, the surprising answer, according
       
  1207   to \cite{Steinberg10}, is that except for one unsatisfactory
       
  1208   proposal nobody has a good idea for how PIP should be modified to
       
  1209   work correctly on multi-processor systems. The difficulties become
       
  1210   clear when considering that locking and releasing a resource always
       
  1211   requires a small amount of time. If processes work independently,
       
  1212   then a low priority process can ``steal'' in such an unguarded
       
  1213   moment a lock for a resource that was supposed allow a high-priority
       
  1214   process to run next. Thus the problem of Priority Inversion is not
       
  1215   really prevented. It seems difficult to design a PIP-algorithm with
       
  1216   a meaningful correctness property on a multi-processor systems where
       
  1217   processes work independently.  We can imagine PIP to be of use in
       
  1218   situations where processes are \emph{not} independent, but
       
  1219   coordinated via a master process that distributes work over some
       
  1220   slave processes. However, a formal investigation of this is beyond
       
  1221   the scope of this paper.  We are not aware of any proofs in this
       
  1222   area, not even informal ones.
       
  1223 
       
  1224   The most closely related work to ours is the formal verification in
       
  1225   PVS for Priority Ceiling done by Dutertre \cite{dutertre99b}. His formalisation
       
  1226   consists of 407 lemmas and 2500 lines of ``specification'' (we do not
       
  1227   know whether this includes also code for proofs).  Our formalisation
       
  1228   consists of around 210 lemmas and overall 6950 lines of readable Isabelle/Isar
       
  1229   code with a few apply-scripts interspersed. The formal model of PIP
       
  1230   is 385 lines long; the formal correctness proof 3800 lines. Some auxiliary
       
  1231   definitions and proofs took 770 lines of code. The properties relevant
       
  1232   for an implementation took 2000 lines.  Our code can be downloaded from
       
  1233   ...
       
  1234 
       
  1235   \bibliographystyle{plain}
       
  1236   \bibliography{root}
       
  1237 *}
       
  1238 
       
  1239 
       
  1240 (*<*)
       
  1241 end
       
  1242 (*>*)