Mention that process_wait() can be changed to an infinite loop
[pintos-anon] / doc / userprog.texi
index 65932604d7099a7d0ae374a63f9b6e0249e9e723..ab6115ce6c67b348a40f5eb1c7e9707c8e1d29c9 100644 (file)
@@ -16,11 +16,12 @@ relevant parts below.
 
 You can build project 2 on top of your project 1 submission or you can
 start with a fresh copy.  No code from project 1 is required for this
-assignment.  The ``alarm clock'' functionality may be useful in later
-projects, but it is not strictly required.
+assignment.  The ``alarm clock'' functionality may be useful in
+projects 3 and 4, but it is not strictly required.
 
 @menu
 * Project 2 Background::        
+* Project 2 Suggested Order of Implementation::  
 * Project 2 Requirements::      
 * Project 2 FAQ::               
 * 80x86 Calling Convention::    
@@ -36,11 +37,12 @@ full access to privileged parts of the system.  Once we start running
 user programs on top of the operating system, this is no longer true.
 This project deals with consequences of the change.
 
-We allow more than one user program to run at a time.  User
-programs are written and compiled to work under the illusion that they
-have the entire machine.  This means that when you load and
-run multiple processes at a time, you must manage memory, scheduling,
-and other state correctly to maintain this illusion.
+We allow more than one process to run at a time.  Each process has one
+thread (multithreaded processes are not supported).  User programs are
+written under the illusion that they have the entire machine.  This
+means that when you load and run multiple processes at a time, you must
+manage memory, scheduling, and other state correctly to maintain this
+illusion.
 
 In the previous project, we compiled our test code directly into your
 kernel, so we had to require certain specific function interfaces within
@@ -435,6 +437,63 @@ verified to be below @code{PHYS_BASE}.  They also assume that you've
 modified @func{page_fault} so that a page fault in the kernel causes
 @code{eax} to be set to 0 and its former value copied into @code{eip}.
 
+@node Project 2 Suggested Order of Implementation
+@section Suggested Order of Implementation
+
+We suggest first implementing the following, which can happen in
+parallel:
+
+@itemize
+@item
+Argument passing (@pxref{Argument Passing}).  Every user programs will
+page fault immediately until argument passing is implemented.
+
+For now, you may simply wish to change
+@example
+*esp = PHYS_BASE;
+@end example
+@noindent to
+@example
+*esp = PHYS_BASE - 12;
+@end example
+in @func{setup_stack}.  That will work for any test program that doesn't
+examine its arguments, although its name will be printed as
+@code{(null)}.
+
+@item
+User memory access (@pxref{Accessing User Memory}).  All system calls
+need to read user memory.  Few system calls need to write to user
+memory.
+
+@item
+System call infrastructure (@pxref{System Calls}).  Implement enough
+code to read the system call number from the user stack and dispatch to
+a handler based on it.
+
+@item
+The @code{exit} system call.  Every user program that finishes in the
+normal way calls @code{exit}.  Even a program that returns from
+@func{main} calls @code{exit} indirectly (see @func{_start} in
+@file{lib/user/entry.c}).
+
+@item
+The @code{write} system call for writing to fd 1, the system console.
+All of our test programs write to the console (the user process version
+of @func{printf} is implemented this way), so they will all malfunction
+until @code{write} is available.
+
+@item
+For now, change @func{process_wait} to an infinite loop (one that waits
+forever).  The provided implementation returns immediately, so Pintos
+will power off before any processes actually get to run.  You will
+eventually need to provide a correct implementation.
+@end itemize
+
+After the above are implemented, user processes should work minimally.
+At the very least, they can write to the console and exit correctly.
+You can then refine your implementation so that some of the tests start
+to pass.
+
 @node Project 2 Requirements
 @section Requirements
 
@@ -489,7 +548,9 @@ Within a command line, multiple spaces are equivalent to a single space,
 so that @code{process_execute("grep foo bar")} is equivalent to our
 original example.  You can impose a reasonable limit on the length of
 the command line arguments.  For example, you could limit the arguments
-to those that will fit in a single page (4 kB).
+to those that will fit in a single page (4 kB).  (There is an unrelated
+limit of 128 bytes on command-line arguments that the @command{pintos}
+utility can pass to the kernel.)
 
 You can parse argument strings any way you like.  If you're lost,
 look at @func{strtok_r}, prototyped in @file{lib/string.h} and
@@ -509,15 +570,15 @@ terminating the process.  It will need to retrieve the system call
 number, then any system call arguments, and carry appropriate actions.
 
 Implement the following system calls.  The prototypes listed are those
-seen by a user program that includes @file{lib/user/syscall.h}.  System
-call numbers for each system call are defined in
+seen by a user program that includes @file{lib/user/syscall.h}.  (This
+header and all other files in @file{lib/user} are for use by user
+programs only.)  System call numbers for each system call are defined in
 @file{lib/syscall-nr.h}:
 
 @deftypefn {System Call} void halt (void)
 Terminates Pintos by calling @func{power_off} (declared in
-@file{threads/init.h}).  Note that this should be seldom used, since
-then you lose some information about possible deadlock situations,
-etc.
+@file{threads/init.h}).  This should be seldom used, because you lose
+some information about possible deadlock situations, etc.
 @end deftypefn
 
 @deftypefn {System Call} void exit (int @var{status})
@@ -539,7 +600,7 @@ the program cannot load or run for any reason.
 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 (i.e.@: killed due to an exception).  If
-@var{pid} is invalid or if it was not a child of the
+@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.
@@ -568,11 +629,15 @@ waits for @var{B}, then @var{A} waits for @var{C}), and so on.
 @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.
+
+Consider implementing this function in terms of @func{filesys_create}.
 @end deftypefn
 
 @deftypefn {System Call} bool remove (const char *@var{file})
 Deletes the file called @var{file}.  Returns true if successful, false
 otherwise.
+
+Consider implementing this function in terms of @func{filesys_remove}.
 @end deftypefn
 
 @deftypefn {System Call} int open (const char *@var{file})
@@ -585,10 +650,14 @@ File descriptors numbered 0 and 1 are reserved for the console: fd 0
 is standard input (@code{stdin}), fd 1 is standard output
 (@code{stdout}).  These special file descriptors are valid as system
 call arguments only as explicitly described below.
+
+Consider implementing this function in terms of @func{filesys_open}.
 @end deftypefn
 
 @deftypefn {System Call} int filesize (int @var{fd})
 Returns the size, in bytes, of the file open as @var{fd}.
+
+Consider implementing this function in terms of @func{file_length}.
 @end deftypefn
 
 @deftypefn {System Call} int read (int @var{fd}, void *@var{buffer}, unsigned @var{size})
@@ -597,6 +666,8 @@ Reads @var{size} bytes from the file open as @var{fd} into
 file), or -1 if the file could not be read (due to a condition other
 than end of file).  Fd 0 reads from the keyboard using
 @func{kbd_getc}.
+
+Consider implementing this function in terms of @func{file_read}.
 @end deftypefn
 
 @deftypefn {System Call} int write (int @var{fd}, const void *@var{buffer}, unsigned @var{size})
@@ -604,11 +675,18 @@ 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.
 
+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.
+
 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
 long as @var{size} is not bigger than a few hundred bytes.  Otherwise,
 lines of text output by different processes may end up interleaved on
 the console, confusing both human readers and our grading scripts.
+
+Consider implementing this function in terms of @func{file_write}.
 @end deftypefn
 
 @deftypefn {System Call} void seek (int @var{fd}, unsigned @var{position})
@@ -623,15 +701,21 @@ have a fixed length until project 4 is complete, so writes past end of
 file will return an error.)  These semantics are implemented in the
 file system and do not require any special effort in system call
 implementation.
+
+Consider implementing this function in terms of @func{file_seek}.
 @end deftypefn
 
 @deftypefn {System Call} unsigned tell (int @var{fd})
 Returns the position of the next byte to be read or written in open
 file @var{fd}, expressed in bytes from the beginning of the file.
+
+Consider implementing this function in terms of @func{file_tell}.
 @end deftypefn
 
 @deftypefn {System Call} void close (int @var{fd})
 Closes file descriptor @var{fd}.
+
+Consider implementing this function in terms of @func{file_close}.
 @end deftypefn
 
 The file defines other syscalls.  Ignore them for now.  You will