You are on page 1of 11

4 Deadlocks

Computer systems are full of shared resources, and it is necessary in several situations to control use of these
resources so that only one process can use one of them at a time (i.e., mutual exclusion). For example, two
processes should not send output to the same printer at the same time. Usually, a process needs to have
exclusive access to more than just one resource, and this may lead to deadlock. Some of these request patterns
may lead to deadlock, for example, process A having exclusive access to resource X and is blocked requesting
resource Y which is currently held by process B which in turn is blocked requesting resource X.
A set of processes is said to be deadlocked if each process in the set is waiting for an event that only another
process in the set can cause (in the example above, the event would be releasing a resource that a process
needs). Deadlock can occur under several other circumstances, including the need for exclusive use of shared
memory, the need for exclusive use of shared devices in a networked environment, the need to access database
records that are locked by processes that are reading/updating the records, etc.
If any of the resources in the paragraphs above were preemptable, meaning the resource can be taken away
from the process without causing an error in the computation, then the deadlock could be avoided. It all of the
resources were nonpreemptable, meaning taking them away would lead to error in the computation, then the
deadlock would be possible.
Like critical sections, deadlock is a global condition, not a local one. That is, the individual threads involved in
a deadlock have no error. The problem arises from the collective action of a group of threads. Four conditions
must hold for there to be a deadlock:
1. Mutual exclusion: Each resource is either currently assigned to exactly one (and no other) process or is
available.
2. Hold and wait condition: Processes currently holding resources granted earlier are allowed to request
new resources
3. No pre-emption condition: Resources previously granted to a process cannot be forcibly taken away
from the process. They must be explicitly released by the process holding them.
4. Circular wait condition: There must be a circular chain of two or more processes, each of which is
waiting for a resource held by the next member of the chain.

4.1 Deadlock Modelling


How can deadlock be modelled so that it could be understood better?
The model represents which resources are allocated to each process. There are two levels to the model: a system
state-transition model, and a process-resource graph. The system state-transition model represents every state
the system could be in at any given moment, with the goal of identifying the states in which two or more
processes are deadlocked. This knowledge can then guide policies for implementing deadlock avoidance,
prevention, and detection strategies.
The process-resource model describes the details for an individual system state: which processes have been
allocated particular resources, which processes are blocked waiting for resources, etc.

4.1.1 Process-Resource Graph


A process-resource graph is a directed graph with two kinds of nodes: processes, shown as circles, and
resources, shown as squares.
An arc from a resource node to a process node means that the resource has previously been requested, granted
to, and is currently held by that process (see Figure 42 (a)).
An arc from a process to a resource node means that the process is currently blocked waiting for that resource
(see Figure 42 (b)).
Figure 42(c) shows a deadlock. Process C is waiting for resource T which is held by process D. Process D is
not able to release resource T because it is blocked waiting for resource U which is currently held by the

CSC 314 – Operating Systems Denis L. Nkweteyim Page 65


blocked process C. A cycle in the graph is an indication of a deadlock involving the processes and resources in
the cycle, assuming that there is only one resource of that type available. If resource T represents a floppy disk
drive for example, and there are two of them available in the system, then there would be no deadlock because
one of them would be allocated to process D, and the other to process S.

Figure 42: Resource allocation graphs (a) Holding a resource; (b)


Requesting a resource; (c) Deadlock

The example in Figure 43 illustrates how a resource graph can be used. Three processes (A, B, and C, make
requests for three resources (R, S, and T) as shown in Figure 43 (a), (b), and (c). Assume round robin
scheduling is used such that the processor receives the requests in the order shown in Figure 43 (d). Figure 43
(e), (f), (g), (h), (i), and (j) show the six resulting process-resource graphs. The cycle in Figure 43 (j) is an
indication of a deadlock.
If the OS however knew that granting a particular request might lead to deadlock, the OS can suspend the
process until the condition that would lead to deadlock is cleared. For example, if the OS suspended process B
and used the schedule in Figure 43 (k), then the corresponding process-resource graphs are shown in Figure 43
(l), (m), (n), (o), (p), and (q), and this sequence does not lead to deadlock.
Note again that the treatment of process-resource graphs here has assumed that there is only one resource of a
particular type present. The approach can however, be generalized to handle multiple resources of a particular
type.

CSC 314 – Operating Systems Denis L. Nkweteyim Page 66


Figure 43: An example of using process-resource graph to analyse deadlock
conditions. (Source: Tanenbaum (2001))

4.1.2 State-Transition Model


The process-resource model only provides a snapshot of the interaction between processes and resources, but
says nothing about the dynamics of the system (the different states and the transitions between them). The state-
transition model focuses on the dynamics (the transitions between states).

CSC 314 – Operating Systems Denis L. Nkweteyim Page 67


Let S be the set of states that the system can be in. The initial state s0 represents the situation in which all
resources are unallocated.
Let P be a set of processes {pi}c. Any process pi may cause a state transition depending on whether pi
Requests a resource (designated by a transition with the label ri),
Is allocated a resource (designated by a transition with the label ai),
Deallocates a resource (designated by a transition with the label di).
Process pi is said to be blocked in state sj if pi cannot cause a state transition out of sj. In
the example on the right for example, process p2 is blocked in state sj because all the
transitions out of state sj are as a result of processes other than p2.
If we can determine that there is no series of state transitions leading from the current
state to one in which process pi is unblocked, the then process can never execute again,
i.e., pi is deadlocked. In other words, if pi is blocked, and all possible transitions from
that state to other states still leave pi blocked, then pi is deadlocked.
We next consider a simple state transition model example (Figure 1).

Figure 1. Simple state transition diagram for one process which may request up to two units of a single resource
type
The model represents a process which may request up to two units of a single resource type, one at a time. S0 is
the initial state; the process holds no resource, and the only possible state transition is to state s1, through a
request (r) for a resource. At state s1, the process still holds no resource but is waiting for one. When the
resource is allocated, the process transitions to state s2. From state s2, the process may release, i.e., deallocate
(d) the resource and return to state s0, or request (r) the second resource to transition to state s3 (waiting for
requested resource), and to s4 when the resource gets allocated. From s4, there is only one possible transition,
and that is to s2 if one of the resources held by the process is released.
Of course, there cannot be any deadlock here because only one process is involved.
The model can be extended to consider two processes as shown in Figure 1.

CSC 314 – Operating Systems Denis L. Nkweteyim Page 68


Figure 1. State transition diagram for 2 processes

In the figure, the state transition diagram of Figure 1 has been replicated to simultaneously represent the states
for the two processes, i.e., state sij represents a state in which the first process is in state si, and the second
process in state sj. Some states are not feasible, for example, s44 would represent a state in which both processes
have acquired both of the units of the resource, which is not possible.
State s33 is a deadlock state since both processes are holding one unit of the resource and waiting for the other.

4.2 Handling Deadlocks


Operating systems design uses one or more of four strategies to handle deadlocks:
1. ignore the problem
2. detection and recovery
3. avoidance
4. prevention

4.2.1 Ignoring Deadlocks


Also known as the ostrich approach, you simply stick your head in the sand and pretend the problem is not
there at all. The reason this approach is used is because there are so many opportunities for deadlock, which as
we said before, results from interaction between several processes. The ability for several processes to run
concurrently is a big plus, but that comes at the risk of deadlocks. However, resources are usually of plentiful
supply, and the chance for a deadlock is usually small. The question then is, should multiprogramming be
abandoned for the sake of ensuring that deadlocks never occur? Most OS design take the view that the
convenience of multiprogramming far outweighs the inconvenience brought about by the occasional deadlock,
and so simply ignore the deadlock problem.

CSC 314 – Operating Systems Denis L. Nkweteyim Page 69


4.2.2 Detection and Recovery
In this approach, the system does not attempt to prevent deadlocks but rather, lets them occur and tries to detect
them when they do occur, and then take some action to recover from the deadlock. The recovery phase would
involve prempting resources from processes (in effect violating the nonpremption condition).
We first consider a simple case where only one resource of a particular type is available. A process-resource
graph will be used to detect whether or not a deadlock is present. Assume the current state of resource
ownership by various processes is as follows9:
1. Process A holds R and wants S
2. Process B holds nothing but wants T
3. Process C holds nothing but want S
4. Process D holds U and wants S and T
5. Process E holds T and wants V
6. Process F holds W and wants S
7. Process G holds V and wants U
The problem is to detect if the system is deadlocked, and if so, which processes and resources are involved.
The process resource graph in Figure 44 represents the current state of the system. The cycle DTEVGUD
indicates that there is a deadlock involving processes D, E, and G, and resources T, V, and U. Algorithms exist
that can be used to detect cycles in directed graphs.

Figure 44: Process Resource graph

We next consider a case with multiple resources of each type, and a matrix-based solution to deadlock
detection. Let there be n processes, P1 through Pn, m resource classes with E1 resources of class 1, E2 resources
of class 2,…Em resources of class m, i.e., E is the existing resource vector, and gives the total number of
instances of each resource in existence.
Let A be the vector of currently available (i.e., unassigned) resources. Hence Ai is the number of resources of
class i that is currently unassigned.
Let C represent the current allocation matrix. Cell Cij of this matrix represents the number of instances of
resource j that are currently held by process pi.
Let R represent the request matrix. Cell Rij of this matrix represents the number of instances of resource j that
process pi wants.

These four data structures are illustrated in Figure 45. The following holds true: i.e., sum of
available and allocated resources equals the total number of available resources.

9This example is taken from Tanenbaum (2001)

CSC 314 – Operating Systems Denis L. Nkweteyim Page 70


Figure 45: Data structures required for deadlock detection
The deadlock detection algorithm is based on comparing vectors. Let the relation A ≤ B mean that every
element of vector A is less than or equal to the corresponding element in vector B.
Each process is initially assumed to be unmarked. As the algorithm progresses, processes will be marked,
indicating that they are able to complete and are thus not deadlocked. When the algorithm terminates, every
unmarked processes are known to be deadlocked. The algorithm involves the following steps:
1. Look for an unmarked process Pi for which the ith row of R is less than or equal to A.
2. If such a process is found, add the ith row of C to A and go back to step 1
3. If no such processes exist, the algorithm terminates
When the algorithm finishes, all unmarked processes, if any, are deadlocked.
In step 1, the algorithm is looking for a process that can be run to completion (i.e., whose resource demands can
be met by available resources). The process then runs to completion, and returns the resources it was holding to
the pool of available resources (step 2). The process is then marked as completed.
An example of the working of the deadlock detection algorithm is given in Figure 46. There are three processes
and four resource classes (tape drive, plotters, scanners, and CD Rom drives).
The existing resource vector E and currently available resource vector A are given, as well as the current
allocation matrix C, and the additional resource requirement matrix R.
The algorithm checks and discovers that process 1 and process 2 cannot run because their resource
requirements cannot be met. However, the third process can run, and when it comes to completion, releases its
resources, giving
A = (2 2 2 0)
Process 2 can now run, giving
A = (4 2 2 1)
Finally, process 1 can run.

CSC 314 – Operating Systems Denis L. Nkweteyim Page 71


Figure 46: Deadlock detection algorithm example

4.2.3 Deadlock Avoidance


The discussion on deadlock detection assumed that a process asks for all the resources it needs at once
(modelled using the R matrix). But that is not usually the case. The deadlock avoidance approach attempts to
determine if there is algorithm that avoids deadlocks by making the right choice vis-à-vis resource allocation all
the time.
Deadlock avoidance algorithms make use of the notion of safe and unsafe states. A state is said to be safe if it is
not deadlocked and there is some scheduling order in which every process can run to completion even if all of
them suddenly request their maximum number of resources immediately.
For example, in Figure 47 (a), 3 processes are competing for a single resource type. Process A currently has 3
but may eventually need a total of 9, B has 2 but may need 4, and C has 2 but may need 7. A total of 10 units of
the resource is available, and 7 of them are in use, so 3 are free. State A is safe because even if all the processes
suddenly request their maximum resource requirements, the scheduler could run process B exclusively (state
(b)) and then release its resources (state (c)). C can then run (state d), and when c releases its resources (state
(e)), after which A can run.

Figure 47: Demonstrating that state (a) is safe

Assume now that with the same initial state as above, A requests and gets another resource (state (b) of Figure
48). The scheduler could run B with all its resource demands (state (b)), and then B can release its resources (d).
Now, we cannot guarantee that A or C can successfully run to completion. In retrospect, the allocation of a unit
of the resource to A in state (b) was an error. State (b) is said to be an unsafe state because there is no sequence
that guarantees completion.
It should be noted that an unsafe state is not a deadlocked state. With luck, a process may release some of its
resources, allowing another process to run to completion before at some stage, the former process makes its
maximum resource demand.

CSC 314 – Operating Systems Denis L. Nkweteyim Page 72


Figure 48: Demonstration that state (b) is unsafe

Safe and unsafe states can also be demonstrated in the context of the state-transition model, but we shall not
cover that here. Interested readers can read on this on pages 389-391 of Nutt (2003).

4.2.4 The Banker’s Algorithm


The Banker’s Algorithm for a Single Resource
This is a deadlock avoidance algorithm proposed by Djikstra in 1965. It is modelled after the way a banker may
operate in relation to the provision of loans to its customers. Each customer is extended a line of credit which
shows the maximum amount of money the customer can borrow. The algorithm checks to see if granting the
request leads to an unsafe state; if it does, the request is denied; if it leads to a safe state, the request is
honoured.
The working of the algorithm is illustrated in Figure 49.

Figure 49: Banker's algorithm for single resource (a) safe, (b) safe, (c)
unsafe

Four customers A, B, C, D (processes) are granted lines of credits, i.e., maximum resource demands (Max
column). In this example, only 10 units of the resource (10 million CFA) are available to the banker (the
operating system). The customers go about their business, sometimes making loan requests. Figure 49 (b)
illustrates the situation at a certain moment. That is a safe state because even if all customers make their
maximum demands, all can be delayed, except C, whose request can be met. When C releases its resources (i.e.,
pays back its debt), four units of the resource will be available, enough to service either B or D, and so on.
However, if B requested a unit in (b), and the request was granted leading to state (c), and suddenly all the
customers make their maximum request, none of them will be serviced, i.e., the system is deadlocked.
The banker’s algorithm considers each request as it is made, and checks if granting the request leads to a safe
state. If it does, the request is granted; if not it is postponed until later. A state is judged to be safe if there are
enough resources to satisfy some customer. If so, the loan is assumed repaid, and the customer now closest to
the limit checked and so on. If all loans can eventually be repaid, the state is safe, and the initial request can be
granted.

The Banker’s Algorithm for Multiple Resources


This generalizes the algorithm as demonstrated in Figure 50.

CSC 314 – Operating Systems Denis L. Nkweteyim Page 73


Figure 50: Banker’s algorithm with multiple resources

The matrix on the left (current resource assignment) and the right (resources still needed) correspond to the C
and R matrix in Figure 50. Vector E is the existing resources vector, vector P the possessed (i.e., assigned)
resource vector, vector A the available resources. The algorithm is as follows:
1. Look for a row R whose unmet resource needs are all smaller than or equal to A. if no such rows exist,
the system will deadlock since no process can run to completion
2. Assume the process of the row chosen requests all the resources it needs and finishes. Mark that process
as terminated and add all its resources to the A vector.
3. Repeat steps 1 and 2 until either all processes are marked terminated, in which case the initial state was
safe, or until a deadlock occurs in which case the initial case was not safe.
Going back to the example, which is a safe state, consider what happens if B requests a scanner. This request
can be granted because the resulting state is still safe (D can finish, then A or E, and then the rest). However,
after granting B’s request above, and E requests the last scanner, granting that request would reduce the
available resources vector to (1 0 0 0), which leads to deadlock. So, E’s request needs to be delayed.
The problem with the deadlock avoidance algorithms
Processes rarely know in advance what their maximum resource needs are, so although in theory the algorithms
are excellent, in practice they are useless.

4.2.5 Deadlock Prevention


Deadlock prevention follows the following strategy: is it possible to design the operating system such that one
of the 4 conditions that must be met for there to be a deadlock is violated?

4.2.5.1 Attacking the Mutual Exclusion Condition


The mutual exclusion condition is required for most concurrent processes, and in general, is not a good idea to
violate that condition. So this approach is seldom used.

4.2.5.2 Attacking the Hold and Wait Condition


Is it possible to prevent processes that hold resources from waiting for more resources? One way this could be
achieved is to require all processes to request all their resources before starting execution, but this is usually not
possible. And in any case, providing all the required resources at the beginning of execution can be wasteful as
resources may be held much longer than required, while some other processes need them.
Another approach is to require a process requesting a resource to first drop all the resources it currently holds,
and then compete for everything it wants all at once again

4.2.5.3 Attacking the No Pre-emption Condition


This approach is not promising because if a process holds a resource (a printer for example), you do not want to
pre-empt the process to release that resource.

CSC 314 – Operating Systems Denis L. Nkweteyim Page 74


4.2.5.4 Attacking the Circular Wait Condition
One way to go about this is to have a rule that says a process is entitled to a maximum of one resource at a time.
But this is not realistic in many situations.
An alternative approach is to provide a global numbering of all available resources, and apply the following
rule: processes can request resources whenever they want, but all requests must be made in numerical order. A
process may request a device followed by a higher numbered one, but not the other way round. With this rule,
resource allocation graphs can never have cycles, and hence deadlocks. A less strict rule, but which also works
is that a process should not be allowed to request a resource that has a smaller numerical value than the
resources it currently holds.
The performance penalty to pay for using this global numbering approach is that if a process needs a resource
with a smaller number, then it must drop all the resources it currently holds, and then tries to acquire what it
needs in increasing numerical order.

CSC 314 – Operating Systems Denis L. Nkweteyim Page 75

You might also like