1586 for machine instructions. Therefore we cannot characterise what are |
1586 for machine instructions. Therefore we cannot characterise what are |
1587 ``good'' programs that contain for every locking request for a |
1587 ``good'' programs that contain for every locking request for a |
1588 resource also a corresponding unlocking request. Second, we need to |
1588 resource also a corresponding unlocking request. Second, we need to |
1589 distinghish between a thread that ``just'' locks a resource for a |
1589 distinghish between a thread that ``just'' locks a resource for a |
1590 finite amount of time (even if it is very long) and one that locks |
1590 finite amount of time (even if it is very long) and one that locks |
1591 it forever (there might be a loop in between the locking and |
1591 it forever (there might be an unbounded loop in between the locking and |
1592 unlocking requests). |
1592 unlocking requests). |
1593 |
1593 |
1594 Because of these problems, we decided in our earlier paper |
1594 Because of these problems, we decided in our earlier paper |
1595 \cite{ZhangUrbanWu12} to leave out this property and let the |
1595 \cite{ZhangUrbanWu12} to leave out this property and let the |
1596 programmer take on the responsibility to program threads in such a |
1596 programmer take on the responsibility to program threads in such a |
1599 Sha et al.~in their paper. However, in this paper we can make an |
1599 Sha et al.~in their paper. However, in this paper we can make an |
1600 improvement by establishing a finite bound on the duration of |
1600 improvement by establishing a finite bound on the duration of |
1601 Priority Inversion measured by the number of events. The events can |
1601 Priority Inversion measured by the number of events. The events can |
1602 be seen as a \textit{rough(!)} abstraction of the ``runtime |
1602 be seen as a \textit{rough(!)} abstraction of the ``runtime |
1603 behaviour'' of threads and also as an abstract notion of |
1603 behaviour'' of threads and also as an abstract notion of |
1604 ``time''---when a new event happened, some time must have passed. |
1604 ``time''---when a new event happens, some time must have passed. |
1605 |
1605 |
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 number 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 (recall for this that a state is a list of |
1610 al.~informally make two assumtions: first, there is a finite pool of |
1610 events). For this finiteness bound to exist, Sha et al.~informally |
1611 threads (active or hibernating) and second, each of them giving up |
1611 make two assumtions: first, there is a finite pool of threads |
1612 its resources after a finite amount of time. However, we do not |
1612 (active or hibernating) and second, each of them giving up its |
1613 have this concept of active or hibernating threads in our model. In |
1613 resources after a finite amount of time. However, we do not have |
1614 fact we can dispence with the first assumption altogether and allow |
1614 this concept of active or hibernating threads in our model. In fact |
1615 that in our model we can create or exit threads |
1615 we can dispence with the first assumption altogether and allow that |
|
1616 in our model we can create new threads or exit existing threads |
1616 arbitrarily. Consequently, the avoidance of indefinite priority |
1617 arbitrarily. Consequently, the avoidance of indefinite priority |
1617 inversion we are trying to establish is in our model not true, |
1618 inversion we are trying to establish is in our model not true, |
1618 unless we put up an upper bound on the number of threads that |
1619 unless we stipulate an upper bound on the number of threads that |
1619 have been created upto any valid future state after @{term |
1620 have been created during the time leading to any future state |
1620 s}. Otherwise our PIP scheduler could be ``swamped'' with @{text |
1621 after @{term s}. Otherwise our PIP scheduler could be ``swamped'' |
1621 "Create"}-requests. So our first assumption states: |
1622 with @{text "Create"}-requests. So our first assumption states: |
1622 |
1623 |
1623 \begin{quote} {\bf Assumption on the number of threads created |
1624 \begin{quote} {\bf Assumption on the number of threads created |
1624 after the state {\boldmath@{text s}}:} Given the |
1625 after the state {\boldmath@{text s}}:} Given the |
1625 state @{text s}, in every ``future'' valid state @{text "es @ s"}, we |
1626 state @{text s}, in every ``future'' valid state @{text "es @ s"}, we |
1626 require that the number of created threads is less than |
1627 require that the number of created threads is less than |
1636 "s' @ s"} after @{text s}. Instead, we need to put this bound on |
1637 "s' @ s"} after @{text s}. Instead, we need to put this bound on |
1637 the @{text "Create"} events for all valid states after @{text s}. |
1638 the @{text "Create"} events for all valid states after @{text s}. |
1638 This ensures that no matter which ``future'' state is reached, the |
1639 This ensures that no matter which ``future'' state is reached, the |
1639 number of @{text "Create"}-events is finite. We use @{text "es @ s"} |
1640 number of @{text "Create"}-events is finite. We use @{text "es @ s"} |
1640 to stand for \emph{future states} after @{text s}---it is @{text s} |
1641 to stand for \emph{future states} after @{text s}---it is @{text s} |
1641 extended with some list of events. |
1642 extended with some list @{text es} of events. |
1642 |
1643 |
1643 For our second assumption about giving up resources after a finite |
1644 For our second assumption about giving up resources after a finite |
1644 amount of ``time'', let us introduce the following definition about |
1645 amount of ``time'', let us introduce the following definition about |
1645 threads that can potentially block @{text th}: |
1646 threads that can potentially block @{text th}: |
1646 |
1647 |
1649 \end{isabelle} |
1650 \end{isabelle} |
1650 |
1651 |
1651 \noindent This set contains all treads that are not detached in |
1652 \noindent This set contains all treads that are not detached in |
1652 state @{text s}. According to our definiton of @{text "detached"}, |
1653 state @{text s}. According to our definiton of @{text "detached"}, |
1653 this means a thread in @{text "blockers"} either holds or waits for |
1654 this means a thread in @{text "blockers"} either holds or waits for |
1654 some resource. Our Theorem~1 implies that they can all potentially |
1655 some resource in state @{text s} . Our Them~1 implies that any of |
1655 block @{text th} after state @{text s}. We need to make the |
1656 those threads can all potentially block @{text th} after state |
1656 following assumption about the threads in this set: |
1657 @{text s}. We need to make the following assumption about the |
|
1658 threads in the @{text "blockers"}-set: |
1657 |
1659 |
1658 \begin{quote} |
1660 \begin{quote} |
1659 {\bf Assumptions on the threads {\boldmath{@{term "th' \<in> blockers"}}}:} |
1661 {\bf Assumptions on the threads {\boldmath{@{term "th' \<in> blockers"}}}:} |
1660 For each such @{text "th'"} there exists a finite bound @{text "BND(th')"} |
1662 For each such @{text "th'"} there exists a finite bound @{text "BND(th')"} |
1661 such that for all future |
1663 such that for all future |
1669 anymore) after a finite number of events in @{text "es @ s"}. Again |
1671 anymore) after a finite number of events in @{text "es @ s"}. Again |
1670 we have to state this bound to hold in all valid states after @{text |
1672 we have to state this bound to hold in all valid states after @{text |
1671 s}. The bound reflects how each thread @{text "th'"} is programmed: |
1673 s}. The bound reflects how each thread @{text "th'"} is programmed: |
1672 Though we cannot express what instructions a thread is executing, |
1674 Though we cannot express what instructions a thread is executing, |
1673 the events in our model correspond to the system calls made by |
1675 the events in our model correspond to the system calls made by |
1674 thread. Our @{text "BND(th')"} binds the number of these ``calls''. |
1676 a thread. Our @{text "BND(th')"} binds the number of these ``calls''. |
1675 |
1677 |
1676 The main reason for these two assumptions is that we can prove the |
1678 The main reason for these two assumptions is that we can prove the |
1677 following: The number of states after @{text s} in which the thread |
1679 following: The number of states after @{text s} in which the thread |
1678 @{text th} is not running (that is where Priority Inversion occurs) |
1680 @{text th} is not running (that is where Priority Inversion occurs) |
1679 can be bounded by the number of actions the threads in @{text |
1681 can be bounded by the number of actions the threads in @{text |
1680 blockers} perform and how many threads are newly created. To state |
1682 blockers} perform (i.e.~events) and how many threads are newly |
1681 our bound formally, we need to make a definition of what we mean by |
1683 created. To state our bound formally, we need to make a definition |
1682 intermediate states; it will be the list of states starting from |
1684 of what we mean by intermediate states between a state @{text s} and |
1683 @{text s} upto the state @{text "es @ s"}. For example, suppose |
1685 a future state after @{text s}; they will be the list of states |
1684 $\textit{es} = [\textit{e}_n, \textit{e}_{n-1}, \ldots, \textit{e}_2, |
1686 starting from @{text s} upto the state \mbox{@{text "es @ s"}}. For |
1685 \textit{e}_1]$, then the intermediate states from @{text s} upto |
1687 example, suppose $\textit{es} = [\textit{e}_n, \textit{e}_{n-1}, |
1686 @{text "es @ s"} are |
1688 \ldots, \textit{e}_2, \textit{e}_1]$, then the intermediate states |
|
1689 from @{text s} upto @{text "es @ s"} are |
1687 |
1690 |
1688 \begin{center} |
1691 \begin{center} |
1689 \begin{tabular}{l} |
1692 \begin{tabular}{l} |
1690 $\textit{s}$\\ |
1693 $\textit{s}$\\ |
1691 $\textit{e}_1 :: \textit{s}$\\ |
1694 $\textit{e}_1 :: \textit{s}$\\ |
1709 \noindent |
1712 \noindent |
1710 Our theorem can then be stated as follows: |
1713 Our theorem can then be stated as follows: |
1711 |
1714 |
1712 \begin{theorem} |
1715 \begin{theorem} |
1713 Given our assumptions about bounds, we have that |
1716 Given our assumptions about bounds, we have that |
1714 |
|
1715 \[ |
1717 \[ |
1716 @{text "len"}\,[@{text "s'"} |
1718 @{text "len"}\,[@{text "s'"} |
1717 \leftarrow @{text "s upto es"}.\;\; @{text "th"} \not\in @{text "running s'"}] \;\;\leq\;\; |
1719 \leftarrow @{text "s upto es"}.\;\; @{text "th"} \not\in @{text "running s'"}] \;\;\leq\;\; |
1718 @{text "BC"} + \sum @{text "th'"} \in @{text "blockers"}.\;\; @{text "BND(th')"}\;. |
1720 @{text "BC"} + \sum @{text "th'"} \in @{text "blockers"}.\;\; @{text "BND(th')"}\;. |
1719 \] |
1721 \] |
1720 |
|
1721 \end{theorem} |
1722 \end{theorem} |
1722 |
1723 |
|
1724 \noindent This theorem uses Isabelle's list-comprehension notation, |
|
1725 which lists all intermediate states between @{text s} and @{text "es |
|
1726 @ s"}, and then filters this list according to states in which |
|
1727 @{text th} is not running. By calculating the number of elements in |
|
1728 the filtered list using the function @{text len}, we have the number |
|
1729 of intermediate states in which @{text th} is not running and which |
|
1730 by the theorem is bounded by the term on the right-hand side. |
|
1731 |
1723 \begin{proof} There are two characterisations for the number of |
1732 \begin{proof} There are two characterisations for the number of |
1724 events in @{text es}: First, for each corresponding state in @{text |
1733 events in @{text es}: First, in each state in |
1725 "s upto es"}, either @{text th} is running or not running. That |
1734 @{text "s upto es"}, clearly either @{text th} is running or |
1726 means |
1735 not running. Together with @{text "len es = len (s upto es)"}, that |
1727 |
1736 implies % |
1728 \begin{equation}\label{firsteq} |
1737 |
1729 @{text "len es"} = |
1738 \begin{equation} |
1730 @{text len} [@{text "s'"} \leftarrow @{text "s upto es"}.\;\; @{text "th"} \in @{text "running s'"}] + |
1739 \label{firsteq} |
1731 @{text len} [@{text "s'"} \leftarrow @{text "s upto es"}.\;\; @{text "th"} \not\in @{text "running s'"}] |
1740 \begin{array}{lcl} |
|
1741 @{text "len es"} & \;=\; & |
|
1742 @{text len}\, [@{text "s'"} \leftarrow @{text "s upto es"}.\;\; @{text "th"} \in @{text "running s'"}]\\ |
|
1743 & & +\; |
|
1744 @{text len}\, [@{text "s'"} \leftarrow @{text "s upto es"}.\;\; @{text "th"} \not\in @{text "running s'"}] |
|
1745 \end{array} |
1732 \end{equation} |
1746 \end{equation} |
1733 |
1747 |
1734 \noindent Second by Thm~\ref{mainthm}, the events are either the |
1748 \noindent Second by Thm~\ref{mainthm}, the events are either the |
1735 actions of @{text th} or @{text "Create"}-events or actions of the |
1749 actions of @{text th} or @{text "Create"}-events or actions of the |
1736 threads in blockers. That is |
1750 threads in blockers. That is |
1737 |
1751 % |
1738 \begin{equation}\label{secondeq} |
1752 \begin{equation}\label{secondeq} |
1739 @{text "len es"} = @{text "len (actions_of {th} es)"} + |
1753 \begin{array}{lcl} |
1740 @{text "len (filter isCreate es)"} + |
1754 @{text "len es"} & \;=\; & @{text "len (actions_of {th} es)"}\\ |
1741 @{text "len (actions_of blockers es)"} |
1755 & & +\; @{text "len (filter isCreate es)"}\\ |
|
1756 & & +\; @{text "len (actions_of blockers es)"} |
|
1757 \end{array} |
1742 \end{equation} |
1758 \end{equation} |
1743 |
1759 |
1744 \noindent |
1760 \noindent Furthermore we know that an action of @{text th} in the |
1745 Further we know that an action of @{text th} can only be taken when @{text th} is running. Therefore |
1761 intermediate states @{text "s upto es"} can only be taken when |
1746 |
1762 @{text th} is running. Therefore |
|
1763 % |
1747 \[ |
1764 \[ |
1748 @{text "len (actions_of {th} es)"} \leq |
1765 @{text "len (actions_of {th} es)"} \;\leq\; |
1749 @{text len} [@{text "s'"} \leftarrow @{text "s upto es"}.\;\; @{text "th"} \in @{text "running s'"}] |
1766 @{text len}\,[@{text "s'"} \leftarrow @{text "s upto es"}.\;\; @{text "th"} \in @{text "running s'"}] |
1750 \] |
1767 \] |
1751 |
1768 |
1752 \noindent Substituting this into \eqref{firsteq} gives |
1769 \noindent holds. Substituting this into \eqref{firsteq} gives |
1753 |
1770 % |
1754 \[ |
1771 \[ |
1755 @{text len} [@{text "s'"} \leftarrow @{text "s upto es"}.\;\; @{text "th"} \not\in @{text "running s'"}] |
1772 @{text len}\,[@{text "s'"} \leftarrow @{text "s upto es"}.\;\; @{text "th"} \not\in @{text "running s'"}] |
1756 \leq @{text "len es"} - @{text "len (actions_of {th} es)"} |
1773 \;\leq\; @{text "len es"} - @{text "len (actions_of {th} es)"} |
1757 \] |
1774 \] |
1758 |
1775 |
|
1776 \noindent |
1759 into which we can substitute \eqref{secondeq} yielding |
1777 into which we can substitute \eqref{secondeq} yielding |
1760 |
1778 % |
1761 \[ |
1779 \[ |
1762 @{text len} [@{text "s'"} \leftarrow @{text "s upto es"}.\;\; @{text "th"} \not\in @{text "running s'"}] \leq |
1780 \begin{array}{rcl} |
1763 @{text "len (filter isCreate es)"} + @{text "len (actions_of blockers es)"} |
1781 @{text len} [@{text "s'"} \leftarrow @{text "s upto es"}.\;\; @{text "th"} \not\in @{text "running s'"}] & \;\;\leq\;\; & |
|
1782 @{text "len (filter isCreate es)"}\\ |
|
1783 & & \quad + @{text "len (actions_of blockers es)"} |
|
1784 \end{array} |
1764 \] |
1785 \] |
1765 |
1786 |
1766 \noindent By our first assumption we know that the @{text |
1787 \noindent By our first assumption we know that the number of @{text |
1767 "Create"}-events are bounded by the bound @{text BC}. By our second |
1788 "Create"}-events are bounded by the bound @{text BC}. By our second |
1768 assumption we can prove that the actions of all blockers is bounded |
1789 assumption we can prove that the actions of all blockers is bounded |
1769 by the sum of bounds of the individual blocking threads, that is |
1790 by the sum of bounds of the individual blocking threads, that is |
1770 |
1791 |
1771 \[ |
1792 \[ |
1775 |
1796 |
1776 \noindent With this in place we can conclude our theorem.\hfill\qed |
1797 \noindent With this in place we can conclude our theorem.\hfill\qed |
1777 \end{proof} |
1798 \end{proof} |
1778 |
1799 |
1779 \noindent This theorem is the main conclusion we obtain for the |
1800 \noindent This theorem is the main conclusion we obtain for the |
1780 Priority Inheritance Protocol: it shows that the set of @{text blockers} |
1801 Priority Inheritance Protocol. It is based on the fact that the set of |
1781 is fixed at state @{text s} when @{text th} becomes the thread with |
1802 @{text blockers} is fixed at state @{text s} when @{text th} becomes |
1782 highest priority. Then no additional blocker of @{text th} can |
1803 the thread with highest priority. Then no additional blocker of |
1783 appear after the state @{text s}. And in this way we can bound the |
1804 @{text th} can appear after the state @{text s}. And in this way we |
1784 number of states where the thread @{text th} with the highest |
1805 can bound the number of states where the thread @{text th} with the |
1785 priority is prevented from running. |
1806 highest priority is prevented from running. |
1786 *} |
1807 Our bound does not depend on the restriction of well-nested critical |
1787 (*<*) |
1808 sections in the Priority Inheritance Protocol as imposed by Sha et al. |
1788 end |
1809 *} (*<*) end (*>*) |
1789 (*>*) |
|
1790 |
1810 |
1791 section {* Properties for an Implementation\label{implement} *} |
1811 section {* Properties for an Implementation\label{implement} *} |
1792 |
1812 |
1793 text {* |
1813 text {* |
1794 While our formalised proof gives us confidence about the correctness of our model of PIP, |
1814 While our formalised proof gives us confidence about the correctness of our model of PIP, |
1801 We can however improve upon this. For this let us define the notion |
1821 We can however improve upon this. For this let us define the notion |
1802 of @{term children} of a thread @{text th} in a state @{text s} as |
1822 of @{term children} of a thread @{text th} in a state @{text s} as |
1803 |
1823 |
1804 \begin{isabelle}\ \ \ \ \ %%% |
1824 \begin{isabelle}\ \ \ \ \ %%% |
1805 \begin{tabular}{@ {}l} |
1825 \begin{tabular}{@ {}l} |
1806 HERE?? %%@ {thm children_def2} |
1826 ?? @{thm children_def} |
1807 \end{tabular} |
1827 \end{tabular} |
1808 \end{isabelle} |
1828 \end{isabelle} |
1809 |
1829 |
1810 \noindent |
1830 \noindent |
1811 where a child is a thread that is only one ``hop'' away from the thread |
1831 where a child is a thread that is only one ``hop'' away from the thread |
1812 @{text th} in the @{term RAG} (and waiting for @{text th} to release |
1832 @{text th} in the @{term RAG} (and waiting for @{text th} to release |
1813 a resource). We can prove the following lemma. |
1833 a resource). We can prove the following lemma. |
1814 |
1834 |
1815 \begin{lemma}\label{childrenlem} |
1835 \begin{lemma}\label{childrenlem} |
1816 HERE %@{text "If"} @ {thm (prem 1) cp_rec} @{text "then"} |
1836 HERE %@ {text "If"} @ {thm (prem 1) cp_rec} @{text "then"} |
1817 \begin{center} |
1837 \begin{center} |
1818 %@ {thm (concl) cp_rec}. |
1838 %@ {thm (concl) cp_rec}. |
1819 \end{center} |
1839 \end{center} |
1820 \end{lemma} |
1840 \end{lemma} |
1821 |
1841 |