@node Task 2--User Programs
@chapter Task 2: User Programs

Now that you've worked with PintOS and are becoming familiar with its
infrastructure and thread package, it's time to start working on the
parts of the system that allow running user programs.
The base code already supports loading and
running user programs, but no I/O or interactivity
is possible.  In this task, you will enable programs to interact with
the OS via system calls.

You will be working out of the @file{userprog} directory for this
assignment, but you will also be interacting with almost every
other part of PintOS.  We will describe the
relevant parts below.

You can build task 2 on top of your task 1 submission or you can
start fresh.  No code from task 1 is required for this
assignment.  The ``alarm clock'' functionality from task 0 may be useful in
task 3, but it is not strictly required.

You might find it useful to go back and reread how to run the tests
(@pxref{Testing}).

@menu
* Task 2 Background::        
* Task 2 Suggested Order of Implementation::  
* Task 2 Requirements::      
* Task 2 FAQ::               
* 80x86 Calling Convention::    
@end menu

@node Task 2 Background
@section Background

Up to now, all of the code you have run under PintOS has been part
of the operating system kernel.  This means, for example, that all the
test code from the last assignment ran as part of the kernel, with
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 task deals with the consequences.

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 task, we compiled our test code directly into your
kernel, so we had to require certain specific function interfaces within
the kernel.  From now on, we will test your operating system by running
user programs.  This gives you much greater freedom.  You must make sure
that the user program interface meets the specifications described here,
but given that constraint you are free to restructure or rewrite kernel
code however you wish.

@menu
* Task 2 Source Files::      
* Using the File System::       
* How User Programs Work::      
* Virtual Memory Layout::       
* Accessing User Memory::       
@end menu

@node Task 2 Source Files
@subsection Source Files

The easiest way to get an overview of the programming you will be
doing is to simply go over each part you'll be working with.  In
@file{userprog}, you'll find a small number of files, but here is
where the bulk of your work will be:

@table @file
@item process.c
@itemx process.h
Loads ELF binaries and starts processes.

@item pagedir.c
@itemx pagedir.h
A simple manager for 80@var{x}86 hardware page tables.
Although you probably won't want to modify this code for this task,
you may want to call some of its functions.
@xref{Page Tables}, for more information.

@item syscall.c
@itemx syscall.h
Whenever a user process wants to access some kernel functionality, it
invokes a system call.  This is a skeleton system call
handler.  Currently, it just prints a message and terminates the user
process.  In part 2 of this task you will add code to do everything
else needed by system calls.

@item exception.c
@itemx exception.h
When a user process performs a privileged or prohibited operation, it
traps into the kernel as an ``exception'' or ``fault.''@footnote{We
will treat these terms as synonyms.  There is no standard
distinction between them, although Intel processor manuals make 
a minor distinction between them on 80@var{x}86.}  These files handle
exceptions.  Currently all exceptions simply print a message and
terminate the process.  Some, but not all, solutions to task 2
require modifying @func{page_fault} in this file.

@item gdt.c
@itemx gdt.h
The 80@var{x}86 is a segmented architecture.  The Global Descriptor
Table (GDT) is a table that describes the segments in use.  These
files set up the GDT.  You should not need to modify these
files for any of the tasks.  You can read the code if
you're interested in how the GDT works.

@item tss.c
@itemx tss.h
The Task-State Segment (TSS) is used for 80@var{x}86 architectural
task switching.  PintOS uses the TSS only for switching stacks when a
user process enters an interrupt handler, as does Linux.  You
should not need to modify these files for any of the tasks.
You can read the code if you're interested in how the TSS
works.
@end table

@node Using the File System
@subsection Using the File System

You will need to interface to the file system code for this task,
because
user programs are loaded from the file system and many of the
system calls you must implement deal with the file system.  However,
the focus of this task is not the file system, so we have
provided a simple but complete file system in the @file{filesys}
directory.  You
will want to look over the @file{filesys.h} and @file{file.h}
interfaces to understand how to use the file system, and especially
its many limitations.

There is no need to modify the file system code for this task, and so
we recommend that you do not.  Working on the file system is likely to
distract you from this task's focus.

You will have to tolerate the following limitations of the provided
filesystem implementation:

@itemize @bullet
@item
No internal synchronization.  Concurrent accesses will interfere with one
another.  You should use synchronization to ensure that only one process at a
time is executing file system code. No finer-grained synchronisation 
(for eg. per-file locking) is expected.

@item
File size is fixed at creation time.  The root directory is
represented as a file, so the number of files that may be created is also
limited.

@item
File data is allocated as a single extent, that is, data in a single
file must occupy a contiguous range of sectors on disk.  External
fragmentation can therefore become a serious problem as a file system is
used over time.

@item
No subdirectories.

@item
File names are limited to 14 characters.

@item
A system crash mid-operation may corrupt the disk in a way
that cannot be repaired automatically.  There is no file system repair
tool anyway.
@end itemize

One important feature is included:

@itemize @bullet
@item
Unix-like semantics for @func{filesys_remove} are implemented.
That is, if a file is open when it is removed, its blocks
are not deallocated and it may still be accessed by any
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 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'')
options do this.  To copy @file{@var{file}} into the
PintOS file system, use the command @file{pintos -p @var{file} -- -q}.
(The @samp{--} is needed because @option{-p} is for the @command{pintos}
script, not for the simulated kernel.)  To copy it to the PintOS file
system under the name @file{@var{newname}}, add @option{-a
@var{newname}}: @file{pintos -p @var{file} -a @var{newname} -- -q}.  The
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{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 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 filesys.dsk --filesys-size=2
pintos -f -q
pintos -p ../../examples/echo -a echo -- -q
pintos -q run 'echo x'
@end example

The three final steps can actually be combined into a single command:

@example
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{--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 --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
@var{file}} kernel action, e.g.@: @code{pintos -q rm @var{file}}.  Also,
@command{ls} lists the files in the file system and @code{cat
@var{file}} prints a file's contents to the display.

@node How User Programs Work
@subsection How User Programs Work

PintOS can run normal C programs, as long as they fit into memory and use
only the system calls you implement.  Notably, @func{malloc} cannot be
implemented because none of the system calls required for this task
allow for memory allocation.  PintOS also can't run programs that use
floating point operations, since the kernel doesn't save and restore the
processor's floating-point unit when switching threads.

The @file{src/examples} directory contains a few sample user
programs.  The @file{Makefile} in this directory
compiles the provided examples, and you can edit it
compile your own programs as well.  Some of the example programs will
only work once task 3 has been implemented.

PintOS can load @dfn{ELF} executables with the loader provided for you
in @file{userprog/process.c}.  ELF is a file format used by Linux,
Solaris, and many other operating systems for object files,
shared libraries, and executables.  You can actually use any compiler
and linker that output 80@var{x}86 ELF executables to produce programs
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 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 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
@subsection Virtual Memory Layout

Virtual memory in PintOS is divided into two regions: user virtual
memory and kernel virtual memory.  User virtual memory ranges from
virtual address 0 up to @code{PHYS_BASE}, which is defined in
@file{threads/vaddr.h} and defaults to @t{0xc0000000} (3 GB).  Kernel
virtual memory occupies the rest of the virtual address space, from
@code{PHYS_BASE} up to 4 GB.

User virtual memory is per-process.
When the kernel switches from one process to another, it
also switches user virtual address spaces by changing the processor's
page directory base register (see @func{pagedir_activate} in
@file{userprog/pagedir.c}).  @struct{thread} contains a pointer to a
process's page table.

Kernel virtual memory is global.  It is always mapped the same way,
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} accesses
physical address @t{0x1234}, and so on up to the size of the machine's
physical memory.

A user program can only access its own user virtual memory.  An attempt to
access kernel virtual memory causes a page fault, handled by
@func{page_fault} in @file{userprog/exception.c}, and the process
will be terminated.  Kernel threads can access both kernel virtual
memory and, if a user process is running, the user virtual memory of
the running process.  However, even in the kernel, an attempt to
access memory at an unmapped user virtual address
will cause a page fault.

@page
@menu
* Typical Memory Layout::       
@end menu

@node Typical Memory Layout
@subsubsection Typical Memory Layout

Conceptually, each process is
free to lay out its own user virtual memory however it
chooses.  In practice, user virtual memory is laid out like this:

@html
<CENTER>
@end html
@example
@group
   PHYS_BASE +----------------------------------+
             |            user stack            |
             |                 |                |
             |                 |                |
             |                 V                |
             |          grows downward          |
             |                                  |
             |                                  |
             |                                  |
             |                                  |
             |           grows upward           |
             |                 ^                |
             |                 |                |
             |                 |                |
             +----------------------------------+
             | uninitialized data segment (BSS) |
             +----------------------------------+
             |     initialized data segment     |
             +----------------------------------+
             |           code segment           |
  0x08048000 +----------------------------------+
             |                                  |
             |                                  |
             |                                  |
             |                                  |
             |                                  |
           0 +----------------------------------+
@end group
@end example
@html
</CENTER>
@end html

In this task, the user stack is fixed in size, but in task 3 it
will be allowed to grow.  Traditionally, the size of the uninitialized
data segment can be adjusted with a system call, but you will not have
to implement this.

The code segment in PintOS starts at user virtual address
@t{0x08084000}, approximately 128 MB from the bottom of the address
space.  This value is specified in @bibref{SysV-i386} and has no deep
significance.

The linker sets the layout of a user program in memory, as directed by a
``linker script'' that tells it the names and locations of the various
program segments.  You can learn more about linker scripts by reading
the ``Scripts'' chapter in the linker manual, accessible via @samp{info
ld}.

To view the layout of a particular executable, run @command{objdump}
(80@var{x}86) with the @option{-p}
option.

@node Accessing User Memory
@subsection Accessing User Memory

As part of a system
call, the kernel must often access memory through pointers provided by a user
program.  The kernel must be very careful about doing so, because
the user can pass a null pointer, a pointer to
unmapped virtual memory, or a pointer to kernel virtual address space
(above @code{PHYS_BASE}).  All of these types of invalid pointers must
be rejected without harm to the kernel or other running processes, by
terminating the offending process and freeing its resources.

There are at least two reasonable ways to do this correctly.  The
first method is to verify
the validity of a user-provided pointer, then dereference it.  If you
choose this route, you'll want to look at the functions in
@file{userprog/pagedir.c} and in @file{threads/vaddr.h}, specifically 
@func{pagedir_get_page} and @func{is_user_vaddr}.  This is the
simplest way to handle user memory access.

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.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).

In either case, you need to make sure not to ``leak'' resources.  For
example, suppose that your system call has acquired a lock or
allocated memory with @func{malloc}.  If you encounter an invalid user pointer
afterward, you must still be sure to release the lock or free the page
of memory.  If you choose to verify user pointers before dereferencing
them, this should be straightforward.  It's more difficult to handle
if an invalid pointer causes a page fault,
because there's no way to return an error code from a memory access.
Therefore, for those who want to try the latter technique, we'll
provide a little bit of helpful code:

@verbatim
/* Reads a byte at user virtual address UADDR.
   UADDR must be below PHYS_BASE.
   Returns the byte value if successful, -1 if a segfault
   occurred. */
static int
get_user (const uint8_t *uaddr)
{
  int result;
  asm ("movl $1f, %0; movzbl %1, %0; 1:"
       : "=&a" (result) : "m" (*uaddr));
  return result;
}
 
/* Writes BYTE to user address UDST.
   UDST must be below PHYS_BASE.
   Returns true if successful, false if a segfault occurred. */
static bool
put_user (uint8_t *udst, uint8_t byte)
{
  int error_code;
  asm ("movl $1f, %0; movb %b2, %1; 1:"
       : "=&a" (error_code), "=m" (*udst) : "q" (byte));
  return error_code != -1;
}
@end verbatim

Each of these functions assumes that the user address has already been
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 merely
sets the interupt frame @code{eax} to @t{0xffffffff} and copies the old value
into @code{eip}.

@page
@node Task 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 program 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} to fake the set-up for a minimaml stack.

This will work for any example program that doesn't examine its arguments (e.g. @code{halt.c}), 
although the program's name will be printed as @code{(null)}.

Note that all of the Task 2 tests access the program arguments, so these will still page-fault and die. 
Thus, you will still fail all of the Task 2 tests at this point.

Until you implement argument passing fully, you should only run programs without passing command-line arguments.  
Currently, attempting to pass @strong{any} arguments to a program will cause the kernel to search for a program whose 
name includes those arguments. This will obviously fail and cause the kernel to abort running the program.

@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 purpose of @func{process_wait} is described in more detail 
above it's function stub in @file{src/userprog/process.c}, and more 
information can be found in the description of the @code{wait} system call 
later in this document.
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,
although you will still fail all of the Task 2 tests 
(as these all print the program name @code{argv[0]} in their output).
However, you should at least be able to write to the console and exit correctly.
You can then refine your implementation so that some of the tests start
to pass (your first step should be to complete @func{process_wait} so 
that user programs return correctly). In order to minimise the amount of 
time you spend on this exercise, it is vital that you implement the 
@code{write}, @code{exit} and @code{wait} system calls before beginning the 
others.

@node Task 2 Requirements
@section Requirements

@menu
* Task 2 Design Document::   
* Process Termination Messages::  
* Argument Passing::            
* System Calls::                
* Denying Writes to Executables::  
@end menu

@node Task 2 Design Document
@subsection Design Document

When you submit your work for task 2, you must also submit a completed copy of
@uref{userprog.tmpl, , the task 2 design document template}. 
You can find a template design document for this task in @file{pintos/doc/userprog.tmpl} and also on CATe.
You are free to submit your design document as either a @file{.txt} or @file{.pdf} file.
We recommend that you read the design document template before you start working on the task.  
@xref{Task Documentation}, for a sample design document that goes along with a fictitious task.

@node Process Termination Messages
@subsection Process Termination Messages

Whenever a user process terminates, because it called @code{exit}
or for any other reason, print the process's name
and exit code, formatted as if printed by @code{printf ("%s:
exit(%d)\n", @dots{});}.  The name printed should be the full name
passed to @func{process_execute}, omitting command-line arguments.
Do not print these messages when a kernel thread that is not a user
process terminates, or
when the @code{halt} system call is invoked.  The message is optional
when a process fails to load.

Aside from this, don't print any other
messages that PintOS as provided doesn't already print.  You may find
extra messages useful during debugging, but they will confuse the
grading scripts and thus lower your score.

@node Argument Passing
@subsection Argument Passing

Currently, @func{process_execute}, found in @file{src/userprog/process.c}, does not support passing arguments to new processes.
Instead, the entire command line will be treated as the program name, resulting in the kernel failing to load the correct program file into memory.
You will need to fix this.

Implement argument passing by extending @func{process_execute} so that rather than simply taking a program file name to be the whole command line, 
it instead divides the command line into words at spaces. 
The first word is the program name, the second word is the first argument, and so on.  
That is, @code{process_execute("grep foo bar")} should run @command{grep} passing two arguments @code{foo} and @code{bar}.

Within a command line, multiple spaces are equivalent to a single space, 
so that @code{process_execute("grep @w{ }foo @w{ }@w{ }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).  
(There is an @strong{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 implemented with thorough comments in @file{lib/string.c}.  
You can find more about it by looking at the man page (run @code{man strtok_r} at the prompt).

Virtually all the code you will write relating to argument passing will be in @func{process_execute} and @func{start_process}. 
@func{process_execute} creates a new thread, calling @func{start_process} to load the actual process into the thread and set up the stack and other related structures.
You must ensure that the correct executable file is loaded within @func{start_process}.

@xref{Program Startup Details}, for information on exactly how you
need to set up the stack.

@node System Calls
@subsection System Calls

Implement the system call handler in @file{userprog/syscall.c}.  The
skeleton implementation we provide ``handles'' system calls by
terminating the process.  It will need to retrieve the system call
number, then any system call arguments, and carry out appropriate actions.

Implement the following system calls.  The prototypes listed are those
seen by a user program that includes @file{lib/user/syscall.h}.  (This
header, and all others 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{shutdown_power_off} (declared in
@file{devices/shutdown.h}).  This should be seldom used, because you lose
some information about possible deadlock situations, etc.
@var{*Warning*: The original PintOS documentation on the Stanford website
is outdated and incorrectly places the shutdown function in the wrong 
location. It's advisable that you don't use it as a reference
in completing any of the tasks.}
@end deftypefn

@deftypefn {System Call} void exit (int @var{status})
Terminates the current user program, sending its exit @var{status} to the
kernel.  If the process's parent @code{wait}s for it (see below), this
is the status
that will be returned.  Conventionally, a @var{status} of 0 indicates
success and nonzero values indicate errors.
@end deftypefn

@deftypefn {System Call} pid_t exec (const char *@var{cmd_line})
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 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 are 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.

As a special case, you must ensure that PintOS does not terminate until the initial process exits. 
The supplied PintOS code tries to do this by calling @func{process_wait} (in @file{userprog/process.c}) 
from @func{main} (in @file{threads/init.c}).

We strongly suggest that you implement @func{process_wait} according to the comment at the top of the function 
and then implement the @code{wait} system call in terms of @func{process_wait}.

Be aware that implementing this system call requires considerably more work than any of the others.
@end deftypefn

@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})
Opens the file called @var{file}.  Returns a nonnegative integer handle
called a ``file descriptor'' (fd), or -1 if the file could not be
opened.  

File descriptors numbered 0 and 1 are reserved for the console: fd 0
(@code{STDIN_FILENO}) is standard input, fd 1 (@code{STDOUT_FILENO}) is
standard output.  The @code{open} system call will never return either
of these file descriptors, which are valid as system call arguments only
as explicitly described below.

Each process has an independent set of file descriptors.  File
descriptors are not inherited by child processes.

When a single file is opened more than once, whether by a single
process or different processes, each @code{open} returns a new file
descriptor.  Different file descriptors for a single file are closed
independently in separate calls to @code{close} and they do not share
a file position.
@end deftypefn

@deftypefn {System Call} int filesize (int @var{fd})
Returns the size, in bytes, of the file open as @var{fd}.
@end deftypefn

@deftypefn {System Call} int read (int @var{fd}, void *@var{buffer}, unsigned @var{size})
Reads @var{size} bytes from the file open as @var{fd} into
@var{buffer}.  Returns the number of bytes actually read (0 at end of
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{input_getc}, which can be found in @file{src/devices/input.h}.
@end deftypefn

@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, 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 behaviour is
to write as many bytes as possible up to end-of-file and return the
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
long as @var{size} is not bigger than a few hundred bytes.  (It is
reasonable to break up larger buffers.)  Otherwise,
lines of text output by different processes may end up interleaved on
the console, confusing both human readers and our grading scripts.
@end deftypefn

@deftypefn {System Call} void seek (int @var{fd}, unsigned @var{position})
Changes the next byte to be read or written in open file @var{fd} to
@var{position}, expressed in bytes from the beginning of the file.
(Thus, a @var{position} of 0 is the file's start.)

A seek past the current end of a file is not an error.  
A later read obtains 0 bytes, indicating end of file.  
Normally, a later write would extend the file, filling any unwritten gap with zeros.  
However, in PintOS files have a fixed length, 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.
@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.
@end deftypefn

@deftypefn {System Call} void close (int @var{fd})
Closes file descriptor @var{fd}.  
Exiting or terminating a process implicitly closes all its open file
descriptors, as if by calling this function for each one.
@end deftypefn

The system call handler defines other syscalls.  Ignore them for now.  You will
implement the rest in task 3, so be
sure to design your system with extensibility in mind.

To implement syscalls, you need to provide ways to read and write data
in user virtual address space.
You need this ability before you can
even obtain the system call number, because the system call number is
on the user's stack in the user's virtual address space.
This can be a bit tricky: what if the user provides an invalid
pointer, a pointer into kernel memory, or a block
partially in one of those regions?  You should handle these cases by
terminating the user process.  We recommend
writing and testing this code before implementing any other system
call functionality.  @xref{Accessing User Memory}, for more information.

You must synchronize system calls so that
any number of user processes can make them at once.  In particular, it
is not safe to call into the file system code provided in the
@file{filesys} directory from multiple threads at once.  Your system
call implementation must treat the file system code as a critical
section.  Don't forget
that @func{process_execute} also accesses files.  For now, we
recommend against modifying code in the @file{filesys} directory.

We have provided you a user-level function for each system call in
@file{lib/user/syscall.c}.  These provide a way for user processes to
invoke each system call from a C program.  Each uses a little inline
assembly code to invoke the system call and (if appropriate) returns the
system call's return value.

When you're done with this part, and forevermore, PintOS should be
bulletproof.  Nothing that a user program can do should ever cause the
OS to crash, panic, fail an assertion, or otherwise malfunction.  It is
important to emphasize this point: our tests will try to break your
system calls in many, many ways.  You need to think of all the corner
cases and handle them.  The sole way a user program should be able to
cause the OS to halt is by invoking the @code{halt} system call.

If a system call is passed an invalid argument, acceptable options
include returning an error value (for those calls that return a
value), returning an undefined value, or terminating the process.

@xref{System Call Details}, for details on how system calls work.

@node Denying Writes to Executables
@subsection Denying Writes to Executables

Add code to deny writes to files in use as executables.  Many OSes do
this because of the unpredictable results if a process tried to run code
that was in the midst of being changed on disk.  This is especially
important once virtual memory is implemented in task 3, but it can't
hurt even now.

You can use @func{file_deny_write} to prevent writes to an open file.
Calling @func{file_allow_write} on the file will re-enable them (unless
the file is denied writes by another opener).  Closing a file will also
re-enable writes.  Thus, to deny writes to a process's executable, you
must keep it open as long as the process is still running.

@node Task 2 FAQ
@section FAQ

@table @b
@item How much code will I need to write?

Here's a summary of our reference solution, produced by the
@command{diffstat} program.  The final row gives total lines inserted
and deleted; a changed line counts as both an insertion and a deletion.

@verbatim
 threads/thread.c     |   13 
 threads/thread.h     |   26 +
 userprog/exception.c |    8 
 userprog/process.c   |  247 ++++++++++++++--
 userprog/syscall.c   |  468 ++++++++++++++++++++++++++++++-
 userprog/syscall.h   |    1 
 6 files changed, 725 insertions(+), 38 deletions(-)
@end verbatim

The reference solution represents just one possible solution.  Many
other solutions are also possible and many of those differ greatly from
the reference solution.  Some excellent solutions may not modify all the
files modified by the reference solution, and some may modify files not
modified by the reference solution.

@item Do we need a working Task 1 to implement Task 2?

No.

@item The kernel always panics when I run @code{pintos -p @var{file} -- -q}.

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}
will exceed the limit.  Use @samp{pintos -p ../../examples/echo -a echo
-- -q} to put the file under the name @file{echo} instead.

Is the file system full?

Does the file system already contain 16 files?  The base PintOS file
system has a 16-file limit.

The file system may be so fragmented that there's not enough contiguous
space for your file.

@item When I run @code{pintos -p ../file --}, @file{file} isn't copied.

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
(or haven't done so correctly).  The basic C library for user programs tries
to read @var{argc} and @var{argv} off the stack.  If the stack
isn't properly set up, this causes a page fault.

@item All my user programs die with @code{system call!}

You'll have to implement system calls before you see anything else.
Every reasonable program tries to make at least one system call
(@func{exit}) and most programs make more than that.  Notably,
@func{printf} invokes the @code{write} system call.  The default system
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 disassemble user programs?

The @command{objdump} (80@var{x}86) utility can disassemble entire user
programs or object files.  Invoke it as @code{objdump -d
@var{file}}.  You can use GDB's
@code{disassemble} command to disassemble individual functions
(@pxref{GDB}).

@item Why do many C include files not work in PintOS programs?
@itemx Can I use lib@var{foo} in my PintOS programs?

The C library we provide is very limited.  It does not include many of
the features that are expected of a real operating system's C library.
The C library must be built specifically for the operating system (and
architecture), since it must make system calls for I/O and memory
allocation.  (Not all functions do, of course, but usually the library
is compiled as a unit.)

The chances are good that the library you want uses parts of the C library
that PintOS doesn't implement.  It will probably take at least some
porting effort to make it work under PintOS.  Notably, the PintOS
user program C library does not have a @func{malloc} implementation.

@item How do I compile new user programs?

Modify @file{src/examples/Makefile}, then run @command{make}.

@item Can I run user programs under a debugger?

Yes, with some limitations.  @xref{GDB}.

@item What's the difference between @code{tid_t} and @code{pid_t}?

A @code{tid_t} identifies a kernel thread, which may have a user
process running in it (if created with @func{process_execute}) or not
(if created with @func{thread_create}).  It is a data type used only
in the kernel.

A @code{pid_t} identifies a user process.  It is used by user
processes and the kernel in the @code{exec} and @code{wait} system
calls.

You can choose whatever suitable types you like for @code{tid_t} and
@code{pid_t}.  By default, they're both @code{int}.  You can make them
a one-to-one mapping, so that the same values in both identify the
same process, or you can use a more complex mapping.  It's up to you.

@item What should I expect from the Task 2 code-review?

The code-review for this task will be conducted with each group in-person.
Our Task 2 code-review will cover @strong{four} main areas: 
functional correctness, efficiency, design quality and general coding style.

@itemize @bullet
@item For @strong{functional correctness}, we will be looking to see if your argument passing code can avoid stack-overflow for all possible input command lines.
We will also be checking if your data structures for storing file descriptors, your file-system accesses and your implementation of the @func{wait} and @func{exit} system calls are all free of any race conditions.

@item For @strong{efficiency}, we will be looking at how you are storing the process parent/child relationships, how you are storing child load status and ensuring that your code does not leak memory in any situation.

@item For @strong{design quality}, we will be looking at how you have abstracted your argument passing code from the underlying stack updates (pushing arguments and their pointers onto the stack) and your system call handler to avoid repetitive code for each syscall case.
We will also be looking at the level of fidelity in your use of synchronisation for the @func{exec}, @func{wait} and @func{exit} system calls.

@item For @strong{general coding style}, we will be paying attention to all of the usual elements of good style 
that you should be used to from last year (e.g. consistent code layout, appropriate use of comments, avoiding magic numbers, etc.)
as well as your use of git (e.g. commit frequency and commit message quality).
In this task, we will be paying particular attention to magic numbers in your system call handler, as well as your use of global variables anywhere in your solution.
@end itemize
@end table

@menu
* Argument Passing FAQ::        
* System Calls FAQ::            
@end menu

@node Argument Passing FAQ
@subsection Argument Passing FAQ

@table @b
@item Isn't the top of stack in kernel virtual memory?

The top of stack is at @code{PHYS_BASE}, typically @t{0xc0000000}, which
is also where kernel virtual memory starts.
But before the processor pushes data on the stack, it decrements the stack
pointer.  Thus, the first (4-byte) value pushed on the stack
will be at address @t{0xbffffffc}.

@item Is @code{PHYS_BASE} fixed?

No.  You should be able to support @code{PHYS_BASE} values that are
any multiple of @t{0x10000000} from @t{0x80000000} to @t{0xf0000000},
simply via recompilation.
@end table

@node System Calls FAQ
@subsection System Calls FAQ

@table @b
@item Can I just cast a @code{struct file *} to get a file descriptor?
@itemx Can I just cast a @code{struct thread *} to a @code{pid_t}?

You will have to make these design decisions yourself.
Most operating systems do distinguish between file
descriptors (or pids) and the addresses of their kernel data
structures.  You might want to give some thought as to why they do so
before committing yourself.

@item Can I set a maximum number of open files per process?

It is better not to set an arbitrary limit.  You may impose a limit of
128 open files per process, if necessary.

@item What happens when an open file is removed?
@anchor{Removing an Open File}

You should implement the standard Unix semantics for files.  That is, when
a file is removed any process which has a file descriptor for that file
may continue to use that descriptor.  This means that
they can read and write from the file.  The file will not have a name,
and no other processes will be able to open it, but it will continue
to exist until all file descriptors referring to the file are closed
or the machine shuts down.

@item How can I run user programs that need more than 4 kB stack space?

You may modify the stack setup code to allocate more than one page of
stack space for each process.  In the next task, 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
@section 80@var{x}86 Calling Convention

This section summarizes important points of the convention used for
normal function calls on 32-bit 80@var{x}86 implementations of Unix.
Some details are omitted for brevity.  If you do want all the details,
refer to @bibref{SysV-i386}.

The calling convention works like this:

@enumerate 1
@item
The caller pushes each of the function's arguments on the stack one by
one, normally using the @code{PUSH} assembly language instruction.
Arguments are pushed in right-to-left order.

The stack grows downward: each push decrements the stack pointer, then
stores into the location it now points to, like the C expression
@samp{*--sp = @var{value}}.

@item
The caller pushes the address of its next instruction (the @dfn{return
address}) on the stack and jumps to the first instruction of the callee.
A single 80@var{x}86 instruction, @code{CALL}, does both.

@item
The callee executes.  When it takes control, the stack pointer points to
the return address, the first argument is just above it, the second
argument is just above the first argument, and so on.

@item
If the callee has a return value, it stores it into register @code{EAX}.

@item
The callee returns by popping the return address from the stack and
jumping to the location it specifies, using the 80@var{x}86 @code{RET}
instruction.

@item
The caller pops the arguments off the stack.
@end enumerate

Consider a function @func{f} that takes three @code{int} arguments.
This diagram shows a sample stack frame as seen by the callee at the
beginning of step 3 above, supposing that @func{f} is invoked as
@code{f(1, 2, 3)}.  The initial stack address is arbitrary:

@html
<CENTER>
@end html
@example
                             +----------------+
                  0xbffffe7c |        3       |
                  0xbffffe78 |        2       |
                  0xbffffe74 |        1       |
stack pointer --> 0xbffffe70 | return address |
                             +----------------+
@end example
@html
</CENTER>
@end html

@menu
* Program Startup Details::     
* System Call Details::         
@end menu

@node Program Startup Details
@subsection Program Startup Details

The PintOS C library for user programs designates @func{_start}, in
@file{lib/user/entry.c}, as the entry point for user programs.  This
function is a wrapper around @func{main} that calls @func{exit} if
@func{main} returns:

@example
void
_start (int argc, char *argv[]) 
@{
  exit (main (argc, argv));
@}
@end example

The kernel must put the arguments for the initial function on the stack
before it allows the user program to begin executing.  The arguments are
passed in the same way as the normal calling convention (@pxref{80x86
Calling Convention}).

Consider how to handle arguments for the following example command:
@samp{/bin/ls -l foo bar}.
First, break the command into words: @samp{/bin/ls},
@samp{-l}, @samp{foo}, @samp{bar}.  Place the words at the top of the
stack.  Order doesn't matter, because they will be referenced through
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 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 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}:

@html
<CENTER>
@end html
@multitable {@t{0xbfffffff}} {return address} {@t{/bin/ls\0}} {@code{void (*) ()}}
@item Address @tab Name @tab Data @tab Type
@item @t{0xbffffffc} @tab @code{argv[3][@dots{}]} @tab @samp{bar\0} @tab @code{char[4]}
@item @t{0xbffffff8} @tab @code{argv[2][@dots{}]} @tab @samp{foo\0} @tab @code{char[4]}
@item @t{0xbffffff5} @tab @code{argv[1][@dots{}]} @tab @samp{-l\0} @tab @code{char[3]}
@item @t{0xbfffffed} @tab @code{argv[0][@dots{}]} @tab @samp{/bin/ls\0} @tab @code{char[8]}
@item @t{0xbfffffec} @tab word-align @tab 0 @tab @code{uint8_t}
@item @t{0xbfffffe8} @tab @code{argv[4]} @tab @t{0} @tab @code{char *}
@item @t{0xbfffffe4} @tab @code{argv[3]} @tab @t{0xbffffffc} @tab @code{char *}
@item @t{0xbfffffe0} @tab @code{argv[2]} @tab @t{0xbffffff8} @tab @code{char *}
@item @t{0xbfffffdc} @tab @code{argv[1]} @tab @t{0xbffffff5} @tab @code{char *}
@item @t{0xbfffffd8} @tab @code{argv[0]} @tab @t{0xbfffffed} @tab @code{char *}
@item @t{0xbfffffd4} @tab @code{argv} @tab @t{0xbfffffd8} @tab @code{char **}
@item @t{0xbfffffd0} @tab @code{argc} @tab 4 @tab @code{int}
@item @t{0xbfffffcc} @tab return address @tab 0 @tab @code{void (*) ()}
@end multitable
@html
</CENTER>
@end html

In this example, the stack pointer would be initialized to
@t{0xbfffffcc}.

As shown above, your code should start the stack at the very top of
the user virtual address space, in the page just below virtual address
@code{PHYS_BASE} (defined in @file{threads/vaddr.h}).

You may find the non-standard @func{hex_dump} function, declared in
@file{<stdio.h>}, useful for debugging your argument passing code.
Here's what it would show in the above example:

@verbatim
bfffffc0                                      00 00 00 00 |            ....|
bfffffd0  04 00 00 00 d8 ff ff bf-ed ff ff bf f5 ff ff bf |................|
bfffffe0  f8 ff ff bf fc ff ff bf-00 00 00 00 00 2f 62 69 |............./bi|
bffffff0  6e 2f 6c 73 00 2d 6c 00-66 6f 6f 00 62 61 72 00 |n/ls.-l.foo.bar.|
@end verbatim

@node System Call Details
@subsection System Call Details

The first task already dealt with one way that the operating system
can regain control from a user program: interrupts from timers and I/O
devices.  These are ``external'' interrupts, because they are caused
by entities outside the CPU (@pxref{External Interrupt Handling}).

The operating system also deals with software exceptions, which are
events that occur in program code (@pxref{Internal Interrupt
Handling}).  These can be errors such as a page fault or division by
zero.  Exceptions are also the means by which a user program
can request services (``system calls'') from the operating system.

In the 80@var{x}86 architecture, the @samp{int} instruction is the
most commonly used means for invoking system calls.  This instruction
is handled in the same way as other software exceptions.  In PintOS,
user programs invoke @samp{int $0x30} to make a system call.  The
system call number and any additional arguments are expected to be
pushed on the stack in the normal fashion before invoking the
interrupt (@pxref{80x86 Calling Convention}).

Thus, when the system call handler @func{syscall_handler} gets control,
the system call number is in the 32-bit word at the caller's stack
pointer, the first argument is in the 32-bit word at the next higher
address, and so on.  The caller's stack pointer is accessible to
@func{syscall_handler} as the @samp{esp} member of the
@struct{intr_frame} passed to it.  (@struct{intr_frame} is on the kernel
stack.)

The 80@var{x}86 convention for function return values is to place them
in the @code{EAX} register.  System calls that return a value can do
so by modifying the @samp{eax} member of @struct{intr_frame}.

You should try to avoid writing large amounts of repetitive code for
implementing system calls.  Each system call argument, whether an
integer or a pointer, takes up 4 bytes on the stack.  You should be able
to take advantage of this to avoid writing much near-identical code for
retrieving each system call's arguments from the stack.
