Implement graph reduction algorithm

This commit is contained in:
John 2022-04-23 04:48:47 -05:00
parent ddaa60a5ec
commit 8044ba68e3

View File

@ -5,22 +5,71 @@
+-----------------------------------------------+ */ +-----------------------------------------------+ */
#include "graph.hpp" #include "graph.hpp"
using std::vector;
bool blocked(const int num_processes, const int num_resources, const vector<int> resource_counts, const graph::matrix &matrix, int process_id);
/* reducible: /* reducible:
Perform the graph reduction algorithm on the adjacency matrix to detect deadlocks Perform the graph reduction algorithm on the adjacency matrix to detect deadlocks
This algorithm is described in section 5.2 of the Zybook This algorithm is described in section 5.2 of the Zybook
The graph reduction algorithm is implemented here with a few obvious optimizations:
The algorithm should clear at least one blocked process per iteration;
This leads to an easy failure condition, since fewer processes should be blocked than there are remaining iterations.
By extension,
@params: none, uses class-internal data @params: none, uses class-internal data
@returns: @returns:
bool: bool:
true if graph is not reducible (deadlock) true if graph is deadlocked (not reducible)
false if graph is reducible (no deadlock) false if graph is not deadlocked (reducible)
*/ */
bool graph::reducible() { bool graph::reducible() {
// TODO: Implement a function which checks if a process is blocked // Make a copy of the matrix, so we don't overwrite it
// TODO: Use that function to implement the graph reduction algorithm matrix m_copy = m;
//? Make sure when reducing the graph, you don't try to delete the // run for num_processes iterations; there's no point to doing more, since at least one process should clear each time
return false; for (int num_iterations = 0; num_iterations < num_processes; num_iterations++) {
} int num_blocked = 0;
// calculate whether every process is blocked or not
bool graph::is_blocked(int process_id) { for(int p = 0; p < num_processes; p++) {
// check if process is blocked
if (blocked(num_processes,num_resources,resource_counts,m_copy, p)) {
//indicate process is blocked
num_blocked++;
} else {
// erase unblocked process from the graph
m_copy[p][p] = 0;
for (int r = num_processes; r < num_processes + num_resources; r++) {
m_copy[r][p] = 0; m_copy[p][r] = 0;
}
}
}
// print the number of blocked processes
printf("\nIteration %d:\nnum_blocked: %d\n", num_iterations+1, num_blocked);
// If more processes are blocked than can be cleared before the algorithm finishes, give up
if (num_blocked == num_processes - num_iterations) return true;
// Print the new matrix
printf("| ");for(auto x:m_copy){for(auto y:x)printf("%d, ",y);printf("\b\b |\n| ");}printf("\b\b \b\b");
// If no processes are blocked, we won!
if (num_blocked == 0) return false;
}
return true; return true;
} }
bool blocked(const int np, const int nr, const vector<int> rc, const graph::matrix &m, int process_id) {
//* Calculate free resources, and compare free units to requests
vector<int> resources = rc;
for (int r = 0; r < nr; r++) {
// Calculate the number of units available
for (int p = 0; p < np; p++) {
// subtract units currently in use
// a resource is in use when >0 in the allocation quadrant of the table, i.e. [(np,0), (nr+np, np))
resources[r] -= m[r+np][p];
}
// If the program requests more resources than are available, it's blocked
if (m[process_id][r+np] > resources[r]) {
return true;
}
}
// else process is not blocked
return false;
}