-
Notifications
You must be signed in to change notification settings - Fork 306
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1444 from o0PHOENIX0o/DeadLockDetection
#1417 Added Dead lock detection using Resource Allocation Graph
- Loading branch information
Showing
2 changed files
with
294 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,224 @@ | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
|
||
struct Resource; | ||
|
||
typedef struct Process { | ||
int id; | ||
struct Process *next_process; | ||
struct Resource *requested_resource; | ||
int visited; | ||
} Process; | ||
|
||
typedef struct Resource { | ||
int id; | ||
struct Resource *next_resource; | ||
struct Process *allocated_process; | ||
} Resource; | ||
|
||
Process *Phead = NULL; | ||
Resource *Rhead = NULL; | ||
|
||
void Allocate(int R, int P); | ||
int DFS(Process *process); | ||
int DetectCycle(); | ||
void Request(int P, int R); | ||
void Cleanup(); | ||
|
||
|
||
int main() { | ||
// Allocate(ResourceId, ProcessId); | ||
Allocate(1, 1); | ||
Allocate(2, 2); | ||
|
||
// Request(ProcessId, ResourceId); | ||
Request(1, 2); | ||
Request(2, 1); | ||
|
||
Cleanup(); | ||
return 0; | ||
} | ||
|
||
// Function to allocate a resource to a process | ||
void Allocate(int R, int P) { | ||
// Check if the process with ID P already exists in the list | ||
Process *Ptemp = Phead; | ||
while (Ptemp != NULL) { | ||
if (Ptemp->id == P) { | ||
printf("Process with ID %d already exists.\n", P); | ||
return; | ||
} | ||
Ptemp = Ptemp->next_process; | ||
} | ||
|
||
// Check if the resource with ID R already exists in the list | ||
Resource *Rtemp = Rhead; | ||
while (Rtemp != NULL) { | ||
if (Rtemp->id == R) { | ||
printf("Resource with ID %d already exists.\n", R); | ||
return; | ||
} | ||
Rtemp = Rtemp->next_resource; | ||
} | ||
|
||
// Allocate memory for the new process and resource | ||
Process *ProcessNode = (Process *)malloc(sizeof(Process)); | ||
Resource *ResourceNode = (Resource *)malloc(sizeof(Resource)); | ||
if (ProcessNode == NULL || ResourceNode == NULL) { | ||
printf("Memory allocation failed\n"); | ||
exit(1); | ||
} | ||
|
||
// Initialize the new process | ||
ProcessNode->id = P; | ||
ProcessNode->requested_resource = NULL; | ||
ProcessNode->next_process = NULL; | ||
ProcessNode->visited = 0; | ||
|
||
// Initialize the new resource | ||
ResourceNode->id = R; | ||
ResourceNode->allocated_process = ProcessNode; | ||
ResourceNode->next_resource = NULL; | ||
|
||
// Insert the process at the end of the process list | ||
if (Phead == NULL) { | ||
Phead = ProcessNode; | ||
} else { | ||
Ptemp = Phead; | ||
while (Ptemp->next_process != NULL) { | ||
Ptemp = Ptemp->next_process; | ||
} | ||
Ptemp->next_process = ProcessNode; | ||
} | ||
|
||
// Insert the resource at the end of the resource list | ||
if (Rhead == NULL) { | ||
Rhead = ResourceNode; | ||
} else { | ||
Rtemp = Rhead; | ||
while (Rtemp->next_resource != NULL) { | ||
Rtemp = Rtemp->next_resource; | ||
} | ||
Rtemp->next_resource = ResourceNode; | ||
} | ||
|
||
printf("Allocation: Resource R%d --> Process P%d\n", R, P); | ||
} | ||
|
||
// Function to perform DFS to detect cycles in the resource allocation graph | ||
int DFS(Process *process) { | ||
// If the process is NULL, there's nothing to explore | ||
if (process == NULL) { | ||
return 0; | ||
} | ||
|
||
// If process is already visited, a cycle is detected | ||
if (process->visited == 1) { | ||
return 1; // Cycle detected | ||
} | ||
|
||
// Mark the process as visited | ||
process->visited = 1; | ||
|
||
// Recursively visit the allocated process of the requested resource | ||
if (process->requested_resource != NULL) { | ||
Process *WaitingFor = process->requested_resource->allocated_process; | ||
if (DFS(WaitingFor)) { | ||
return 1; // Cycle detected | ||
} | ||
} | ||
|
||
// Reset visited status before returning to allow further detection | ||
process->visited = 0; | ||
return 0; // No cycle detected | ||
} | ||
|
||
// Function to check for cycles in the resource allocation graph | ||
int DetectCycle() { | ||
// Iterates through each process to check for cycles | ||
Process *current_process = Phead; | ||
while (current_process != NULL) { | ||
if (DFS(current_process)) { | ||
return 1; // Cycle detected | ||
} | ||
current_process = current_process->next_process; | ||
} | ||
return 0; // No cycle detected | ||
} | ||
|
||
// Function to request a resource for a process | ||
void Request(int P, int R) { | ||
// Check if graph is empty | ||
if (Phead == NULL || Rhead == NULL) { | ||
printf("Graph is empty.\n"); | ||
return; | ||
} | ||
|
||
// Locate the process with ID P in the list | ||
Process *Ptemp = Phead, *ProcessNode = NULL; | ||
while (Ptemp != NULL) { | ||
if (Ptemp->id == P) { | ||
ProcessNode = Ptemp; | ||
break; | ||
} | ||
Ptemp = Ptemp->next_process; | ||
} | ||
|
||
// Locate the resource with ID R in the list | ||
Resource *Rtemp = Rhead, *ResourceNode = NULL; | ||
while (Rtemp != NULL) { | ||
if (Rtemp->id == R) { | ||
ResourceNode = Rtemp; | ||
break; | ||
} | ||
Rtemp = Rtemp->next_resource; | ||
} | ||
|
||
// Check if the process exists | ||
if (ProcessNode == NULL) { | ||
printf("Process with ID %d not found.\n", P); | ||
return; | ||
} | ||
|
||
// Check if the resource exists | ||
if (ResourceNode == NULL) { | ||
printf("Resource with ID %d not found.\n", R); | ||
return; | ||
} | ||
|
||
// Check if process already has a resource request | ||
if (ProcessNode->requested_resource != NULL) { | ||
printf("Process %d already has a resource request.\n", P); | ||
return; | ||
} | ||
|
||
// Assign the resource to the process as its requested resource | ||
ProcessNode->requested_resource = ResourceNode; | ||
printf("\nRequest: Process P%d --> Resource R%d\n", P, R); | ||
|
||
// Detect any cycles that may have formed after the request | ||
if (DetectCycle()) { | ||
printf("\nCycle detected in the resource allocation graph.\n\n"); | ||
} else { | ||
printf("\nNo cycles detected in the resource allocation graph.\n\n"); | ||
} | ||
} | ||
|
||
// Function to clean up memory allocated for processes and resources | ||
void Cleanup() { | ||
// Free memory allocated for each process in the list | ||
Process *ptemp = Phead; | ||
while (ptemp != NULL) { | ||
Process *node = ptemp; | ||
ptemp = ptemp->next_process; | ||
free(node); | ||
} | ||
|
||
// Free memory allocated for each resource in the list | ||
Resource *Rtemp = Rhead; | ||
while (Rtemp != NULL) { | ||
Resource *node = Rtemp; | ||
Rtemp = Rtemp->next_resource; | ||
free(node); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
# Resource Allocation and Deadlock Detection Program | ||
|
||
## Overview | ||
This C program simulates a basic resource allocation and deadlock detection system. It allows users to allocate resources to processes and request resources on behalf of processes. Using a Depth-First Search (DFS) algorithm, it detects cycles in the resource allocation graph, signaling potential deadlocks in resource requests. | ||
|
||
## Features | ||
- **Resource Allocation:** Allocate resources to processes and track ownership. | ||
- **Resource Requesting:** Processes can request additional resources if they do not currently hold them. | ||
- **Deadlock Detection:** Detects cycles in the resource allocation graph, indicating potential deadlocks. | ||
- **Memory Cleanup:** Frees dynamically allocated memory for processes and resources to prevent memory leaks. | ||
|
||
## Function Descriptions | ||
``` | ||
Allocate(int R, int P) | ||
``` | ||
|
||
Allocates a resource (with ID R) to a process (with ID P) if neither currently exists in the system. | ||
|
||
- **Parameters:** | ||
- int R - Resource ID. | ||
- int P - Process ID. | ||
|
||
- **Behavior:** Checks if a process or resource with the specified ID already exists. If not, it creates and links the resource to the process. | ||
|
||
--- | ||
``` | ||
Request(int P, int R) | ||
``` | ||
|
||
Requests a resource (with ID R) for a process (with ID P). | ||
|
||
- **Parameters:** | ||
- int P - Process ID. | ||
- int R - Resource ID. | ||
|
||
- **Behavior:** Assigns the requested resource to the process. Afterward, it invokes the DetectCycle function to check if this request causes a cycle, indicating a potential deadlock. The function notifies the user if a deadlock is detected. | ||
|
||
--- | ||
|
||
``` | ||
DetectCycle() | ||
``` | ||
|
||
Iterates over all processes to detect cycles in the resource allocation graph. | ||
|
||
- **Returns:** 1 if a cycle (deadlock) is detected, 0 otherwise. | ||
- **Behavior:** Calls DFS on each process to trace resource dependencies. If any cycle is detected in the graph, it signifies a potential deadlock. | ||
|
||
--- | ||
|
||
``` | ||
DFS(Process *process) | ||
``` | ||
|
||
Performs Depth-First Search to trace through the resource allocation graph and detect cycles. | ||
|
||
- Parameters: | ||
- Process *process - Pointer to the process structure to begin the DFS. | ||
- **Returns:** 1 if a cycle is found, 0 if not. | ||
- **Behavior:** Marks each visited process. If it revisits a marked process in the same chain, a cycle is present. | ||
|
||
--- | ||
|
||
``` | ||
Cleanup() | ||
``` | ||
|
||
Frees all dynamically allocated memory used for processes and resources. | ||
|
||
- **Behavior:** Traverses the lists of processes and resources, freeing each node to prevent memory leaks. |