Download as doc, pdf, or txt
Download as doc, pdf, or txt
You are on page 1of 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