Resource Acquisition
6.1.2 Resource Acquisition
For some kinds of resources, such as records in a database system, it is up to the user processes rather than the system to manage resource usage themselves. One way of allowing this is to associate a semaphore with each resource. These
DEADLOCKS CHAP. 6 semaphores are all initialized to 1. Mutexes can be used equally well. The three
steps listed above are then implemented as a down on the semaphore to acquire the resource, the use of the resource, and finally an up on the resource to release it. These steps are shown in Fig. 6-1(a).
typedef int semaphore; typedef int semaphore; semaphore resource 1; semaphore resource 1; semaphore resource 2;
void process A(void) { void process A(void) { down(&resource 1); down(&resource 1); use resource 1( );
down(&resource 2); up(&resource 1); use both resources( ); }
up(&resource 2); up(&resource 1);
(a) (b) Figure 6-1. Using a semaphore to protect resources. (a) One resource. (b) Two resources.
Sometimes processes need two or more resources. They can be acquired se- quentially, as shown in Fig. 6-1(b). If more than two resources are needed, they are just acquired one after another.
So far, so good. As long as only one process is involved, everything works fine. Of course, with only one process, there is no need to formally acquire re- sources, since there is no competition for them.
Now let us consider a situation with two processes, A and B, and two re- sources. Two scenarios are depicted in Fig. 6-2. In Fig. 6-2(a), both processes ask for the resources in the same order. In Fig. 6-2(b), they ask for them in a different order. This difference may seem minor, but it is not.
In Fig. 6-2(a), one of the processes will acquire the first resource before the other one. That process will then successfully acquire the second resource and do its work. If the other process attempts to acquire resource 1 before it has been re- leased, the other process will simply block until it becomes available.
In Fig. 6-2(b), the situation is different. It might happen that one of the proc- esses acquires both resources and effectively blocks out the other process until it is done. However, it might also happen that process A acquires resource 1 and proc- ess B acquires resource 2. Each one will now block when trying to acquire the other one. Neither process will ever run again. Bad news: this situation is a dead- lock.
Here we see how what appears to be a minor difference in coding style— which resource to acquire first—turns out to make the difference between the pro- gram working and the program failing in a hard-to-detect way. Because deadlocks can occur so easily, a lot of research has gone into ways to deal with them. This chapter discusses deadlocks in detail and what can be done about them.
SEC. 6.2
INTRODUCTION TO DEADLOCKS
typedef int semaphore; semaphore resource 1; semaphore resource 1; semaphore resource 2; semaphore resource 2;
void process A(void) { void process A(void) { down(&resource 1); down(&resource 1); down(&resource 2); down(&resource 2); use both resources( );
use both resources( ); up(&resource 2); up(&resource 2); up(&resource 1); up(&resource 1);
void process B(void) { void process B(void) { down(&resource 1); down(&resource 2); down(&resource 2); down(&resource 1); use both resources( );
use both resources( ); up(&resource 2); up(&resource 1); up(&resource 1); up(&resource 2);
(a) (b) Figure 6-2. (a) Deadlock-free code. (b) Code with a potential deadlock.
Parts
» The Second Generation (1955–65): Transistors and Batch Systems
» The Third Generation (1965–1980): ICs and Multiprogramming
» The Fourth Generation (1980–Present): Personal Computers
» System Calls for Process Management
» System Calls for Directory Management
» RESEARCH ON OPERATING SYSTEMS
» Implementing Threads in User Space
» Implementing Threads in the Kernel
» Making Single-Threaded Code Multithreaded
» Mutual Exclusion with Busy Waiting
» Avoiding Locks: Read-Copy-Update
» Scheduling in Interactive Systems
» Scheduling in Real-Time Systems
» The Dining Philosophers Problem
» The Readers and Writers Problem
» The Notion of an Address Space
» Page Tables for Large Memories
» DESIGN ISSUES FOR PAGING SYSTEMS
» Segmentation with Paging: MULTICS
» Segmentation with Paging: The Intel x86
» An Example Program Using File-System Calls
» Device-Independent I/O Software
» Disk Arm Scheduling Algorithms
» Preemptable and Nonpreemptable Resources
» Deadlock Detection with One Resource of Each Type
» Deadlock Detection with Multiple Resources of Each Type
» The Banker’s Algorithm for Multiple Resources
» REQUIREMENTS FOR VIRTUALIZATION
» TYPE 1 AND TYPE 2 HYPERVISORS
» TECHNIQUES FOR EFFICIENT VIRTUALIZATION
» ARE HYPERVISORS MICROKERNELS DONE RIGHT?
» Challenges in Bringing Virtualization to the x86
» VMware Workstation: Solution Overview
» ESX Server: VMware’s type 1 Hypervisor
» Multiprocessor Operating System Types
» Multiprocessor Synchronization
» Low-Level Communication Software
» User-Level Communication Software
» Network Services and Protocols
» File-System-Based Middleware
» Coordination-Based Middleware
» Authentication Using a Physical Object
» Authentication Using Biometrics
» Antivirus and Anti-Antivirus Techniques
» Model-Based Intrusion Detection
» Process-Management System Calls in Linux
» Implementation of Processes and Threads in Linux
» Implementation of the Linux File System
» NFS: The Network File System
» HISTORY OF WINDOWS THROUGH WINDOWS 8.1
» The Native NT Application Programming Interface
» The Win32 Application Programming Interface
» Implementation of the Object Manager
» Subsystems, DLLs, and User-Mode Services
» Job, Process, Thread, and Fiber Management API Calls
» Implementation of Processes and Threads
» Memory-Management System Calls
» Implementation of Memory Management
» Why Is It Hard to Design an Operating System?
» Static vs. Dynamic Structures
» Synchronous vs. Asynchronous Communication
» TRENDS IN OPERATING SYSTEM DESIGN
» SUGGESTIONS FOR FURTHER READING
Show more