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 |