185 whereby threads, priorities and (critical) resources are represented |
185 whereby threads, priorities and (critical) resources are represented |
186 as natural numbers. The event @{term Set} models the situation that |
186 as natural numbers. The event @{term Set} models the situation that |
187 a thread obtains a new priority given by the programmer or |
187 a thread obtains a new priority given by the programmer or |
188 user (for example via the {\tt nice} utility under UNIX). As in Paulson's work, we |
188 user (for example via the {\tt nice} utility under UNIX). As in Paulson's work, we |
189 need to define functions that allow one to make some observations |
189 need to define functions that allow one to make some observations |
190 about states. One, called @{term threads}, calculates the set of |
190 about states. One, called @{term threads}, calculates, given a state @{text s}, the set of |
191 ``live'' threads that we have seen so far in a state: |
191 ``live'' threads that we have seen so far: |
192 |
192 |
193 \begin{isabelle}\ \ \ \ \ %%% |
193 \begin{isabelle}\ \ \ \ \ %%% |
194 \mbox{\begin{tabular}{lcl} |
194 \mbox{\begin{tabular}{lcl} |
195 @{thm (lhs) threads.simps(1)} & @{text "\<equiv>"} & |
195 @{thm (lhs) threads.simps(1)} & @{text "\<equiv>"} & |
196 @{thm (rhs) threads.simps(1)}\\ |
196 @{thm (rhs) threads.simps(1)}\\ |
250 The point of precedences is to schedule threads not according to priorities (because what should |
250 The point of precedences is to schedule threads not according to priorities (because what should |
251 we do in case two threads have the same priority), but according to precedences. |
251 we do in case two threads have the same priority), but according to precedences. |
252 Precedences allow us to always discriminate between two threads with equal priority by |
252 Precedences allow us to always discriminate between two threads with equal priority by |
253 tacking into account the time when the priority was last set. We order precedences so |
253 tacking into account the time when the priority was last set. We order precedences so |
254 that threads with the same priority get a higher precedence if their priority has been |
254 that threads with the same priority get a higher precedence if their priority has been |
255 set earlier, since for such threads it is more urgent to finish their work. In an impementation |
255 set earlier, since for such threads it is more urgent to finish their work. In an implementation |
256 this choice would translate to a quite natural a FIFO-scheduling of processes with |
256 this choice would translate to a quite natural FIFO-scheduling of processes with |
257 the same priority. |
257 the same priority. |
258 |
258 |
259 Next, we introduce the concept of \emph{waiting queues}. They are |
259 Next, we introduce the concept of \emph{waiting queues}. They are |
260 lists of threads associated with every resource. The first thread in |
260 lists of threads associated with every resource. The first thread in |
261 this list (the head, or short @{term hd}) is chosen to be the one |
261 this list (the head, or short @{term hd}) is chosen to be the one |
262 that is in possession of the |
262 that is in possession of the |
263 ``lock'' of the corresponding resource. We model waiting queues as |
263 ``lock'' of the corresponding resource. We model waiting queues as |
264 functions, below abbreviated as @{text wq}, taking a resource as |
264 functions, below abbreviated as @{text wq}. They take a resource as |
265 argument and returning a list of threads. This allows us to define |
265 argument and return a list of threads. This allows us to define |
266 when a thread \emph{holds}, respectively \emph{waits} for, a |
266 when a thread \emph{holds}, respectively \emph{waits} for, a |
267 resource @{text cs} given a waiting queue function. |
267 resource @{text cs} given a waiting queue function @{text wq}. |
268 |
268 |
269 \begin{isabelle}\ \ \ \ \ %%% |
269 \begin{isabelle}\ \ \ \ \ %%% |
270 \begin{tabular}{@ {}l} |
270 \begin{tabular}{@ {}l} |
271 @{thm cs_holding_def[where thread="th"]}\\ |
271 @{thm cs_holding_def[where thread="th"]}\\ |
272 @{thm cs_waiting_def[where thread="th"]} |
272 @{thm cs_waiting_def[where thread="th"]} |
325 \begin{isabelle}\ \ \ \ \ %%% |
325 \begin{isabelle}\ \ \ \ \ %%% |
326 @{thm cs_dependents_def} |
326 @{thm cs_dependents_def} |
327 \end{isabelle} |
327 \end{isabelle} |
328 |
328 |
329 \noindent |
329 \noindent |
330 This definition needs to account for all threads that wait for tread to |
330 This definition needs to account for all threads that wait for a tread to |
331 release a resource. This means we need to include threads that transitively |
331 release a resource. This means we need to include threads that transitively |
332 wait for a resource being realeased (in the picture this means also @{text "th\<^isub>3"}, |
332 wait for a resource being realeased (in the picture above this means also @{text "th\<^isub>3"}, |
333 which cannot make any progress unless @{text "th\<^isub>2"} makes progress which |
333 which cannot make any progress unless @{text "th\<^isub>2"} makes progress which |
334 in turn waits for @{text "th\<^isub>1"}). If there is a cirle in a RAG, then clearly |
334 in turn needs to wait for @{text "th\<^isub>1"}). If there is a cirle in a RAG, then clearly |
335 we have a deadlock. Therefore when a thread requests a resource, |
335 we have a deadlock. Therefore when a thread requests a resource, |
336 we must ensure that the resulting RAG is not not circular. |
336 we must ensure that the resulting RAG is not not circular. |
337 |
337 |
338 Next we introduce the notion of \emph{current precedence} for a thread @{text th} in a |
338 Next we introduce the notion of the \emph{current precedence} for a thread @{text th} in a |
339 state @{text s}, which is defined as |
339 state @{text s}, which is defined as |
340 |
340 |
341 \begin{isabelle}\ \ \ \ \ %%% |
341 \begin{isabelle}\ \ \ \ \ %%% |
342 @{thm cpreced_def2} |
342 @{thm cpreced_def2} |
343 \end{isabelle} |
343 \end{isabelle} |
344 |
344 |
345 \noindent |
345 \noindent |
346 While the precedence of a thread is determined by the programmer (for example when the thread is |
346 While the precedence @{term prec} of a thread is determined by the programmer |
|
347 (for example when the thread is |
347 created), the point of the current precedence is to let scheduler increase this |
348 created), the point of the current precedence is to let scheduler increase this |
348 priority, if needed according to PIP. Therefore the current precedence of @{text th} is |
349 priority, if needed according to PIP. Therefore the current precedence of @{text th} is |
349 given as the maximum of the precedence @{text th} has in state @{text s} \emph{and} all |
350 given as the maximum of the precedence @{text th} has in state @{text s} \emph{and} all |
350 processes that are dependants of @{text th}. Since the notion @{term "dependents"} is |
351 processes that are dependants of @{text th}. Since the notion @{term "dependents"} is |
351 defined as the transitive closure of all dependent threads, we deal correctly with the |
352 defined as the transitive closure of all dependent threads, we deal correctly with the |
352 problem in the algorithm by Sha et al.~\cite{Sha90} where a priority of a thread is |
353 problem in the algorithm by Sha et al.~\cite{Sha90} where a priority of a thread is |
353 lowered prematurely. |
354 lowered prematurely. |
354 |
355 |
355 The next function, called @{term schs}, defines the behaviour of the scheduler. It is defined |
356 The next function, called @{term schs}, defines the behaviour of the scheduler. It is defined |
356 by recursion on the state (a list of events); @{term "schs"} takes a state as argument |
357 by recursion on the state (a list of events); @{term "schs"} takes a state as argument |
357 and returns a \emph{schedule state}, which we defined as a record consisting of ... |
358 and returns a \emph{schedule state}, which we define as a record consisting of two |
|
359 functions |
|
360 |
|
361 \begin{isabelle}\ \ \ \ \ %%% |
|
362 @{text "\<lparr>wq_fun, cprec_fun\<rparr>"} |
|
363 \end{isabelle} |
358 |
364 |
359 In the initial state, the scheduler starts with all resources unlocked and the |
365 In the initial state, the scheduler starts with all resources unlocked and the |
360 precedence of every thread is initialised with @{term "Prc 0 0"}. |
366 precedence of every thread is initialised with @{term "Prc 0 0"}. |
361 |
367 |
362 \begin{isabelle}\ \ \ \ \ %%% |
368 \begin{isabelle}\ \ \ \ \ %%% |