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