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 priority $M$ |
88 continously need to be processed). Since $H$ is blocked by threads |
88 continuously need to be processed). Since $H$ is blocked by threads |
89 with lower priorities, the problem is called Priority Inversion. It |
89 with lower priorities, the problem is called Priority Inversion. It |
90 was first described in \cite{Lampson80} in the context of the Mesa |
90 was first described in \cite{Lampson80} in the context of the Mesa |
91 programming language designed for concurrent programming. |
91 programming language designed for concurrent programming. |
92 |
92 |
93 If the problem of Priority Inversion is ignored, real-time systems |
93 If the problem of Priority Inversion is ignored, real-time systems |
94 can become unpredictable and resulting bugs can be hard to diagnose. |
94 can become unpredictable and resulting bugs can be hard to diagnose. |
95 The classic example where this happened is the software that |
95 The classic example where this happened is the software that |
96 controlled the Mars Pathfinder mission in 1997 \cite{Reeves98}. On |
96 controlled the Mars Pathfinder mission in 1997 \cite{Reeves98}. On |
97 Earth the software run mostly without any problem, but once the |
97 Earth, the software ran mostly without any problem, but once the |
98 spacecraft landed on Mars, it shut down at irregular, but frequent, |
98 spacecraft landed on Mars, it shut down at irregular, but frequent, |
99 intervals leading to loss of project time as normal operation of the |
99 intervals. This led to loss of project time as normal operation of the |
100 craft could only resume the next day (the mission and data already |
100 craft could only resume the next day (the mission and data already |
101 collected were fortunately not lost, because of a clever system |
101 collected were fortunately not lost, because of a clever system |
102 design). The reason for the shutdowns was that the scheduling |
102 design). The reason for the shutdowns was that the scheduling |
103 software fell victim to Priority Inversion: a low priority thread |
103 software fell victim to Priority Inversion: a low priority thread |
104 locking a resource prevented a high priority thread from running in |
104 locking a resource prevented a high priority thread from running in |
188 still have Priority Inversion with $H'$ (which waits for the other |
188 still have Priority Inversion with $H'$ (which waits for the other |
189 resource). The correct behaviour for $L$ is to switch to the highest |
189 resource). The correct behaviour for $L$ is to switch to the highest |
190 remaining priority of the threads that it blocks. A similar error |
190 remaining priority of the threads that it blocks. A similar error |
191 is made in the textbook \cite[Section 2.3.1]{book} which specifies |
191 is made in the textbook \cite[Section 2.3.1]{book} which specifies |
192 for a process that inherited a higher priority and exits a critical |
192 for a process that inherited a higher priority and exits a critical |
193 section ``{\it it resumes the priority it had at the point of entry |
193 section that ``{\it it resumes the priority it had at the point of entry |
194 into the critical section}''. This error can also be found in the |
194 into the critical section}''. This error can also be found in the |
195 textbook \cite[Section 16.4.1]{LiYao03} where the authors write |
195 textbook \cite[Section 16.4.1]{LiYao03} where the authors write |
196 about this process: ``{\it its priority is immediately lowered to the level originally assigned}''; |
196 about this process: ``{\it its priority is immediately lowered to the level originally assigned}''; |
197 and also in the |
197 and also in the |
198 more recent textbook \cite[Page 119]{Laplante11} where the authors |
198 more recent textbook \cite[Page 119]{Laplante11} where the authors |
199 state: ``{\it when [the task] exits the critical section that caused |
199 state: ``{\it when [the task] exits the critical section that caused |
200 the block, it reverts to the priority it had when it entered that |
200 the block, it reverts to the priority it had when it entered that |
201 section}''. The textbook \cite[Page 286]{Liu00} contains a simlar |
201 section}''. The textbook \cite[Page 286]{Liu00} contains a similar |
202 flawed specification and even goes on to develop pseudo-code based |
202 flawed specification and even goes on to develop pseudo-code based |
203 on this flawed specification. Accordingly, the operating system |
203 on this flawed specification. Accordingly, the operating system |
204 primitives for inheritance and restoration of priorities in |
204 primitives for inheritance and restoration of priorities in |
205 \cite{Liu00} depend on maintaining a data structure called |
205 \cite{Liu00} depend on maintaining a data structure called |
206 \emph{inheritance log}. This log is maintained for every thread and |
206 \emph{inheritance log}. This log is maintained for every thread and |
207 broadly specified as containing ``{\it [h]istorical information on |
207 broadly specified as containing ``{\it [h]istorical information on |
208 how the thread inherited its current priority}'' \cite[Page |
208 how the thread inherited its current priority}'' \cite[Page |
209 527]{Liu00}. Unfortunately, the important information about actually |
209 527]{Liu00}. Unfortunately, the important information about actually |
210 computing the priority to be restored solely from this log is not |
210 computing the priority to be restored solely from this log is not |
211 explained in \cite{Liu00} but left as an ``{\it excercise}'' to the |
211 explained in \cite{Liu00} but left as an ``{\it exercise}'' to the |
212 reader. As we shall see, a correct version of PIP does not need to |
212 reader. As we shall see, a correct version of PIP does not need to |
213 maintain this (potentially expensive) log data structure at |
213 maintain this (potentially expensive) log data structure at |
214 all. Surprisingly also the widely read and frequently updated |
214 all. Surprisingly also the widely read and frequently updated |
215 textbook \cite{Silberschatz13} gives the wrong specification. On Page 254 the authors write: ``{\it Upon releasing the |
215 textbook \cite{Silberschatz13} gives the wrong specification. On Page 254 the authors write: ``{\it Upon releasing the |
216 lock, the [low-priority] thread will revert to its original |
216 lock, the [low-priority] thread will revert to its original |
220 While \cite{Laplante11,LiYao03,Liu00,book,Sha90,Silberschatz13} are |
220 While \cite{Laplante11,LiYao03,Liu00,book,Sha90,Silberschatz13} are |
221 the only formal publications we have found that specify the |
221 the only formal publications we have found that specify the |
222 incorrect behaviour, it seems also many informal descriptions of the |
222 incorrect behaviour, it seems also many informal descriptions of the |
223 PIP protocol overlook the possibility that another high-priority |
223 PIP protocol overlook the possibility that another high-priority |
224 process might wait for a low-priority process to finish. A notable |
224 process might wait for a low-priority process to finish. A notable |
225 exception is the texbook \cite{buttazzo}, which gives the correct |
225 exception is the textbook \cite{buttazzo}, which gives the correct |
226 behaviour of resetting the priority of a thread to the highest |
226 behaviour of resetting the priority of a thread to the highest |
227 remaining priority of the threads it blocks. This textbook also |
227 remaining priority of the threads it blocks. This textbook also |
228 gives an informal proof for the correctness of PIP in the style of |
228 gives an informal proof for the correctness of PIP in the style of |
229 Sha et al. Unfortunately, this informal proof is too vague to be |
229 Sha et al. Unfortunately, this informal proof is too vague to be |
230 useful for formalising the correctness of PIP and the specification |
230 useful for formalising the correctness of PIP and the specification |
247 for PIP being correct---a fact that has not been mentioned in the |
247 for PIP being correct---a fact that has not been mentioned in the |
248 literature and not been used in the reference implementation of PIP |
248 literature and not been used in the reference implementation of PIP |
249 in PINTOS. This fact, however, is important for an efficient |
249 in PINTOS. This fact, however, is important for an efficient |
250 implementation of PIP, because we can give the lock to the thread |
250 implementation of PIP, because we can give the lock to the thread |
251 with the highest priority so that it terminates more quickly. We |
251 with the highest priority so that it terminates more quickly. We |
252 are also being able to generalise the scheduler of Sha et |
252 are also able to generalise the scheduler of Sha et |
253 al.~\cite{Sha90} to the practically relevant case where critical |
253 al.~\cite{Sha90} to the practically relevant case where critical |
254 sections can overlap; see Figure~\ref{overlap} \emph{a)} below for |
254 sections can overlap; see Figure~\ref{overlap} \emph{a)} below for |
255 an example of this restriction. In the existing literature there is |
255 an example of this restriction. In the existing literature there is |
256 no proof and also no proving method that cover this generalised |
256 no proof and also no method for proving which covers this generalised |
257 case. |
257 case. |
258 |
258 |
259 \begin{figure} |
259 \begin{figure} |
260 \begin{center} |
260 \begin{center} |
261 \begin{tikzpicture}[scale=1] |
261 \begin{tikzpicture}[scale=1] |
800 \end{tabular} |
801 \end{tabular} |
801 \end{isabelle} |
802 \end{isabelle} |
802 |
803 |
803 Having the scheduler function @{term schs} at our disposal, we can |
804 Having the scheduler function @{term schs} at our disposal, we can |
804 ``lift'', or overload, the notions @{term waiting}, @{term holding}, |
805 ``lift'', or overload, the notions @{term waiting}, @{term holding}, |
805 @{term RAG}, %%@ {term dependants} |
806 @{term RAG}, @{term "TDG"}, %%@ {term dependants} |
806 and @{term cp} to operate on states only. |
807 and @{term cp} to operate on states only. |
807 |
808 |
808 \begin{isabelle}\ \ \ \ \ %%% |
809 \begin{isabelle}\ \ \ \ \ %%% |
809 \begin{tabular}{@ {}rcl} |
810 \begin{tabular}{@ {}rcl} |
810 @{thm (lhs) s_holding_abv} & @{text "\<equiv>"} & @{thm (rhs) s_holding_abv[simplified wq_def]}\\ |
811 @{thm (lhs) s_holding_abv} & @{text "\<equiv>"} & @{thm (rhs) s_holding_abv[simplified wq_def]}\\ |
1625 |
1626 |
1626 Because of these problems, we decided in our earlier paper |
1627 Because of these problems, we decided in our earlier paper |
1627 \cite{ZhangUrbanWu12} to leave out this property and let the |
1628 \cite{ZhangUrbanWu12} to leave out this property and let the |
1628 programmer take on the responsibility to program threads in such a |
1629 programmer take on the responsibility to program threads in such a |
1629 benign manner (in addition to causing no circularity in the |
1630 benign manner (in addition to causing no circularity in the |
1630 RAG). This leave-it-to-the-programmer was also the approach taken by |
1631 RAG). This leave-it-to-the-programmer approach was also taken by |
1631 Sha et al.~in their paper. However, in this paper we can make an |
1632 Sha et al.~in their paper. However, in this paper we can make an |
1632 improvement by establishing a finite bound on the duration of |
1633 improvement by establishing a finite bound on the duration of |
1633 Priority Inversion measured by the number of events. The events can |
1634 Priority Inversion measured by the number of events. The events can |
1634 be seen as a \textit{rough(!)} abstraction of the ``runtime |
1635 be seen as a \textit{rough(!)} abstraction of the ``runtime |
1635 behaviour'' of threads and also as an abstract notion of |
1636 behaviour'' of threads and also as an abstract notion of |
1660 require that the number of created threads is less than |
1661 require that the number of created threads is less than |
1661 a bound @{text "BC"}, that is |
1662 a bound @{text "BC"}, that is |
1662 |
1663 |
1663 \[@{text "len (filter isCreate es) < BC"}\;\] |
1664 \[@{text "len (filter isCreate es) < BC"}\;\] |
1664 |
1665 |
1665 wherby @{text es} is a list of events. |
1666 whereby @{text es} is a list of events. |
1666 \end{quote} |
1667 \end{quote} |
1667 |
1668 |
1668 \noindent Note that it is not enough to just to state that there are |
1669 \noindent Note that it is not enough to just state that there are |
1669 only finite number of threads created up until a single state @{text |
1670 only finite number of threads created up until a single state @{text |
1670 "s' @ s"} after @{text s}. Instead, we need to put this bound on |
1671 "s' @ s"} after @{text s}. Instead, we need to put this bound on |
1671 the @{text "Create"} events for all valid states after @{text s}. |
1672 the @{text "Create"} events for all valid states after @{text s}. |
1672 This ensures that no matter which ``future'' state is reached, the |
1673 This ensures that no matter which ``future'' state is reached, the |
1673 number of @{text "Create"}-events is finite. This bound @{text BC} is assumed |
1674 number of @{text "Create"}-events is finite. This bound @{text BC} is assumed |
1683 \end{isabelle} |
1684 \end{isabelle} |
1684 |
1685 |
1685 \noindent This set contains all threads that are not detached in |
1686 \noindent This set contains all threads that are not detached in |
1686 state @{text s}. According to our definiton of @{text "detached"}, |
1687 state @{text s}. According to our definiton of @{text "detached"}, |
1687 this means a thread in @{text "blockers"} either holds or waits for |
1688 this means a thread in @{text "blockers"} either holds or waits for |
1688 some resource in state @{text s} . Our Thm.~1 implies that any of |
1689 some resource in state @{text s} . Our Thm.~1 implies that only |
1689 such threads can all potentially block @{text th} after state |
1690 these threads can all potentially block @{text th} after state |
1690 @{text s}. We need to make the following assumption about the |
1691 @{text s}. We need to make the following assumption about the |
1691 threads in the @{text "blockers"}-set: |
1692 threads in the @{text "blockers"}-set: |
1692 |
1693 |
1693 \begin{quote} |
1694 \begin{quote} |
1694 {\bf Assumptions on the threads {\boldmath{@{term "th' \<in> blockers"}}}:} |
1695 {\bf Assumptions on the threads {\boldmath{@{term "th' \<in> blockers"}}}:} |
1714 can be bounded by the number of actions the threads in @{text |
1715 can be bounded by the number of actions the threads in @{text |
1715 blockers} perform (i.e.~events) and how many threads are newly |
1716 blockers} perform (i.e.~events) and how many threads are newly |
1716 created. To state our bound formally, we need to make a definition |
1717 created. To state our bound formally, we need to make a definition |
1717 of what we mean by intermediate states between a state @{text s} and |
1718 of what we mean by intermediate states between a state @{text s} and |
1718 a future state after @{text s}; they will be the list of states |
1719 a future state after @{text s}; they will be the list of states |
1719 starting from @{text s} upto the state \mbox{@{text "es @ s"}}. For |
1720 starting from @{text s} up to the state \mbox{@{text "es @ s"}}. For |
1720 example, suppose $\textit{es} = [\textit{e}_n, \textit{e}_{n-1}, |
1721 example, suppose $\textit{es} = [\textit{e}_n, \textit{e}_{n-1}, |
1721 \ldots, \textit{e}_2, \textit{e}_1]$, then the intermediate states |
1722 \ldots, \textit{e}_2, \textit{e}_1]$, then the intermediate states |
1722 from @{text s} upto @{text "es @ s"} are |
1723 from @{text s} upto @{text "es @ s"} are |
1723 |
1724 |
1724 \begin{center} |
1725 \begin{center} |
1950 \end{isabelle} |
1951 \end{isabelle} |
1951 |
1952 |
1952 \noindent The first property is again telling us we do not need to |
1953 \noindent The first property is again telling us we do not need to |
1953 change the @{text RAG}. The second shows that the @{term cp}-values |
1954 change the @{text RAG}. The second shows that the @{term cp}-values |
1954 of all threads other than @{text th} are unchanged. The reason for |
1955 of all threads other than @{text th} are unchanged. The reason for |
1955 this is more subtle: Since @{text th} must be running, that is does |
1956 this is more subtle: Since @{text th} must be running, then it does |
1956 not wait for any resource to be released, it cannot be in any |
1957 not wait for any resource to be released and it cannot be in any |
1957 subtree of any other thread. So all current precedences of other |
1958 subtree of any other thread. So all current precedences of other |
1958 threads are unchanged. |
1959 threads are unchanged. |
1959 |
1960 |
1960 %The second |
1961 %The second |
1961 %however states that only threads that are \emph{not} dependants of @{text th} have their |
1962 %however states that only threads that are \emph{not} dependants of @{text th} have their |
2307 inductive method for protocol verification~\cite{Paulson98} is quite |
2308 inductive method for protocol verification~\cite{Paulson98} is quite |
2308 suitable for our formal model and proof. The traditional application |
2309 suitable for our formal model and proof. The traditional application |
2309 area of this method is security protocols. |
2310 area of this method is security protocols. |
2310 |
2311 |
2311 The second goal of our formalisation is to provide a specification for actually |
2312 The second goal of our formalisation is to provide a specification for actually |
2312 implementing PIP. Textbooks, for example \cite[Section 5.6.5]{Vahalia96}, |
2313 implementing PIP. Textbooks, for example Vahalia \cite[Section 5.6.5]{Vahalia96}, |
2313 explain how to use various implementations of PIP and abstractly |
2314 explain how to use various implementations of PIP and abstractly |
2314 discuss their properties, but surprisingly lack most details important for a |
2315 discuss their properties, but surprisingly lack most details important for a |
2315 programmer who wants to implement PIP (similarly Sha et al.~\cite{Sha90}). |
2316 programmer who wants to implement PIP (similarly Sha et al.~\cite{Sha90}). |
2316 That this is an issue in practice is illustrated by the |
2317 That this is an issue in practice is illustrated by the |
2317 email from Baker we cited in the Introduction. We achieved also this |
2318 email from Baker we cited in the Introduction. We achieved also this |
2318 goal: The formalisation allowed us to efficently implement our version |
2319 goal: The formalisation allowed us to efficently implement our version |
2319 of PIP on top of PINTOS \cite{PINTOS}, a simple instructional operating system for the x86 |
2320 of PIP on top of PINTOS, a simple instructional operating system for the x86 |
2320 architecture. It also gives the first author enough data to enable |
2321 architecture implemented by Pfaff \cite{PINTOS}. It also gives the first author enough data to enable |
2321 his undergraduate students to implement PIP (as part of their OS course). |
2322 his undergraduate students to implement PIP (as part of their OS course). |
2322 A byproduct of our formalisation effort is that nearly all |
2323 A byproduct of our formalisation effort is that nearly all |
2323 design choices for the implementation of PIP scheduler are backed up with a proved |
2324 design choices for the implementation of PIP scheduler are backed up with a proved |
2324 lemma. We were also able to establish the property that the choice of |
2325 lemma. We were also able to establish the property that the choice of |
2325 the next thread which takes over a lock is irrelevant for the correctness |
2326 the next thread which takes over a lock is irrelevant for the correctness |
2335 (the informal specification by Sha et al.~did not). |
2336 (the informal specification by Sha et al.~did not). |
2336 |
2337 |
2337 |
2338 |
2338 PIP is a scheduling algorithm for single-processor systems. We are |
2339 PIP is a scheduling algorithm for single-processor systems. We are |
2339 now living in a multi-processor world. Priority Inversion certainly |
2340 now living in a multi-processor world. Priority Inversion certainly |
2340 occurs also there, see for example \cite{Brandenburg11,Davis11}. |
2341 occurs also there, see for example work by Brandenburg, and Davis and Burns \cite{Brandenburg11,Davis11}. |
2341 However, there is very little ``foundational'' |
2342 However, there is very little ``foundational'' |
2342 work about PIP-algorithms on multi-processor systems. We are not |
2343 work about PIP-algorithms on multi-processor systems. We are not |
2343 aware of any correctness proofs, not even informal ones. There is an |
2344 aware of any correctness proofs, not even informal ones. There is an |
2344 implementation of a PIP-algorithm for multi-processors as part of the |
2345 implementation of a PIP-algorithm for multi-processors as part of the |
2345 ``real-time'' effort in Linux, including an informal description of the implemented scheduling |
2346 ``real-time'' effort in Linux, including an informal description of the implemented scheduling |
2346 algorithm given in \cite{LINUX}. We estimate that the formal |
2347 algorithm given by Rostedt in \cite{LINUX}. We estimate that the formal |
2347 verification of this algorithm, involving more fine-grained events, |
2348 verification of this algorithm, involving more fine-grained events, |
2348 is a magnitude harder than the one we presented here, but still |
2349 is a magnitude harder than the one we presented here, but still |
2349 within reach of current theorem proving technology. We leave this |
2350 within reach of current theorem proving technology. We leave this |
2350 for future work. |
2351 for future work. |
2351 |
2352 |
2352 To us, it seems sound reasoning about scheduling algorithms is fiendishly difficult |
2353 To us, it seems sound reasoning about scheduling algorithms is fiendishly difficult |
2353 if done informally by ``pencil-and-paper''. We infer this from the flawed proof |
2354 if done informally by ``pencil-and-paper''. We infer this from the flawed proof |
2354 in the paper by Sha et al.~\cite{Sha90} and also from \cite{Regehr} where Regehr |
2355 in the paper by Sha et al.~\cite{Sha90} and also from \cite{Regehr} where Regehr |
2355 points out an error in a paper about Preemption |
2356 points out an error in a paper about Preemption |
2356 Threshold Scheduling \cite{ThreadX}. The use of a theorem prover was |
2357 Threshold Scheduling by Wang and Saksena \cite{ThreadX}. The use of a theorem prover was |
2357 invaluable to us in order to be confident about the correctness of our reasoning |
2358 invaluable to us in order to be confident about the correctness of our reasoning |
2358 (for example no corner case can be overlooked). |
2359 (for example no corner case can be overlooked). |
2359 The most closely related work to ours is the formal verification in |
2360 The most closely related work to ours is the formal verification in |
2360 PVS of the Priority Ceiling Protocol done by Dutertre |
2361 PVS of the Priority Ceiling Protocol done by Dutertre~\cite{dutertre99b}---another solution to the Priority Inversion |
2361 \cite{dutertre99b}---another solution to the Priority Inversion |
|
2362 problem, which however needs static analysis of programs in order to |
2362 problem, which however needs static analysis of programs in order to |
2363 avoid it. There have been earlier formal investigations |
2363 avoid it. There have been earlier formal investigations |
2364 into PIP \cite{Faria08,Jahier09,Wellings07}, but they employ model |
2364 into PIP \cite{Faria08,Jahier09,Wellings07}, but they employ model |
2365 checking techniques. The results obtained by them apply, |
2365 checking techniques. The results obtained by them apply, |
2366 however, only to systems with a fixed size, such as a fixed number of |
2366 however, only to systems with a fixed size, such as a fixed number of |