Journal/Paper.thy
changeset 200 ff826e28d85c
parent 199 4a75769a93b5
child 201 fcc6f4c3c32f
equal deleted inserted replaced
199:4a75769a93b5 200:ff826e28d85c
    77   \emph{Priority Inversion}. Suppose three threads having priorities
    77   \emph{Priority Inversion}. Suppose three threads having priorities
    78   $H$(igh), $M$(edium) and $L$(ow). We would expect that the thread
    78   $H$(igh), $M$(edium) and $L$(ow). We would expect that the thread
    79   $H$ blocks any other thread with lower priority and the thread
    79   $H$ blocks any other thread with lower priority and the thread
    80   itself cannot be blocked indefinitely by threads with lower
    80   itself cannot be blocked indefinitely by threads with lower
    81   priority. Alas, in a naive implementation of resource locking and
    81   priority. Alas, in a naive implementation of resource locking and
    82   priorities this property can be violated. For this let $L$ be in the
    82   priorities, this property can be violated. For this let $L$ be in the
    83   possession of a lock for a resource that $H$ also needs. $H$ must
    83   possession of a lock for a resource that $H$ also needs. $H$ must
    84   therefore wait for $L$ to exit the critical section and release this
    84   therefore wait for $L$ to exit the critical section and release this
    85   lock. The problem is that $L$ might in turn be blocked by any thread
    85   lock. The problem is that $L$ might in turn be blocked by any thread
    86   with priority $M$, and so $H$ sits there potentially waiting
    86   with priority $M$, and so $H$ sits there potentially waiting
    87   indefinitely (consider the case where threads with propority $M$
    87   indefinitely (consider the case where threads with propority $M$
   216   textbook \cite{Silberschatz13} gives the wrong specification. On Page 254 the authors write: ``{\it Upon releasing the
   216   textbook \cite{Silberschatz13} gives the wrong specification. On Page 254 the authors write: ``{\it Upon releasing the
   217   lock, the [low-priority] thread will revert to its original
   217   lock, the [low-priority] thread will revert to its original
   218   priority.}'' The same error is also repeated later in this popular textbook.
   218   priority.}'' The same error is also repeated later in this popular textbook.
   219 
   219 
   220   
   220   
   221   While \cite{Laplante11,LiYao03,Liu00,book,Sha90,Silberschatz13} are the only
   221   While \cite{Laplante11,LiYao03,Liu00,book,Sha90,Silberschatz13} are
   222   formal publications we have found that specify the incorrect
   222   the only formal publications we have found that specify the
   223   behaviour, it seems also many informal descriptions of PIP overlook
   223   incorrect behaviour, it seems also many informal descriptions of the
   224   the possibility that another high-priority might wait for a
   224   PIP protocol overlook the possibility that another high-priority
   225   low-priority process to finish.  A notable exception is the texbook
   225   process might wait for a low-priority process to finish.  A notable
   226   \cite{buttazzo}, which gives the correct behaviour of resetting the
   226   exception is the texbook \cite{buttazzo}, which gives the correct
   227   priority of a thread to the highest remaining priority of the
   227   behaviour of resetting the priority of a thread to the highest
   228   threads it blocks. This textbook also gives an informal proof for
   228   remaining priority of the threads it blocks. This textbook also
   229   the correctness of PIP in the style of Sha et al. Unfortunately,
   229   gives an informal proof for the correctness of PIP in the style of
   230   this informal proof is too vague to be useful for formalising the
   230   Sha et al. Unfortunately, this informal proof is too vague to be
   231   correctness of PIP and the specification leaves out nearly all
   231   useful for formalising the correctness of PIP and the specification
   232   details in order to implement PIP efficiently.\medskip\smallskip
   232   leaves out nearly all details in order to implement PIP
   233   %
   233   efficiently.\medskip\smallskip % %The advantage of formalising the
   234   %The advantage of formalising the
   234   %correctness of a high-level specification of PIP in a theorem
   235   %correctness of a high-level specification of PIP in a theorem prover
   235   prover %is that such issues clearly show up and cannot be overlooked
   236   %is that such issues clearly show up and cannot be overlooked as in
   236   as in %informal reasoning (since we have to analyse all possible
   237   %informal reasoning (since we have to analyse all possible behaviours
   237   behaviours %of threads, i.e.~\emph{traces}, that could possibly
   238   %of threads, i.e.~\emph{traces}, that could possibly happen).
   238   happen).
   239 
   239 
   240   \noindent {\bf Contributions:} There have been earlier formal
   240   \noindent {\bf Contributions:} There have been earlier formal
   241   investigations into PIP \cite{Faria08,Jahier09,Wellings07}, but they
   241   investigations into PIP \cite{Faria08,Jahier09,Wellings07}, but they
   242   employ model checking techniques. This paper presents a formalised
   242   employ model checking techniques. This paper presents a formalised
   243   and mechanically checked proof for the correctness of PIP. For this
   243   and mechanically checked proof for the correctness of PIP. For this
   450   we do in case two threads have the same priority), but according to precedences. 
   450   we do in case two threads have the same priority), but according to precedences. 
   451   Precedences allow us to always discriminate between two threads with equal priority by 
   451   Precedences allow us to always discriminate between two threads with equal priority by 
   452   taking into account the time when the priority was last set. We order precedences so 
   452   taking into account the time when the priority was last set. We order precedences so 
   453   that threads with the same priority get a higher precedence if their priority has been 
   453   that threads with the same priority get a higher precedence if their priority has been 
   454   set earlier, since for such threads it is more urgent to finish their work. In an implementation
   454   set earlier, since for such threads it is more urgent to finish their work. In an implementation
   455   this choice would translate to a quite natural FIFO-scheduling of threads with 
   455   this choice would translate to a quite straightforward FIFO-scheduling of threads with 
   456   the same priority. 
   456   the same priority. 
   457   
   457   
   458   Moylan et al.~\cite{deinheritance} considered the alternative of 
   458   Moylan et al.~\cite{deinheritance} considered the alternative of 
   459   ``time-slicing'' threads with equal priority, but found that it does not lead to 
   459   ``time-slicing'' threads with equal priority, but found that it does not lead to 
   460   advantages in practice. On the contrary, according to their work having a policy 
   460   advantages in practice. On the contrary, according to their work having a policy 
   565   \noindent
   565   \noindent
   566   If there is no cycle, then every @{text RAG} can be pictured as a forest of trees, as
   566   If there is no cycle, then every @{text RAG} can be pictured as a forest of trees, as
   567   for example in Figure~\ref{RAGgraph}.
   567   for example in Figure~\ref{RAGgraph}.
   568 
   568 
   569   Because of the @{text RAG}s, we will need to formalise some results
   569   Because of the @{text RAG}s, we will need to formalise some results
   570   about graphs.  While there are few formalisations for graphs already
   570   about graphs.  While there are a few formalisations for graphs already
   571   implemented in Isabelle, we choose to introduce our own library of
   571   implemented in Isabelle, we choose to introduce our own library of
   572   graphs for PIP. The justification for this is that we wanted to have
   572   graphs for PIP. The justification for this is that we wanted to have
   573   a more general theory of graphs which is capable of representing
   573   a more general theory of graphs which is capable of representing
   574   potentially infinite graphs (in the sense of infinitely branching
   574   potentially infinite graphs (in the sense of infinitely branching
   575   and infinite size): the property that our @{text RAG}s are actually
   575   and infinite size): the property that our @{text RAG}s are actually
   576   forests of finitely branching trees having only an finite depth
   576   forests of finitely branching trees having only a finite depth
   577   should be something we can \emph{prove} for our model of PIP---it
   577   should be something we can \emph{prove} for our model of PIP---it
   578   should not be an assumption we build already into our model. It
   578   should not be an assumption we build already into our model. It
   579   seemed for our purposes the most convenient represeantation of
   579   seems for our purposes the most convenient representation of
   580   graphs are binary relations given by sets of pairs shown in
   580   graphs are binary relations given by sets of pairs shown in
   581   \eqref{pairs}. The pairs stand for the edges in graphs. This
   581   \eqref{pairs}. The pairs stand for the edges in graphs. This
   582   relation-based representation has the advantage that the notions
   582   relation-based representation has the advantage that the notions
   583   @{text "waiting"} and @{text "holiding"} are already defined in
   583   @{text "waiting"} and @{text "holding"} are already defined in
   584   terms of relations amongst theads and resources. Also, we can easily
   584   terms of relations amongst threads and resources. Also, we can easily
   585   re-use the standard notions for transitive closure operations @{term
   585   re-use the standard notions for transitive closure operations @{term
   586   "trancl DUMMY"} and @{term "rtrancl DUMMY"}, as well as relation
   586   "trancl DUMMY"} and @{term "rtrancl DUMMY"}, as well as relation
   587   composition for our graphs.  A \emph{forest} is defined in our
   587   composition for our graphs.  A \emph{forest} is defined in our
   588   representation as the relation @{text rel} that is \emph{single
   588   representation as the relation @{text rel} that is \emph{single
   589   valued} and \emph{acyclic}:
   589   valued} and \emph{acyclic}:
   630   %\endnote{{\bf Lemma about overlapping paths}}
   630   %\endnote{{\bf Lemma about overlapping paths}}
   631   
   631   
   632   The locking mechanism of PIP ensures that for each thread node,
   632   The locking mechanism of PIP ensures that for each thread node,
   633   there can be many incoming holding edges in the @{text RAG}, but at most one
   633   there can be many incoming holding edges in the @{text RAG}, but at most one
   634   out going waiting edge.  The reason is that when a thread asks for
   634   out going waiting edge.  The reason is that when a thread asks for
   635   resource that is locked already, then the thread is blocked and
   635   a resource that is locked already, then the thread is blocked and
   636   cannot ask for another resource.  Clearly, also every resource can
   636   cannot ask for another resource.  Clearly, also every resource can
   637   only have at most one outgoing holding edge---indicating that the
   637   only have at most one outgoing holding edge---indicating that the
   638   resource is locked. So if the @{text "RAG"} is well-founded and
   638   resource is locked. So if the @{text "RAG"} is well-founded and
   639   finite, we can always start at a thread waiting for a resource and
   639   finite, we can always start at a thread waiting for a resource and
   640   ``chase'' outgoing arrows leading to a single root of a tree,
   640   ``chase'' outgoing arrows leading to a single root of a tree,
   682   @{text th} itself). Since the notion of current precedence is defined as the 
   682   @{text th} itself). Since the notion of current precedence is defined as the 
   683   transitive closure of the dependent
   683   transitive closure of the dependent
   684   threads in the @{text TDG}, we deal correctly with the problem in the informal
   684   threads in the @{text TDG}, we deal correctly with the problem in the informal
   685   algorithm by Sha et al.~\cite{Sha90} where a priority of a thread is
   685   algorithm by Sha et al.~\cite{Sha90} where a priority of a thread is
   686   lowered prematurely (see Introduction). We again introduce an abbreviation for current
   686   lowered prematurely (see Introduction). We again introduce an abbreviation for current
   687   precedeces of a set of threads, written @{text "cprecs wq s ths"}.
   687   precedences of a set of threads, written @{text "cprecs wq s ths"}.
   688   
   688   
   689   \begin{isabelle}\ \ \ \ \ %%%
   689   \begin{isabelle}\ \ \ \ \ %%%
   690   @{thm cpreceds_def}
   690   @{thm cpreceds_def}
   691   \end{isabelle}
   691   \end{isabelle}
   692 
   692 
   700   \end{isabelle}
   700   \end{isabelle}
   701 
   701 
   702   \noindent
   702   \noindent
   703   The first function is a waiting queue function (that is, it takes a
   703   The first function is a waiting queue function (that is, it takes a
   704   resource @{text "cs"} and returns the corresponding list of threads
   704   resource @{text "cs"} and returns the corresponding list of threads
   705   that lock, respectively wait for, it); the second is a function that
   705   that lock or wait for it); the second is a function that
   706   takes a thread and returns its current precedence (see
   706   takes a thread and returns its current precedence (see
   707   the definition in \eqref{cpreced}). We assume the usual getter and setter methods for
   707   the definition in \eqref{cpreced}). We assume the usual getter and setter methods for
   708   such records.
   708   such records.
   709 
   709 
   710   In the initial state, the scheduler starts with all resources unlocked (the corresponding 
   710   In the initial state, the scheduler starts with all resources unlocked (the corresponding 
   820   about @{text TDG}s and @{term cprec}, which are more convenient to use in 
   820   about @{text TDG}s and @{term cprec}, which are more convenient to use in 
   821   subsequent proofs. 
   821   subsequent proofs. 
   822 
   822 
   823   \begin{isabelle}\ \ \ \ \ %%%
   823   \begin{isabelle}\ \ \ \ \ %%%
   824   \begin{tabular}{@ {}rcl}
   824   \begin{tabular}{@ {}rcl}
   825   @{thm (lhs) tG_alt_def}  & @{text "\<equiv>"} & @{thm (rhs) tG_alt_def}\\
   825   @{thm (lhs) tG_alt_def}  & @{text "="} & @{thm (rhs) tG_alt_def}\\
   826   @{thm (lhs) cp_s_def}  & @{text "\<equiv>"} & @{thm (rhs) cp_s_def}\\
   826   @{thm (lhs) cp_s_def}  & @{text "="} & @{thm (rhs) cp_s_def}\\
   827   \end{tabular}\\
   827   \end{tabular}\\
   828   \mbox{}\hfill\numbered{overloaded}
   828   \mbox{}\hfill\numbered{overloaded}
   829   \end{isabelle}
   829   \end{isabelle}
   830 
   830 
   831   \noindent Next we can introduce 
   831   \noindent Next we can introduce 
   894   \noindent This is because the @{text Set} event is for a thread to change
   894   \noindent This is because the @{text Set} event is for a thread to change
   895   its \emph{own} priority---therefore it must be running.
   895   its \emph{own} priority---therefore it must be running.
   896 
   896 
   897   If a thread wants to lock a resource, then the thread
   897   If a thread wants to lock a resource, then the thread
   898   needs to be running and also we have to make sure that the resource
   898   needs to be running and also we have to make sure that the resource
   899   lock does not lead to a cycle in the RAG (the prurpose of the second
   899   lock does not lead to a cycle in the RAG (the purpose of the second
   900   premise in the rule below). In practice, ensuring the latter is the
   900   premise in the rule below). In practice, ensuring the latter is the
   901   responsibility of the programmer.  In our formal model we brush
   901   responsibility of the programmer.  In our formal model we brush
   902   aside these problematic cases in order to be able to make some
   902   aside these problematic cases in order to be able to make some
   903   meaningful statements about PIP.\footnote{This situation is similar
   903   meaningful statements about PIP.\footnote{This situation is similar
   904   to the infamous \emph{occurs check} in Prolog: In order to say
   904   to the infamous \emph{occurs check} in Prolog: In order to say
  1639   What we will establish in this section is that there can only be a
  1639   What we will establish in this section is that there can only be a
  1640   finite number of states after state @{term s} in which the thread
  1640   finite number of states after state @{term s} in which the thread
  1641   @{term th} is blocked (recall for this that a state is a list of
  1641   @{term th} is blocked (recall for this that a state is a list of
  1642   events).  For this finiteness bound to exist, Sha et al.~informally
  1642   events).  For this finiteness bound to exist, Sha et al.~informally
  1643   make two assumptions: first, there is a finite pool of threads
  1643   make two assumptions: first, there is a finite pool of threads
  1644   (active or hibernating) and second, each of them giving up its
  1644   (active or hibernating) and second, each of these threads will give up its
  1645   resources after a finite amount of time.  However, we do not have
  1645   resources after a finite amount of time.  However, we do not have
  1646   this concept of active or hibernating threads in our model.  In fact
  1646   this concept of active or hibernating threads in our model.  In fact
  1647   we can dispense with the first assumption altogether and allow that
  1647   we can dispense with the first assumption altogether and allow that
  1648   in our model we can create new threads or exit existing threads
  1648   in our model we can create new threads or exit existing threads
  1649   arbitrarily. Consequently, the avoidance of indefinite priority
  1649   arbitrarily. Consequently, the avoidance of indefinite priority
  1650   inversion we are trying to establish is in our model not true,
  1650   inversion we are trying to establish is in our model not true,
  1651   unless we stipulate an upper bound on the number of threads that
  1651   unless we stipulate an upper bound on the number of threads that
  1652   have been created during the time leading to any future state
  1652   have been created during the time leading to any future state after
  1653   after @{term s}. Otherwise our PIP scheduler could be ``swamped''
  1653   @{term s}. Otherwise our PIP scheduler could be ``swamped'' with
  1654   with @{text "Create"}-requests from of lower priority threads.  
  1654   @{text "Create"}-requests of lower priority threads.  So our first
  1655 So our first assumption states:
  1655   assumption states:
  1656 
  1656 
  1657   \begin{quote} {\bf Assumption on the number of threads created 
  1657   \begin{quote} {\bf Assumption on the number of threads created 
  1658   after the state {\boldmath@{text s}}:} Given the
  1658   after the state {\boldmath@{text s}}:} Given the
  1659   state @{text s}, in every ``future'' valid state @{text "es @ s"}, we
  1659   state @{text s}, in every ``future'' valid state @{text "es @ s"}, we
  1660   require that the number of created threads is less than
  1660   require that the number of created threads is less than
  1680 
  1680 
  1681   \begin{isabelle}\ \ \ \ \ %%%
  1681   \begin{isabelle}\ \ \ \ \ %%%
  1682   @{thm blockers_def[THEN eq_reflection]}
  1682   @{thm blockers_def[THEN eq_reflection]}
  1683   \end{isabelle}
  1683   \end{isabelle}
  1684 
  1684 
  1685   \noindent This set contains all treads that are not detached in
  1685   \noindent This set contains all threads that are not detached in
  1686   state @{text s}. According to our definiton of @{text "detached"},
  1686   state @{text s}. According to our definiton of @{text "detached"},
  1687   this means a thread in @{text "blockers"} either holds or waits for
  1687   this means a thread in @{text "blockers"} either holds or waits for
  1688   some resource in state @{text s} . Our Them~1 implies that any of
  1688   some resource in state @{text s} . Our Thm.~1 implies that any of
  1689   those threads can all potentially block @{text th} after state
  1689   those threads can all potentially block @{text th} after state
  1690   @{text s}. We need to make the following assumption about the
  1690   @{text s}. We need to make the following assumption about the
  1691   threads in the @{text "blockers"}-set:
  1691   threads in the @{text "blockers"}-set:
  1692 
  1692 
  1693   \begin{quote}
  1693   \begin{quote}
  1847   While our formalised proof gives us confidence about the correctness of our model of PIP, 
  1847   While our formalised proof gives us confidence about the correctness of our model of PIP, 
  1848   we found that the formalisation can even help us with efficiently implementing it.
  1848   we found that the formalisation can even help us with efficiently implementing it.
  1849   For example Baker complained that calculating the current precedence
  1849   For example Baker complained that calculating the current precedence
  1850   in PIP is quite ``heavy weight'' in Linux (see the Introduction).
  1850   in PIP is quite ``heavy weight'' in Linux (see the Introduction).
  1851   In our model of PIP the current precedence of a thread in a state @{text s}
  1851   In our model of PIP the current precedence of a thread in a state @{text s}
  1852   depends on the precedenes of all threads in its subtree---a ``global'' transitive notion,
  1852   depends on the precedences of all threads in its subtree---a ``global'' transitive notion,
  1853   which is indeed heavy weight (see the equation for @{text cprec} shown in \eqref{overloaded}).
  1853   which is indeed heavy weight (see the equation for @{text cprec} shown in \eqref{overloaded}).
  1854   We can however improve upon this. For this recall the notion
  1854   We can however improve upon this. For this recall the notion
  1855   of @{term children} of a thread @{text th} defined in \eqref{children}.
  1855   of @{term children} of a thread @{text th} defined in \eqref{children}.
  1856   There a child is a thread that is only one ``hop'' away from the thread
  1856   There a child is a thread that is only one ``hop'' away from the thread
  1857   @{text th} in the @{term TDG} (and waiting for @{text th} to release
  1857   @{text th} in the @{term TDG} (and waiting for @{text th} to release
  1869   \noindent
  1869   \noindent
  1870   That means the current precedence of a thread @{text th} can be
  1870   That means the current precedence of a thread @{text th} can be
  1871   computed by considering the static precedence of @{text th}
  1871   computed by considering the static precedence of @{text th}
  1872   and 
  1872   and 
  1873   the current precedences of the children of @{text th}. Their 
  1873   the current precedences of the children of @{text th}. Their 
  1874   @{text "cprec"}s, in general general, need to be computed by recursively decending into 
  1874   @{text "cprec"}s, in general, need to be computed by recursively decending into 
  1875   deeper ``levels'' of the @{text TDG}. 
  1875   deeper ``levels'' of the @{text TDG}. 
  1876   However, the current precedence of a thread @{text th}, say, 
  1876   However, the current precedence of a thread @{text th}, say, 
  1877   only needs to be recomputed when @{text "(i)"} its static
  1877   only needs to be recomputed when @{text "(i)"} its static
  1878   precedence is re-set or when @{text "(ii)"} one of
  1878   precedence is re-set or when @{text "(ii)"} one of
  1879   its children changes its current precedence or when @{text "(iii)"} the children set changes
  1879   its children changes its current precedence or when @{text "(iii)"} the children set changes
  1880   (for example in an @{text "V"}-event).   
  1880   (for example in a @{text "V"}-event).   
  1881   If only the static precedence or the children-set changes, then we can 
  1881   If only the static precedence or the children-set changes, then we can 
  1882   avoid the recursion and compute the @{text cprec} of @{text th} locally.
  1882   avoid the recursion and compute the @{text cprec} of @{text th} locally.
  1883   In such cases
  1883   In such cases
  1884   the recursion does not need to decend into the corresponding subtree.
  1884   the recursion does not need to descend into the corresponding subtree.
  1885   Once the current 
  1885   Once the current 
  1886   precedence is computed in this more efficient manner, the selection
  1886   precedence is computed in this more efficient manner, the selection
  1887   of the thread with highest precedence from a set of ready threads is
  1887   of the thread with highest precedence from a set of ready threads is
  1888   a standard scheduling operation and implemented in most operating
  1888   a standard scheduling operation and implemented in most operating
  1889   systems.
  1889   systems.
  2042 *}
  2042 *}
  2043 
  2043 
  2044 text {*
  2044 text {*
  2045   \noindent
  2045   \noindent
  2046   In the other case where there is no thread that takes over @{text cs}, 
  2046   In the other case where there is no thread that takes over @{text cs}, 
  2047   we can show how
  2047   we can prove that the updated @{text RAG} merely deletes the relevant edge and
  2048   to recalculate the @{text RAG} and also show that no current precedence needs
  2048   that no current precedence needs to be recalculated
  2049   to be recalculated for any thread @{text "th''"}.
  2049   for any thread @{text "th''"}.
  2050 
  2050 
  2051   \begin{isabelle}\ \ \ \ \ %%%
  2051   \begin{isabelle}\ \ \ \ \ %%%
  2052   \begin{tabular}{@ {}l}
  2052   \begin{tabular}{@ {}l}
  2053   @{thm (concl) valid_trace_v_e.RAG_s}\\
  2053   @{thm (concl) valid_trace_v_e.RAG_s}\\
  2054   @{term "\<forall>th''. cprec (e#s) th'' = cprec s th''"}
  2054   @{term "\<forall>th''. cprec (e#s) th'' = cprec s th''"}
  2233   \caption{Our version of the {\tt lock\_acquire} function for the small operating 
  2233   \caption{Our version of the {\tt lock\_acquire} function for the small operating 
  2234   system PINTOS.  It implements the operation corresponding to a @{text P}-event.\label{code}}
  2234   system PINTOS.  It implements the operation corresponding to a @{text P}-event.\label{code}}
  2235   \end{figure}
  2235   \end{figure}
  2236 
  2236 
  2237  
  2237  
  2238   Line 6 and 7 of {\tt lock\_acquire} make the operation of acquiring a lock atomic by disabling all 
  2238   Lines 6 and 7 of {\tt lock\_acquire} make the operation of acquiring a lock atomic by disabling all 
  2239   interrupts, but saving them for resumption at the end of the function (Line 31).
  2239   interrupts, but saving them for resumption at the end of the function (Line 31).
  2240   In Line 8, the interesting code with respect to scheduling starts: we 
  2240   In Line 8, the interesting code with respect to scheduling starts: we 
  2241   first check whether the lock is already taken (its value is then 0 indicating ``already 
  2241   first check whether the lock is already taken (its value is then 0 indicating ``already 
  2242   taken'', or 1 for being ``free''). In case the lock is taken, we enter the
  2242   taken'', or 1 for being ``free''). In case the lock is taken, we enter the
  2243   if-branch inserting the current thread into the waiting queue of this lock (Line 9).
  2243   if-branch inserting the current thread into the waiting queue of this lock (Line 9).
  2277   
  2277   
  2278 
  2278 
  2279   Similar operations need to be implementated for the @{ML_text lock_release} function, which
  2279   Similar operations need to be implementated for the @{ML_text lock_release} function, which
  2280   we however do not show. The reader should note though that we did \emph{not} verify our C-code. 
  2280   we however do not show. The reader should note though that we did \emph{not} verify our C-code. 
  2281   This is in contrast, for example, to the work on seL4, which actually verified in Isabelle/HOL
  2281   This is in contrast, for example, to the work on seL4, which actually verified in Isabelle/HOL
  2282   that their C-code satisfies its specification, thought this specification does not contain 
  2282   that their C-code satisfies its specification, though this specification does not contain 
  2283   anything about PIP \cite{sel4}.
  2283   anything about PIP \cite{sel4}.
  2284   Our verification of PIP however provided us with the justification for designing 
  2284   Our verification of PIP however provided us with (formally proven) insights on how to design 
  2285   the C-code. It gave us confidence that leaving the ``chase'' early, whenever
  2285   the C-code. It gave us confidence that leaving the ``chase'' early, whenever
  2286   there is no change in the calculated current precedence, does not break the
  2286   there is no change in the calculated current precedence, does not break the
  2287   correctness of the algorithm.
  2287   correctness of the algorithm.
  2288 *}
  2288 *}
  2289 
  2289