prio/Paper/Paper.thy
changeset 314 ccb6c0601614
parent 313 3d154253d5fe
child 315 f05f6aeb32f4
equal deleted inserted replaced
313:3d154253d5fe 314:ccb6c0601614
   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, can 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   efficient 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 *}
   166 
   166 
   382   \begin{isabelle}\ \ \ \ \ %%%
   382   \begin{isabelle}\ \ \ \ \ %%%
   383   @{text "\<lparr>wq_fun, cprec_fun\<rparr>"}
   383   @{text "\<lparr>wq_fun, cprec_fun\<rparr>"}
   384   \end{isabelle}
   384   \end{isabelle}
   385 
   385 
   386   \noindent
   386   \noindent
   387   The first function is a waiting queue function (that is, it takes a resource @{text "cs"} and returns the
   387   The first function is a waiting queue function (that is, it takes a
   388   corresponding list of threads that wait for it), the second is a function that takes
   388   resource @{text "cs"} and returns the corresponding list of threads
   389   a thread and returns its current precedence (see \eqref{cpreced}). We assume the usual getter and 
   389   that lock, respectively wait for, it); the second is a function that
   390   setter methods for such records.
   390   takes a thread and returns its current precedence (see
       
   391   \eqref{cpreced}). We assume the usual getter and setter methods for
       
   392   such records.
   391 
   393 
   392   In the initial state, the scheduler starts with all resources unlocked (the corresponding 
   394   In the initial state, the scheduler starts with all resources unlocked (the corresponding 
   393   function is defined in \eqref{allunlocked}) and the
   395   function is defined in \eqref{allunlocked}) and the
   394   current precedence of every thread is initialised with @{term "Prc 0 0"}; that means 
   396   current precedence of every thread is initialised with @{term "Prc 0 0"}; that means 
   395   \mbox{@{abbrev initial_cprec}}. Therefore
   397   \mbox{@{abbrev initial_cprec}}. Therefore
   426 
   428 
   427   \noindent 
   429   \noindent 
   428   More interesting are the cases where a resource, say @{text cs}, is locked or released. In these cases
   430   More interesting are the cases where a resource, say @{text cs}, is locked or released. In these cases
   429   we need to calculate a new waiting queue function. For the event @{term "P th cs"}, we have to update
   431   we need to calculate a new waiting queue function. For the event @{term "P th cs"}, we have to update
   430   the function so that the new thread list for @{text cs} is the old thread list plus the thread @{text th} 
   432   the function so that the new thread list for @{text cs} is the old thread list plus the thread @{text th} 
   431   appended to the end of that list (remember the head of this list is seen to be in the possession of this
   433   appended to the end of that list (remember the head of this list is assigned to be in the possession of this
   432   resource). This gives the clause
   434   resource). This gives the clause
   433 
   435 
   434   \begin{isabelle}\ \ \ \ \ %%%
   436   \begin{isabelle}\ \ \ \ \ %%%
   435   \begin{tabular}{@ {}l}
   437   \begin{tabular}{@ {}l}
   436   @{thm (lhs) schs.simps(5)} @{text "\<equiv>"}\\ 
   438   @{thm (lhs) schs.simps(5)} @{text "\<equiv>"}\\ 
   510   In this definition @{term "DUMMY ` DUMMY"} stands for the image of a set under a function.
   512   In this definition @{term "DUMMY ` DUMMY"} stands for the image of a set under a function.
   511   Note that in the initial state, that is where the list of events is empty, the set 
   513   Note that in the initial state, that is where the list of events is empty, the set 
   512   @{term threads} is empty and therefore there is neither a thread ready nor running.
   514   @{term threads} is empty and therefore there is neither a thread ready nor running.
   513   If there is one or more threads ready, then there can only be \emph{one} thread
   515   If there is one or more threads ready, then there can only be \emph{one} thread
   514   running, namely the one whose current precedence is equal to the maximum of all ready 
   516   running, namely the one whose current precedence is equal to the maximum of all ready 
   515   threads. We use the set-comprehension to capture both possibilities.
   517   threads. We use sets to capture both possibilities.
   516   We can now also conveniently define the set of resources that are locked by a thread in a
   518   We can now also conveniently define the set of resources that are locked by a thread in a
   517   given state.
   519   given state.
   518 
   520 
   519   \begin{isabelle}\ \ \ \ \ %%%
   521   \begin{isabelle}\ \ \ \ \ %%%
   520   @{thm holdents_def}
   522   @{thm holdents_def}
   535 
   537 
   536   \noindent
   538   \noindent
   537   The first rule states that a thread can only be created, if it does not yet exists.
   539   The first rule states that a thread can only be created, if it does not yet exists.
   538   Similarly, the second rule states that a thread can only be terminated if it was
   540   Similarly, the second rule states that a thread can only be terminated if it was
   539   running and does not lock any resources anymore (this simplifies slightly our model;
   541   running and does not lock any resources anymore (this simplifies slightly our model;
   540   in practice we would expect the operating system releases all held lock of a
   542   in practice we would expect the operating system releases all locks held by a
   541   thread that is about to exit). The event @{text Set} can happen
   543   thread that is about to exit). The event @{text Set} can happen
   542   if the corresponding thread is running. 
   544   if the corresponding thread is running. 
   543 
   545 
   544   \begin{center}
   546   \begin{center}
   545   @{thm[mode=Rule] thread_set[where thread=th]}
   547   @{thm[mode=Rule] thread_set[where thread=th]}
   547 
   549 
   548   \noindent
   550   \noindent
   549   If a thread wants to lock a resource, then the thread needs to be
   551   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
   552   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
   553   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
   554   the responsibility of the programmer.  In our formal
   553   model we just exclude such problematic cases in order to be able to make
   555   model we brush aside these problematic cases in order to be able to make
   554   some meaningful statements about PIP.\footnote{This situation is
   556   some meaningful statements about PIP.\footnote{This situation is
   555   similar to the infamous occurs check in Prolog: In order to say
   557   similar to the infamous occurs check in Prolog: In order to say
   556   anything meaningful about unification, one needs to perform an occurs
   558   anything meaningful about unification, one needs to perform an occurs
   557   check. But in practice the occurs check is ommited and the
   559   check. But in practice the occurs check is ommited and the
   558   responsibility for avoiding problems rests with the programmer.}
   560   responsibility for avoiding problems rests with the programmer.}
   884 (*<*)
   886 (*<*)
   885 end
   887 end
   886 (*>*)
   888 (*>*)
   887 
   889 
   888 
   890 
   889 section {* Properties for an Implementation\label{implement}*}
   891 section {* Properties for an Implementation\label{implement} *}
   890 
   892 
   891 text {*
   893 text {*
   892   While a formal correctness proof for our model of PIP is certainly
   894   While a formal correctness proof for our model of PIP is certainly
   893   attractive (especially in light of the flawed proof by Sha et
   895   attractive (especially in light of the flawed proof by Sha et
   894   al.~\cite{Sha90}), we found that the formalisation can even help us
   896   al.~\cite{Sha90}), we found that the formalisation can even help us
  1123 *}
  1125 *}
  1124 
  1126 
  1125 section {* Conclusion *}
  1127 section {* Conclusion *}
  1126 
  1128 
  1127 text {* 
  1129 text {* 
  1128   The Priority Inheritance Protocol is a classic textbook algorithm
  1130   The Priority Inheritance Protocol (PIP) is a classic textbook
  1129   used in real-time systems in order to avoid the problem of Priority
  1131   algorithm used in real-time systems in order to avoid the problem of
  1130   Inversion.
  1132   Priority Inversion.  While classic and widely used, PIP does have its faults: for
  1131 
  1133   example it does not prevent deadlocks where threads have circular
  1132   A clear and simple understanding of the problem at hand is both a
  1134   lock dependencies.
  1133   prerequisite and a byproduct of such an effort, because everything
  1135 
  1134   has finally be reduced to the very first principle to be checked
  1136   We had two aims in mind with our formalisation
  1135   mechanically.
  1137   of PIP: One is to understand the relevant literature and to make the
  1136 
  1138   notions in its correctness proof precise so that they can be
  1137   Our formalisation and the one presented
  1139   processed by a theorem prover, because a mechanically checked proof
  1138   in \cite{Wang09} are the only ones that employ Paulson's method for
  1140   avoids the flaws that crept into the informal reasoning by Sha et
  1139   verifying protocols which are \emph{not} security related. 
  1141   al.~\cite{Sha90}. We achieved this aim: The correctness of PIP now
  1140 
  1142   hinges only on the assumptions behind our formal model, which can
  1141   TO DO 
  1143   now be debated and potentially be modified. The reasoning, which is
       
  1144   sometimes quite intricate and tedious, has been checked beyond any
       
  1145   reasonable doubt by Isabelle. We can confirm that Paulson's
       
  1146   inductive approach to protocol verification \cite{Paulson98} is
       
  1147   quite suitable for our formal model and proof. The traditianal
       
  1148   application area of this approach are security protocols.
       
  1149   The only other application of Paulson's approach outside this area we know of 
       
  1150   is \cite{Wang09}.
       
  1151 
       
  1152   The second aim is to provide a specification for PIP so that it can
       
  1153   actually be implemented. Textbooks, like \cite[Section
       
  1154   5.6.5]{Vahalia96}, explain how to use various implementations of PIP
       
  1155   and abstractly discuss its properties, but surprisinly lack many
       
  1156   details for an implementor.  That this is an issue in practice is
       
  1157   illustrated by the email from Baker we cited in the
       
  1158   Introduction. The formalisation gives the first author enough data
       
  1159   to enable his undergraduate students to implement PIP on top of
       
  1160   PINTOS, an small operating system for teaching purposes.  Given the
       
  1161   results in Section~\ref{implement}, we also succeeded with this
       
  1162   aim. A byproduct of our formalisation effort is that nearly all
       
  1163   design choices for the PIP scheduler are backed up with a proved
       
  1164   lemma.
       
  1165 
       
  1166 
       
  1167 
       
  1168  
  1142 
  1169 
  1143   no clue about multi-processor case according to \cite{Steinberg10} 
  1170   no clue about multi-processor case according to \cite{Steinberg10} 
  1144 
  1171 
  1145 *}
       
  1146 
       
  1147 text {*
       
  1148   \bigskip
       
  1149   The priority inversion phenomenon was first published in
       
  1150   \cite{Lampson80}.  The two protocols widely used to eliminate
       
  1151   priority inversion, namely PI (Priority Inheritance) and PCE
       
  1152   (Priority Ceiling Emulation), were proposed in \cite{Sha90}. PCE is
       
  1153   less convenient to use because it requires static analysis of
       
  1154   programs. Therefore, PI is more commonly used in
       
  1155   practice\cite{locke-july02}. However, as pointed out in the
       
  1156   literature, the analysis of priority inheritance protocol is quite
       
  1157   subtle\cite{yodaiken-july02}.  A formal analysis will certainly be
       
  1158   helpful for us to understand and correctly implement PI. All
       
  1159   existing formal analysis of PI
       
  1160   \cite{Jahier09,Wellings07,Faria08} are based on the
       
  1161   model checking technology. Because of the state explosion problem,
       
  1162   model check is much like an exhaustive testing of finite models with
       
  1163   limited size.  The results obtained can not be safely generalized to
       
  1164   models with arbitrarily large size. Worse still, since model
       
  1165   checking is fully automatic, it give little insight on why the
       
  1166   formal model is correct. It is therefore definitely desirable to
       
  1167   analyze PI using theorem proving, which gives more general results
       
  1168   as well as deeper insight. And this is the purpose of this paper
       
  1169   which gives a formal analysis of PI in the interactive theorem
       
  1170   prover Isabelle using Higher Order Logic (HOL). The formalization
       
  1171   focuses on on two issues:
       
  1172 
  1172 
  1173   \begin{enumerate}
  1173   \begin{enumerate}
  1174   \item The correctness of the protocol model itself. A series of desirable properties is 
  1174   \item The correctness of the protocol model itself. A series of desirable properties is 
  1175     derived until we are fully convinced that the formal model of PI does 
  1175     derived until we are fully convinced that the formal model of PI does 
  1176     eliminate priority inversion. And a better understanding of PI is so obtained 
  1176     eliminate priority inversion. And a better understanding of PI is so obtained 
  1180     A point never mentioned in literature. 
  1180     A point never mentioned in literature. 
  1181   \item The correctness of the implementation. A series of properties is derived the meaning 
  1181   \item The correctness of the implementation. A series of properties is derived the meaning 
  1182     of which can be used as guidelines on how PI can be implemented efficiently and correctly. 
  1182     of which can be used as guidelines on how PI can be implemented efficiently and correctly. 
  1183   \end{enumerate} 
  1183   \end{enumerate} 
  1184 
  1184 
  1185   The rest of the paper is organized as follows: Section \ref{overview} gives an overview 
  1185  
  1186   of PI. Section \ref{model} introduces the formal model of PI. Section \ref{general} 
  1186    Contributions
  1187   discusses a series of basic properties of PI. Section \ref{extension} shows formally 
       
  1188   how priority inversion is controlled by PI. Section \ref{implement} gives properties 
       
  1189   which can be used for guidelines of implementation. Section \ref{related} discusses 
       
  1190   related works. Section \ref{conclusion} concludes the whole paper.
       
  1191 
       
  1192   The basic priority inheritance protocol has two problems:
       
  1193 
       
  1194   It does not prevent a deadlock from happening in a program with circular lock dependencies.
       
  1195   
       
  1196   A chain of blocking may be formed; blocking duration can be substantial, though bounded.
       
  1197 
       
  1198 
       
  1199   Contributions
       
  1200 
  1187 
  1201   Despite the wide use of Priority Inheritance Protocol in real time operating
  1188   Despite the wide use of Priority Inheritance Protocol in real time operating
  1202   system, it's correctness has never been formally proved and mechanically checked. 
  1189   system, it's correctness has never been formally proved and mechanically checked. 
  1203   All existing verification are based on model checking technology. Full automatic
  1190   All existing verification are based on model checking technology. Full automatic
  1204   verification gives little help to understand why the protocol is correct. 
  1191   verification gives little help to understand why the protocol is correct.