Exercise 3: Register Dicts Are Genuinely Independent Copies — Possible Solution ==================================================================== THE TEST ------------------------------ p1 = kernel.create_process(num_pages=1) p2 = kernel.create_process(num_pages=1) cpu = CPU() p1.transition(ProcessState.RUNNING) cpu.current_pid = p1.pid cpu.registers['PC'] = 5 context_switch_fixed(cpu, p1, p2) # p1.registers now holds a SAVED copy cpu.registers['PC'] = 999 # mutate the CPU's CURRENT (p2's) registers directly print(p1.registers) RESULT ------------------------------ after mutating the CPU's current (p2's) registers, p1's own SAVED registers: {'PC': 5, 'ACC': 0, 'R1': 0, 'R2': 0} p1.registers still shows PC=5 -- completely unaffected by the later mutation to cpu.registers['PC'], even though cpu.registers is now 999. WHY dict(...) IS THE PART THAT MAKES THIS SAFE ------------------------------ context_switch_fixed()'s own save line is: old_pcb.registers = dict(cpu.registers) dict(cpu.registers) constructs a genuinely NEW dictionary object, copying every key-value pair out of cpu.registers at that exact moment. Once that line runs, old_pcb.registers and cpu.registers are two separate objects living at two separate memory locations -- they simply no longer have anything to do with each other, even though they happened to contain identical values right after the copy. Mutating one afterward -- cpu.registers['PC'] = 999 -- only ever touches the dict cpu.registers currently points at; it has no way to reach back and affect old_pcb.registers, which points somewhere else entirely. WHAT WOULD HAPPEN WITHOUT dict(...) ------------------------------ If the save line had instead been written as: old_pcb.registers = cpu.registers # NO dict(...) -- just an assignment this would make old_pcb.registers and cpu.registers point at the EXACT SAME dictionary object -- not two copies with equal contents, but one single object with two names. Any later mutation through either name -- cpu.registers['PC'] = 999, for instance -- would be visible through BOTH names immediately, since there's only one real dictionary underneath. p1's own "saved" state would silently drift along with whatever the CPU's currently-running process does next, completely defeating the purpose of saving it in the first place. This is the exact same category of bug Chapter 3's own PageTable work implicitly avoided by always working with real byte ranges rather than accidentally-shared references. WHY THIS WORKS AS AN ANSWER ------------------------------ Deliberately mutating the CPU's own current registers AFTER a switch and confirming the previous process's own saved state is unaffected verifies dict(...) is doing genuine, real copying -- not just happening to produce equal-looking values that would actually still be silently linked underneath.