clarified specification for wait() system call
[pintos-anon] / doc / userprog.texi
index 3541540173dee33fd674a50783dfc716c9dd9e17..d3a70c810f7eb10e0b9823bb0fb82b3b962dbf59 100644 (file)
@@ -204,7 +204,7 @@ commands for copying files out of a VM are similar, but substitute
 @option{-g} for @option{-p}.
 
 Incidentally, these commands work by passing special commands
-@command{put} and @command{get} on the kernel's command line and copying
+@command{extract} and @command{append} on the kernel's command line and copying
 to and from a special simulated ``scratch'' disk.  If you're very
 curious, you can look at the @command{pintos} script as well as
 @file{filesys/fsutil.c} to learn the implementation details.
@@ -406,7 +406,7 @@ The second method is to check only that a user
 pointer points below @code{PHYS_BASE}, then dereference it.
 An invalid user pointer will cause a ``page fault'' that you can
 handle by modifying the code for @func{page_fault} in
-@file{userprog/exception.cc}.  This technique is normally faster
+@file{userprog/exception.c}.  This technique is normally faster
 because it takes advantage of the processor's MMU, so it tends to be
 used in real kernels (including Linux).
 
@@ -443,7 +443,7 @@ put_user (uint8_t *udst, uint8_t byte)
 {
   int error_code;
   asm ("movl $1f, %0; movb %b2, %1; 1:"
-       : "=&a" (error_code), "=m" (*udst) : "r" (byte));
+       : "=&a" (error_code), "=m" (*udst) : "q" (byte));
   return error_code != -1;
 }
 @end verbatim
@@ -622,14 +622,44 @@ You must use appropriate synchronization to ensure this.
 @end deftypefn
 
 @deftypefn {System Call} int wait (pid_t @var{pid})
-If process @var{pid} is still alive, waits until it dies.
-Then, returns the status that @var{pid} passed to @code{exit},
-or -1 if @var{pid}
-was terminated by the kernel (e.g.@: killed due to an exception).  If
-@var{pid} does not refer to a child of the
-calling thread, or if @code{wait} has already been successfully
-called for the given @var{pid}, returns -1 immediately, without
-waiting.
+Waits for a child process @var{pid} and retrieves the child's exit status.
+
+If @var{pid} is still alive, waits until it terminates.  Then, returns
+the status that @var{pid} passed to @code{exit}.  If @var{pid} did not
+call @code{exit()}, but was terminated by the kernel (e.g.@: killed
+due to an exception), @code{wait(pid)} must return -1.  It is perfectly
+legal for a parent process to wait for child processes that have already
+terminated by the time the parent calls @code{wait}, but the kernel must
+still allow the parent to retrieve its child's exit status, or learn
+that the child was terminated by the kernel.
+
+@code{wait} must fail and return -1 immediately if any of the
+following conditions is true:
+@itemize @bullet
+@item
+@var{pid} does not refer to a direct child of the calling process.
+@var{pid} is a direct child of the calling process if and
+only if the calling process received @var{pid} as a return value 
+from a successful call to @code{exec}.  
+
+Note that children are not inherited: if @var{A} spawns child @var{B}
+and @var{B} spawns child process @var{C}, then @var{A} cannot wait for
+@var{C}, even if @var{B} is dead.  A call to @code{wait(C)} by process
+@var{A} must fail.  Similarly, orphaned processes are not assigned to
+a new parent if their parent process exits before they do.
+
+@item
+The process that calls @code{wait} has already called @code{wait} on
+@var{pid}.  That is, a process may wait for any given child at most 
+once.
+@end itemize
+
+Processes may spawn any number of children, wait for them in any order, 
+and may even exit without having waited for some or all of their children.
+Your design should consider all the ways in which waits can occur.
+All of a process's resources, including its @struct{thread}, must be
+freed whether its parent ever waits for it or not, and regardless of
+whether the child exits before or after its parent.
 
 You must ensure that Pintos does not terminate until the initial
 process exits.  The supplied Pintos code tries to do this by calling
@@ -639,18 +669,6 @@ process exits.  The supplied Pintos code tries to do this by calling
 function and then implement the @code{wait} system call in terms of
 @func{process_wait}.
 
-All of a process's resources, including its @struct{thread}, must be
-freed whether its parent ever waits for it or not, and regardless of
-whether the child exits before or after its parent.
-
-Children are not inherited: if @var{A} has child @var{B} and
-@var{B} has child @var{C}, then @code{wait(C)} always returns immediately
-when called from @var{A}, even if @var{B} is dead.
-
-Consider all the ways a wait can occur: nested waits (@var{A} waits
-for @var{B}, then @var{B} waits for @var{C}), multiple waits (@var{A}
-waits for @var{B}, then @var{A} waits for @var{C}), and so on.
-
 Implementing this system call requires considerably more work than any
 of the rest.
 @end deftypefn
@@ -872,7 +890,7 @@ call handler just prints @samp{system call!} and terminates the program.
 Until then, you can use @func{hex_dump} to convince yourself that
 argument passing is implemented correctly (@pxref{Program Startup Details}).
 
-@item How can I can disassemble user programs?
+@item How can I disassemble user programs?
 
 The @command{objdump} (80@var{x}86) or @command{i386-elf-objdump}
 (SPARC) utility can disassemble entire user
@@ -1090,17 +1108,18 @@ pointers.
 
 Then, push the address of each string plus a null pointer sentinel, on
 the stack, in right-to-left order.  These are the elements of
-@code{argv}.  The order ensure that @code{argv[0]} is at the lowest
-virtual address.  Word-aligned accesses are faster than unaligned
-accesses, so for best performance round the stack pointer down to a
-multiple of 4 before the first push.
+@code{argv}.  The null pointer sentinel ensures that @code{argv[argc]}
+is a null pointer, as required by the C standard.  The order ensures
+that @code{argv[0]} is at the lowest virtual address.  Word-aligned
+accesses are faster than unaligned accesses, so for best performance
+round the stack pointer down to a multiple of 4 before the first push.
 
 Then, push @code{argv} (the address of @code{argv[0]}) and @code{argc},
 in that order.  Finally, push a fake ``return address'': although the
 entry function will never return, its stack frame must have the same
 structure as any other.
 
-The table below show the state of the stack and the relevant registers
+The table below shows the state of the stack and the relevant registers
 right before the beginning of the user program, assuming
 @code{PHYS_BASE} is @t{0xc0000000}: