V-Lab@ANDC

Deadlock Detection Using Resource Allocation Graph

Aim

The objective of this virtual lab is to provide a comprehensive understanding of Resource Allocation Graphs (RAGs) and their usage for the allocation of resources to processes and to detect potential deadlocks for two conditions (hold-and-wait and circular-wait) through interactive simulation. RAG is explained with respect to its usage in resource allocation to different processes maintained by the operating system

Theory and Applications
Key Concepts
  • Resource Allocation Graph (RAG)
  • It is a directed graph with two types of nodes representing either processes or resources, and arrows representing either allocation of a resource to a process (i.e. assignment edge), or the request by a process to access a resource resource (i.e. request edge). It is useful for visualising if a resource is free or in use, and which resources a process is requesting for.


  • Deadlock
  • A deadlock is a situation where processes are stuck and cannot continue with their execution. This happens when a set of processes cannot acquire the resources they need to complete their work because those resources are held by other processes, a circular path of such conditions in a RAG leads to a stuck situation


  • Finding Deadlock
  • The procedure of finding a deadlock depends on whether the resources are single instance or multi-instance. Detection of deadlock in a single instance scenario is straightforward, but gets complicated in case of multi-instance. Generally, it can be said that a deadlock may be present if the following 4 conditions are present in the RAG:

    1. Mutual Exclusion: Each resource can be held by only one process.
    2. No Preemption: Resources must be released manually from a process before being reassigned a request by another process.
    3. Hold and Wait: A process is already holding a resource while requesting the same instance or another resource that is currently held.
    4. Circular Wait: A hold and wait condition occurs in a circular form in the RAG

Applications of RAG in the Real World
  1. Server Load Balancing – To evenly distribute requests across available servers and avoid bottlenecks.
  2. Operating Systems – Managing process-resource allocation to detect and prevent deadlocks in CPU and memory usage.
  3. Database Management – Efficient transaction scheduling which avoids deadlocks.
  4. Cloud Resource Management – Allocating virtual machines and storage resources efficiently to various services.
  5. Traffic Systems – Coordinating traffic light resources and vehicle flows to prevent circular wait deadlocks.
Procedure

Following two steps are followed to detect deadlocks in RAG:


  1. Create RAG using the input given by the user:
    • Enter the number of resources and specify the instances for each resource.
    • Enter the number of processes to be included in RAG.
    • To add a request edge, right-click on a process icon, then right-click on the resource it is requesting.
    • To add an assignment edge, right-click on a resource icon, then right-click on the process that holds it.

  2. Find Deadlock in the given Graph:

  3. Following two conditions are checked to find potential deadlock:


    1. Hold and Wait: For each process, check if it is holding a resource while requesting the same instance or another resource that is currently held. If true, the edge is highlighted in yellow. (toggle 'view hold & wait')
    2. Circular Wait: Use Depth First Search on each node to check for a cycle. If a cycle is found, the edge is highlighted in green. (toggle 'view circular wait')
Code
// JavaScript Code Example
// Node Structure: Defines the processes and resources in the system
        const nodes = [
            { id: 'P1', type: 'process' },
            { id: 'P2', type: 'process' },
            { id: 'R1.1', type: 'resource', group: 'R1' },
            { id: 'R1.2', type: 'resource', group: 'R1' },
            { id: 'R2.1', type: 'resource', group: 'R2' }
        ];

// Links Structure: Defines the relationships (edges) between processes and resources
        const links = [
            { source: 'P1', target: 'R1.1' },
            { source: 'R1.2', target: 'P2' },
            { source: 'P2', target: 'R2.1' }
        ];

// Function to detect all circular waits (causing deadlocks) and return involved edges
        function detectAllCycleEdges(links) {
            let visited = new Set();    // Tracks nodes that have been fully processed
            let stack = new Set();      // Tracks nodes in the current DFS recursion
            let edgeStack = [];         // Tracks the edges being traversed in the current DFS path
            let allCycleEdges = [];     // To store all the cycles detected
        
        // Helper function to perform Depth-First Search (DFS) to find cycles
            function dfs(node) {
                if (stack.has(node)) {
                    // Cycle found: return the edges involved in this cycle
                    allCycleEdges.push([...edgeStack]); // Save a copy of the current edge stack
                    return;
                }
                if (visited.has(node)) {
                    // Node has already been fully processed, skip it
                    return;
                }
        
                // Mark the node as visited and add to the current recursion stack
                visited.add(node);
                stack.add(node);
        
                // Traverse all outgoing edges from the current node
                for (let link of links) {
                    if (link.source === node) {
                        // Add the current edge to the edge stack
                        edgeStack.push(link);
                        dfs(link.target); // Continue DFS to the target node
                        // Backtrack: remove the edge from the stack if no cycle found
                        edgeStack.pop();
                    }
                }
                // Backtrack: remove the node from the recursion stack
                stack.delete(node);
            }
            // Start DFS from each node in nodes1
            for (let node of nodes) {
                dfs(node.id); // Perform DFS starting from the node's ID
            }
            return allCycleEdges; // Return all cycles found
        }

// Function to calculate hold-wait edges (potential deadlock scenarios)
        function calc_hold_wait_edges(){
            yellowLinks=[];//empty 
            for(let link of links){
                const sourceNode = nodes.find(node => node.id === link.source.id || node.id === link.source);
                const targetNode = nodes.find(node => node.id === link.target.id || node.id === link.target);
                if(sourceNode.type==="resource" && targetNode.type==="process"){//hold wait can only form
                  //resource to process and + process to another resource
                    for (let link1 of links){
                        if(link.target===link1.source){
                            for(let link2 of links){
                                if(link2.source===link1.target){
                                    yellowLinks.push(link)
                                    yellowLinks.push(link1)
                                }
                            }
                        }
                        
                    }
                }
                
            }
            console.log("Yellow_links calculated : " , yellowLinks);
        }

// Function to add a new process node
        function addNode(value) {
            const numberOfNodes = value;
            // Check if the input is a valid number
            if (isNaN(numberOfNodes) || numberOfNodes <= 0) {
                let message="Please Enter a Valid Number that is greater than 1"; 
                show_message(message); 
                return;
            }
            
            for (let i = 0; i < numberOfNodes; i++) {
                const newNodeId = `P${nodes.filter((node) => node.type === "process").length + 1}`;
                const newNode = {
                    id: newNodeId,
                    type: "process",
                    x: width / 2,
                    y: height / 2,};
                nodes.push(newNode);
            }
            console.log("nodes : ", nodes);
            hide_addProcess()            //hide the form 
            renderGraph(); // Call renderGraph() once after adding all nodes
        }

// Function to add multiple resources (Adds m resource each having n resource instances)
            function addMultipleResources(value,value1) {
                let m = value;
                let n = value1
                // Validate inputs: Must be natural numbers (positive integers)
                if (isNaN(m) || isNaN(n) || m < 1 || n < 1 || !Number.isInteger(m) || !Number.isInteger(n)) {
                    let message="Please Enter a Valid Number that is greater than 1";
                    show_message(message); 
                    return;
                }
                // Find the highest existing resource number
                const resourceNumbers = nodes
                    .filter(node => node.type === 'resource')
                    .map(node => parseInt(node.id.split('.')[0].substring(1)))
                    .filter(num => !isNaN(num));
            
                let startingResourceNumber = (resourceNumbers.length > 0 ? Math.max(...resourceNumbers) : 0) + 1;
            
                // Create m resources, each with n instances
                for (let i = 0; i < m; i++) {
                    let resourceNumber = startingResourceNumber + i;
            
                    for (let j = 1; j <= n; j++) {
                        const newResourceId = `R${resourceNumber}.${j}`;
                        const newResource = { id: newResourceId, type: 'resource', group: `R${resourceNumber}` };
                        nodes.push(newResource);
                    }
                }
                console.log("nodes:", nodes);
                renderGraph();
            }

// Function to add a new resource instance
        function addResourceInstance(value) {
            const resourceNumber =value;
            if (resourceNumber) {
                const existingResources = nodes.filter(node => 
                    node.type === 'resource' && node.id.startsWith(`R${resourceNumber}.`)
                );
                if (existingResources.length > 0) {
                    let maxNumber = 0;
                    nodes.forEach(node => {
                        if (node.type === "resource" && node.id.startsWith(`R${resourceNumber}.`)) {
                            let match = node.id.match(/R\d+\.(\d+)$/); // Extract only the last numeric part
                            if (match) {
                                let num = parseInt(match[1]); // Convert to number
                                maxNumber = Math.max(maxNumber, num);
                            }
                        }
                    });
                    const newInstanceNumber = maxNumber + 1;            
                    const newResourceId = `R${resourceNumber}.${newInstanceNumber}`;
                    const newResource = { id: newResourceId, type: 'resource', group: `R${resourceNumber}` };
                    nodes.push(newResource);
                    console.log("nodes : " , nodes);
                } else {
                    const newResourceId = `R${resourceNumber}.1`;
                    const newResource = { id: newResourceId, type: 'resource', group: `R${resourceNumber}` };
                    nodes.push(newResource);
                    console.log("nodes : " , nodes);
                }
                renderGraph();
            }
        }
                
Practice

Instructions to Use

1. Process: Process nodes are represented by blue-colored circles and are numbered as P1, P2, P3, ..., Pn if the graph has ‘n’ processes.

2. Resource: Each resource is represented by a gray-colored rectangle box containing one or more resource instances, represented by orange-colored rectangles. A resource must have at least one resource instance.

3. Resource Instance: Each resource instance is represented by an orange-colored rectangle box and is numbered as Rm.n, where ‘m’ denotes the resource number and ‘n’ denotes the instance number within that resource. For example: R1.1, R1.2 ; R2.1, R2.2

4. Selection: Right-click (or long-press on mobile devices) on any process or resource instance to select it. The selected item will have a green boundary. To deselect, right-click (or long-press) again.

5. Drag/Movement: Drag any process or resource in the graph simulation using a left-click (or a simple tap on mobile devices).

6. Assignment Edge Creation: First, right-click (or long-press) on any resource instance, and then right-click (or long-press) on any process. This will create an assignment edge (blue in color) from that resource instance to the process. (Note: A single resource instance cannot be assigned to two different processes.)

7. Requesting Edge Creation: First, right-click (or long-press) on any process, and then right-click (or long-press) on any resource instance. This will create a requesting edge (red in color) from that process to the resource instance. (Note: A single process cannot request two different resource instances of the same resource.)

8. Assignment/Requesting Edge Deletion: To delete an edge (either assignment or requesting), right-click (or long-press) on it is tail process/resource instance and then right-click (or long-press) on it is head process/resource instance.

Note: Use long-press instead of right-click on mobile devices.

Button functionalities

Following buttons are provided for graph simulation ( Click on any button to see it is functionality)

1.Add Processes: Use to add “n” number of processes into the graph.

2.Add Resources: Use to add “r” number of resources with each having minimum “s” number of resource-instances.

3.Add Resource-Instance: Use this button to add 1 more Resource-Instance to any of the existing resources.

4.View Hold-wait: Activate the Visualisation of Hold-wait condition in the graph. The edges in hold-wait condition will then be highlighted with yellow color.

5.View Circular-wait: Activate the Visualisation of Circular-wait condition in the graph. The edges in circular-wait will then be highlighted with green color.

6.Delete: Activate deletion mode, after this right-click(long press for mobiles) on any Process or Resource-Instance to delete it.

7.Reset: Make the graph simulation empty or delete everything.

8.Edge Creation/ Edge Deletion: Use to read instructions to create or delete edges.(Both of these buttons do not toggle any functionality.)

Note: Buttons having activation can be deactivated if again left-click (simple click for mobiles) on the button. The activated button is deactivated on left-click (simple click for mobiles).

How many Processes, you want to add in the graph ?

In which Resource, you want to add 1 more Resource-Instance ?

How many Resources, you want to add in the graph and the minimum Resource Instances does they all have ?

Result

In this experiment, an interactive RAG is created to simulate the allocation and request of resources by processes. The provision to add multiple processes, multiple resources with more than one instance empowers realistic simulation of RAGs. The necessary conditions like hold-and-wait and circular-wait are detected and shown visually for quick grasping of concepts related to deadlock detection


Through the graphical interface, occurrences of deadlock conditions are identified in real time. Furthermore, the provided simulation emphasized on the necessity of careful resource management and controlled request handling for preventing deadlock issues in concurrent systems.

Quiz

INSTRUCTIONS

  • There are 4 questions in total
  • Read each question carefully before answering.
  • Select the correct option(s) (multiple options CAN be correct).
  • Click Next to move to the following question.
  • At the end, you can view your quiz report and retake the quiz if needed.
References
Team & Tools

Students

Mentor

  • Prof. Sharanjit Kaur, Department of Computer Science

Tools Used

  • Vanilla HTML, CSS, JS - for creating the web page D3 - for graph simulation