OS - Module - 3
OS - Module - 3
Module : 3
Deadlocks
Every process needs some resources to complete its execution. However, the resource is granted
in a sequential order.
* The process requests for some resource.
* OS grant the resource if it is available otherwise let the process waits.
* The process uses it and release on the completion.
A Deadlock is a situation where each of the computer process waits for a resource which is being
assigned to some another process. In this situation, none of the process gets executed since the
resource it needs, is held by some other process which is also waiting for some other resource to
be released.
Let us assume that there are three processes P1, P2 and P3. There are three different resources
R1, R2 and R3. R1 is assigned to P1, R2 is assigned to P2 and R3 is assigned to P3.
After some time, P1 demands for R1 which is being used by P2. P1 halts its execution since it
can't complete without R2. P2 also demands for R3 which is being used by P3. P2 also stops its
execution because it can't continue without R3. P3 also demands for R1 which is being used by
P1 therefore P3 also stops its execution.
In this scenario, a cycle is being formed among the three processes. None of the process is
progressing and they are all waiting. The computer becomes unresponsive since all the processes
got blocked.
System Model
* For the purposes of deadlock discussion, a system can be modeled as a collection of limited
resources that can be divided into different categories and allocated to a variety of processes,
each with different requirements.
* Memory, printers, CPUs, open files, tape drives, CD-ROMs, and other resources are
examples of resource categories.
* By definition, all resources within a category are equivalent, and any of the resources within
that category can equally satisfy a request from that category. If this is not the case (i.e. if
there is some difference between the resources within a category), then that category must be
subdivided further. For example, the term “printers” may need to be subdivided into “laser
printers” and “color inkjet printers.”
* Some categories may only have one resource.
* The kernel keeps track of which resources are free and which are allocated, to which process
they are allocated, and a queue of processes waiting for this resource to become available for
all kernel-managed resources. Mutexes or wait() and signal() calls can be used to control
application-managed resources (i.e. binary or counting semaphores. )
* When every process in a set is waiting for a resource that is currently assigned to another
process in the set, the set is said to be deadlocked.
Components :
* Resources − The system has a set of resources that are shared among processes.
These resources can be hardware or software components, such as memory, files,
printers, or network connections. Each resource is identified by a unique name or
identifier.
* Processes − The system has a set of processes that request and release
resources. Processes are units of execution that can be started, suspended, resumed, and
terminated. Each process is identified by a unique process ID.
* Resource Allocation − Each resource can be in one of two states , allocated or available.
A resource that is allocated to a process cannot be used by any other process until it is
released.
* Request and Release − A process can request a resource by sending a request to the
system. If the resource is available, it will be allocated to the process. When a process is
finished using a resource, it must release it so that it can be used by other processes.
* Resource Dependency − Some processes may require multiple resources to complete
their tasks. A resource dependency graph can be used to represent the relationships
between processes and resources and to detect potential deadlocks.
* Deadlock Detection − A deadlock can occur when two or more processes are waiting for
resources that are being held by other processes, creating a circular
dependency. Deadlock detection algorithms can be used to detect when a deadlock has
occurred, so that corrective action can be taken.
* Deadlock Resolution − Once a deadlock has been detected, it can be resolved by
breaking the circular dependency between the processes. This can be done by releasing
one or more resources that are being held by a process, or by preempting one or more
processes that are holding resources. The Working of some of the techniques are given
below −
* Resource preemption is a technique used to break the circular wait condition of a
deadlock. The operating system can preempt resources from one or more processes
involved in the deadlock and allocate them to the processes that need them.
Preemption can be done either selectively or globally. In selective preemption,
only the resources that are required to resolve the deadlock are preempted, while in
global preemption, all the resources held by the deadlocked processes are
preempted.
* When a process is terminated, all the resources held by the process are released,
and other processes can proceed. However, this approach can lead to data loss and
inconsistency if the terminated process was in the middle of a critical task.
* Deadlock Avoidance − Deadlock avoidance is a technique used to prevent the
occurrence of deadlocks in a computer system. The goal of deadlock avoidance is to
ensure that all resources required by a process are available before the process starts
execution, thereby avoiding the possibility of deadlock.
There are several algorithms that can be used for deadlock avoidance, including the banker's
algorithm and the resource allocation graph. These algorithms use a mathematical model to
analyze resource allocation and to determine whether a process should be allowed to start or
wait for resources.
* The banker's algorithm is a widely used method for deadlock avoidance. It is a resource
allocation algorithm that checks whether a requested resource can be granted to a process
without causing a deadlock. The algorithm works by simulating the allocation of
resources and checking whether a safe state can be reached. A safe state is a state where
all processes can complete their execution without causing a deadlock.
* The resource allocation graph is another method for deadlock avoidance. It represents
the allocation of resources as a directed graph. Each process is represented by a node, and
each resource is represented by an edge. The algorithm checks for cycles in the graph to
determine whether a deadlock has occurred. If a cycle is detected, the process requesting
the resource is blocked until the required resource becomes available.
Deadlock Characterization
A deadlock happens in operating system when two or more processes need some resource to
complete their execution that is held by the other process.
A deadlock occurs if the four Coffman conditions hold true. But these conditions are not
mutually exclusive. They are given as follows −
Mutual Exclusion
There should be a resource that can only be held by one process at a time. In the diagram below,
there is a single instance of Resource 1 and it is held by Process 1 only.
No Preemption
A resource cannot be preempted from a process by force. A process can only release a resource
voluntarily. In the diagram below, Process 2 cannot preempt Resource 1 from Process 1. It will
only be released when Process 1 relinquishes it voluntarily after its execution is complete.
Circular Wait
A process is waiting for the resource held by the second process, which is waiting for the
resource held by the third process and so on, till the last process is waiting for a resource held by
the first process. This forms a circular chain. For example: Process 1 is allocated Resource2 and
it is requesting Resource 1. Similarly, Process 2 is allocated Resource 1 and it is requesting
Resource 2. This forms a circular wait loop.
The system reallocation graph is a directed graph that briefs you about the deadlock more
precisely. Like every graph, it also has a set of vertices and a set of edges. Further, the set of
vertices can be classified into two types of nodes P and R. Where P is the set of vertices
indicating the set of active processes and R is the set of vertices indicating all types of
resources in the system.
When a process requests for a resource it denoted by the request edge in the resource-allocation
graph. The request edge is a directed edge from the requesting process Pi to requested resource
Rj i.e. Pi -> Rj.
Well, when a resource is allotted to some process then it is denoted by the assignment edge. The
assignment edge is the directed edge from the instance of resource Rj to the process Pi i.e. Rj ->
Pi.
In the graph, resources are denoted by the rectangles and the processes are denoted by
the circles. If a resource has multiple instances then it is denoted by the dots inside the rectangle.
When a process request for an instance of the resource it directs a request edge to the resource. If
the resource is able to allocate the resource instance to the requesting process then immediately
the request edge is converted to assignment edge.
The request edge always points to the resource rectangle in the graph, not to dots (instance)
inside the rectangle. Although the assignment edge nominates the dot (instance) to a process.
To understand deadlock we let us take an example. Consider we have following set of nodes and
edges.
The figure below shows that the process P1 has requested for the instance of resource R1 is
already holding the instance of resource R2. The process P2 has requested for the instance of
resource R3 and is already holding the instances of resource R1 and R3. The process P3 has not
requested for any resource instance but is holding the instance for resource R3.
Remember if the resource allocation graph has a cycle and every resource has a single instance
then it implies that a deadlock has occurred. In case, the resources have multiple instances then a
cycle in the graph need not be indicating the occurrence of deadlock.
Consider that the process P3 is requesting for the instance of resource R2 which is already held by
the process P1 and P2. In this case, you will observe that there are two cycles in the resource
allocation graph:
Process P1, P2 and P3 are now in deadlock as each process in the cycle is waiting for the resource
held by another process. But every cycle in the resource allocation graph does not indicate the
deadlock, you have to observe the cycle carefully while dealing with deadlock problem. So, this
is how you can characterize the deadlock in the system.
Ostrich Algorithm
The ostrich algorithm means that the deadlock is simply ignored and it is assumed that it will
never occur. This is done because in some systems the cost of handling the deadlock is much
higher than simply ignoring it as it occurs very rarely. So, it is simply assumed that the deadlock
will never occur and the system is rebooted if it occurs by any chance.
Deadlock Prevention
Deadlock Prevention
If we simulate deadlock with a table which is standing on its four legs then we can also simulate
four legs with the four conditions which when occurs simultaneously, cause the deadlock.
However, if we break one of the legs of the table then the table will fall definitely. The same
happens with deadlock, if we can be able to violate one of the four necessary conditions and
don't let them occur together then we can prevent the deadlock.
Let's see how we can prevent each of the conditions.
1. Mutual Exclusion
Mutual section from the resource point of view is the fact that a resource can never be used by
more than one process simultaneously which is fair enough but that is the main reason behind the
deadlock. If a resource could have been used by more than one process at the same time then the
process would have never been waiting for any resource.
However, if we can be able to violate resources behaving in the mutually exclusive manner then
the deadlock can be prevented.
Spooling
For a device like printer, spooling can work. There is a memory associated with the printer which
stores jobs from each of the process into it. Later, Printer collects all the jobs and print each one
of them according to FCFS. By using this mechanism, the process doesn't have to wait for the
printer and it can continue whatever it was doing. Later, it collects the output when it is
produced.
Although, Spooling can be an effective approach to violate mutual exclusion but it suffers from
two kinds of problems.
* This cannot be applied to every resource.
* After some point of time, there may arise a race condition between the processes to get
space in that spool.
We cannot force a resource to be used by more than one process at the same time since it will not
be fair enough and some serious problems may arise in the performance. Therefore, we cannot
violate mutual exclusion for a process practically.
3. No Preemption
Deadlock arises due to the fact that a process can't be stopped once it starts. However, if we take
the resource away from the process which is causing deadlock then we can prevent deadlock.
This is not a good approach at all since if we take a resource away which is being used by the
process then all the work which it has done till now can become inconsistent.
Consider a printer is being used by any process. If we take the printer away from that process
and assign it to some other process then all the data which has been printed can become
inconsistent and ineffective and also the fact that the process can't start printing again from
where it has left which causes performance inefficiency.
4. Circular Wait
To violate circular wait, we can assign a priority number to each of the resource. A process can't
request for a lesser priority resource. This ensures that not a single process can request a resource
which is being utilized by some other process and no cycle will be formed.
Among all the methods, violating Circular wait is the only approach that can be implemented
practically.
The main task of the OS is detecting the deadlocks. The OS can detect the deadlocks with the
help of Resource allocation graph.
In single instanced resource types, if a cycle is being formed in the system then there will
definitely be a deadlock. On the other hand, in multiple instanced resource type graph, detecting
a cycle is not just enough. We have to apply the safety algorithm on the system by converting the
resource allocation graph into the allocation matrix and request matrix.
In order to recover the system from deadlocks, either OS considers resources or processes.
For Resource
We can snatch one of the resources from the owner of the resource (process) and give it to the
other process with the expectation that it will complete the execution and will release this
resource sooner. Well, choosing a resource which will be snatched is going to be a bit difficult.
System passes through various states to get into the deadlock state. The operating system
canrollback the system to the previous safe state. For this purpose, OS needs to implement check
pointing at every state.
The moment, we get into deadlock, we will rollback all the allocations to get into the previous
safe state.
For Process
Kill a process
Killing a process can solve our problem but the bigger concern is to decide which process to kill.
Generally, Operating system kills a process which has done least amount of work until now.
This is not a suggestible approach but can be implemented if the problem becomes very serious.
Killing all process will lead to inefficiency in the system because all the processes will execute
again from starting.
Deadlock avoidance
In complex systems involving multiple processes and shared resources, the potential for
deadlocks arises when processes wait for each other to release resources, causing a standstill.
The resulting deadlocks can cause severe issues in computer systems, such as performance
degradation and even system crashes. To prevent such problems, the technique of deadlock
avoidance is employed. It entails scrutinizing the requests made by processes for resources and
evaluating the available resources to determine if the grant of such requests would lead to a
deadlock. In cases where granting a request would result in a deadlock, the system denies the
request. Deadlock avoidance is a crucial aspect of operating system design and plays an
indispensable role in upholding the dependability and steadiness of computer systems.
A safe state refers to a system state where the allocation of resources to each process ensures the
avoidance of deadlock. The successful execution of all processes is achievable, and the
likelihood of a deadlock is low. The system attains a safe state when a suitable sequence of
resource allocation enables the successful completion of all processes.
Conversely, an unsafe state implies a system state where a deadlock may occur. The successful
completion of all processes is not assured, and the risk of deadlock is high. The system is
insecure when no sequence of resource allocation ensures the successful execution of all
processes.
When resource categories have only single instances of their resources, Resource- Allocation
Graph Algorithm is used. In this algorithm, a cycle is a necessary and sufficient condition for
deadlock.
When resource categories have multiple instances of their resources, Banker’s Algorithm is used.
In this algorithm, a cycle is a necessary but not a sufficient condition for deadlock.
Resource Allocation Graph (RAG) is a popular technique used for deadlock avoidance. It is a
directed graph that represents the processes in the system, the resources available, and the
relationships between them. A process node in the RAG has two types of edges, request edges,
and assignment edges. A request edge represents a request by a process for a resource, while an
assignment edge represents the assignment of a resource to a process.
To determine whether the system is in a safe state or not, the RAG is analyzed to check for
cycles. If there is a cycle in the graph, it means that the system is in an unsafe state, and granting
a resource request can lead to a deadlock. In contrast, if there are no cycles in the graph, it means
that the system is in a safe state, and resource allocation can proceed without causing a deadlock.
The RAG technique is straightforward to implement and provides a clear visual representation of
the processes and resources in the system. It is also an effective way to identify the cause of a
deadlock if one occurs. However, one of the main limitations of the RAG technique is that it
assumes that all resources in the system are allocated at the start of the analysis. This assumption
can be unrealistic in practice, where resource allocation can change dynamically during system
operation. Therefore, other techniques such as the Banker's Algorithm are used to overcome this
limitation.
Banker’s Algorithm
The banker's algorithm is a deadlock avoidance algorithm used in operating systems. It was
proposed by Edsger Dijkstra in 1965. The banker's algorithm works on the principle of ensuring
that the system has enough resources to allocate to each process so that the system never enters a
deadlock state. It works by keeping track of the total number of resources available in the system
and the number of resources allocated to each process.
The algorithm is used to prevent deadlocks that can occur when multiple processes are
competing for a finite set of resources. The resources can be of different types such as memory,
CPU cycles, or I/O devices. It works by first analysing the current state of the system and
determining if granting a resource request from a process will result in a safe state. A state is
considered safe if there is at least one sequence of resource allocations that can satisfy all
processes without causing a deadlock.
The Banker's algorithm assumes that each process declares its maximum resource requirements
upfront. Based on this information, the algorithm allocates resources to each
Resource-Allocation Graph process such that the total number of allocated resources never
exceeds the total number of available resources. The algorithm does not grant access to resources
that could potentially lead to a deadlock situation. The Banker's algorithm uses a matrix called
the "allocation matrix" to keep track of the resources allocated to each process, and a "request
matrix" to keep track of the resources requested by each process. It also uses a "need matrix" to
represent the resources that each process still needs to complete its execution.
To determine if a request can be granted, the algorithm checks if there is enough available
resources to satisfy the request, and then checks if granting the request will still result in a safe
state. If the request can be granted safely, the algorithm grants the resources and updates the
allocation matrix, request matrix, and need matrix accordingly. If the request cannot be granted
safely, the process must wait until sufficient resources become available.
Define the total number of available resources for each resource type.
Create a matrix called the "allocation matrix" to represent the current resource allocation for each
process.
Create a matrix called the "need matrix" to represent the remaining resource needs for each
process.
2. Define a request
If the requested resources are not available, the process must wait.
If the state is safe, grant the request by updating the allocation matrix and the need matrix.
If the state is not safe, do not grant the request and let the process wait.
When a process has finished its execution, releases its allocated resources by updating the
allocation matrix and the need matrix.
The above steps are repeated for each resource request made by any process in the system.
Overall, the Banker's algorithm is an effective way to avoid deadlocks in resource constrained
systems by carefully managing resource allocations and predicting potential conflicts before they
arise.
Deadlock detection
Deadlock detection and recovery is the process of detecting and resolving deadlocks in an
operating system. A deadlock occurs when two or more processes are blocked, waiting for each
other to release the resources they need. This can lead to a system-wide stall, where no process
can make progress.
Prevention: The operating system takes steps to prevent deadlocks from occurring by ensuring
that the system is always in a safe state, where deadlocks cannot occur. This is achieved through
resource allocation algorithms such as the Banker’s Algorithm.
Detection and Recovery: If deadlocks do occur, the operating system must detect and resolve
them. Deadlock detection algorithms, such as the Wait-For Graph, are used to identify deadlocks,
and recovery algorithms, such as the Rollback and Abort algorithm, are used to resolve them.
The recovery algorithm releases the resources held by one or more processes, allowing the
system to continue to make progress.
In this case for Deadlock detection, we can run an algorithm to check for the cycle in the
Resource Allocation Graph. The presence of a cycle in the graph is a sufficient condition for
deadlock.
In the above diagram, resource 1 and resource 2 have single instances. There is a cycle R1 → P1
→ R2 → P2. So, Deadlock is Confirmed.
Detection of the cycle is necessary but not a sufficient condition for deadlock detection, in this
case, the system may or may not be in deadlock varies according to different situations.
The Wait-For Graph Algorithm is a deadlock detection algorithm used to detect deadlocks in a
system where resources can have multiple instances. The algorithm works by constructing a
Wait-For Graph, which is a directed graph that represents the dependencies between processes
and resources.
Improved System Stability: Deadlocks can cause system-wide stalls, and detecting and resolving
deadlocks can help to improve the stability of the system.
Better Resource Utilization: By detecting and resolving deadlocks, the operating system can
ensure that resources are efficiently utilized and that the system remains responsive to user
requests.
Better System Design: Deadlock detection and recovery algorithms can provide insight into the
behavior of the system and the relationships between processes and resources, helping to inform
and improve the design of the system.
Performance Overhead: Deadlock detection and recovery algorithms can introduce a significant
overhead in terms of performance, as the system must regularly check for deadlocks and take
appropriate action to resolve them.
False Positives and Negatives: Deadlock detection algorithms are not perfect and may produce
false positives or negatives, indicating the presence of deadlocks when they do not exist or
failing to detect deadlocks that do exist.
Risk of Data Loss: In some cases, recovery algorithms may require rolling back the state of one
or more processes, leading to data loss or corruption.
Prevention: The operating system takes steps to prevent deadlocks from occurring by ensuring
that the system is always in a safe state, where deadlocks cannot occur. This is achieved through
resource allocation algorithms such as the Banker’s Algorithm.
Detection and Recovery: If deadlocks do occur, the operating system must detect and resolve
them. Deadlock detection algorithms, such as the Wait-For Graph, are used to identify deadlocks,
and recovery algorithms, such as the Rollback and Abort algorithm, are used to resolve them.
The recovery algorithm releases the resources held by one or more processes, allowing the
system to continue to make progress.
Killing all the processes involved in the deadlock. Killing process one by one.
After killing each process check for deadlock again and keep repeating the process
till the system recovers from deadlock. Killing all the processes one by one helps a
system to break circular wait conditions.
Resource Preemption –
Resources are preempted from the processes involved in the deadlock, and
preempted resources are allocated to other processes so that there is a possibility of
recovering the system from the deadlock. In this case, the system goes into
starvation.