0% found this document useful (0 votes)
27 views19 pages

2 Labda

The document contains code for implementing the Banker's algorithm to avoid deadlocks in an operating system. It includes functions to check if a process can be allocated resources, find the safety sequence, and handle additional resource requests from processes.

Uploaded by

sujit suresh
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
27 views19 pages

2 Labda

The document contains code for implementing the Banker's algorithm to avoid deadlocks in an operating system. It includes functions to check if a process can be allocated resources, find the safety sequence, and handle additional resource requests from processes.

Uploaded by

sujit suresh
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
You are on page 1/ 19

Digital Assignment 2

Operating Systems
Hridyesh Das 21BDS0167
Question
a) Write a program to avoid deadlock using
Banker’s algorithm ( Safety Sequence Algorithm
).
b) #include <iostream>
c) #include <vector>
d) #include <algorithm>
e)
f) using namespace std;
g)
h) // Function to check if a process can be allocated resources
i) bool canAllocateResources(const vector<vector<int>>& max, const
vector<vector<int>>& allocated, const vector<vector<int>>& need,
const vector<int>& available, int process)
j) {
k) int numResources = available.size();
l)
m) // Check if the requested resources are available
n) for (int i = 0; i < numResources; i++) {
o) if (need[process][i] > available[i])
p) return false;
q) }
r)
s) return true;
t) }
u)
v) // Function to find the safety sequence using Banker's algorithm
w) vector<int> findSafetySequence(const vector<vector<int>>& max, const
vector<vector<int>>& allocated, const vector<int>& available)
x) {
y) int numProcesses = max.size();
z) int numResources = available.size();
aa)
bb) // Initialize the need matrix
cc) vector<vector<int>> need(numProcesses, vector<int>(numResources));
dd) for (int i = 0; i < numProcesses; i++) {
ee) for (int j = 0; j < numResources; j++) {
ff) need[i][j] = max[i][j] - allocated[i][j];
gg) }
hh) }
ii)
jj) // Initialize the finish and safety sequence vectors
kk) vector<bool> finish(numProcesses, false);
ll) vector<int> safetySequence;
mm)
nn) // Initialize the work and available vectors
oo) vector<int> work = available;
pp)
qq) // Find a safe sequence
rr) int count = 0;
ss) while (count < numProcesses) {
tt) bool found = false;
uu) for (int i = 0; i < numProcesses; i++) {
vv) if (!finish[i] && canAllocateResources(max, allocated, need,
work, i)) {
ww) // Allocate resources
xx) for (int j = 0; j < numResources; j++) {
yy) work[j] += allocated[i][j];
zz) }
aaa)
bbb) // Mark the process as finished and add it to the
safety sequence
ccc) finish[i] = true;
ddd) safetySequence.push_back(i);
eee)
fff) found = true;
ggg) count++;
hhh) break;
iii) }
jjj) }
kkk)
lll) if (!found) {
mmm) // No process found that can be allocated resources
nnn) break;
ooo) }
ppp) }
qqq)
rrr) // If a safety sequence is found, return it
sss) if (count == numProcesses) {
ttt) return safetySequence;
uuu) }
vvv)
www) // If no safety sequence is found, return an empty sequence
xxx) return {};
yyy) }
zzz)
aaaa) int main()
bbbb) {
cccc) int numProcesses, numResources;
dddd)
eeee) cout << "Enter the number of processes: ";
ffff) cin >> numProcesses;
gggg)
hhhh) cout << "Enter the number of resources: ";
iiii) cin >> numResources;
jjjj)
kkkk) // Initialize the max matrix
llll) vector<vector<int>> max(numProcesses,
vector<int>(numResources));
mmmm) cout << "Enter the maximum demand of each process for
each resource:\n";
nnnn) for (int i = 0; i < numProcesses; i++) {
oooo) cout << "Process " << i << ": ";
pppp) for (int j = 0; j < numResources; j++) {
qqqq) cin >> max[i][j];
rrrr) }
ssss) }
tttt)
uuuu) // Initialize the allocated matrix
vvvv) vector<vector<int>>
allocated(numProcesses, vector<int>(numResources));
wwww) cout << "Enter the allocated resources of each process for
each resource:\n";
xxxx) for (int i = 0; i < numProcesses; i++) {
yyyy) cout << "Process " << i << ": ";
zzzz) for (int j = 0; j < numResources; j++) {
aaaaa) cin >> allocated[i][j];
bbbbb) }
ccccc) }
ddddd)
eeeee) // Initialize the available vector
fffff) vector<int> available(numResources);
ggggg) cout << "Enter the available resources for each resource:\n";
hhhhh) for (int i = 0; i < numResources; i++) {
iiiii) cin >> available[i];
jjjjj) }
kkkkk)
lllll) // Find the safety sequence
mmmmm) vector<int> safetySequence = findSafetySequence(max,
allocated, available);
nnnnn)
ooooo) if (safetySequence.empty()) {
ppppp) cout << "No safety sequence exists. Deadlock detected!\n";
qqqqq) } else {
rrrrr) cout << "Safety sequence: ";
sssss) for (int i = 0; i < safetySequence.size(); i++) {
ttttt) cout << safetySequence[i];
uuuuu) if (i != safetySequence.size() - 1) {
vvvvv) cout <<"->";
wwwww) }
xxxxx) }
yyyyy) cout << "\n";
zzzzz) }
aaaaaa)
bbbbbb) return 0;
cccccc) }
dddddd)
Output

b) Implement Bankers-additional
resource request algorithm
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

/ Function to check if a process can be allocated resources


bool canAllocateResources(const vector<vector<int>>& max,
const vector<vector<int>>& allocated,
const vector<vector<int>>& need, const vector<int>&
available, int process)
{
int numResources = available.size();

/ Check if the requested resources are available


for (int i = 0; i < numResources; i++) {
if (need[process][i] > available[i])
return false;
}

return true;
}

/ Function to find the safety sequence using Banker's algorithm


vector<int> findSafetySequence(const vector<vector<int>>& max, const
vector<vector<int>>& allocated,
const vector<int>& available)
{
int numProcesses = max.size();
int numResources = available.size();

// Initialize the need matrix


vector<vector<int>> need(numProcesses, vector<int>(numResources));
for (int i = 0; i < numProcesses; i++) {
for (int j = 0; j < numResources; j++) {
need[i][j] = max[i][j] - allocated[i]
[j];
}
}

/ Initialize the finish and safety sequence


vectors vector<bool> finish(numProcesses, false);
vector<int> safetySequence;

/ Initialize the work and available vectors


vector<int> work = available;

/ Find a safe sequence


int count = 0;
while (count < numProcesses)
{ bool found = false;
for (int i = 0; i < numProcesses; i++) {
if (!finish[i] && canAllocateResources(max, allocated, need, work,
i)) {
// Allocate resources
for (int j = 0; j < numResources; j++) {
work[j] += allocated[i][j];
}

/ Mark the process as finished and add it to the safety


sequence finish[i] = true;
safetySequence.push_back(i);
found = true;
count++;
break;
}
}

if (!found) {
/ No process found that can be allocated
resources break;
}
}

/ If a safety sequence is found, return


it if (count == numProcesses) {
return safetySequence;
}

/ If no safety sequence is found, return an empty


sequence return {};
}

// Function to check if a resource request can be granted


bool canGrantRequest(const vector<vector<int>>& max, const
vector<vector<int>>& allocated,
const vector<vector<int>>& need, const
vector<int>& available, int process,
const vector<int>& request)
{
int numResources = available.size();

/ Check if the requested resources are within the need of the


process for (int i = 0; i < numResources; i++) {
if (request[i] > need[process][i])
return false;
}

/ Check if the requested resources are within the available


resources for (int i = 0; i < numResources; i++) {
if (request[i] > available[i])
return false;
}

return true;
}
// Function to handle additional resource requests
bool handleResourceRequest(vector<vector<int>>& max,
vector<vector<int>>& allocated,
vector<int>& available, int process, const
vector<int>& request)
{
int numResources = available.size();

if (!canGrantRequest(max, allocated, max, available, process,


request)) return false;

/ Temporarily allocate the requested resources


for (int i = 0; i < numResources; i++) {
allocated[process][i] +=
request[i]; available[i] -=
request[i]; max[process][i] -=
request[i];
}

/ Find a safety sequence with the new allocation


vector<int> safetySequence = findSafetySequence(max, allocated, available);

if (!safetySequence.empty()) {
cout << "Request can be granted. Safety sequence: ";
for (int i = 0; i < safetySequence.size(); i++) {
cout << safetySequence[i];
if (i != safetySequence.size() - 1) {
cout << " -> ";
}
}
cout << "\n";
return true;
} else {
/ Roll back the allocation
for (int i = 0; i < numResources; i++) {
allocated[process][i] -= request[i];
available[i] += request[i];
max[process][i] += request[i];
}
cout << "Request cannot be granted. Deadlock detected!\
n"; return false;
}
}

int main()
{
int numProcesses, numResources;

cout << "Enter the number of processes: ";


cin >> numProcesses;

cout << "Enter the number of resources: ";


cin >> numResources;

// Initialize the max matrix


vector<vector<int>> max(numProcesses, vector<int>(numResources));
cout << "Enter the maximum demand of each process for each resource:\n";
for (int i = 0; i < numProcesses; i++) {
cout << "Process " << i << ": ";
for (int j = 0; j < numResources; j++) {
cin >> max[i][j];
}
}

// Initialize the allocated matrix


vector<vector<int>> allocated(numProcesses, vector<int>(numResources));
cout << "Enter the allocated resources of each process for each resource:\n";
for (int i = 0; i < numProcesses; i++) {
cout << "Process " << i << ": ";
for (int j = 0; j < numResources; j++) {
cin >> allocated[i][j];
}
}

/ Initialize the available vector


vector<int> available(numResources);
cout << "Enter the available resources for each resource:\
n"; for (int i = 0; i < numResources; i++) {
cin >> available[i];
}

/ Find the safety sequence


vector<int> safetySequence = findSafetySequence(max, allocated, available);

if (safetySequence.empty()) {
cout << "No safety sequence exists. Deadlock detected!\n";
} else {
cout << "Safety sequence: ";
for (int i = 0; i < safetySequence.size(); i++)
{ cout << safetySequence[i];
if (i != safetySequence.size() - 1) {
cout << " -> ";
}
}
cout << "\n";
}

/ Handle additional resource


requests int process;
vector<int> request(numResources);

cout << "Enter the process requesting additional resources:


"; cin >> process;

cout << "Enter the additional resource request for process " << process
<< ":\n";
for (int i = 0; i < numResources; i++) {
cin >> request[i];
}

handleResourceRequest(max, allocated, available, process, request);

return 0;
}
Output

C ) Write a program to provide a solution


for Producer-Consumer problem using
Semaphore(in-built Synchronization Tool).
from threading import Thread, Semaphore
import time
import random

BUFFER_SIZE = 5 # Size of the buffer


NUM_ITEMS = 10 # Number of items to produce/consume

buffer = []
mutex = Semaphore(1) # Semaphore to control access to the buffer
empty = Semaphore(BUFFER_SIZE) # Semaphore to track empty slots in the buffer
full = Semaphore(0) # Semaphore to track filled slots in the buffer

def producer():
for _ in range(NUM_ITEMS):
item = random.randint(1, 100) # Generate a random item
empty.acquire() # Wait for an empty slot in the buffer
mutex.acquire() # Obtain exclusive access to the buffer
buffer.append(item) # Add item to the buffer
print("Producer produced item:", item) mutex.release()
# Release the mutex
full.release() # Notify consumer that the buffer is no longer empty
time.sleep(random.random()) # Sleep for a random time

def consumer():
for _ in range(NUM_ITEMS):
full.acquire() # Wait for a filled slot in the buffer
mutex.acquire() # Obtain exclusive access to the buffer
item = buffer.pop(0) # Remove item from the buffer
print("Consumer consumed item:", item) mutex.release()
# Release the mutex
empty.release() # Notify producer that the buffer is no longer full
time.sleep(random.random()) # Sleep for a random time

# Create producer and consumer threads


producer_thread = Thread(target=producer)
consumer_thread = Thread(target=consumer)

# Start the threads


producer_thread.start()
consumer_thread.start()

# Wait for the threads to finish


producer_thread.join()
consumer_thread.join()

print("Program completed.")
Output

D ) Implement Reader writer problem using


semaphore(in-built Synchronization Tool).
from threading import Thread, Semaphore
import time
import random

READERS_COUNT = 3 # Number of reader threads


WRITERS_COUNT = 2 # Number of writer threads

readers = []
writers = []

mutex = Semaphore(1) # Semaphore to control access to the shared resource


resource = Semaphore(1) # Semaphore to control access to the resource
read_count = 0 # Counter to keep track of the number of readers reading

def reader(reader_id):
global read_count

while True:
time.sleep(random.random()) # Simulate reading time
mutex.acquire() # Obtain exclusive access to the read_count variable
read_count += 1 # Increment the number of readers
if read_count == 1:
resource.acquire() # If this is the first reader, acquire the
resource
mutex.release() # Release the mutex

# Read from the resource


print(f"Reader {reader_id} is reading.")

mutex.acquire() # Obtain exclusive access to the read_count variable


read_count -= 1 # Decrement the number of readers
if read_count == 0:
resource.release() # If this is the last reader, release the
resource
mutex.release() # Release the mutex

def writer(writer_id):
while True:
time.sleep(random.random()) # Simulate writing time

resource.acquire() # Acquire exclusive access to the resource

# Write to the resource


print(f"Writer {writer_id} is writing.")

resource.release() # Release the resource

# Create reader threads


for i in range(READERS_COUNT):
readers.append(Thread(target=reader, args=(i,)))

# Create writer threads


for i in range(WRITERS_COUNT):
writers.append(Thread(target=writer, args=(i,)))

# Start the reader threads for


reader_thread in readers:
reader_thread.start()

# Start the writer threads for


writer_thread in writers:
writer_thread.start()
# Wait for the reader threads to
finish for reader_thread in readers:
reader_thread.join()

# Wait for the writer threads to


finish for writer_thread in writers:
writer_thread.join()

print("Program completed.")

Output
E ) Implement a solution for the classical
synchronization problem: Dining Philosophers
using monitor(User defined Constructs).
from threading import Thread, Condition
import time
import random

NUM_PHILOSOPHERS = 5 # Number of philosophers


EATING_TIME = 2 # Time spent eating in seconds
THINKING_TIME = 2 # Time spent thinking in seconds
MEALS_TO_EAT = 5 # Number of meals each philosopher must eat

class DiningPhilosophers:
def __init__(self):
self.forks = [Condition() for _ in range(NUM_PHILOSOPHERS)] # Forks as
conditions
self.is_fork_taken = [False] * NUM_PHILOSOPHERS # Track whether a fork
is taken
self.meals_count = [0] * NUM_PHILOSOPHERS # Track number of meals each
philosopher has eaten

def get_left_fork(self, philosopher_id):


self.forks[philosopher_id].acquire() # Acquire the left fork
self.is_fork_taken[philosopher_id] = True

def get_right_fork(self, philosopher_id):


right_philosopher_id = (philosopher_id + 1) % NUM_PHILOSOPHERS
self.forks[right_philosopher_id].acquire() # Acquire the right fork
self.is_fork_taken[right_philosopher_id] = True

def release_forks(self, philosopher_id):


self.forks[philosopher_id].release() # Release the left fork
self.is_fork_taken[philosopher_id] = False

right_philosopher_id = (philosopher_id + 1) % NUM_PHILOSOPHERS


self.forks[right_philosopher_id].release() # Release the right fork
self.is_fork_taken[right_philosopher_id] = False

def can_eat(self, philosopher_id):


left_philosopher_id = (philosopher_id + NUM_PHILOSOPHERS - 1) %
NUM_PHILOSOPHERS
right_philosopher_id = (philosopher_id + 1) % NUM_PHILOSOPHERS

return (
not self.is_fork_taken[left_philosopher_id] and
not self.is_fork_taken[right_philosopher_id]
)

def increment_meals_count(self, philosopher_id):


self.meals_count[philosopher_id] += 1

def get_meals_count(self, philosopher_id):


return self.meals_count[philosopher_id]

def philosopher(philosopher_id, dining):


while dining.get_meals_count(philosopher_id) < MEALS_TO_EAT:
# Thinking
print(f"Philosopher {philosopher_id} is thinking.")
time.sleep(THINKING_TIME)

# Hungry
print(f"Philosopher {philosopher_id} is hungry.")

with dining.forks[philosopher_id]:
while not dining.can_eat(philosopher_id):
dining.forks[philosopher_id].wait() # Wait until both forks are
available

dining.get_left_fork(philosopher_id)
dining.get_right_fork(philosopher_id)

# Eating
print(f"Philosopher {philosopher_id} is eating.")
time.sleep(EATING_TIME)

with dining.forks[philosopher_id]:
dining.release_forks(philosopher_id)
dining.increment_meals_count(philosopher_id)
dining.forks[philosopher_id].notify_all() # Notify other
philosophers that forks are available

print(f"Philosopher {philosopher_id} finished eating.")

# Create a DiningPhilosophers instance


dining = DiningPhilosophers()

# Create philosopher threads


philosophers = []
for i in range(NUM_PHILOSOPHERS):
philosophers.append(Thread(target=philosopher, args=(i, dining)))

# Start philosopher threads


for philosopher_thread in philosophers:
philosopher_thread.start()

# Wait for philosopher threads to finish


for philosopher_thread in philosophers:
philosopher_thread.join()

print("Program completed.")
Output :

You might also like