There are three system calls for executing programs and operating on processes.
SpaceId Exec (char *executable, int pipectrl)
Create a user process by creating a new address space, initializing it from the executable program file, and starting a new thread (via Thread::Fork ) to run within it. To start execution of the child process, the kernel sets up the CPU state for the new process and then calls Machine::Run to start the machine simulator executing the specified program's instructions in the context of the newly created address space. Note that Nachos Exec combines the Unix fork and exec system calls: Exec both creates a new process (like Unix fork ) and executes a specified program within its context (like Unix exec ).
Exec returns a unique SpaceId identifying the child user process. The SpaceId can be passed as an argument to other system calls (e.g., Join ) to identify the process, thus it must be unique among all currently existing processes. However, your kernel should be able to recycle SpaceId values so that it does not run out of them. By convention, the SpaceId 0 will be used to indicate an error.
The pipectrl parameter is discussed in Pipes . User programs not using pipes should always pass zero in pipectrl . Don't worry about this parameter for Lab 4; save it for Lab 5.
A user process calls Exit to indicate that it is finished and ready to terminate. The user program may call Exit explicitly, or it may simply return from main , since the common runtime library routine (in start.s ) that calls main to start the program also calls Exit when main returns. The kernel handles an Exit system call by destroying the process data structures and thread(s), reclaiming any memory assigned to the process, and arranging to return the exit status value as the result of the Join on this process, if any. Note that other processes are not affected: do not confuse Exit with Halt .
Note : if you are implementing threads ( Threads ), then Exit destroys the calling thread rather than the entire process/address space. The process and its address space are destroyed only when the last thread calls Exit , or if one of its threads generates a fatal exception.
Warning : the Exit system call should never return; it should always destroy the calling thread. Returning from Exit may cause your Nachos system to mysteriously shut down. To see why, look at the startup instruction sequence in test/start.s .
This is called by a process (the joiner ) to wait for the termination of the process (the joinee ) whose SpaceId is given by the joineeId argument. If the joinee is still active, then Join blocks until the joinee exits. When the joinee has exited, Join returns the joinee's exit status to the joiner. To simplify the implementation, impose the following limitations on Join : the joiner must be the parent of the joinee, and each joinee may be joined on at most once. Nachos Join is basically equivalent to the Unix wait system call.