76 priorities this property can be violated. For this let $L$ be in the |
76 priorities this property can be violated. For this let $L$ be in the |
77 possession of a lock for a resource that $H$ also needs. $H$ must |
77 possession of a lock for a resource that $H$ also needs. $H$ must |
78 therefore wait for $L$ to exit the critical section and release this |
78 therefore wait for $L$ to exit the critical section and release this |
79 lock. The problem is that $L$ might in turn be blocked by any thread |
79 lock. The problem is that $L$ might in turn be blocked by any thread |
80 with priority $M$, and so $H$ sits there potentially waiting |
80 with priority $M$, and so $H$ sits there potentially waiting |
81 indefinitely. Since $H$ is blocked by threads with lower priorities, |
81 indefinitely (consider the case where threads with propority $M$ |
82 the problem is called Priority Inversion. It was first described in |
82 continously need to be processed). Since $H$ is blocked by threads |
83 \cite{Lampson80} in the context of the Mesa programming language |
83 with lower priorities, the problem is called Priority Inversion. It |
84 designed for concurrent programming. |
84 was first described in \cite{Lampson80} in the context of the Mesa |
|
85 programming language designed for concurrent programming. |
85 |
86 |
86 If the problem of Priority Inversion is ignored, real-time systems |
87 If the problem of Priority Inversion is ignored, real-time systems |
87 can become unpredictable and resulting bugs can be hard to diagnose. |
88 can become unpredictable and resulting bugs can be hard to diagnose. |
88 The classic example where this happened is the software that |
89 The classic example where this happened is the software that |
89 controlled the Mars Pathfinder mission in 1997 \cite{Reeves98}. On |
90 controlled the Mars Pathfinder mission in 1997 \cite{Reeves98}. On |
319 \begin{isabelle}\ \ \ \ \ %%% |
320 \begin{isabelle}\ \ \ \ \ %%% |
320 \mbox{\begin{tabular}{r@ {\hspace{2mm}}c@ {\hspace{2mm}}l@ {\hspace{7mm}}l} |
321 \mbox{\begin{tabular}{r@ {\hspace{2mm}}c@ {\hspace{2mm}}l@ {\hspace{7mm}}l} |
321 \isacommand{datatype} event |
322 \isacommand{datatype} event |
322 & @{text "="} & @{term "Create thread priority\<iota>"}\\ |
323 & @{text "="} & @{term "Create thread priority\<iota>"}\\ |
323 & @{text "|"} & @{term "Exit thread"} \\ |
324 & @{text "|"} & @{term "Exit thread"} \\ |
324 & @{text "|"} & @{term "Set thread priority\<iota>"} & {\rm reset of the priority for} @{text thread}\\ |
325 & @{text "|"} & @{term "Set thread priority\<iota>"} & |
|
326 @{text thread} {\rm resets its own priority} \\ |
325 & @{text "|"} & @{term "P thread cs"} & {\rm request of resource} @{text "cs"} {\rm by} @{text "thread"}\\ |
327 & @{text "|"} & @{term "P thread cs"} & {\rm request of resource} @{text "cs"} {\rm by} @{text "thread"}\\ |
326 & @{text "|"} & @{term "V thread cs"} & {\rm release of resource} @{text "cs"} {\rm by} @{text "thread"} |
328 & @{text "|"} & @{term "V thread cs"} & {\rm release of resource} @{text "cs"} {\rm by} @{text "thread"} |
327 \end{tabular}} |
329 \end{tabular}} |
328 \end{isabelle} |
330 \end{isabelle} |
329 |
331 |
435 \begin{isabelle}\ \ \ \ \ %%% |
437 \begin{isabelle}\ \ \ \ \ %%% |
436 @{abbrev "preceds ths s"} |
438 @{abbrev "preceds ths s"} |
437 \end{isabelle} |
439 \end{isabelle} |
438 |
440 |
439 \noindent |
441 \noindent |
440 for the set of precedences of threads @{text ths} in state @{text s}. |
442 for the precedences of a set of threads @{text ths} in state @{text s}. |
441 The point of precedences is to schedule threads not according to priorities (because what should |
443 The point of precedences is to schedule threads not according to priorities (because what should |
442 we do in case two threads have the same priority), but according to precedences. |
444 we do in case two threads have the same priority), but according to precedences. |
443 Precedences allow us to always discriminate between two threads with equal priority by |
445 Precedences allow us to always discriminate between two threads with equal priority by |
444 taking into account the time when the priority was last set. We order precedences so |
446 taking into account the time when the priority was last set. We order precedences so |
445 that threads with the same priority get a higher precedence if their priority has been |
447 that threads with the same priority get a higher precedence if their priority has been |
482 @{thm waiting_raw_def[where thread="th"]} |
484 @{thm waiting_raw_def[where thread="th"]} |
483 \end{tabular} |
485 \end{tabular} |
484 \end{isabelle} |
486 \end{isabelle} |
485 |
487 |
486 \noindent |
488 \noindent |
487 In this definition we assume @{text "set"} converts a list into a set. |
489 In this definition we assume that @{text "set"} converts a list into a set. |
488 Note that in the first definition the condition about @{text "th \<in> set (wq cs)"} does not follow |
490 Note that in the first definition the condition about @{text "th \<in> set (wq cs)"} does not follow |
489 from @{text "th = hd (set (wq cs))"}, since the head of an empty list is undefined in Isabelle/HOL. |
491 from @{text "th = hd (set (wq cs))"}, since the head of an empty list is undefined in Isabelle/HOL. |
490 At the beginning, that is in the state where no thread is created yet, |
492 At the beginning, that is in the state where no thread is created yet, |
491 the waiting queue function will be the function that returns the |
493 the waiting queue function will be the function that returns the |
492 empty list for every resource. |
494 empty list for every resource. |
621 resource that is locked already, then the thread is blocked and |
623 resource that is locked already, then the thread is blocked and |
622 cannot ask for another resource. Clearly, also every resource can |
624 cannot ask for another resource. Clearly, also every resource can |
623 only have at most one outgoing holding edge---indicating that the |
625 only have at most one outgoing holding edge---indicating that the |
624 resource is locked. So if the @{text "RAG"} is well-founded and |
626 resource is locked. So if the @{text "RAG"} is well-founded and |
625 finite, we can always start at a thread waiting for a resource and |
627 finite, we can always start at a thread waiting for a resource and |
626 ``chase'' outgoing arrows leading to a single root of a tree. |
628 ``chase'' outgoing arrows leading to a single root of a tree, |
|
629 which must be a ready thread. |
627 |
630 |
628 The use of relations for representing @{text RAG}s allows us to |
631 The use of relations for representing @{text RAG}s allows us to |
629 conveniently define the \emph{Thread Dependants Graph} (TDG): |
632 conveniently define the \emph{Thread Dependants Graph} (TDG): |
630 |
633 |
631 \begin{isabelle}\ \ \ \ \ %%% |
634 \begin{isabelle}\ \ \ \ \ %%% |
632 @{thm tG_raw_def}\\ |
635 @{thm tG_raw_def}\\ |
633 \mbox{}\hfill\numbered{dependants} |
636 \mbox{}\hfill\numbered{dependants} |
634 \end{isabelle} |
637 \end{isabelle} |
635 |
638 |
636 \noindent This definition represents all threads in a @{text RAG} that wait |
639 \noindent This definition is the relation that one thread is waiting for |
637 for a thread to release a resource, but the corresponding |
640 another to release a resource, but the corresponding |
638 resource is ``hidden''. |
641 resource is ``hidden''. |
639 In Figure~\ref{RAGgraph} this means the @{text TDG} connects @{text "th\<^sub>0"} with |
642 In Figure~\ref{RAGgraph} this means the @{text TDG} connects |
640 @{text "th\<^sub>1"} and @{text "th\<^sub>2"}, which both wait for |
643 @{text "th\<^sub>1"} and @{text "th\<^sub>2"} to @{text "th\<^sub>0"}, which both wait for |
641 resource @{text "cs\<^sub>1"}; and @{text "th\<^sub>2"} with @{text "th\<^sub>3"}, which |
644 resource @{text "cs\<^sub>1"} to be released; and @{text "th\<^sub>3"} to @{text "th\<^sub>2"}, which |
642 cannot make any progress unless @{text "th\<^sub>2"} makes progress. |
645 cannot make any progress unless @{text "th\<^sub>2"} makes progress. |
643 Similarly for the other threads. |
646 Similarly for the other threads. |
644 If |
647 If |
645 there is a circle of dependencies in a @{text RAG} (and thus @{text TDG}), then clearly we have a |
648 there is a circle of dependencies in a @{text RAG} (and thus @{text TDG}), then clearly we have a |
646 deadlock. Therefore when a thread requests a resource, we must |
649 deadlock. Therefore when a thread requests a resource, we must |
647 ensure that the resulting @{text RAG} and @{text TDG} are not circular. In practice, the |
650 ensure that the resulting @{text RAG} and @{text TDG} are not circular. In practice, the |
648 programmer has to ensure this. Our model will enforce that critical |
651 programmer has to ensure this. Our model will enforce that critical |
649 resources can only be requested provided no circularity can arise. |
652 resources can only be requested provided no circularity can arise (but |
|
653 they can overlap, see Fig~\ref{overlap}). |
650 |
654 |
651 Next we introduce the notion of the \emph{current precedence} of a thread @{text th} in a |
655 Next we introduce the notion of the \emph{current precedence} of a thread @{text th} in a |
652 state @{text s}. It is defined as |
656 state @{text s}. It is defined as |
653 |
657 |
654 \begin{isabelle}\ \ \ \ \ %%% |
658 \begin{isabelle}\ \ \ \ \ %%% |
660 While the precedence @{term prec} of any |
664 While the precedence @{term prec} of any |
661 thread is determined statically (for example when the thread is |
665 thread is determined statically (for example when the thread is |
662 created), the point of the current precedence is to dynamically |
666 created), the point of the current precedence is to dynamically |
663 increase this precedence, if needed according to PIP. Therefore the |
667 increase this precedence, if needed according to PIP. Therefore the |
664 current precedence of @{text th} is given as the maximum of the |
668 current precedence of @{text th} is given as the maximum of the |
665 precedence of @{text th} \emph{and} all threads in its subtree. Since the notion of current precedence is defined as the |
669 precedences of all threads in its subtree (which includes by definition |
|
670 @{text th} itself). Since the notion of current precedence is defined as the |
666 transitive closure of the dependent |
671 transitive closure of the dependent |
667 threads in the @{text TDG}, we deal correctly with the problem in the informal |
672 threads in the @{text TDG}, we deal correctly with the problem in the informal |
668 algorithm by Sha et al.~\cite{Sha90} where a priority of a thread is |
673 algorithm by Sha et al.~\cite{Sha90} where a priority of a thread is |
669 lowered prematurely (see Introduction). We again introduce an abbreviation for current |
674 lowered prematurely (see Introduction). We again introduce an abbreviation for current |
670 precedeces of a set of threads, written @{text "cprecs wq s ths"}. |
675 precedeces of a set of threads, written @{text "cprecs wq s ths"}. |
872 |
877 |
873 \begin{center} |
878 \begin{center} |
874 @{thm[mode=Rule] thread_set[where thread=th]} |
879 @{thm[mode=Rule] thread_set[where thread=th]} |
875 \end{center} |
880 \end{center} |
876 |
881 |
877 \noindent If a thread wants to lock a resource, then the thread |
882 \noindent This is because the @{text Set} event is for a thread to change |
|
883 its \emph{own} priority---therefore it must be running. |
|
884 |
|
885 If a thread wants to lock a resource, then the thread |
878 needs to be running and also we have to make sure that the resource |
886 needs to be running and also we have to make sure that the resource |
879 lock does not lead to a cycle in the RAG (the prurpose of the second |
887 lock does not lead to a cycle in the RAG (the prurpose of the second |
880 premise in the rule below). In practice, ensuring the latter is the |
888 premise in the rule below). In practice, ensuring the latter is the |
881 responsibility of the programmer. In our formal model we brush |
889 responsibility of the programmer. In our formal model we brush |
882 aside these problematic cases in order to be able to make some |
890 aside these problematic cases in order to be able to make some |
1021 highest precedence; we show that in every future state (denoted by |
1029 highest precedence; we show that in every future state (denoted by |
1022 @{text "s' @ s"}) in which @{text th} is still alive, either @{text |
1030 @{text "s' @ s"}) in which @{text th} is still alive, either @{text |
1023 th} is running or it is blocked by a thread that was alive in the |
1031 th} is running or it is blocked by a thread that was alive in the |
1024 state @{text s} and was waiting for or in the possession of a lock |
1032 state @{text s} and was waiting for or in the possession of a lock |
1025 in @{text s}. Since in @{text s}, as in every state, the set of |
1033 in @{text s}. Since in @{text s}, as in every state, the set of |
1026 alive threads is finite, @{text th} can only be blocked a finite |
1034 alive threads is finite, @{text th} can only be blocked by a finite |
1027 number of threads. We will actually prove a |
1035 number of threads. We will actually prove a |
1028 stronger statement where we also provide the current precedence of |
1036 stronger statement where we also provide the current precedence of |
1029 the blocking thread. |
1037 the blocking thread. |
1030 |
1038 |
1031 However, the theorem we are going to prove hinges upon a number of |
1039 However, the theorem we are going to prove hinges upon a number of |
1057 \end{tabular} |
1065 \end{tabular} |
1058 \end{isabelle} |
1066 \end{isabelle} |
1059 \end{quote} |
1067 \end{quote} |
1060 |
1068 |
1061 \begin{quote} |
1069 \begin{quote} |
1062 {\bf Assumptions on the events in {\boldmath@{text "s'"}:}} We want to prove that @{text th} cannot |
1070 {\bf Assumptions on the events in {\boldmath@{text "s'"}:}} |
1063 be blocked indefinitely. Of course this can happen if threads with higher priority |
1071 %We want to prove that @{text th} cannot |
1064 than @{text th} are continuously created in @{text s'}. Therefore we have to assume that |
1072 %be blocked indefinitely. Of course this can happen if threads with higher priority |
|
1073 %than @{text th} are continuously created in @{text s'}. |
|
1074 To make sure @{text th} has the highest precedence we have to assume that |
1065 events in @{text s'} can only create (respectively set) threads with equal or lower |
1075 events in @{text s'} can only create (respectively set) threads with equal or lower |
1066 priority than @{text prio} of @{text th}. We also need to assume that the |
1076 priority than @{text prio} of @{text th}. For the same reason, we also need to assume that the |
1067 priority of @{text "th"} does not get reset and all other reset priorities are either |
1077 priority of @{text "th"} does not get reset and all other reset priorities are either |
1068 less or equal. Moreover, we assume that @{text th} does |
1078 less or equal. Moreover, we assume that @{text th} does |
1069 not get ``exited'' in @{text "s'"}. This can be ensured by assuming the following three implications. |
1079 not get ``exited'' in @{text "s'"}. This can be ensured by assuming the following three implications. |
1070 \begin{isabelle}\ \ \ \ \ %%% |
1080 \begin{isabelle}\ \ \ \ \ %%% |
1071 \begin{tabular}{l} |
1081 \begin{tabular}{l} |
1149 |
1159 |
1150 \begin{lemma}\label{notdetached} |
1160 \begin{lemma}\label{notdetached} |
1151 If @{term "th' \<in> running (s' @ s)"} and @{term "th \<noteq> th'"} then @{term "\<not>detached s th'"}. |
1161 If @{term "th' \<in> running (s' @ s)"} and @{term "th \<noteq> th'"} then @{term "\<not>detached s th'"}. |
1152 \end{lemma} |
1162 \end{lemma} |
1153 |
1163 |
1154 \begin{proof} Let us assume @{text "th'"} is detached in state |
1164 \begin{proof} Let us assume otherwise, that is @{text "th'"} is detached in state |
1155 @{text "s"}, then, according to the definition of detached, @{text |
1165 @{text "s"}, then, according to the definition of detached, @{text |
1156 "th’"} does not hold or wait for any resource. Hence the @{text |
1166 "th’"} does not hold or wait for any resource. Hence the @{text |
1157 cp}-value of @{text "th'"} in @{text s} is not boosted, that is |
1167 cp}-value of @{text "th'"} in @{text s} is not boosted, that is |
1158 @{term "cp s th' = prec th' s"}, and is therefore lower than the |
1168 @{term "cp s th' = prec th' s"}, and is therefore lower than the |
1159 precedence (as well as the @{text "cp"}-value) of @{term "th"}. This |
1169 precedence (as well as the @{text "cp"}-value) of @{term "th"}. This |
1589 Like in the work by Sha et al.~our result in Thm 1 does not yet |
1599 Like in the work by Sha et al.~our result in Thm 1 does not yet |
1590 guarantee the absence of indefinite Priority Inversion. For this we |
1600 guarantee the absence of indefinite Priority Inversion. For this we |
1591 further need the property that every thread gives up its resources |
1601 further need the property that every thread gives up its resources |
1592 after a finite amount of time. We found that this property is not so |
1602 after a finite amount of time. We found that this property is not so |
1593 straightforward to formalise in our model. There are mainly two |
1603 straightforward to formalise in our model. There are mainly two |
1594 reasons for this: First, we do not specify what ``running'' the code |
1604 reasons for this: First, we do not specify what ``running the code'' |
1595 of a thread means, for example by giving an operational semantics |
1605 of a thread means, for example by giving an operational semantics |
1596 for machine instructions. Therefore we cannot characterise what are |
1606 for machine instructions. Therefore we cannot characterise what are |
1597 ``good'' programs that contain for every locking request for a |
1607 ``good'' programs that contain for every locking request for a |
1598 resource also a corresponding unlocking request. Second, we need to |
1608 resource also a corresponding unlocking request. Second, we need to |
1599 distinghish between a thread that ``just'' locks a resource for a |
1609 distinghish between a thread that ``just'' locks a resource for a |
1616 |
1626 |
1617 What we will establish in this section is that there can only be a |
1627 What we will establish in this section is that there can only be a |
1618 finite number of states after state @{term s} in which the thread |
1628 finite number of states after state @{term s} in which the thread |
1619 @{term th} is blocked (recall for this that a state is a list of |
1629 @{term th} is blocked (recall for this that a state is a list of |
1620 events). For this finiteness bound to exist, Sha et al.~informally |
1630 events). For this finiteness bound to exist, Sha et al.~informally |
1621 make two assumtions: first, there is a finite pool of threads |
1631 make two assumptions: first, there is a finite pool of threads |
1622 (active or hibernating) and second, each of them giving up its |
1632 (active or hibernating) and second, each of them giving up its |
1623 resources after a finite amount of time. However, we do not have |
1633 resources after a finite amount of time. However, we do not have |
1624 this concept of active or hibernating threads in our model. In fact |
1634 this concept of active or hibernating threads in our model. In fact |
1625 we can dispence with the first assumption altogether and allow that |
1635 we can dispence with the first assumption altogether and allow that |
1626 in our model we can create new threads or exit existing threads |
1636 in our model we can create new threads or exit existing threads |