added btthreadall to dump all threads
[pintos-anon] / doc / userprog.texi
index f005d55e41add3d1cd3c7fd506deb4c23b7d5005..a1321950fd3f877328f801853839be7c9cf69741 100644 (file)
@@ -183,14 +183,16 @@ threads that have it open, until the last one closes it.  @xref{Removing
 an Open File}, for more information.
 @end itemize
 
-You need to be able to create simulated disks.  The
-@command{pintos-mkdisk} program provides this functionality.  From the
-@file{userprog/build} directory, execute @code{pintos-mkdisk fs.dsk@tie{}2}.
-This command creates a 2 MB simulated disk named @file{fs.dsk}.  Then
-format the disk by passing @option{-f -q} on the kernel's command
-line: @code{pintos -f -q}.  The @option{-f} option causes the disk to be
-formatted, and @option{-q} causes Pintos to exit as soon as the format
-is done.
+You need to be able to create a simulated disk with a file system
+partition.  The @command{pintos-mkdisk} program provides this
+functionality.  From the @file{userprog/build} directory, execute
+@code{pintos-mkdisk filesys.dsk --filesys-size=2}.  This command
+creates a simulated disk named @file{filesys.dsk} that contains a @w{2
+MB} Pintos file system partition.  Then format the file system
+partition by passing @option{-f -q} on the kernel's command line:
+@code{pintos -f -q}.  The @option{-f} option causes the file system to
+be formatted, and @option{-q} causes Pintos to exit as soon as the
+format is done.
 
 You'll need a way to copy files in and out of the simulated file system.
 The @code{pintos} @option{-p} (``put'') and @option{-g} (``get'')
@@ -204,21 +206,20 @@ 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
-to and from a special simulated ``scratch'' disk.  If you're very
+@command{extract} and @command{append} on the kernel's command line and copying
+to and from a special simulated ``scratch'' partition.  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.
 
-Here's a summary of how to create and format a disk, copy the
-@command{echo} program into the new disk, and then run @command{echo},
-passing argument @code{x}.  (Argument passing won't work until
-you implemented it.)  It assumes
-that you've already built the
-examples in @file{examples} and that the current directory is
-@file{userprog/build}:
+Here's a summary of how to create a disk with a file system partition,
+format the file system, copy the @command{echo} program into the new
+disk, and then run @command{echo}, passing argument @code{x}.
+(Argument passing won't work until you implemented it.)  It assumes
+that you've already built the examples in @file{examples} and that the
+current directory is @file{userprog/build}:
 
 @example
-pintos-mkdisk fs.dsk 2
+pintos-mkdisk filesys.dsk --filesys-size=2
 pintos -f -q
 pintos -p ../../examples/echo -a echo -- -q
 pintos -q run 'echo x'
@@ -227,19 +228,20 @@ pintos -q run 'echo x'
 The three final steps can actually be combined into a single command:
 
 @example
-pintos-mkdisk fs.dsk 2
+pintos-mkdisk filesys.dsk --filesys-size=2
 pintos -p ../../examples/echo -a echo -- -f -q run 'echo x'
 @end example
 
 If you don't want to keep the file system disk around for later use or
 inspection, you can even combine all four steps into a single command.
-The @code{--fs-disk=@var{n}} option creates a temporary disk
+The @code{--filesys-size=@var{n}} option creates a temporary file
+system partition
 approximately @var{n} megabytes in size just for the duration of the
 @command{pintos} run.  The Pintos automatic test suite makes extensive
 use of this syntax:
 
 @example
-pintos --fs-disk=2 -p ../../examples/echo -a echo -- -f -q run 'echo x'
+pintos --filesys-size=2 -p ../../examples/echo -a echo -- -f -q run 'echo x'
 @end example
 
 You can delete a file from the Pintos file system using the @code{rm
@@ -272,11 +274,11 @@ for Pintos.  (We've provided compilers and linkers that should do just
 fine.)
 
 You should realize immediately that, until you copy a
-test program to the simulated disk, Pintos will be unable to do
+test program to the simulated file system, Pintos will be unable to do
 useful work.  You won't be able to do
-interesting things until you copy a variety of programs to the disk.
-You might want to create a clean reference disk and copy that
-over whenever you trash your @file{fs.dsk} beyond a useful state,
+interesting things until you copy a variety of programs to the file system.
+You might want to create a clean reference file system disk and copy that
+over whenever you trash your @file{filesys.dsk} beyond a useful state,
 which may happen occasionally while debugging.
 
 @node Virtual Memory Layout
@@ -301,7 +303,7 @@ regardless of what user process or kernel thread is running.  In
 Pintos, kernel virtual memory is mapped one-to-one to physical
 memory, starting at @code{PHYS_BASE}.  That is, virtual address
 @code{PHYS_BASE} accesses physical
-address 0, virtual address @code{PHYS_BASE} + @t{0x1234} access
+address 0, virtual address @code{PHYS_BASE} + @t{0x1234} accesses
 physical address @t{0x1234}, and so on up to the size of the machine's
 physical memory.
 
@@ -406,7 +408,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 +445,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
@@ -616,16 +618,50 @@ Runs the executable whose name is given in @var{cmd_line}, passing any
 given arguments, and returns the new process's program id (pid).  Must
 return pid -1, which otherwise should not be a valid pid, if
 the program cannot load or run for any reason.
+Thus, the parent process cannot return from the @code{exec} until it
+knows whether the child process successfully loaded its executable.
+You must use appropriate synchronization to ensure this.
 @end deftypefn
 
 @deftypefn {System Call} int wait (pid_t @var{pid})
-Waits for process @var{pid} to die and returns the status it passed to
-@code{exit}.  Returns -1 if @var{pid}
-was terminated by the kernel (e.g.@: killed due to an exception).  If
-@var{pid} is 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
@@ -635,18 +671,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
@@ -654,11 +678,16 @@ of the rest.
 @deftypefn {System Call} bool create (const char *@var{file}, unsigned @var{initial_size})
 Creates a new file called @var{file} initially @var{initial_size} bytes
 in size.  Returns true if successful, false otherwise.
+Creating a new file does not open it: opening the new file is a
+separate operation which would require a @code{open} system call.
 @end deftypefn
 
 @deftypefn {System Call} bool remove (const char *@var{file})
 Deletes the file called @var{file}.  Returns true if successful, false
 otherwise.
+A file may be removed regardless of whether it is open or closed, and
+removing an open file does not close it.  @xref{Removing an Open
+File}, for details.
 @end deftypefn
 
 @deftypefn {System Call} int open (const char *@var{file})
@@ -696,13 +725,13 @@ than end of file).  Fd 0 reads from the keyboard using
 
 @deftypefn {System Call} int write (int @var{fd}, const void *@var{buffer}, unsigned @var{size})
 Writes @var{size} bytes from @var{buffer} to the open file @var{fd}.
-Returns the number of bytes actually written, or -1 if the file could
-not be written.
+Returns the number of bytes actually written, which may be less than
+@var{size} if some bytes could not be written.
 
 Writing past end-of-file would normally extend the file, but file growth
 is not implemented by the basic file system.  The expected behavior is
 to write as many bytes as possible up to end-of-file and return the
-actual number written, or -1 if no bytes could be written at all.
+actual number written, or 0 if no bytes could be written at all.
 
 Fd 1 writes to the console.  Your code to write to the console should
 write all of @var{buffer} in one call to @func{putbuf}, at least as
@@ -825,7 +854,7 @@ modified by the reference solution.
 
 @item The kernel always panics when I run @code{pintos -p @var{file} -- -q}.
 
-Did you format the disk (with @samp{pintos -f})?
+Did you format the file system (with @samp{pintos -f})?
 
 Is your file name too long?  The file system limits file names to 14
 characters.  A command like @samp{pintos -p ../../examples/echo -- -q}
@@ -846,6 +875,8 @@ Files are written under the name you refer to them, by default, so in
 this case the file copied in would be named @file{../file}.  You
 probably want to run @code{pintos -p ../file -a file --} instead.
 
+You can list the files in your file system with @code{pintos -q ls}.
+
 @item All my user programs die with page faults.
 
 This will happen if you haven't implemented argument passing
@@ -863,7 +894,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
@@ -893,7 +924,7 @@ Modify @file{src/examples/Makefile}, then run @command{make}.
 
 @item Can I run user programs under a debugger?
 
-Yes, with some limitations.  @xref{Debugging User Programs}.
+Yes, with some limitations.  @xref{GDB}.
 
 @item What's the difference between @code{tid_t} and @code{pid_t}?
 
@@ -970,6 +1001,18 @@ or the machine shuts down.
 You may modify the stack setup code to allocate more than one page of
 stack space for each process.  In the next project, you will implement a
 better solution.
+
+@item What should happen if an @code{exec} fails midway through loading?
+
+@code{exec} should return -1 if the child process fails to load for
+any reason.  This includes the case where the load fails part of the
+way through the process (e.g.@: where it runs out of memory in the
+@code{multi-oom} test).  Therefore, the parent process cannot return
+from the @code{exec} system call until it is established whether the
+load was successful or not.  The child must communicate this
+information to its parent using appropriate synchronization, such as a
+semaphore (@pxref{Semaphores}), to ensure that the information is
+communicated without race conditions.
 @end table
 
 @node 80x86 Calling Convention
@@ -1069,17 +1112,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}: