|CS 321 Spring 2013 > Lecture Notes for Monday, April 1, 2013|
By a resource we mean something that can be obtained, used for a time, and then relinquished. Examples of resources include processor time, logical memory space, physical memory space, space on a storage device, concurrency primitives (semaphores, etc.), process IDs, file descriptors, and access to a device (e.g., a printer). In our dicussion, resources will be acquired by processes; but here “process” really means “process or thread”.
When a process is allowed to use a resource, we say it acquires the resource. When a process voluntarily gives up access to the resource, we say is releases the resource. If the resource is taken away involuntarily, then the resource has been preempted.
A resource is preemptable if it can be preempted without ill effects. For example, in an interactive system, processor time and physical memory space are generally preemptable. Logical memory space is not. Access to a disk drive is preemptable. Access to a CD-ROM drive while it is burning should not be. Some of the preemptable resources we have listed might not be preemptable on a real-time system.
An important responsibility of an OS is to manage access to resources. Problems when there are conflicting requests for resources are called resource contention.
We will focus on a type of resource contention known as deadlock. A set of processes is in deadlock if each process is waiting for an event that only another process in the set can cause. Since they are all waiting, doing nothing, none of them will cause any of these events, and so none of the processes can do anything.
We are particularly interested in resource deadlock, which happens when the events being awaited are the release of resources so that they may be acquired by the waiting process.
Four conditions must hold for resource deadlock to occur.
The first three conditions above are general properties of the system; typically they always hold or never hold. But the circular-wait condition may hold at some times and not at other times. We can determine whether the circular-wait condition holds using a resource graph.
A resource graph is a collection of nodes joined by arrows. We have one node for each process and one node for each resource. If a process holds a resource, then we draw an arrow from the resource’s node to the process’s node. If a process has requested a resource and is waiting for it, then we draw an arrow from the process’s node to the resource’s node.
The circular-wait condition holds if the resource graph contains a directed cycle: a way of starting at a node, following arrows, and then coming back to starting node. There are efficient algorithms to determine the existence of a directed cycle.