A system consists of a finite number of resources to be distributed among a number of competing processes. The resources are partitioned into several types, each consisting of some number of identical instances. Memory space, CPU cycles, files, and I/O devices (such as printers and DVD drives) are examples of resource types. If a system has two CPUs, then the resource type CPU has two instances. Similarly, the resource type printer may have five instances. If a process requests an instance of a resource type, the allocation of any instance of the type will satisfy the request. If it will not, then the instances are not identical, and the resource type classes have not been defined properly.
For example, a system may have two printers. These two printers may be defined to be in the same resource class if no one cares which printer prints which output. However, if one printer is on the ninth floor and the other is in the basement, then people on the ninth floor may not see both printers as equivalent, and separate resource classes may need to be defined for each printer. A process must request a resource before using it and must release the resource after using it.
A process may request as many resources as it requires to carry out its designated task. Obviously, the number of resources requested may not exceed the total number of resources available in the system. In other words, a process cannot request three printers if the system has only two. Under the normal mode of operation, a process may utilize a resource in only the following sequence:
1. Request. If the request cannot be granted immediately (for example, if the resource is being used by another process), then the requesting process must wait until it can acquire the resource.
2. Use, The process can operate on the resource (for example, if the resource is a printer, the process can print on the printer).
3. Release. The process releases the resource. The request and release of resources are system calls, as explained in Chapter 2. Examples are the request () and release() device, open() and close () file, and allocat e () and free () memory system calls. Request and release of resources that are not managed by the operating system can be accomplished through the waitO and signal () operations on semaphores or through acquisition and release of a mutex lock. For each use of a kernelmanaged resource by a process or thread, the operating system checks to make sure that the process has requested and has been allocated the resource.
A system table records whether each resource is free or allocated; for each resource that is allocated, the table also records the process to which it is allocated. If a process requests a resource that is currently allocated to another process, it can be added to a queue of processes waiting for this resource. A set of processes is in a deadlock state when every process in the set is waiting for an event that can be caused only by another process in the set.
The events with which we are mainly concerned here are resource acquisition and release. The resources maybe either physical resources (for example, printers, tape drives, memory space, and CPU cycles) or logical resources (for example, files, semaphores, and monitors). However, other types of events may result in deadlocks (for example, the 1PC facilities discussed in Chapter 3). To illustrate a deadlock state, consider a system with three CD RVV drives. Suppose each of three processes holds one of these CD RW drives. If each process now requests another drive, the three processes will be in a deadlock state. Each is waiting for the event "CD RVV is released," which can be caused only by one of the other waiting processes. This example illustrates a deadlock involving the same resource type. Deadlocks may also involve different resource types. For example, consider a system with one printer and one DVD drive.
Suppose that process P. is holding the DVD and process P; is holding the printer. If P, requests the printer and P. requests the DVD drive, a deadlock occurs. A programmer who is developing multithreaded applications must pay particular attention to this problem. Multithreaded programs are good candidates for deadlock because multiple threads can. compete for shared resources