1581 after a finite amount of time. We found that this property is not so |
1581 after a finite amount of time. We found that this property is not so |
1582 straightforward to formalise in our model. There are mainly two |
1582 straightforward to formalise in our model. There are mainly two |
1583 reasons for this: First, we do not specify what ``running'' the code |
1583 reasons for this: First, we do not specify what ``running'' the code |
1584 of a thread means, for example by giving an operational semantics |
1584 of a thread means, for example by giving an operational semantics |
1585 for machine instructions. Therefore we cannot characterise what are |
1585 for machine instructions. Therefore we cannot characterise what are |
1586 ``good'' programs that contain for every locking request also a |
1586 ``good'' programs that contain for every locking request for a |
1587 corresponding unlocking request for a resource. Second, we need to |
1587 resource also a corresponding unlocking request. Second, we need to |
1588 distinghish between a thread that ``just'' locks a resource for a |
1588 distinghish between a thread that ``just'' locks a resource for a |
1589 finite amount of time (even if it is very long) and one that locks |
1589 finite amount of time (even if it is very long) and one that locks |
1590 it forever (there might be a lookp in between the locking and |
1590 it forever (there might be a loop in between the locking and |
1591 unlocking requests). |
1591 unlocking requests). |
1592 |
1592 |
1593 Because of these problems, we decided in our earlier paper |
1593 Because of these problems, we decided in our earlier paper |
1594 \cite{ZhangUrbanWu12} to leave out this property and let the |
1594 \cite{ZhangUrbanWu12} to leave out this property and let the |
1595 programmer assume the responsibility to program threads in such a |
1595 programmer take on the responsibility to program threads in such a |
1596 benign manner (in addition to causing no circularity in the |
1596 benign manner (in addition to causing no circularity in the |
1597 RAG). This leave-it-to-the-programmer was also the approach taken by |
1597 RAG). This leave-it-to-the-programmer was also the approach taken by |
1598 Sha et al.~in their paper. However, in this paper we can make an |
1598 Sha et al.~in their paper. However, in this paper we can make an |
1599 improvement: we can look at the \emph{events} that are happening |
1599 improvement by establishing a finite bound on the duration of |
1600 after a Priority Inversion occurs. The events can be seen as a |
1600 Priority Inversion measured by the number of events. The events can |
1601 \textbf{rough} abstraction of the ``runtime behaviour'' of threads |
1601 be seen as a \textit{rough(!)} abstraction of the ``runtime |
1602 and also as an abstract notion of ``time''---when a new event |
1602 behaviour'' of threads and also as an abstract notion of |
1603 happened, some time must have passed. In this setting we can prove |
1603 ``time''---when a new event happened, some time must have passed. |
1604 a more direct bound for the absence of indefinite Priority |
1604 In this setting we can prove a more direct bound for the absence of |
1605 Inversion. This is what we shall show below. |
1605 indefinite Priority Inversion. This is what we shall show below. |
1606 |
1606 |
1607 What we will establish in this section is that there can only be a |
1607 What we will establish in this section is that there can only be a |
1608 finite amount of states after state @{term s} in which the thread |
1608 finite number of states after state @{term s} in which the thread |
1609 @{term th} is blocked. For this finiteness bound to exist, Sha et |
1609 @{term th} is blocked. For this finiteness bound to exist, Sha et |
1610 al.~assume in their work that there is a finite pool of threads |
1610 al.~informally make two assumtions: first, there is a finite pool of |
1611 (active or hibernating). However, we do not have this concept of |
1611 threads (active or hibernating) and second, each of them giving up |
1612 active or hibernating threads in our model. Rather, in our model we |
1612 its resources after a finite amount of time. However, we do not |
1613 can create or exit threads arbitrarily. Consequently, the avoidance |
1613 have this concept of active or hibernating threads in our model. In |
1614 of indefinite priority inversion we are trying to establish is in |
1614 fact we can dispence with the first assumption altogether and allow |
1615 our model not true, unless we require that the number of threads |
1615 that in our model we can create or exit threads |
1616 created is bounded in every valid future state after @{term s}. So |
1616 arbitrarily. Consequently, the avoidance of indefinite priority |
1617 our first assumption states: |
1617 inversion we are trying to establish is in our model not true, |
|
1618 unless we require that the number of threads created is bounded in |
|
1619 every valid future state after @{term s}. So our first assumption |
|
1620 states: |
1618 |
1621 |
1619 \begin{quote} {\bf Assumption on the number of threads created in |
1622 \begin{quote} {\bf Assumption on the number of threads created in |
1620 every valid state after the state {\boldmath@{text s}}:} Given the |
1623 every valid state after the state {\boldmath@{text s}}:} Given the |
1621 state @{text s}, in every ``future'' valid state @{text "t @ s"}, we |
1624 state @{text s}, in every ``future'' valid state @{text "t @ s"}, we |
1622 require that the number of created threads is less than |
1625 require that the number of created threads is less than |
1659 s}. The bound reflects how each thread @{text "th'"} is programmed: |
1662 s}. The bound reflects how each thread @{text "th'"} is programmed: |
1660 Though we cannot express what instructions a thread is executing, |
1663 Though we cannot express what instructions a thread is executing, |
1661 the events in our model correspond to the system calls made by |
1664 the events in our model correspond to the system calls made by |
1662 thread. Our @{text "BND(th')"} binds the number of these calls. |
1665 thread. Our @{text "BND(th')"} binds the number of these calls. |
1663 |
1666 |
1664 The main reason for these two assumptions is that we can prove: the |
1667 The main reason for these two assumptions is that we can prove the |
1665 number of states after @{text s} in which the thread @{text th} is |
1668 following: The number of states after @{text s} in which the thread |
1666 is not running (that is where Priority Inversion occurs) can be |
1669 @{text th} is not running (that is where Priority Inversion occurs) |
1667 bounded by the number of actions the threads in @{text blockers} |
1670 can be bounded by the number of actions the threads in @{text |
1668 perform and how many threads are newly created. This bound can be |
1671 blockers} perform and how many threads are newly created. This bound |
1669 stated for all valid states @{term "t @ s"} that can happen after |
1672 can be stated for all valid intermediate states @{term "t @ s"} that |
1670 @{text s}. To state our bound we need to make a definition of what we |
1673 can happen after @{text s}. To state our bound we need to make a |
1671 mean by intermediate states: it will be the list of traces/states starting |
1674 definition of what we mean by intermediate states; it will be the |
1672 from @{text s} ending in @{text "t @ s"} |
1675 list of states starting from @{text s} upto the state @{text "t @ |
|
1676 s"}. For example, suppose $\textit{t} = |
|
1677 [\textit{e}_n, \textit{e}_{n-1}, \ldots, \textit{e}_2, \textit{e}_1]$, then |
|
1678 the intermediate states from @{text s} upto @{text "t @ s"} are |
1673 |
1679 |
1674 \begin{center} |
1680 \begin{center} |
1675 @{text "t @ s"},\; \ldots,\; @{text "e2 :: e1 :: s"},\;@{text "e1 :: s"},\;@{text "s"} |
1681 \begin{tabular}{l} |
|
1682 $\textit{s}$\\ |
|
1683 $\textit{e}_1 :: \textit{s}$\\ |
|
1684 $\textit{e}_2 :: \textit{e}_1 :: \textit{s}$\\ |
|
1685 \ldots\\ |
|
1686 $\textit{e}_{n - 1} :: \ldots :: \textit{e}_2 :: \textit{e}_1 :: \textit{s}$\\ |
|
1687 \end{tabular} |
1676 \end{center} |
1688 \end{center} |
1677 |
1689 |
1678 \noindent This can be defined by the following recursive functions |
1690 |
|
1691 \noindent This can be defined by the following recursive function |
1679 |
1692 |
1680 \begin{center} |
1693 \begin{center} |
1681 \begin{tabular}{rcl} |
1694 \begin{tabular}{lcl} |
1682 @{text "s upto t"} & $\equiv$ & @{text "if (t = []) then [s]"} \\ |
1695 @{text "s upto []"} & $\dn$ & $[]$\\ |
1683 & & @{text "else (t @ s) :: s upto (tail t)"} |
1696 @{text "s upto (e::es)"} & $\dn$ & @{text "(es @ s) :: s upto es"} |
1684 \end{tabular} |
1697 \end{tabular} |
1685 \end{center} |
1698 \end{center} |
1686 |
1699 |
1687 |
1700 |
1688 \noindent Assume you have an extension @{text t}, this essentially |
1701 \noindent Assume you have an extension @{text t}, this essentially |