prio/Paper/Paper.thy
changeset 310 4d93486cb302
parent 309 e44c4055d430
child 311 23632f329e10
equal deleted inserted replaced
309:e44c4055d430 310:4d93486cb302
   155   checking techniques. This paper presents a formalised and
   155   checking techniques. This paper presents a formalised and
   156   mechanically checked proof for the correctness of PIP (to our
   156   mechanically checked proof for the correctness of PIP (to our
   157   knowledge the first one; the earlier informal proof by Sha et
   157   knowledge the first one; the earlier informal proof by Sha et
   158   al.~\cite{Sha90} is flawed).  In contrast to model checking, our
   158   al.~\cite{Sha90} is flawed).  In contrast to model checking, our
   159   formalisation provides insight into why PIP is correct and allows us
   159   formalisation provides insight into why PIP is correct and allows us
   160   to prove stronger properties that, as we will show, inform an
   160   to prove stronger properties that, as we will show, can inform an
   161   implementation.  For example, we found by ``playing'' with the formalisation
   161   implementation.  For example, we found by ``playing'' with the formalisation
   162   that the choice of the next thread to take over a lock when a
   162   that the choice of the next thread to take over a lock when a
   163   resource is released is irrelevant for PIP being correct. Something
   163   resource is released is irrelevant for PIP being correct. Something
   164   which has not been mentioned in the relevant literature.
   164   which has not been mentioned in the relevant literature.
   165 *}
   165 *}
   548   \noindent
   548   \noindent
   549   If a thread wants to lock a resource, then the thread needs to be
   549   If a thread wants to lock a resource, then the thread needs to be
   550   running and also we have to make sure that the resource lock does
   550   running and also we have to make sure that the resource lock does
   551   not lead to a cycle in the RAG. In practice, ensuring the latter is
   551   not lead to a cycle in the RAG. In practice, ensuring the latter is
   552   of course the responsibility of the programmer.  In our formal
   552   of course the responsibility of the programmer.  In our formal
   553   model we just exclude such problematic cases in order to make
   553   model we just exclude such problematic cases in order to be able to make
   554   some meaningful statements about PIP.\footnote{This situation is
   554   some meaningful statements about PIP.\footnote{This situation is
   555   similar to the infamous occurs check in Prolog: in order to say
   555   similar to the infamous occurs check in Prolog: In order to say
   556   anything meaningful about unification, one needs to perform an occurs
   556   anything meaningful about unification, one needs to perform an occurs
   557   check, but in practice the occurs check is ommited and the
   557   check. But in practice the occurs check is ommited and the
   558   responsibility for avoiding problems rests with the programmer.}
   558   responsibility for avoiding problems rests with the programmer.}
   559  
   559  
   560   \begin{center}
   560   \begin{center}
   561   @{thm[mode=Rule] thread_P[where thread=th]}
   561   @{thm[mode=Rule] thread_P[where thread=th]}
   562   \end{center}
   562   \end{center}
   583   \noindent
   583   \noindent
   584   This completes our formal model of PIP. In the next section we present
   584   This completes our formal model of PIP. In the next section we present
   585   properties that show our model of PIP is correct.
   585   properties that show our model of PIP is correct.
   586 *}
   586 *}
   587 
   587 
   588 section {* Correctness Proof *}
   588 section {* The Correctness Proof *}
   589 
   589 
   590 (*<*)
   590 (*<*)
   591 context extend_highest_gen
   591 context extend_highest_gen
   592 begin
   592 begin
   593 print_locale extend_highest_gen
   593 print_locale extend_highest_gen
   594 thm extend_highest_gen_def
   594 thm extend_highest_gen_def
   595 thm extend_highest_gen_axioms_def
   595 thm extend_highest_gen_axioms_def
   596 thm highest_gen_def
   596 thm highest_gen_def
   597 (*>*)
   597 (*>*)
   598 text {* 
   598 text {* 
   599   Sha et al.~\cite{Sha90} state their correctness criterion of PIP in terms
   599   Sha et al.~\cite[Theorem 6]{Sha90} state their correctness criterion for PIP in terms
   600   of the number of critical resources: if there are @{text m} critical
   600   of the number of critical resources: if there are @{text m} critical
   601   resources, then a blocked job can only be blocked @{text m} times---that is
   601   resources, then a blocked job can only be blocked @{text m} times---that is
   602   a bounded number of times.
   602   a bounded number of times.
   603   For their version of PIP, this property is \emph{not} true (as pointed out by 
   603   For their version of PIP, this property is \emph{not} true (as pointed out by 
   604   Yodaiken \cite{Yodaiken02}) as a high-priority thread can be
   604   Yodaiken \cite{Yodaiken02}) as a high-priority thread can be
   605   blocked an unbounded number of times by creating medium-priority
   605   blocked an unbounded number of times by creating medium-priority
   606   threads that block a thread locking a critical resource and having 
   606   threads that block a thread, which in turn locks a critical resource and has
   607   a too low priority. In the way we have set up our formal model of PIP, 
   607   too low priority to make progress. In the way we have set up our formal model of PIP, 
   608   their proof idea, even when fixed, does not seem to go through.
   608   their proof idea, even when fixed, does not seem to go through.
   609 
   609 
   610   The idea behind our correctness criterion of PIP is as follows: for all states
   610   The idea behind our correctness criterion of PIP is as follows: for all states
   611   @{text s}, we know the corresponding thread @{text th} with the highest precedence;
   611   @{text s}, we know the corresponding thread @{text th} with the highest precedence;
   612   we show that in every future state (denoted by @{text "s' @ s"}) in which
   612   we show that in every future state (denoted by @{text "s' @ s"}) in which
   613   @{text th} is still active, either @{text th} is running or it is blocked by a 
   613   @{text th} is still alive, either @{text th} is running or it is blocked by a 
   614   thread that was active in the state @{text s}. Since in @{text s}, as in every 
   614   thread that was alive in the state @{text s}. Since in @{text s}, as in every 
   615   state, the set of active threads is finite, @{text th} can only be blocked a
   615   state, the set of alive threads is finite, @{text th} can only be blocked a
   616   finite number of times. We will actually prove a stricter bound. However,
   616   finite number of times. We will actually prove a stricter bound below. However,
   617   this correctness criterion hinges on a number of assumptions about the states
   617   this correctness criterion hinges upon a number of assumptions about the states
   618   @{text s} and @{text "s' @ s"}, the thread @{text th} and the events happening
   618   @{text s} and @{text "s' @ s"}, the thread @{text th} and the events happening
   619   in @{text s'}. We list them next.
   619   in @{text s'}. We list them next:
   620 
   620 
   621   \begin{quote}
   621   \begin{quote}
   622   {\bf Assumptions on the states @{text s} and @{text "s' @ s"}:} In order to make 
   622   {\bf Assumptions on the states @{text s} and @{text "s' @ s"}:} In order to make 
   623   any meaningful statement, we need to require that @{text "s"} and 
   623   any meaningful statement, we need to require that @{text "s"} and 
   624   @{text "s' @ s"} are valid states, namely
   624   @{text "s' @ s"} are valid states, namely
   629   \end{tabular}
   629   \end{tabular}
   630   \end{isabelle}
   630   \end{isabelle}
   631   \end{quote}
   631   \end{quote}
   632 
   632 
   633   \begin{quote}
   633   \begin{quote}
   634   {\bf Assumptions on the thread @{text "th"}:} The thread @{text th} must be active in @{text s} and 
   634   {\bf Assumptions on the thread @{text "th"}:} The thread @{text th} must be alive in @{text s} and 
   635   has the highest precedence of all active threads in @{text s}. Furthermore the
   635   has the highest precedence of all alive threads in @{text s}. Furthermore the
   636   priority of @{text th} is @{text prio}.
   636   priority of @{text th} is @{text prio} (we need this in the next assumptions).
   637   \begin{isabelle}\ \ \ \ \ %%%
   637   \begin{isabelle}\ \ \ \ \ %%%
   638   \begin{tabular}{l}
   638   \begin{tabular}{l}
   639   @{term "th \<in> threads s"}\\
   639   @{term "th \<in> threads s"}\\
   640   @{term "prec th s = Max (cprec s ` threads s)"}\\
   640   @{term "prec th s = Max (cprec s ` threads s)"}\\
   641   @{term "prec th s = (prio, DUMMY)"}
   641   @{term "prec th s = (prio, DUMMY)"}
   646   \begin{quote}
   646   \begin{quote}
   647   {\bf Assumptions on the events in @{text "s'"}:} We want to prove that @{text th} cannot
   647   {\bf Assumptions on the events in @{text "s'"}:} We want to prove that @{text th} cannot
   648   be blocked indefinitely. Of course this can happen if threads with higher priority
   648   be blocked indefinitely. Of course this can happen if threads with higher priority
   649   than @{text th} are continously created in @{text s'}. Therefore we have to assume that  
   649   than @{text th} are continously created in @{text s'}. Therefore we have to assume that  
   650   events in @{text s'} can only create (respectively set) threads with equal or lower 
   650   events in @{text s'} can only create (respectively set) threads with equal or lower 
   651   priority than @{text prio} of the thread @{text th}. We also have to assume that @{text th} does
   651   priority than @{text prio} of @{text th}. We also need to assume that the
   652   not get ``exited'' in @{text "s'"}.
   652   priority of @{text "th"} does not get reset and also that @{text th} does
       
   653   not get ``exited'' in @{text "s'"}. This can be ensured by assuming the following three implications. 
   653   \begin{isabelle}\ \ \ \ \ %%%
   654   \begin{isabelle}\ \ \ \ \ %%%
   654   \begin{tabular}{l}
   655   \begin{tabular}{l}
   655   {If}~~@{text "Create _ prio' \<in> set s'"}~~{then}~~@{text "prio' \<le> prio"}\\
   656   {If}~~@{text "Create th' prio' \<in> set s'"}~~{then}~~@{text "prio' \<le> prio"}\\
   656   {If}~~@{text "Set th' prio' \<in> set s'"}~~{then}~~@{text "th' \<noteq> th"}~~{and}~~@{text "prio' \<le> prio"}\\
   657   {If}~~@{text "Set th' prio' \<in> set s'"}~~{then}~~@{text "th' \<noteq> th"}~~{and}~~@{text "prio' \<le> prio"}\\
   657   {If}~~@{text "Exit th' \<in> set s'"}~~{then}~~@{text "th' \<noteq> th"}\\
   658   {If}~~@{text "Exit th' \<in> set s'"}~~{then}~~@{text "th' \<noteq> th"}\\
   658   \end{tabular}
   659   \end{tabular}
   659   \end{isabelle}
   660   \end{isabelle}
   660   \end{quote}
   661   \end{quote}
   661 
   662 
   662   \noindent
   663   \noindent
   663   Under these assumptions we will prove the following property:
   664   Under these assumptions we will prove the following correctness property:
   664 
   665 
   665   \begin{theorem}\label{mainthm}
   666   \begin{theorem}\label{mainthm}
   666   Given the assumptions about states @{text "s"} and @{text "s' @ s"},
   667   Given the assumptions about states @{text "s"} and @{text "s' @ s"},
   667   the thread @{text th} and the events in @{text "s'"},
   668   the thread @{text th} and the events in @{text "s'"},
   668   if @{term "th' \<in> running (s' @ s)"} and @{text "th' \<noteq> th"} then
   669   if @{term "th' \<in> running (s' @ s)"} and @{text "th' \<noteq> th"} then
   672   \noindent
   673   \noindent
   673   This theorem ensures that the thread @{text th}, which has the highest 
   674   This theorem ensures that the thread @{text th}, which has the highest 
   674   precedence in the state @{text s}, can only be blocked in the state @{text "s' @ s"} 
   675   precedence in the state @{text s}, can only be blocked in the state @{text "s' @ s"} 
   675   by a thread @{text th'} that already existed in @{text s}. As we shall see shortly,
   676   by a thread @{text th'} that already existed in @{text s}. As we shall see shortly,
   676   that means by only finitely many threads. Consequently, indefinite wait of
   677   that means by only finitely many threads. Consequently, indefinite wait of
   677   @{text th}---whcih is Priority Inversion---cannot occur.
   678   @{text th}---which would be Priority Inversion---cannot occur.
   678 
   679 
   679   In what follows we will describe properties of PIP that allow us to prove 
   680   In what follows we will describe properties of PIP that allow us to prove 
   680   Theorem~\ref{mainthm}. It is relatively easily to see that
   681   Theorem~\ref{mainthm}. It is relatively easily to see that
   681 
   682 
   682   \begin{isabelle}\ \ \ \ \ %%%
   683   \begin{isabelle}\ \ \ \ \ %%%
   698   \end{tabular}
   699   \end{tabular}
   699   \end{isabelle}
   700   \end{isabelle}
   700 
   701 
   701   \noindent
   702   \noindent
   702   The first one states that every waiting thread can only wait for a single
   703   The first one states that every waiting thread can only wait for a single
   703   resource (because it gets suspended after requesting that resource), and
   704   resource (because it gets suspended after requesting that resource and having
   704   the second that every resource can only be held by a single thread. The
   705   to wait for it); the second that every resource can only be held by a single thread; 
   705   third property establishes that in every given valid state, there is
   706   the third property establishes that in every given valid state, there is
   706   at most one running thread.
   707   at most one running thread. We can also show the following properties 
       
   708   about the RAG in @{text "s"}.
       
   709 
       
   710   \begin{isabelle}\ \ \ \ \ %%%
       
   711   \begin{tabular}{@ {}l}
       
   712   %@{thm[mode=IfThen] }\\
       
   713   %@{thm[mode=IfThen] }\\
       
   714   %@{thm[mode=IfThen] }
       
   715   \end{tabular}
       
   716   \end{isabelle}
   707 
   717 
   708   TODO
   718   TODO
   709 
   719 
   710   \noindent
   720   \noindent
   711   The following lemmas show how RAG is changed with the execution of events:
   721   The following lemmas show how RAG is changed with the execution of events: