2062 In the second case we know that resource @{text cs} is locked. We can show that |
2062 In the second case we know that resource @{text cs} is locked. We can show that |
2063 |
2063 |
2064 \begin{isabelle}\ \ \ \ \ %%% |
2064 \begin{isabelle}\ \ \ \ \ %%% |
2065 \begin{tabular}{@ {}l} |
2065 \begin{tabular}{@ {}l} |
2066 @{thm (concl) valid_trace_p_w.RAG_es}\\ |
2066 @{thm (concl) valid_trace_p_w.RAG_es}\\ |
2067 @{text "If"} @{thm (prem 2) valid_trace_p_w.cp_kept} @{text "then"} |
2067 @{text "If"} @{thm (prem 2) valid_trace_p_w.cp_kept_tG} @{text "then"} |
2068 @{thm (concl) valid_trace_p_w.cp_kept_tG} |
2068 @{thm (concl) valid_trace_p_w.cp_kept_tG} |
2069 \end{tabular} |
2069 \end{tabular} |
2070 \end{isabelle} |
2070 \end{isabelle} |
2071 |
2071 |
2072 \noindent |
2072 \noindent That means we have to add a waiting edge to the @{text |
2073 That means we have to add a waiting edge to the @{text RAG}. Furthermore |
2073 RAG}. Furthermore the current precedence for all threads that are |
2074 the current precedence for all threads that are not dependants of @{text "th'"} |
2074 not ancestors of @{text "th"} are unchanged. For the others we need |
2075 are unchanged. For the others we need to follow the edges |
2075 to follow the edges in the @{text TDG} and recompute the @{term |
2076 in the @{text RAG} and recompute the @{term "cp"}. To do this we can start from @{term "th"} |
2076 "cp"}. To do this we can start from @{term "th"} and follow the |
2077 and follow the @{term "depend"}-edges to recompute using Lemma~\ref{childrenlem} |
2077 @{term "children"}-edges to recompute the @{term "cp"} of every |
2078 the @{term "cp"} of every |
2078 thread encountered on the way using Lemma~\ref{childrenlem}. Since |
2079 thread encountered on the way. Since the @{term "depend"} |
2079 the @{text RAG}, and thus @{text "TDG"}, are loop free, this |
2080 is loop free, this procedure will always stop. The following lemma shows, however, |
2080 procedure will always stop. The following lemma shows, however, that |
2081 that this procedure can actually stop often earlier without having to consider all |
2081 this procedure can actually stop often earlier without having to |
2082 dependants. |
2082 consider all ancestors. |
2083 |
2083 |
2084 \begin{isabelle}\ \ \ \ \ %%% |
2084 \begin{isabelle}\ \ \ \ \ %%% |
2085 \begin{tabular}{@ {}l} |
2085 \begin{tabular}{@ {}ll} |
2086 %%@ {t hm[mode=IfThen] eq_up_self}\\ |
2086 @{text If} & @{thm (prem 2) valid_trace_p_w.cp_up_tG}\\ |
2087 HERE |
2087 & @{thm (prem 4) valid_trace_p_w.cp_up_tG} and \\ |
2088 %@{text "If"} @ {thm (prem 1) eq_up}, @ {thm (prem 2) eq_up} and @ {thm (prem 3) eq_up}\\ |
2088 & @{thm (prem 3) valid_trace_p_w.cp_up_tG}\\ |
2089 %@{text "then"} @ {thm (concl) eq_up}. |
2089 & @{text then} @{thm (concl) valid_trace_p_w.cp_up_tG}\\ |
2090 \end{tabular} |
2090 \end{tabular} |
2091 \end{isabelle} |
2091 \end{isabelle} |
2092 |
2092 |
2093 \noindent |
2093 \noindent This lemma states that if an intermediate @{term cp}-value |
2094 This lemma states that if an intermediate @{term cp}-value does not change, then |
2094 does not change (in this case the @{text cprec}-value of @{text "th'"}), then the procedure can |
2095 the procedure can also stop, because none of its dependent threads will |
2095 also stop, because none of @{text "th'"} ancestor-threads will have their |
2096 have their current precedence changed. |
2096 current precedence changed. |
2097 *} |
2097 |
|
2098 *} |
2098 |
2099 |
2099 text {* |
2100 text {* |
2100 As can be seen, a pleasing byproduct of our formalisation is that the properties in |
2101 As can be seen, a pleasing byproduct of our formalisation is that the properties in |
2101 this section closely inform an implementation of PIP, namely whether the |
2102 this section closely inform an implementation of PIP, namely whether the |
2102 RAG needs to be reconfigured or current precedences need to |
2103 @{text RAG} needs to be reconfigured or current precedences need to |
2103 be recalculated for an event. This information is provided by the lemmas we proved. |
2104 be recalculated for an event. This information is provided by the lemmas we proved. |
2104 We confirmed that our observations translate into practice by implementing |
2105 We confirmed that our observations translate into practice by implementing |
2105 our version of PIP on top of PINTOS, a small operating system written in C and used for teaching at |
2106 our version of PIP on top of PINTOS, a small operating system written in C and used for teaching at |
2106 Stanford University \cite{PINTOS}. An alternative would have been the small Xv6 operating |
2107 Stanford University \cite{PINTOS}. An alternative would have been the small Xv6 operating |
2107 system used for teaching at MIT \cite{Xv6link,Xv6}. However this operating system implements |
2108 system used for teaching at MIT \cite{Xv6link,Xv6}. However this operating system implements |
2210 The waiting queue is referenced in the usual C-way as @{ML_text "&lock->wq"}. |
2211 The waiting queue is referenced in the usual C-way as @{ML_text "&lock->wq"}. |
2211 Next, we record that the current thread is waiting for the lock (Line 10). |
2212 Next, we record that the current thread is waiting for the lock (Line 10). |
2212 Thus we established two pointers: one in the waiting queue of the lock pointing to the |
2213 Thus we established two pointers: one in the waiting queue of the lock pointing to the |
2213 current thread, and the other from the currend thread pointing to the lock. |
2214 current thread, and the other from the currend thread pointing to the lock. |
2214 According to our specification in Section~\ref{model} and the properties we were able |
2215 According to our specification in Section~\ref{model} and the properties we were able |
2215 to prove for @{text P}, we need to ``chase'' all the dependants |
2216 to prove for @{text P}, we need to ``chase'' all the ancestor threads |
2216 in the RAG (Resource Allocation Graph) and update their |
2217 in the @{text RAG} and update their |
2217 current precedence; however we only have to do this as long as there is change in the |
2218 current precedence; however we only have to do this as long as there is change in the |
2218 current precedence. |
2219 current precedence. |
2219 |
2220 |
2220 The ``chase'' is implemented in the while-loop in Lines 13 to 24. |
2221 The ``chase'' is implemented in the while-loop in Lines 13 to 24. |
2221 To initialise the loop, we |
2222 To initialise the loop, we |
2224 Inside the loop, we first update the precedence of the lock held by @{ML_text pt} (Line 14). |
2225 Inside the loop, we first update the precedence of the lock held by @{ML_text pt} (Line 14). |
2225 Next, we check whether there is a change in the current precedence of @{ML_text pt}. If not, |
2226 Next, we check whether there is a change in the current precedence of @{ML_text pt}. If not, |
2226 then we leave the loop, since nothing else needs to be updated (Lines 15 and 16). |
2227 then we leave the loop, since nothing else needs to be updated (Lines 15 and 16). |
2227 If there is a change, then we have to continue our ``chase''. We check what lock the |
2228 If there is a change, then we have to continue our ``chase''. We check what lock the |
2228 thread @{ML_text pt} is waiting for (Lines 17 and 18). If there is none, then |
2229 thread @{ML_text pt} is waiting for (Lines 17 and 18). If there is none, then |
2229 the thread @{ML_text pt} is ready (the ``chase'' is finished with finding a root in the RAG). In this |
2230 the thread @{ML_text pt} is ready (the ``chase'' is finished with finding a root in the @{text RAG}). |
|
2231 In this |
2230 case we update the ready-queue accordingly (Lines 19 and 20). If there is a lock @{ML_text pt} is |
2232 case we update the ready-queue accordingly (Lines 19 and 20). If there is a lock @{ML_text pt} is |
2231 waiting for, we update the waiting queue for this lock and we continue the loop with |
2233 waiting for, we update the waiting queue for this lock and we continue the loop with |
2232 the holder of that lock |
2234 the holder of that lock |
2233 (Lines 22 and 23). After all current precedences have been updated, we finally need |
2235 (Lines 22 and 23). After all current precedences have been updated, we finally need |
2234 to block the current thread, because the lock it asked for was taken (Line 25). |
2236 to block the current thread, because the lock it asked for was taken (Line 25). |