OS-Unit-3 New
OS-Unit-3 New
Stack: Temporary data such as method/function arguments, return address and local variables are stored
in the stack.
Text: Consists of the current activity as reflected by the program counter value and the processor’s
register content.
A program itself is not a process. A program is a passive entity, such as a file containing a list of
instructions stored on disk (often called an executable file). In contrast, a process is an active entity,
with a program counter specifying the next instruction to execute and a set of associated resources. A
program becomes a process when an executable file is loaded into memory. Two common techniques
for loading executable files are double-clicking an icon representing the executable file and entering
the name of the executable file on the command line (as in prog.exe or a.out).
SSK 1
Unit-3
Process state
As a process executes, it changes state. The state of a process is defined in part by the current activity
of that process. A process may be in one of the following states:
Each process is represented in the operating system by a process control block (PCB) — also called a
task control block. A PCB is shown in Figure 3.3. It contains many pieces of information associated with
a specific process, including these:
Process state: The state may be new, ready, running, waiting, halted, and so on.
Program counter: The counter indicates the address of the next instruction to be executed for
this process.
CPU registers: The registers vary in number and type, depending on the computer architecture.
They include accumulators, index registers, stack pointers, and general-purpose registers, plus
SSK 2
Unit-3
any condition-code information. Along with the program counter, this state information must
be saved when an interrupt occurs, to allow the process to be continued correctly afterward.
CPU-scheduling information: This information includes a process priority, pointers to
scheduling queues, and any other scheduling parameters.
Memory-management information: This information may include such items as the value of
the base and limit registers and the page tables, or the segment tables, depending on the
memory system used by the operating system
• Accounting information: This information includes the amount of CPU and real time used, time limits,
account numbers, job or process numbers, and so on.
• I/O status information: This information includes the list of I/O devices allocated to the process, a list
of open files, and so on.
SSK 3
Unit-3
Threads
A process is a program that performs a single thread of execution. For example, when a process is
running a word-processor program, a single thread of instructions is being executed. This single thread
of control allows the process to perform only one task at a time.
The user cannot simultaneously type in characters and run the spell checker within the same process.
Most modern operating systems have extended the process concept to allow a process to have multiple
threads of execution and thus to perform more than one task at a time. This feature is especially
beneficial on multicore systems, where multiple threads can run in parallel.
Process Scheduling
The objective of multiprogramming is to have some process running at all times, to maximize CPU
utilization.
The objective of time sharing is to switch the CPU among processes so frequently that users can interact
with each program while it is running. To meet these objectives, the process scheduler selects an
available process (possibly from a set of several available processes) for program execution on the CPU.
For a single-processor system, there will never be more than one running process. If there are more
processes, the rest will have to wait until the CPU is free and can be rescheduled.
A common representation of process scheduling is a queueing diagram, such as that in Figure 3.6. Each
rectangular box represents a queue. Two types of queues are present: the ready queue and a set of
device queues. The circles represent the resources that serve the queues, and the arrows indicate the
flow of processes in the system.
SSK 4
Unit-3
A new process is initially put in the ready queue. It waits there until it is selected for execution, or
dispatched. Once the process is allocated the CPU and is executing, one of several events could occur:
• The process could issue and I/O request and then be placed in an I/O queue.
• The process could create a new child process and wait for the child’s termination.
• The process could be removed forcibly from the CPU, as a result of an interrupt, and be put back in
the ready queue.
In the first two cases, the process eventually switches from the waiting state to the ready state and is
then put back in the ready queue. A process continues this cycle until it terminates, at which time it is
removed from all queues and has its PCB and resources deallocated.
Context Switching
When an interrupt occurs, the system needs to save the current context of the process running on the
CPU so that it can restore that context when its processing is done, essentially suspending the process
and then resuming it.
Switching the CPU to another process requires performing a state save of the current process and a
state restore of a different process. This task is known as a context switch.
When a context switch occurs, the kernel saves the context of the old process in its PCB and loads the
saved context of the new process scheduled to run.
Operation on processes
Process Creation
During the course of execution, a process may create several new processes. The creating process is
called a parent process, and the new processes are called the children of that process. Each of these
new processes may in turn create other processes, forming a tree of processes.
Most operating systems (including UNIX, Linux, and Windows) identify processes according to a unique
process identifier (or pid), which is typically an integer number. The pid provides a unique value for
each process in the system, and it can be used as an index to access various attributes of a process
within the kernel.
When a process creates a new process, two possibilities for execution exist:
1. The parent continues to execute concurrently with its children.
2. The parent waits until some or all of its children have terminated.
SSK 5
Unit-3
There are also two address-space possibilities for the new process:
1. The child process is a duplicate of the parent process.
2. The child process has a new program loaded into it.
A new process is created by the fork() system call. The new process consists of a copy of the address
space of the original process. This mechanism allows the parent process to communicate easily with
its child process.
Both processes (the parent and the child) continue execution at the instruction after the fork().
After a fork() system call, one of the two processes typically uses the exec() system call to replace the
process’s memory space with a new program.
The exec() system call loads a binary file into memory and starts its execution. In this manner, the two
processes are able to communicate and then go their separate ways. The parent can then create more
children; or, if it has nothing else to do while the child runs, it can issue a wait() system call to move
itself off the ready queue until the termination of the child.
Process Termination
A process terminates when it finishes executing its final statement and asks the operating system to
delete it by using the exit() system call. At that point, the process may return a status value (typically
an integer) to its parent process (via the wait() system call).
All the resources of the process—including physical and virtual memory, open files, and I/O buffers—
are deallocated by the operating system.
A process can cause the termination of another process via an appropriate system call (for example,
TerminateProcess() inWindows). Usually, such a system call can be invoked only by the parent of the
process that is to be terminated. Otherwise, users could arbitrarily kill each other’s jobs.
SSK 6
Unit-3
A parent may terminate the execution of one of its children for a variety of reasons, such as these:
The child has exceeded its usage of some of the resources that it has been allocated. (To
determine whether this has occurred, the parent must have a mechanism to inspect the state
of its children.)
The task assigned to the child is no longer required.
The parent is exiting, and the operating system does not allow a child to continue if its parent
terminates.
Some systems do not allow a child to exist if its parent has terminated. In such systems, if a process
terminates (either normally or abnormally), then all its children must also be terminated. This
phenomenon, referred to as cascading termination, is normally initiated by the operating system.
When a process terminates, its resources are deallocated by the operating system. However, its entry
in the process table must remain there until the parent calls wait(), because the process table contains
the process’s exit status. A process that has terminated, but whose parent has not yet called wait(), is
known as a zombie process.
Now consider what would happen if a parent did not invoke wait() and instead terminated, thereby
leaving its child processes as orphans.
Multi-threaded processes
A thread is a basic unit of CPU utilization; it comprises a thread ID, a program counter, a register set,
and a stack. It shares with other threads belonging to the same process its code section, data section,
and other operating-system resources, such as open files and signals. Most software applications that
run on modern computers are multithreaded.
A word processor may have a thread for displaying graphics, another thread for responding to
keystrokes from the user, and a third thread for performing spelling and grammar checking in the
background.
SSK 7
Unit-3
Typically, RPC servers are multithreaded. When a server receives a message, it services the message
using a separate thread. This allows the server to service several concurrent requests.
Finally, most operating-system kernels are now multithreaded. Several threads operate in the kernel,
and each thread performs a specific task, such as managing devices, managing memory, or interrupt
handling.
The benefits of multithreaded programming can be broken down into four major categories:
SSK 8
Unit-3
Multithreading Model
1. Many-to-One Model
The many-to-one model maps many user-level threads to one kernel thread. Thread management is
done by the thread library in user space, so it is efficient. However, the entire process will block if a
thread makes a blocking system call.
Also, because only one thread can access the kernel at a time, multiple threads are unable to run in
parallel on multicore systems.
2. One-to-One Model
The one-to-one model maps each user thread to a kernel thread. It provides more concurrency than
the many-to-one model by allowing another thread to run when a thread makes a blocking system call.
It also allows multiple threads to run in parallel on multiprocessors.
The only drawback to this model is that creating a user thread requires creating the corresponding
kernel thread.
SSK 9
Unit-3
3. Many-to-Many Model
The many-to-many model multiplexes many user-level threads to a smaller or equal number of kernel
threads. The number of kernel threads may be specific to either a particular application or a particular
machine (an application may be allocated more kernel threads on a multiprocessor than on a single
processor).
In many-to-many model, developers can create as many user threads as necessary, and the
corresponding kernel threads can run in parallel on a multiprocessor. Also, when a thread performs a
blocking system call, the kernel can schedule another thread for execution.
One variation on the many-to-many model still multiplexes many user- level threads to a smaller or
equal number of kernel threads but also allows a user-level thread to be bound to a kernel thread. This
variation is sometimes referred to as the two-level model. Eg Solaris OS.
SSK 10
Unit-3
Multicore systems
A multicore processor is an integrated circuit that has two or more processor cores attached for enhanced
performance and reduced power consumption. These processors also enable more efficient simultaneous
processing of multiple tasks, such as with parallel processing and multithreading. A dual core setup is similar to
having multiple, separate processors installed on a computer. However, because the two processors are plugged
into the same socket, the connection between them is faster.
On a system with a single computing core, concurrency merely means that the execution of the threads
will be interleaved over time because the processing core is capable of executing only one thread at a
time. On a system with multiple cores, however, concurrency means that the threads can run in parallel,
because the system can assign a separate thread to each core.
Modern Intel CPUs frequently support two threads per core, while the Oracle T4 CPU supports eight
threads per core. This support means that multiple threads can be loaded into the core for fast
switching. Multicore computers will no doubt continue to increase in core counts and hardware thread
support.
Programming Challenges
The trend towards multicore systems continues to place pressure on system designers and application
programmers to make better use of the multiple computing cores. Designers of operating systems must
write scheduling algorithms that use multiple processing cores to allow the parallel execution
1. Identifying tasks: This involves examining applications to find areas that can be divided into separate,
concurrent tasks. Ideally, tasks are independent of one another and thus can run in parallel on individual
cores.
2. Balance: While identifying tasks that can run in parallel, programmers must also ensure that the tasks
perform equal work of equal value. In some instances, a certain task may not contribute as much value
to the overall process as other tasks. Using a separate execution core to run that task may not be worth
the cost.
3. Data splitting: Just as applications are divided into separate tasks, the data accessed and manipulated
by the tasks must be divided to run on separate cores.
SSK 11
Unit-3
4. Data dependency: The data accessed by the tasks must be examined for dependencies between two or
more tasks. When one task depends on data from another, programmers must ensure that the execution
of the tasks is synchronized to accommodate the data dependency.
5. Testing and debugging: When a program is running in parallel on multiple cores, many different
execution paths are possible. Testing and debugging such concurrent programs is inherently more
difficult than testing and debugging single-threaded applications.
Types of Parallelism
1. Data parallelism focuses on distributing subsets of the same data across multiple computing cores and
performing the same operation on each core.
Consider, for example, summing the contents of an array of size N. On a single-core system, one thread would
simply sum the elements [0] . . . [N − 1]. On a dual-core system, however, thread A, running on core 0, could sum
the elements [0] . . . [N/2 − 1] while thread B, running on core 1, could sum the elements [N/2] . . . [N − 1]. The
two threads would be running in parallel on separate computing cores.
2. Task parallelism involves distributing not data but tasks (threads) across multiple computing cores. Each
thread is performing a unique operation. Different threads may be operating on the same data, or they may be
operating on different data.
Consider again our example above. In contrast to that situation, an example of task parallelism might involve two
threads, each performing a unique statistical operation on the array of elements. The threads again are operating
in parallel on separate computing cores, but each is performing a unique operation.
Fundamentally, then, data parallelism involves the distribution of data across multiple cores and task parallelism
on the distribution of tasks across multiple cores.
SSK 12
Unit-3
Algorithms based on preemptive scheduling are Round Robin (RR), Shortest Remaining Time First
(SRTF), Priority (preemptive version), etc.
Non-Preemptive Scheduling
Non-preemptive Scheduling is used when a process terminates, or a process switches from running
to the waiting state. In this scheduling, once the resources (CPU cycles) are allocated to a process,
the process holds the CPU till it gets terminated or reaches a waiting state. In the case of non -
preemptive scheduling does not interrupt a process running CPU in the middle of the execution.
Instead, it waits till the process completes its CPU burst time, and then it can allocate the CPU to
another process.
Algorithms based on non-preemptive scheduling are: Shortest Job First (SJF basically non
preemptive) and Priority (nonpreemptive version), etc.
The FCFS scheduling algorithm is non-preemptive. Once the CPU has been allocated to a process, that
process keeps the CPU until it releases the CPU, either by terminating or by requesting I/O.
With this scheme, the process that requests the CPU first is allocated the CPU first. The implementation
of the FCFS policy is easily managed with a FIFO queue. When a process enters the ready queue, its PCB
is linked onto the tail of the queue. When the CPU is free, it is allocated to the process at the head of
the queue. The running process is then removed from the queue. The code for FCFS scheduling is simple
to write and understand.
On the negative side, the average waiting time under the FCFS policy is often quite long. Consider the
following set of processes that arrive at time 0, with the length of the CPU burst given in milliseconds:
SSK 13
Unit-3
If the processes arrive in the order P1, P2, P3, and are served in FCFS order, we get the result shown in
the following Gantt chart, which is a bar chart that illustrates a particular schedule, including the start
and finish times of each of the participating processes:
The waiting time is 0 milliseconds for process P1, 24 milliseconds for process P2, and 27 milliseconds
for process P3. Thus, the average waiting time is (0 + 24 + 27)/3 = 17 milliseconds. If the processes arrive
in the order P2, P3, P1, however, the results will be as shown in the following Gantt chart:
The average waiting time is now (6 + 0 + 3)/3 = 3 milliseconds. This reduction is substantial. Thus, the
average waiting time under an FCFS policy is generally not minimal and may vary substantially if the
processes’ CPU burst times vary greatly.
SSK 14
Unit-3
This algorithm associates with each process the length of the process’s next CPU burst. When the CPU
is available, it is assigned to the process that has the smallest next CPU burst. If the next CPU bursts of
two processes are the same, FCFS scheduling is used to break the tie. Note that a more appropriate
term for this scheduling method would be the shortest-next- CPU-burst algorithm, because scheduling
depends on the length of the next CPU burst of a process, rather than its total length.
By comparison, if we were using the FCFS scheduling scheme, the average waiting time would be 10.25
milliseconds.
The SJF scheduling algorithm is provably optimal, in that it gives the minimum average waiting time for
a given set of processes.
SSK 15
Unit-3
A preemptive SJF algorithm will preempt the currently executing process, when the next CPU burst of
the newly arrived process may be shorter than what is left of the currently executing process.
As an example, consider the following four processes, with the length of the CPU burst given in
milliseconds:
Process P1 is started at time 0, since it is the only process in the queue. Process P2 arrives at time 1.
The remaining time for process P1 (7 milliseconds) is larger than the time required by process P2 (4
milliseconds), so process P1 is preempted, and process P2 is scheduled. The average waiting time for
this example is [(10 − 1) + (1 − 1) + (17 − 2) + (5 − 3)]/4 = 26/4 = 6.5 milliseconds. Nonpreemptive SJF
scheduling would result in an average waiting time of 7.75 milliseconds.
Priority Scheduling
A priority is associated with each process, and the CPU is allocated to the process with the highest
priority. Equal-priority processes are scheduled in FCFS order. An SJF algorithm is simply a priority
algorithm where the priority (p) is the inverse of the (predicted) next CPU burst. The larger the CPU
burst, the lower the priority, and vice versa.
As an example, consider the following set of processes, assumed to have arrived at time 0 in the order
P1, P2, ···, P5, with the length of the CPU burst given in milliseconds:
SSK 16
Unit-3
A major problem with priority scheduling algorithms is indefinite blocking, or starvation. A process that
is ready to run but waiting for the CPU can be considered blocked. A priority scheduling algorithm can
leave some low- priority processes waiting indefinitely.
A solution to the problem of indefinite blockage of low-priority processes is aging. Aging involves
gradually increasing the priority of processes that wait in the system for a long time.
Round-Robin Scheduling
The round-robin (RR) scheduling algorithm is designed especially for time- sharing systems. It is similar
to FCFS scheduling, but preemption is added to enable the system to switch between processes. A small
unit of time, called a time quantum or time slice, is defined. The ready queue is treated as a circular
queue.
The CPU scheduler goes around the ready queue, allocating the CPU to each process for a time interval
of up to 1 time quantum.
To implement RR scheduling, we again treat the ready queue as a FIFO queue of processes. New
processes are added to the tail of the ready queue. The CPU scheduler picks the first process from the
ready queue, sets a timer to interrupt after 1 time quantum, and dispatches the process.
Consider the following set of processes that arrive at time 0, with the length of the CPU burst given in
milliseconds:
If we use a time quantum of 4 milliseconds, then process P1 gets the first 4 milliseconds. Since it requires
another 20 milliseconds, it is preempted after the first time quantum, and the CPU is given to the next
process in the queue, process P2. Process P2 does not need 4 milliseconds, so it quits before its time
quantum expires. The CPU is then given to the next process, process P3. Once each process has received
SSK 17
Unit-3
1 time quantum, the CPU is returned to process P1 for an additional time quantum. The resulting RR
schedule is as follows:
SSK 18
Unit-3
Process synchronization
When several processes access and manipulate the same data concurrently and the outcome of the
execution depends on the particular order in which the access takes place, is called a race condition.
To guard against the race condition above, we need to ensure that only one process at a time can be
manipulating the variable counter. To make such a guarantee, we require that the processes be
synchronized in some way.
Process Synchronization is the coordination of execution of multiple processes in a multi-process
system to ensure that they access shared resources in a controlled and predictable manner. It aims
to resolve the problem of race conditions and other synchronization issues in a concurrent system.
A solution to the critical-section problem must satisfy the following three requirements:
1. Mutual exclusion. If process Pi is executing in its critical section, then no other processes can be
executing in their critical sections.
SSK 19
Unit-3
2. Progress. If no process is executing in its critical section and some processes wish to enter their critical
sections, then only those processes that are not executing in their remainder sections can participate
in deciding which will enter its critical section next, and this selection cannot be postponed indefinitely.
5 3. Bounded waiting. There exists a bound, or limit, on the number of times that other processes are
allowed to enter their critical sections after a process has made a request to enter its critical section
and before that request is granted.
Two general approaches are used to handle critical sections in operating systems: preemptive kernels
and nonpreemptive kernels.
A preemptive kernel allows a process to be preempted while it is running in kernel mode.
A nonpreemptive kernel does not allow a process running in kernel mode to be preempted; a kernel-
mode process will run until it exits kernel mode, blocks, or voluntarily yields control of the CPU.
Peterson’s Solution
Peterson’s solution is a software-based solution to the critical-section problem which is restricted to
two processes that alternate execution between their critical sections and remainder sections.
The processes are numbered P0 and P1. For convenience, when presenting Pi , we use Pj to denote the
other process; that is, j equals 1 − i.
Peterson’s solution requires the two processes to share two data items:
int turn;
boolean flag[2];
Entry Section while(true)
flag[i]=true;
turn=j;
while(flag[j]==true && turn==j);
CRITICAL SECTION
The variable turn indicates whose turn it is to enter its critical section. That is, if turn == i, then process
Pi is allowed to execute in its critical section. The flag array is used to indicate if a process is ready to
enter its critical section. For example, if flag[i] is true, this value indicates that Pi is ready to enter its
critical section.
To enter the critical section, process Pi first sets flag[i] to be true and then sets turn to the value j,
thereby asserting that if the other process wishes to enter the critical section, it can do so. If both
processes try to enter at the same time, turn will be set to both i and j at roughly the same time. Only
SSK 20
Unit-3
one of these assignments will last; the other will occur but will be overwritten immediately. The
eventual value of turn determines which of the two processes is allowed to enter its critical section first.
Semaphore
Semaphore is an integer variable which is used in a mutual exclusive manner by various concurrent co-
operative processes inorder to achieve synchronization.
Binary Semaphore: This is also known as mutex lock. It can have only two values 0 and 1. Initially its
value is initialized to 1. It is used to implement the solution of critical section problems with multiple
processes.
Counting Semaphore: Its value can range over an unrestricted domain. It is used to control access to a
resource that has multiple instances (-∞ to +∞ )
A semaphore S is an integer variable that is accessed only through two standard atomic operations:
wait() and signal().
The wait() operation was originally termed P and signal() was originally called V.
wait(S) {
while (S<=0);
S=S-1;
signal(S) {
S++;
If the value of S is zero in P(S) then it will in the while loop without executing the following instruction
i.e. cannot enter the critical section.
If the value of S is 1, it will decrement the value of S then enter the critical section.
SSK 21
Unit-3
Consider five philosophers who spend their lives thinking and eating. The philosophers share a circular
table surrounded by five chairs, each belonging to one philosopher. In the center of the table is a bowl
of rice, and the table is laid with five single chopsticks (Figure 5.13). When a philosopher thinks, she
does not interact with her colleagues. From time to time, a philosopher gets hungry and tries to pick up
the two chopsticks that are closest to her (the chopsticks that are between her and her left and right
neighbors). A philosopher may pick up only one chopstick at a time. Obviously, she cannot pick up a
chopstick that is already in the hand of a neighbor. When a hungry philosopher has both her chopsticks
at the same time, she eats without releasing the chopsticks. When she is finished eating, she puts down
both chopsticks and starts thinking again.
One simple solution is to represent each chopstick with a semaphore. A philosopher tries to grab a
chopstick by executing a wait() operation on that semaphore. She releases her chopsticks by executing
the signal() operation on the appropriate semaphores. Thus, the shared data are where all the elements
of chopstick are initialized to 1. The structure of philosopher i is shown below:
semaphore chopstick[5];
do {
wait(chopstick[i]);
wait(chopstick[(i+1) % 5]);
This solution imposes the restriction that a philosopher may pick up her chopsticks only if both of
them are available. To code this solution, we need to distinguish among three states in which we may
find a philosopher. For this purpose, we introduce the following data structure:
This allows philosopher i to delay herself when she is hungry but is unable to obtain the chopsticks she
needs. We are now in a position to describe our solution to the dining-philosophers problem. The
distribution of the chopsticks is controlled by the monitor DiningPhilosophers.
Each philosopher, before starting to eat, must invoke the operation pickup(). This act may result in the
suspension of the philosopher process. After the successful completion of the operation, the
philosopher may eat. Following this, the philosopher invokes the putdown() operation. Thus,
philosopher i must invoke the operations pickup() and putdown() in the following sequence:
DiningPhilosophers.pickup(i);
DiningPhilosophers.putdown(i);
SSK 23
Unit-3
Deadlock
A process request resources and if the resources are not available at that time, the process enters a
waiting state.
Sometimes, a waiting process is never again able to change state because the resources it has requested
are held by other waiting processes. This situation is called a deadlock.
Request and release of resources that are not managed by the operating system can be accomplished
through the wait() and signal() operations on semaphores.
A system table records whether each resource is free or allocated, the table also records the process to
which it is allocated.
If the process requests a resource that is currently allocated to another process, it can be added to a
queue of processes waiting for this resources.
Deadlocks may also involve different resource types. For example, consider a system with one printer
and one DVD drive. Suppose that process Pi is holding the DVD and process Pj is holding the printer. If
Pi requests the printer and Pj requests the DVD drive, a deadlock occurs.
Deadlock Characterization
A deadlock situation can arise if the following four conditions hold simultaneously
in a system:
1. Mutual exclusion. At least one resource must be held in a non sharable mode; that is, only one
process at a time can use the resource. If another process requests that resource, the requesting
process must be delayed until the resource has been released.
2. Hold and wait. A process must be holding at least one resource and waiting to acquire additional
resources that are currently being held by other processes.
3. No preemption. Resources cannot be preempted; that is, a resource can be released only
voluntarily by the process holding it, after that process has completed its task.
4. Circular wait. A set {P0, P1, ..., Pn} of waiting processes must exist such that P0 is waiting for a
resource held by P1, P1 is waiting for a resource held by P2, ..., Pn−1 is waiting for a resource
held by Pn, and Pn is waiting for a resource held by P0.
SSK 24
Unit-3
Resource-Allocation-Graph Algorithm
A claim edge Pi → Rj indicates that process Pi may request resource Rj at some time in the future. This
edge resembles a request edge in direction but is represented in the graph by a dashed line. When
process Pi requests resource Rj, the claim edge Pi → Rj is converted to a request edge. Similarly, when
a resource Rj is released by Pi, the assignment edge Rj → Pi is reconverted to a claim edge Pi → Rj .
Now suppose that process Pi requests resource Rj. The request can be granted only if converting the
request edge Pi → Rj to an assignment edge Rj → Pi does not result in the formation of a cycle in the
resource-allocation graph. We check for safety by using a cycle-detection algorithm. An algorithm for
detecting a cycle in this graph requires an order of n2 operations, where n is the number of processes
in the system.
Suppose that P2 requests R2. Although R2 is currently free, we cannot allocate it to P2, since this
action will create a cycle in the graph. If P1 requests R2, and P2 requests R1, then a deadlock will
occur.
SSK 25
Unit-3
Banker’s Algorithm
Banker’s Algorithm is a deadlock avoidance algorithm which works with multiple instances of each
resource type.
When a new process enters the system, it must declare the maximum number of instances of each
resource type that it may need. This number may not exceed the total number of resources in the
system.
When a user requests a set of resources, the system must determine whether the allocation of these
resources will leave the system in a safe state. If it will, the resources are allocated; otherwise, the
process must wait until some other process releases enough resources.
The following data structures must be maintained to implement the Banker’s Algorithm:
1) Available: It indicates the number of available resources of each type.
If Available[j] equals k, then k instances of resource type Rj are available.
3) Allocation: It defines the number of resources of each type currently allocated to each process. If
Allocation[i][j] equals k, then process Pi is currently allocated k instances of resource type Rj .
SSK 26
Unit-3
Q. Consider a system with five processes P0 through P4 and three resource types A, B, and C. Resource
type A has ten instances, resource type B has five instances, and resource type C has seven instances.
Suppose that, at time T0, the following snapshot of the system has been taken:
A B C A B C A B C A B C
P0 0 1 0 7 5 3 3 3 2 7 4 3
P1 2 0 0 3 2 2 5 3 2 1 2 2
P2 3 0 2 9 0 2 7 4 3 6 0 0
P3 2 1 1 2 2 2 7 4 5 0 1 1
P4 0 0 2 4 3 3 7 5 5 4 3 1
SSK 27
Unit-3
Process A B C
P0 7 4 3
P1 1 2 2
P2 6 0 0
P3 0 1 1
P4 4 3 1
Need<=Available
Need<=Available
New available= 3 3 2 + 2 0 0 = 5 3 2
Need<=Available
Need<=Available
New available= 5 3 2 + 2 1 1 = 7 4 3
Need<=Available
SSK 28
Unit-3
New available= 7 4 3 + 0 0 2 = 7 4 5
Need<=Available
New available= 7 4 5 + 0 1 0 = 7 5 5
Need<=Available
New available= 7 5 5 + 3 0 2 = 10 5 7
Therefore, the system is in the safe state as the sequence <P1, P3, P4, P0, P2> satisfies the safety
algorithm.
Deadlock recovery
There are two options for breaking a deadlock. One is simply to abort one or more processes to break
the circular wait. The other is to preempt some resources from one or more of the deadlocked
processes.
Process Termination
To eliminate deadlocks by aborting a process, we use one of two methods. In both methods, the system
reclaims all resources allocated to the terminated processes.
• Abort all deadlocked processes. This method clearly will break the deadlock cycle, but at great
expense. The deadlocked processes may have computed for a long time, and the results of these partial
computations must be discarded and probably will have to be recomputed later.
• Abort one process at a time until the deadlock cycle is eliminated. This method incurs considerable
overhead, since after each process is aborted, a deadlock-detection algorithm must be invoked to
determine whether any processes are still deadlocked.
Aborting a process may not be easy. If the process was in the midst of updating a file, terminating it will
leave that file in an incorrect state. Similarly, if the process was in the midst of printing data on a printer,
the system must reset the printer to a correct state before printing the next job.
SSK 29
Unit-3
Resource Preemption
If preemption is required to deal with deadlocks, then three issues need to be addressed:
1. Selecting a victim: As in process termination, we must determine the order of preemption to
minimize cost. Cost factors may include such parameters as the number of resources a deadlocked
process is holding and the amount of time the process has thus far consumed.
2. Rollback: If we preempt a resource from a process, it cannot continue with its normal execution; it
is missing some needed resource. We must roll back the process to some safe state and restart it from
that state.
3. Starvation. In a system where victim selection is based primarily on cost factors, it may happen that
the same process is always picked as a victim. As a result, this process never completes its designated
task, a starvation situation any practical system must address. Clearly, we must ensure that a process
can be picked as a victim only a (small) finite number of times. The most common solution is to include
the number of rollbacks in the cost factor.
SSK 30