The above race condition appears in a number of similar contexts where two processes exchange data. The problem is that the parent and child threads need to synchronize with each other, so that the parent doesn't reclaim or reuse memory before the child is finished accessing it.
On the other hand, when a user program invokes a system call via the
``syscall'' instruction, re-executing that instruction after returning
from the system call leads to an infinite system call loop. Thus, as
part of executing a system call, the exception handler code in Nachos
needs to update PCReg to point to the instruction following the
``syscall'' instruction. Updating PCReg is not as trivial as first
seems, however, due to the possibility of delayed branches. The
following code properly updates the program counter. In particular,
not properly updating NextPCReg can lead to improper execution.
pc = machine->ReadRegister(PCReg);
machine->WriteRegister(PrevPCReg, pc);
pc = machine->ReadRegister(NextPCReg);
machine->WriteRegister(PCReg, pc);
pc += 4;
machine->WriteRegister(NextPCReg, pc);
Use of the following test programs greatly helped convince me that my implementation was (finally) correct:
Modify the shell so that it can run jobs in background. For example, if the first character of the file is an ``&'', start the process as normal, but don't invoke a ``Join.'' Instead, prompt the user for the next command.
With the modified shell, run the ConsoleA and ConsoleB programs concurrently.