diff --git a/src/reducible.cpp b/src/reducible.cpp index 6503613..af23576 100644 --- a/src/reducible.cpp +++ b/src/reducible.cpp @@ -5,22 +5,71 @@ +-----------------------------------------------+ */ #include "graph.hpp" +using std::vector; + +bool blocked(const int num_processes, const int num_resources, const vector resource_counts, const graph::matrix &matrix, int process_id); + /* reducible: Perform the graph reduction algorithm on the adjacency matrix to detect deadlocks 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 @returns: bool: - true if graph is not reducible (deadlock) - false if graph is reducible (no deadlock) + true if graph is deadlocked (not reducible) + false if graph is not deadlocked (reducible) */ bool graph::reducible() { - // TODO: Implement a function which checks if a process is blocked - // TODO: Use that function to implement the graph reduction algorithm - //? Make sure when reducing the graph, you don't try to delete the - return false; + // Make a copy of the matrix, so we don't overwrite it + matrix m_copy = m; + // run for num_processes iterations; there's no point to doing more, since at least one process should clear each time + for (int num_iterations = 0; num_iterations < num_processes; num_iterations++) { + int num_blocked = 0; + // calculate whether every process is blocked or not + 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; } -bool graph::is_blocked(int process_id) { - return true; +bool blocked(const int np, const int nr, const vector rc, const graph::matrix &m, int process_id) { + //* Calculate free resources, and compare free units to requests + vector 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; } \ No newline at end of file