Journal/Paper.thy
changeset 22 9f0b78fcc894
parent 20 b56616fd88dd
child 23 24e6884d9258
equal deleted inserted replaced
21:55d1591b17f0 22:9f0b78fcc894
    52   thread with priority $M$, and so $H$ sits there potentially waiting
    52   thread with priority $M$, and so $H$ sits there potentially waiting
    53   indefinitely. Since $H$ is blocked by threads with lower
    53   indefinitely. Since $H$ is blocked by threads with lower
    54   priorities, the problem is called Priority Inversion. It was first
    54   priorities, the problem is called Priority Inversion. It was first
    55   described in \cite{Lampson80} in the context of the
    55   described in \cite{Lampson80} in the context of the
    56   Mesa programming language designed for concurrent programming.
    56   Mesa programming language designed for concurrent programming.
    57 
    57  
    58   If the problem of Priority Inversion is ignored, real-time systems
    58   If the problem of Priority Inversion is ignored, real-time systems
    59   can become unpredictable and resulting bugs can be hard to diagnose.
    59   can become unpredictable and resulting bugs can be hard to diagnose.
    60   The classic example where this happened is the software that
    60   The classic example where this happened is the software that
    61   controlled the Mars Pathfinder mission in 1997 \cite{Reeves98}.
    61   controlled the Mars Pathfinder mission in 1997 \cite{Reeves98}.
    62   Once the spacecraft landed, the software shut down at irregular
    62   Once the spacecraft landed, the software shut down at irregular
    79   wait indefinitely, because $L$ cannot be blocked by threads having
    79   wait indefinitely, because $L$ cannot be blocked by threads having
    80   priority $M$. While a few other solutions exist for the Priority
    80   priority $M$. While a few other solutions exist for the Priority
    81   Inversion problem, PIP is one that is widely deployed and
    81   Inversion problem, PIP is one that is widely deployed and
    82   implemented. This includes VxWorks (a proprietary real-time OS used
    82   implemented. This includes VxWorks (a proprietary real-time OS used
    83   in the Mars Pathfinder mission, in Boeing's 787 Dreamliner, Honda's
    83   in the Mars Pathfinder mission, in Boeing's 787 Dreamliner, Honda's
    84   ASIMO robot, etc.), but also the POSIX 1003.1c Standard realised for
    84   ASIMO robot, etc.) and ThreadX (another proprietary real-time OS
       
    85   used in HP inkjet printers \cite{ThreadX}), but also
       
    86   the POSIX 1003.1c Standard realised for
    85   example in libraries for FreeBSD, Solaris and Linux. 
    87   example in libraries for FreeBSD, Solaris and Linux. 
    86 
    88 
    87   Two advantages of PIP are that increasing the priority of a thread
    89   Two advantages of PIP are that it is deterministic and that increasing the priority of a thread
    88   can be performed dynamically by the scheduler and is deterministic.
    90   can be performed dynamically by the scheduler.
    89   This is in contrast to \emph{Priority Ceiling}
    91   This is in contrast to \emph{Priority Ceiling}
    90   \cite{Sha90}, another solution to the Priority Inversion problem,
    92   \cite{Sha90}, another solution to the Priority Inversion problem,
    91   which requires static analysis of the program in order to prevent
    93   which requires static analysis of the program in order to prevent
    92   Priority Inversion, and also to the Windows NT scheduler, which avoids
    94   Priority Inversion, and also in contrast to the Windows NT scheduler, which avoids
    93   this problem by randomly boosting the priority of ready (low priority) threads
    95   this problem by randomly boosting the priority of ready low-priority threads
    94   (e.g.~\cite{WINDOWSNT}).
    96   (see for instance~\cite{WINDOWSNT}).
    95   However, there has also been strong criticism against
    97   However, there has also been strong criticism against
    96   PIP. For instance, PIP cannot prevent deadlocks when lock
    98   PIP. For instance, PIP cannot prevent deadlocks when lock
    97   dependencies are circular, and also blocking times can be
    99   dependencies are circular, and also blocking times can be
    98   substantial (more than just the duration of a critical section).
   100   substantial (more than just the duration of a critical section).
    99   Though, most criticism against PIP centres around unreliable
   101   Though, most criticism against PIP centres around unreliable
   145   locks \emph{two} resources, and two high-priority threads $H$ and
   147   locks \emph{two} resources, and two high-priority threads $H$ and
   146   $H'$ each wait for one of them.  If $L$ releases one resource
   148   $H'$ each wait for one of them.  If $L$ releases one resource
   147   so that $H$, say, can proceed, then we still have Priority Inversion
   149   so that $H$, say, can proceed, then we still have Priority Inversion
   148   with $H'$ (which waits for the other resource). The correct
   150   with $H'$ (which waits for the other resource). The correct
   149   behaviour for $L$ is to switch to the highest remaining priority of
   151   behaviour for $L$ is to switch to the highest remaining priority of
   150   the threads that it blocks. The advantage of formalising the
   152   the threads that it blocks. While 
       
   153   \cite{Sha90} is the only formal publication we have 
       
   154   found that describes the incorrect behaviour, not all, but many
       
   155   informal\footnote{informal as in ``found on the Web''} 
       
   156   descriptions of PIP overlook the possibility that another
       
   157   high-priority might wait for a low-priority process to finish.
       
   158   The advantage of formalising the
   151   correctness of a high-level specification of PIP in a theorem prover
   159   correctness of a high-level specification of PIP in a theorem prover
   152   is that such issues clearly show up and cannot be overlooked as in
   160   is that such issues clearly show up and cannot be overlooked as in
   153   informal reasoning (since we have to analyse all possible behaviours
   161   informal reasoning (since we have to analyse all possible behaviours
   154   of threads, i.e.~\emph{traces}, that could possibly happen).\footnote{While 
   162   of threads, i.e.~\emph{traces}, that could possibly happen).\medskip\smallskip
   155   \cite{Sha90} is the only formal publication we have 
       
   156   found that describes the incorrect behaviour, not all, but many
       
   157   informal descriptions of PIP overlook the case...}\medskip
       
   158 
   163 
   159   \noindent
   164   \noindent
   160   {\bf Contributions:} There have been earlier formal investigations
   165   {\bf Contributions:} There have been earlier formal investigations
   161   into PIP \cite{Faria08,Jahier09,Wellings07}, but they employ model
   166   into PIP \cite{Faria08,Jahier09,Wellings07}, but they employ model
   162   checking techniques. This paper presents a formalised and
   167   checking techniques. This paper presents a formalised and
   324 
   329 
   325   \begin{isabelle}\ \ \ \ \ %%%
   330   \begin{isabelle}\ \ \ \ \ %%%
   326   @{thm cs_depend_def}
   331   @{thm cs_depend_def}
   327   \end{isabelle}
   332   \end{isabelle}
   328 
   333 
   329   \noindent
   334 
   330   If there is no cycle, then every RAG can be pictured as a forrest of trees, for example as follows:
   335   \begin{figure}[t]
   331 
       
   332   \begin{figure}[ph]
       
   333   \begin{center}
   336   \begin{center}
   334   \newcommand{\fnt}{\fontsize{7}{8}\selectfont}
   337   \newcommand{\fnt}{\fontsize{7}{8}\selectfont}
   335   \begin{tikzpicture}[scale=1]
   338   \begin{tikzpicture}[scale=1]
   336   %%\draw[step=2mm] (-3,2) grid (1,-1);
   339   %%\draw[step=2mm] (-3,2) grid (1,-1);
   337 
   340 
   366   \end{center}
   369   \end{center}
   367   \caption{An instance of a Resource Allocation Graph (RAG).\label{RAGgraph}}
   370   \caption{An instance of a Resource Allocation Graph (RAG).\label{RAGgraph}}
   368   \end{figure}
   371   \end{figure}
   369 
   372 
   370   \noindent
   373   \noindent
       
   374   If there is no cycle, then every RAG can be pictured as a forrest of trees, as
       
   375   for example in Figure~\ref{RAGgraph}.
       
   376 
   371   We will design our scheduler  
   377   We will design our scheduler  
   372   so that every thread can be in the possession of several resources, that is 
   378   so that every thread can be in the possession of several resources, that is 
   373   it has potentially several incoming holding edges in the RAG, but has at most one outgoing  
   379   it has potentially several incoming holding edges in the RAG, but has at most one outgoing  
   374   waiting edge. The reason is that when a thread asks for resource that is locked
   380   waiting edge. The reason is that when a thread asks for resource that is locked
   375   already, then the process is blocked and cannot ask for another resource.
   381   already, then the process is blocked and cannot ask for another resource.
  1006 section {* Properties for an Implementation\label{implement} *}
  1012 section {* Properties for an Implementation\label{implement} *}
  1007 
  1013 
  1008 text {*
  1014 text {*
  1009   While our formalised proof gives us confidence about the correctness of our model of PIP, 
  1015   While our formalised proof gives us confidence about the correctness of our model of PIP, 
  1010   we found that the formalisation can even help us with efficiently implementing it.
  1016   we found that the formalisation can even help us with efficiently implementing it.
  1011 
       
  1012   For example Baker complained that calculating the current precedence
  1017   For example Baker complained that calculating the current precedence
  1013   in PIP is quite ``heavy weight'' in Linux (see the Introduction).
  1018   in PIP is quite ``heavy weight'' in Linux (see the Introduction).
  1014   In our model of PIP the current precedence of a thread in a state @{text s}
  1019   In our model of PIP the current precedence of a thread in a state @{text s}
  1015   depends on all its dependants---a ``global'' transitive notion,
  1020   depends on all its dependants---a ``global'' transitive notion,
  1016   which is indeed heavy weight (see Def.~shown in \eqref{cpreced}).
  1021   which is indeed heavy weight (see Def.~shown in \eqref{cpreced}).
  1248 
  1253 
  1249   \noindent
  1254   \noindent
  1250   This lemma states that if an intermediate @{term cp}-value does not change, then
  1255   This lemma states that if an intermediate @{term cp}-value does not change, then
  1251   the procedure can also stop, because none of its dependent threads will
  1256   the procedure can also stop, because none of its dependent threads will
  1252   have their current precedence changed.
  1257   have their current precedence changed.
  1253   *}
  1258   *}(*<*)end(*>*)text {*
  1254 (*<*)
       
  1255 end
       
  1256 (*>*)
       
  1257 text {*
       
  1258   \noindent
       
  1259   As can be seen, a pleasing byproduct of our formalisation is that the properties in
  1259   As can be seen, a pleasing byproduct of our formalisation is that the properties in
  1260   this section closely inform an implementation of PIP, namely whether the
  1260   this section closely inform an implementation of PIP, namely whether the
  1261   RAG needs to be reconfigured or current precedences need to
  1261   RAG needs to be reconfigured or current precedences need to
  1262   be recalculated for an event. This information is provided by the lemmas we proved.
  1262   be recalculated for an event. This information is provided by the lemmas we proved.
  1263   We confirmed that our observations translate into practice by implementing
  1263   We confirmed that our observations translate into practice by implementing
  1286   an unlocked resource is given next to the waiting thread with the
  1286   an unlocked resource is given next to the waiting thread with the
  1287   highest precedence is realised in our implementation by priority queues. We implemented
  1287   highest precedence is realised in our implementation by priority queues. We implemented
  1288   them as \emph{Braun trees} \cite{Paulson96}, which provide efficient @{text "O(log n)"}-operations
  1288   them as \emph{Braun trees} \cite{Paulson96}, which provide efficient @{text "O(log n)"}-operations
  1289   for accessing and updating. In the code we shall describe below, we use the function
  1289   for accessing and updating. In the code we shall describe below, we use the function
  1290   @{ML_text "queue_insert"}, for inserting a new element into a priority queue, and 
  1290   @{ML_text "queue_insert"}, for inserting a new element into a priority queue, and 
  1291   @{ML_text "queue_update"}, for updating the position of an element that is already
  1291   the function @{ML_text "queue_update"}, for updating the position of an element that is already
  1292   in a queue. Both functions take an extra argument that specifies the
  1292   in a queue. Both functions take an extra argument that specifies the
  1293   comparison function used for organising the priority queue.
  1293   comparison function used for organising the priority queue.
  1294   
  1294   
  1295   Apart from having to implement relatively complex data\-structures in C
  1295   Apart from having to implement relatively complex data\-structures in C
  1296   using pointers, our experience with the implementation has been very positive: our specification 
  1296   using pointers, our experience with the implementation has been very positive: our specification 
  1312   If not, then the assertions indicate a bug in PINTOS and the result will be
  1312   If not, then the assertions indicate a bug in PINTOS and the result will be
  1313   a ``kernel panic''. 
  1313   a ``kernel panic''. 
  1314 
  1314 
  1315 
  1315 
  1316 
  1316 
  1317   \begin{figure}[t]
  1317   \begin{figure}[tph]
  1318   \begin{lstlisting}
  1318   \begin{lstlisting}
  1319 void lock_acquire (struct lock *lock)
  1319 void lock_acquire (struct lock *lock)
  1320 { ASSERT (lock != NULL);
  1320 { ASSERT (lock != NULL);
  1321   ASSERT (!intr_context());
  1321   ASSERT (!intr_context());
  1322   ASSERT (!lock_held_by_current_thread (lock));
  1322   ASSERT (!lock_held_by_current_thread (lock));
  1457   verification of this algorithm, involving more fine-grained events,
  1457   verification of this algorithm, involving more fine-grained events,
  1458   is a magnitude harder than the one we presented here, but still
  1458   is a magnitude harder than the one we presented here, but still
  1459   within reach of current theorem proving technology. We leave this
  1459   within reach of current theorem proving technology. We leave this
  1460   for future work.
  1460   for future work.
  1461 
  1461 
       
  1462   To us, it seems sound reasoning about scheduling algorithms is fiendishly difficult
       
  1463   if done informally by ``pencil-and-paper''. This is proved by the flawed proof
       
  1464   in the paper by Sha et al.~\cite{Sha90} and also by Regehr \cite{Regehr} who 
       
  1465   pointed out an error in a paper about Preemption 
       
  1466   Threshold Scheduling \cite{ThreadX}. The use of a theorem prover was
       
  1467   invaluable to us in order to feel confident about the correctness of our results.  
  1462   The most closely related work to ours is the formal verification in
  1468   The most closely related work to ours is the formal verification in
  1463   PVS of the Priority Ceiling Protocol done by Dutertre
  1469   PVS of the Priority Ceiling Protocol done by Dutertre
  1464   \cite{dutertre99b}---another solution to the Priority Inversion
  1470   \cite{dutertre99b}---another solution to the Priority Inversion
  1465   problem, which however needs static analysis of programs in order to
  1471   problem, which however needs static analysis of programs in order to
  1466   avoid it. There have been earlier formal investigations
  1472   avoid it. There have been earlier formal investigations
  1476   consists of around 210 lemmas and overall 6950 lines of readable Isabelle/Isar
  1482   consists of around 210 lemmas and overall 6950 lines of readable Isabelle/Isar
  1477   code with a few apply-scripts interspersed. The formal model of PIP
  1483   code with a few apply-scripts interspersed. The formal model of PIP
  1478   is 385 lines long; the formal correctness proof 3800 lines. Some auxiliary
  1484   is 385 lines long; the formal correctness proof 3800 lines. Some auxiliary
  1479   definitions and proofs span over 770 lines of code. The properties relevant
  1485   definitions and proofs span over 770 lines of code. The properties relevant
  1480   for an implementation require 2000 lines. 
  1486   for an implementation require 2000 lines. 
  1481   %The code of our formalisation 
  1487   The code of our formalisation 
  1482   %can be downloaded from
  1488   can be downloaded from the Mercurial repository at
  1483   %\url{http://www.inf.kcl.ac.uk/staff/urbanc/pip.html}.
  1489   \url{http://www.inf.kcl.ac.uk/staff/urbanc/pip.html}.
  1484 
  1490 
  1485   %\medskip
  1491   %\medskip
  1486 
  1492 
  1487   %\noindent
  1493   %\noindent
  1488   %{\bf Acknowledgements:}
  1494   %{\bf Acknowledgements:}