prio/Paper/Paper.thy
changeset 300 8524f94d251b
parent 299 4fcd802eba59
child 301 e820ee5f76f7
equal deleted inserted replaced
299:4fcd802eba59 300:8524f94d251b
   136   to its original priority level.'' This leads them to believe that an
   136   to its original priority level.'' This leads them to believe that an
   137   implementation of PIP is ``rather straightforward''~\cite{Sha90}.
   137   implementation of PIP is ``rather straightforward''~\cite{Sha90}.
   138   Unfortunately, as Yodaiken points out, this behaviour is too
   138   Unfortunately, as Yodaiken points out, this behaviour is too
   139   simplistic.  Consider the case where the low priority thread $L$
   139   simplistic.  Consider the case where the low priority thread $L$
   140   locks \emph{two} resources, and two high-priority threads $H$ and
   140   locks \emph{two} resources, and two high-priority threads $H$ and
   141   $H'$ each wait for one of them.  If $L$ then releases one resource
   141   $H'$ each wait for one of them.  If $L$ releases one resource
   142   so that $H$, say, can proceed, then we still have Priority Inversion
   142   so that $H$, say, can proceed, then we still have Priority Inversion
   143   with $H'$ (which waits for the other resource). The correct
   143   with $H'$ (which waits for the other resource). The correct
   144   behaviour for $L$ is to revert to the highest remaining priority of
   144   behaviour for $L$ is to revert to the highest remaining priority of
   145   the threads that it blocks. The advantage of formalising the
   145   the threads that it blocks. The advantage of formalising the
   146   correctness of a high-level specification of PIP in a theorem prover
   146   correctness of a high-level specification of PIP in a theorem prover
   147   is that such issues clearly show up and cannot be overlooked as in
   147   is that such issues clearly show up and cannot be overlooked as in
   148   informal reasoning (since we have to analyse all possible behaviours
   148   informal reasoning (since we have to analyse all possible behaviours
   149   of threads, i.e.~\emph{traces}, that could possibly happen).
   149   of threads, i.e.~\emph{traces}, that could possibly happen).\medskip
   150 
   150 
   151   There have been earlier formal investigations into PIP, but ...\cite{Faria08}
   151   \noindent
       
   152   {\bf Contributions:} There have been earlier formal investigations 
       
   153   into PIP, but ...\cite{Faria08}
   152 
   154 
   153   vt (valid trace) was introduced earlier, cite
   155   vt (valid trace) was introduced earlier, cite
   154   
   156   
   155   distributed PIP
   157   distributed PIP
   156 
   158 
   319   \node (D) at (4,-0.7) [draw, rounded corners=1mm, rectangle, very thick] {@{text "th\<^isub>2"}};
   321   \node (D) at (4,-0.7) [draw, rounded corners=1mm, rectangle, very thick] {@{text "th\<^isub>2"}};
   320   \node (E) at (6,-0.7) [draw, circle, very thick, inner sep=0.4mm] {@{text "cs\<^isub>2"}};
   322   \node (E) at (6,-0.7) [draw, circle, very thick, inner sep=0.4mm] {@{text "cs\<^isub>2"}};
   321   \node (E1) at (6, 0.2) [draw, circle, very thick, inner sep=0.4mm] {@{text "cs\<^isub>3"}};
   323   \node (E1) at (6, 0.2) [draw, circle, very thick, inner sep=0.4mm] {@{text "cs\<^isub>3"}};
   322   \node (F) at (8,-0.7) [draw, rounded corners=1mm, rectangle, very thick] {@{text "th\<^isub>3"}};
   324   \node (F) at (8,-0.7) [draw, rounded corners=1mm, rectangle, very thick] {@{text "th\<^isub>3"}};
   323 
   325 
   324   \draw [->,line width=0.6mm] (A) to node [pos=0.45,sloped,above=-0.5mm] {\fnt{}holding}  (B);
   326   \draw [<-,line width=0.6mm] (A) to node [pos=0.54,sloped,above=-0.5mm] {\fnt{}holding}  (B);
   325   \draw [->,line width=0.6mm] (C) to node [pos=0.4,sloped,above=-0.5mm] {\fnt{}waiting}  (B);
   327   \draw [->,line width=0.6mm] (C) to node [pos=0.4,sloped,above=-0.5mm] {\fnt{}waiting}  (B);
   326   \draw [->,line width=0.6mm] (D) to node [pos=0.4,sloped,below=-0.5mm] {\fnt{}waiting}  (B);
   328   \draw [->,line width=0.6mm] (D) to node [pos=0.4,sloped,below=-0.5mm] {\fnt{}waiting}  (B);
   327   \draw [->,line width=0.6mm] (D) to node [pos=0.45,sloped,below=-0.5mm] {\fnt{}holding}  (E);
   329   \draw [<-,line width=0.6mm] (D) to node [pos=0.54,sloped,below=-0.5mm] {\fnt{}holding}  (E);
   328   \draw [->,line width=0.6mm] (D) to node [pos=0.45,sloped,above=-0.5mm] {\fnt{}holding}  (E1);
   330   \draw [<-,line width=0.6mm] (D) to node [pos=0.54,sloped,above=-0.5mm] {\fnt{}holding}  (E1);
   329   \draw [->,line width=0.6mm] (F) to node [pos=0.45,sloped,below=-0.5mm] {\fnt{}waiting}  (E);
   331   \draw [->,line width=0.6mm] (F) to node [pos=0.45,sloped,below=-0.5mm] {\fnt{}waiting}  (E);
   330   \end{tikzpicture}
   332   \end{tikzpicture}
   331   \end{center}
   333   \end{center}
   332 
   334 
   333   \noindent
   335   \noindent
   414   \hspace{8mm}@{term "(|wq_fun = wq\<iota>, cprec_fun = cpreced wq\<iota> (Set th prio # s)|)"}
   416   \hspace{8mm}@{term "(|wq_fun = wq\<iota>, cprec_fun = cpreced wq\<iota> (Set th prio # s)|)"}
   415   \end{tabular}
   417   \end{tabular}
   416   \end{isabelle}
   418   \end{isabelle}
   417 
   419 
   418   \noindent 
   420   \noindent 
   419   More interesting are the cases when a resource, say @{text cs}, is locked or released. In this case
   421   More interesting are the cases when a resource, say @{text cs}, is locked or released. In these cases
   420   we need to calculate a new waiting queue function. For the event @{term P}, we have to update
   422   we need to calculate a new waiting queue function. For the event @{term "P th cs"}, we have to update
   421   the function so that the new thread list for @{text cs} is old thread list plus the thread @{text th} 
   423   the function so that the new thread list for @{text cs} is old thread list plus the thread @{text th} 
   422   appended to the end of that list (remember the head of this list is seen to be in the possession of the
   424   appended to the end of that list (remember the head of this list is seen to be in the possession of this
   423   resource).
   425   resource).
   424 
   426 
   425   \begin{isabelle}\ \ \ \ \ %%%
   427   \begin{isabelle}\ \ \ \ \ %%%
   426   \begin{tabular}{@ {}l}
   428   \begin{tabular}{@ {}l}
   427   @{thm (lhs) schs.simps(5)} @{text "\<equiv>"}\\ 
   429   @{thm (lhs) schs.simps(5)} @{text "\<equiv>"}\\ 
   430   \hspace{8mm}@{term "(|wq_fun = new_wq, cprec_fun = cpreced new_wq (P th cs # s)|)"}
   432   \hspace{8mm}@{term "(|wq_fun = new_wq, cprec_fun = cpreced new_wq (P th cs # s)|)"}
   431   \end{tabular}
   433   \end{tabular}
   432   \end{isabelle}
   434   \end{isabelle}
   433 
   435 
   434   \noindent
   436   \noindent
   435   The clause for event @{term V} is similar, except that we need to update the waiting queue function
   437   The clause for event @{term "V th cs"} is similar, except that we need to update the waiting queue function
   436   so that the thread that possessed the lock is deleted from the corresponding thread list. For this we use
   438   so that the thread that possessed the lock is deleted from the corresponding thread list. For this we use
   437   the auxiliary function @{term release}. A simple version of @{term release} would
   439   the auxiliary function @{term release}. A simple version of @{term release} would
   438   just delete this thread and return the rest, namely
   440   just delete this thread and return the rest, namely
   439 
   441 
   440   \begin{isabelle}\ \ \ \ \ %%%
   442   \begin{isabelle}\ \ \ \ \ %%%
   443   @{term "release (DUMMY # qs)"} & @{text "\<equiv>"} & @{term "qs"}\\
   445   @{term "release (DUMMY # qs)"} & @{text "\<equiv>"} & @{term "qs"}\\
   444   \end{tabular}
   446   \end{tabular}
   445   \end{isabelle}
   447   \end{isabelle}
   446 
   448 
   447   \noindent
   449   \noindent
   448   In practice, however, often the thread with the highest precedence will get the
   450   In practice, however, often the thread with the highest precedence in the list will get the
   449   lock next. We have implemented this choice, but later found out that the choice 
   451   lock next. We have implemented this choice, but later found out that the choice 
   450   about which thread is chosen next is actually irrelevant for the correctness of PIP.
   452   of which thread is chosen next is actually irrelevant for the correctness of PIP.
   451   Therefore we prove the stronger result where @{term release} is defined as
   453   Therefore we prove the stronger result where @{term release} is defined as
   452 
   454 
   453   \begin{isabelle}\ \ \ \ \ %%%
   455   \begin{isabelle}\ \ \ \ \ %%%
   454   \begin{tabular}{@ {}lcl}
   456   \begin{tabular}{@ {}lcl}
   455   @{term "release []"} & @{text "\<equiv>"} & @{term "[]"}\\
   457   @{term "release []"} & @{text "\<equiv>"} & @{term "[]"}\\
   469   \hspace{5mm}@{text "let"} @{text "new_wq = release (wq cs)"} @{text "in"}\\
   471   \hspace{5mm}@{text "let"} @{text "new_wq = release (wq cs)"} @{text "in"}\\
   470   \hspace{8mm}@{term "(|wq_fun = new_wq, cprec_fun = cpreced new_wq (V th cs # s)|)"}
   472   \hspace{8mm}@{term "(|wq_fun = new_wq, cprec_fun = cpreced new_wq (V th cs # s)|)"}
   471   \end{tabular}
   473   \end{tabular}
   472   \end{isabelle}
   474   \end{isabelle}
   473 
   475 
   474   Having the scheduler function @{term schs} at our disposal, we can ``lift'' the notions
   476   Having the scheduler function @{term schs} at our disposal, we can ``lift'', or
   475   @{term waiting}, @{term holding}, @{term depend} and @{term cp} such that they only depend 
   477   overload, the notions
   476   on states.
   478   @{term waiting}, @{term holding}, @{term depend} and @{term cp} to operate on states only.
   477 
   479 
   478   \begin{isabelle}\ \ \ \ \ %%%
   480   \begin{isabelle}\ \ \ \ \ %%%
   479   \begin{tabular}{@ {}rcl}
   481   \begin{tabular}{@ {}rcl}
   480   @{thm (lhs) s_holding_abv} & @{text "\<equiv>"} & @{thm (rhs) s_holding_abv}\\
   482   @{thm (lhs) s_holding_abv} & @{text "\<equiv>"} & @{thm (rhs) s_holding_abv}\\
   481   @{thm (lhs) s_waiting_abv} & @{text "\<equiv>"} & @{thm (rhs) s_waiting_abv}\\
   483   @{thm (lhs) s_waiting_abv} & @{text "\<equiv>"} & @{thm (rhs) s_waiting_abv}\\
   483   @{thm (lhs) cp_def}        & @{text "\<equiv>"} & @{thm (rhs) cp_def}
   485   @{thm (lhs) cp_def}        & @{text "\<equiv>"} & @{thm (rhs) cp_def}
   484   \end{tabular}
   486   \end{tabular}
   485   \end{isabelle}
   487   \end{isabelle}
   486 
   488 
   487   \noindent
   489   \noindent
   488   With these abbreviations we can introduce for states 
   490   With these abbreviations we can introduce 
   489   the notion of threads being @{term readys} (i.e.~threads
   491   the notion of threads being @{term readys} in a state (i.e.~threads
   490   that do not wait for any resource) and the running thread.
   492   that do not wait for any resource) and the running thread.
   491 
   493 
   492   \begin{isabelle}\ \ \ \ \ %%%
   494   \begin{isabelle}\ \ \ \ \ %%%
   493   \begin{tabular}{@ {}l}
   495   \begin{tabular}{@ {}l}
   494   @{thm readys_def}\\
   496   @{thm readys_def}\\
   501   function @{text f}. 
   503   function @{text f}. 
   502   Note that in the initial case, that is where the list of events is empty, the set 
   504   Note that in the initial case, that is where the list of events is empty, the set 
   503   @{term threads} is empty and therefore there is no thread ready nor a running.
   505   @{term threads} is empty and therefore there is no thread ready nor a running.
   504   If there is one or more threads ready, then there can only be \emph{one} thread
   506   If there is one or more threads ready, then there can only be \emph{one} thread
   505   running, namely the one whose current precedence is equal to the maximum of all ready 
   507   running, namely the one whose current precedence is equal to the maximum of all ready 
   506   threads. We can also define the set of resources that are locked by a thread in any
   508   threads. We use the set-comprehension to capture both possibilites.
       
   509   We can now also define the set of resources that are locked by a thread in any
   507   given state.
   510   given state.
   508 
   511 
   509   \begin{isabelle}\ \ \ \ \ %%%
   512   \begin{isabelle}\ \ \ \ \ %%%
   510   @{thm holdents_def}
   513   @{thm holdents_def}
   511   \end{isabelle}
   514   \end{isabelle}
   572 
   575 
   573 text {* TO DO *}
   576 text {* TO DO *}
   574 
   577 
   575 section {* Conclusion *}
   578 section {* Conclusion *}
   576 
   579 
   577 text {* TO DO *}
   580 text {* 
       
   581   The Priority Inheritance Protocol is a classic textbook algorithm
       
   582   used in real-time systems in order to avoid the problem of Priority
       
   583   Inversion.
       
   584 
       
   585   TO DO 
       
   586 
       
   587 *}
   578 
   588 
   579 text {*
   589 text {*
   580   \bigskip
   590   \bigskip
   581   The priority inversion phenomenon was first published in
   591   The priority inversion phenomenon was first published in
   582   \cite{Lampson80}.  The two protocols widely used to eliminate
   592   \cite{Lampson80}.  The two protocols widely used to eliminate