Operating Systems

Start Lecture #6

Chapter 6 Deadlocks

deadlock gridlock

Remark: Deadlocks are closely related to process management so belong here, right after chapter 2. It was here in 2e. A goal of 3e is to make sure that the basic material gets covered in one semester. But I know we will do the first 6 chapters so there is no need for us to postpone the study of deadlock.

A deadlock occurs when every member of a set of processes is waiting for an event that can only be caused by a member of the set.

Often the event waited for is the release of a resource.

In the automotive world deadlocks are called gridlocks.

For a computer science example consider two processes A and B that each want to print a file currently on a CD-ROM Drive.

  1. A has obtained ownership of the printer and will release it after getting the CD Drive and printing one file.
  2. B has obtained ownership of the CD drive and will release it after getting the printer and printing one file.
  3. A tries to get ownership of the drive, but is told to wait for B to release it.
  4. B tries to get ownership of the printer, but is told to wait for A to release it.

Bingo: deadlock!

6.1 Resources

A resource is an object granted to a process.

6.1.1 Preemptable and Nonpreemptable Resources

Resources come in two types

  1. Preemptable, meaning that the resource can be taken away from its current owner (and given back later). An example is memory.
  2. Non-preemptable, meaning that the resource cannot be taken away. An example is a printer.

The interesting issues arise with non-preemptable resources so those are the ones we study.

The life history of a resource is a sequence of

  1. Request
  2. Allocate
  3. Use
  4. Release

Processes request the resource, use the resource, and release the resource. The allocate decisions are made by the system and we will study policies used to make these decisions.

6.1.2 Resource Acquisition

A simple example of the trouble you can get into.

Recall from the semaphore/critical-section treatment last chapter, that it is easy to cause trouble if a process dies or stays forever inside its critical section. We assume processes do not do this. Similarly, we assume that no process retains a resource forever. It may obtain the resource an unbounded number of times (i.e. it can have a loop forever with a resource request inside), but each time it gets the resource, it must release it eventually.

6.2 Introduction to Deadlocks

Definition: A deadlock occurs when a every member of a set of processes is waiting for an event that can only be caused by a member of the set.

Often the event waited for is the release of a resource.

6.2.1 (Necessary) Conditions for Deadlock

The following four conditions (Coffman; Havender) are necessary but not sufficient for deadlock. Repeat: They are not sufficient.

  1. Mutual exclusion: A resource can be assigned to at most one process at a time (no sharing).
  2. Hold and wait: A processing holding a resource is permitted to request another.
  3. No preemption: A process must release its resources; they cannot be taken away.
  4. Circular wait: There must be a chain of processes such that each member of the chain is waiting for a resource held by the next member of the chain.

One can say If you want a deadlock, you must have these four conditions.. But of course you don't actually want a deadlock, so you would more likely say If you want to prevent deadlock, you need only violate one or more of these four conditions..

The first three are static characteristics of the system and resources. That is, for a given system with a fixed set of resources, the first three conditions are either always true or always false: They don't change with time. The truth or falsehood of the last condition does indeed change with time as the resources are requested/allocated/released.

6.2.2 Deadlock Modeling

On the right are several examples of a Resource Allocation Graph, also called a Reusable Resource Graph.

Homework: 5.

Consider two concurrent processes P1 and P2 whose programs are.

    P1                   P2
    request R1           request R2
    request R2           request R1
    release R2           release R1
    release R1           release R2
  

On the board draw the resource allocation graph for various possible executions of the processes, indicating when deadlock occurs and when deadlock is no longer avoidable.

There are four strategies used for dealing with deadlocks.

  1. Ignore the problem
  2. Detect deadlocks and recover from them
  3. Prevent deadlocks by violating one of the 4 necessary conditions.
  4. Avoid deadlocks by carefully deciding when to allocate resources.

6.3 Ignoring the problem—The Ostrich Algorithm

The put your head in the sand approach.

6.4 Detecting Deadlocks and Recovering From Them

6.4.1 Detecting Deadlocks with Single Unit Resources

Consider the case in which there is only one instance of each resource.

To find a directed cycle in a directed graph is not hard. The algorithm is in the book. The idea is simple.

  1. For each node in the graph do a depth first traversal to see if the graph is a DAG (directed acyclic graph), building a list as you go down the DAG (and pruning it as you backtrack back up).
  2. If you ever find the same node twice on your list, you have found a directed cycle, the graph is not a DAG, and deadlock exists among the processes in your current list.
  3. If you never find the same node twice, the graph is a DAG and no deadlock exists (right now).

The searches are finite since there are a finite number of nodes.

6.4.2 Detecting Deadlocks with Multiple Unit Resources

This is more difficult.

6.4.3 Recovery from deadlock

Recovery through Preemption

Perhaps you can temporarily preempt a resource from a process. Not likely.

Recovery through Rollback

Database (and other) systems take periodic checkpoints. If the system does take checkpoints, one can roll back to a checkpoint whenever a deadlock is detected. You must somehow guarantee forward progress.

Recovery through Killing Processes

Can always be done but might be painful. For example some processes have had effects that can't be simply undone. Print, launch a missile, etc.

Remark: We are doing 6.6 before 6.5 since 6.6 is easier and I believe serves as a good warm-up.

6.6 Deadlock Prevention

Attack one of the Coffman/Havender conditions.

6.6.1 Attacking the Mutual Exclusion Condition

The idea is to use spooling instead of mutual exclusion. Not possible for many kinds of resources.

6.6.2 Attacking the Hold and Wait Condition

Require each processes to request all resources at the beginning of the run. This is often called One Shot.

6.6.3 Attacking the No Preemption Condition

Normally not possible. That is, some resources are inherently pre-emptable (e.g., memory). For those, deadlock is not an issue. Other resources are non-preemptable, such as a robot arm. It is often not possible to find a way to preempt one of these latter resources. One exception is if the resource (say a CD-ROM drive) can be virtualized (recall hypervisors).

6.6.4 Attacking the Circular Wait Condition

Establish a fixed ordering of the resources and require that they be requested in this order. So if a process holds resources #34 and #54, it can request only resources #55 and higher.

It is easy to see that a cycle is no longer possible.

Homework: Consider Figure 6-4. Suppose that in step (o) C requested S instead of requesting R. Would this lead to deadlock? Suppose that it requested both S and R.

6.5 Deadlock Avoidance

Let's see if we can tiptoe through the tulips and avoid deadlock states even though our system does permit all four of the necessary conditions for deadlock.

An optimistic resource manager is one that grants every request as soon as it can. To avoid deadlocks with all four conditions present, the manager must be smart not optimistic.

6.5.1 Resource Trajectories

We plot progress of each process along an axis. In the example we show, there are two processes, hence two axes, i.e., planar. This procedure assumes that we know the entire request and release pattern of the processes in advance so it is not a practical solution. I present it as it is some motivation for the practical solution that follows, the Banker's Algorithm.

Homework: All the trajectories in Figure 6-8 are horizontal or vertical. Is is possible for a trajectory to be a diagonal.

Homework: 11, 12.

6.5.2 Safe States

Avoiding deadlocks given some extra knowledge.

Definition: A state is safe if there is an ordering of the processes such that: if the processes are run in this order, they will all terminate (assuming none exceeds its claim and assuming each would terminate if all its requests are granted).

Recall the comparison made above between detecting deadlocks (with multi-unit resources) and the banker's algorithm (which stays in safe states).

In the definition of a safe state no assumption is made about the running processes. That is, for a state to be safe, termination must occur no matter what the processes do (providing each would terminate if run alone and each never exceeds its claims). Making no assumption on a process's behavior is the same as making the most pessimistic assumption.

Remark: When I say pessimistic I am speaking from the point of view of the resource manager. From the manager's viewpoint, the worst thing a process can do is request resources.

Give an example of each of the following four possibilities. A state that is

  1. Safe and deadlocked—not possible.

  2. Safe and not deadlocked—a trivial is example is a graph with no arcs.

  3. Not safe and deadlocked—easy (any deadlocked state).

  4. Not safe and not deadlocked—interesting.

Is the figure on the right safe or not?

A manager can determine if a state is safe.

The manager then follows the following procedure, which is part of Banker's Algorithms discovered by Dijkstra, to determine if the state is safe.

  1. If there are no processes remaining, the state is safe.

  2. Seek a process P whose maximum additional request for each resource type is less than what remains for that resource type.
  3. The banker now pretends that P has terminated (since the banker knows that it can guarantee this will happen). Hence the banker pretends that all of P's currently held resources are returned. This makes the banker richer and hence perhaps a process that was not eligible to be chosen as P previously, can now be chosen.

  4. Repeat these steps.

Example 1

Consider the example shown in the table on the right.
A safe state with 22 units of one resource
processinitial claimcurrent allocmax add'l
X312
Y1156
Z19109
Total16
Available6

Example 2

This example is a continuation of example 1 in which Z requested 2 units and the manager (foolishly?) granted the request.
An unsafe state with 22 units of one resource
processinitial claimcurrent allocmax add'l
X312
Y1156
Z19127
Total18
Available4

Remark: An unsafe state is not necessarily a deadlocked state. Indeed, for many unsafe states, if the manager gets lucky all processes will terminate successfully. Processes that are not currently blocked can terminate (instead of requesting more resources up to their initial claim, which is the worst case and is the case the manager prepares for). A safe state means that the manager can guarantee that no deadlock will occur (even in the worst case in which processes request as much as permitted by their initial claims.)

6.5.3 The Banker's Algorithm (Dijkstra) for a Single Resource

The algorithm is simple: Stay in safe states. For now, we assume that, before execution begins, all processes are present and all initial claims have been given. We will relax these assumptions very soon.

In a little more detail the banker's algorithm is as follows.

Homework: 16.

6.5.4 The Banker's Algorithm for Multiple Resources

At a high level the algorithm is identical to the one for a single resource type: Stay in safe states.

But what is a safe state in this new setting?

The same definition (if processes are run in a certain order they will all terminate).

Checking for safety is the same idea as above. The difference is that to tell if there are enough free resources for a processes to terminate, the manager must check that for all resource types, the number of free units is at least equal to the max additional need of the process.

Homework: Consider a system containing a total of 12 units of resource R and 24 units of resource S managed by the banker's algorithm. There are three processes P1, P2, and P3. P1's claim is 0 units of R and 12 units of S, written (0,12). P2's claim is (8,15). P3's claim is (8,20). Currently P1 has 4 units of S, P2 has 8 units of R, P3 has 8 units of S, and there are no outstanding requests.

  1. What is the largest number of units of S that P1 can request at this point that the banker will grant?
  2. If P2 instead of P1 makes the request, what is the largest number of units of S that the banker will grant?
  3. If P3 instead of P1 or P2 makes the request, what is the largest number of units of S that the banker will grant?

Remark: Remind me to go over this one next time.

Limitations of the Banker's Algorithm

Homework: 22, 25, and 30. There is an interesting typo in 22. A has claimed 3 units of resource 5, but there are only 2 units in the entire system. Change the problem by having B both claim and be allocated 1 unit of resource 5.