Exercise 1: A Real 3-Process Circular-Wait Deadlock — Possible Solution ==================================================================== THE TEST ------------------------------ programs[r1.pid] = [('ACQUIRE','X'), ('ACQUIRE','Y'), ('RELEASE','Y'), ('RELEASE','X')] programs[r2.pid] = [('ACQUIRE','Y'), ('ACQUIRE','Z'), ('RELEASE','Z'), ('RELEASE','Y')] programs[r3.pid] = [('ACQUIRE','Z'), ('ACQUIRE','X'), ('RELEASE','X'), ('RELEASE','Z')] # run 1000 real steps, QUANTUM=1 RESULT ------------------------------ after 1000 real steps, remaining ops per process: {6: 3, 7: 3, 8: 3} wait-for-graph: {6: {7}, 7: {8}, 8: {6}} cycle detector's own result: [6, 7, 8, 6] Every process is stuck on its second op (its second ACQUIRE), exactly as in Finding 1's own 2-process case, and the wait-for-graph forms a real 3-node cycle: r1 waits for r2, r2 waits for r3, r3 waits for r1. WHY THE SAME DETECTOR CODE WORKS WITH ZERO CHANGES ------------------------------ find_cycle()'s own DFS never assumes anything about how many nodes exist or how they're connected -- it just walks whatever edges build_wait_for_graph() actually produced, following gray (in-progress) nodes until it revisits one, which is the general definition of a cycle in ANY directed graph, regardless of length. build_wait_for_graph() itself only ever asks one local question per waiting process: "who currently holds what I want?" -- it never needs to know the SHAPE of the overall graph to build it correctly. Because both pieces are written in terms of the graph's own general structure, not a hardcoded "two nodes" assumption, a genuine 3-cycle is detected by exactly the same code that found the 2-cycle in Finding 2. WHY THIS MATTERS ------------------------------ A real kernel's own resource contention isn't limited to pairs of processes -- deadlocks in practice often involve three, four, or more processes each holding one resource and waiting for the next one in a chain. A detector that only worked for exactly two processes would be a toy demonstration, not a real one. Confirming the identical mechanism scales to a longer cycle, using the SAME unmodified build_wait_for_graph()/find_cycle() pair, is what actually justifies calling this "wait-for-graph cycle detection" rather than "two-process deadlock detection." WHY THIS WORKS AS AN ANSWER ------------------------------ Deliberately constructing a 3-process cycle (rather than just trusting that "it probably generalizes") and running it through the exact same, completely unmodified detection code from Finding 2 confirms the generality directly -- the result (finding all 3 PIDs in the cycle) is a measured fact about the code's own real behavior, not an assumption about it.