Wordsmithing.
[pintos-anon] / doc / reference.texi
index b51c44ecf657607dee5b217c793f90d7ea7ab53b..c25f3ddebd160d1eefc5574552b6f32f5a826d31 100644 (file)
@@ -52,9 +52,9 @@ sector) into memory.  This is a severe restriction and it means that,
 practically speaking, the loader has to be written in assembly
 language.
 
-Pintos' loader first initializes the CPU.  The first important part of
+The Pintos loader first initializes the CPU.  The first important part of
 this is to enable the A20 line, that is, the CPU's address line
-numbered 20.  For historical reasons, PCs start out with this address
+numbered 20.  For historical reasons, PCs boot with this address
 line fixed at 0, which means that attempts to access memory beyond the
 first 1 MB (2 raised to the 20th power) will fail.  Pintos wants to
 access more memory than this, so we have to enable it.
@@ -79,8 +79,8 @@ then we've just pulled the rug out from under ourselves.
 
 After the page table is initialized, we load the CPU's control
 registers to turn on protected mode and paging, and then we set up the
-segment registers.  We aren't equipped to handle interrupts in
-protected mode yet, so we disable interrupts.
+segment registers.  We aren't yet equipped to handle interrupts in
+protected mode, so we disable interrupts.
 
 Finally it's time to load the kernel from disk.  We use a simple but
 inflexible method to do this: we program the IDE disk
@@ -95,16 +95,17 @@ kernel starting 1 MB into physical memory.
 
 Then we jump to the start of the compiled kernel image.  Using the
 ``linker script'' in @file{threads/kernel.lds.S}, the kernel has
-arranged that it begins with the assembly module
+arranged to begin with the assembly module
 @file{threads/start.S}.  This assembly module just calls
 @func{main}, which never returns.
 
 There's one more trick: the Pintos kernel command line
-is stored in the boot loader.  The @command{pintos} program actually
-modifies the boot loader on disk each time it runs the kernel, putting
+is in stored the boot loader.  The @command{pintos} program actually
+modifies a copy of the boot loader on disk each time it runs the kernel,
+putting
 in whatever command line arguments the user supplies to the kernel,
 and then the kernel at boot time reads those arguments out of the boot
-loader in memory.  This is something of a nasty hack, but it is simple
+loader in memory.  This is not an elegant solution, but it is simple
 and effective.
 
 @node Kernel Initialization
@@ -115,7 +116,7 @@ The kernel proper starts with the @func{main} function.  The
 encounter in Pintos from here on out.
 
 When @func{main} starts, the system is in a pretty raw state.  We're
-in protected mode with paging enabled, but hardly anything else is
+in 32-bit protected mode with paging enabled, but hardly anything else is
 ready.  Thus, the @func{main} function consists primarily of calls
 into other Pintos modules' initialization functions.
 These are usually named @func{@var{module}_init}, where
@@ -141,35 +142,38 @@ called so early in initialization because the console, initialized
 just afterward, tries to use locks, and locks in turn require there to be a
 running thread.
 
-Then we initialize the console so that we can use @func{printf}.
+Then we initialize the console so that @func{printf} will work.
 @func{main} calls @func{vga_init}, which initializes the VGA text
 display and clears the screen.  It also calls @func{serial_init_poll}
 to initialize the first serial port in ``polling mode,'' that is,
 where the kernel busy-waits for the port to be ready for each
-character to be output.  (We use polling mode until we're ready to set
-up interrupts later.)  Finally we initialize the console device and
+character to be output.  (We use polling mode until we're ready to enable
+interrupts, later.)  Finally we initialize the console device and
 print a startup message to the console.
 
 @func{main} calls @func{read_command_line} to break the kernel command
 line into arguments, then @func{parse_options} to read any options at
-the beginning of the command line.  (Executing actions specified on the
-command line happens later.)
+the beginning of the command line.  (Actions specified on the
+command line execute later.)
+
+@func{main} calls @func{random_init} to initialize the kernel random
+number generator.  If the user specified @option{-rs} on the
+@command{pintos} command line, @func{parse_options} already did
+this, but calling it a second time is harmless.
 
 The next block of functions we call initialize the kernel's memory
 system.  @func{palloc_init} sets up the kernel page allocator, which
-doles out memory one or more pages at a time.  @func{malloc_init} sets
-up the allocator that handles odd-sized allocations.
-@func{paging_init} sets up a page table for the kernel.
+doles out memory one or more pages at a time (@pxref{Page Allocator}).
+@func{malloc_init} sets
+up the allocator that handles allocations of arbitrary-size blocks of
+memory (@pxref{Block Allocator}).
+@func{paging_init} sets up a page table for the kernel (@pxref{Page
+Table}).
 
 In projects 2 and later, @func{main} also calls @func{tss_init} and
-@func{gdt_init}, but we'll talk about those later.
-
-@func{main} calls @func{random_init} to initialize the kernel random
-number generator.  If the user specified @option{-rs} on the
-@command{pintos} command line, @func{parse_options} has already done
-this, but calling it a second time is harmless and has no effect.
+@func{gdt_init}.
 
-We initialize the interrupt system in the next set of calls.
+The next set of calls initializes the interrupt system.
 @func{intr_init} sets up the CPU's @dfn{interrupt descriptor table}
 (IDT) to ready it for interrupt handling (@pxref{Interrupt
 Infrastructure}), then @func{timer_init} and @func{kbd_init} prepare for
@@ -177,15 +181,16 @@ handling timer interrupts and keyboard interrupts, respectively.  In
 projects 2 and later, we also prepare to handle interrupts caused by
 user programs using @func{exception_init} and @func{syscall_init}.
 
-Now that interrupts are set up, we can start preemptively scheduling
-threads with @func{thread_start}, which also enables interrupts.
+Now that interrupts are set up, we can start the scheduler
+with @func{thread_start}, which creates the idle thread and enables
+interrupts.
 With interrupts enabled, interrupt-driven serial port I/O becomes
 possible, so we use
 @func{serial_init_queue} to switch to that mode.  Finally,
 @func{timer_calibrate} calibrates the timer for accurate short delays.
 
 If the file system is compiled in, as it will starting in project 2, we
-now initialize the disks with @func{disk_init}, then the
+initialize the disks with @func{disk_init}, then the
 file system with @func{filesys_init}.
 
 Boot is complete, so we print a message.
@@ -225,27 +230,27 @@ grows downward from the end of the page.  It looks like this:
 
 @example
 @group
-        4 kB +---------------------------------+
-             |          kernel stack           |
-             |                |                |
-             |                |                |
-             |                V                |
-             |         grows downward          |
-             |                                 |
-             |                                 |
-             |                                 |
-             |                                 |
-             |                                 |
-             |                                 |
-             |                                 |
-             |                                 |
-             +---------------------------------+
-             |              magic              |
-             |                :                |
-             |                :                |
-             |              status             |
-             |               tid               |
-        0 kB +---------------------------------+
+                  4 kB +---------------------------------+
+                       |          kernel stack           |
+                       |                |                |
+                       |                |                |
+                       |                V                |
+                       |         grows downward          |
+                       |                                 |
+                       |                                 |
+                       |                                 |
+                       |                                 |
+                       |                                 |
+                       |                                 |
+                       |                                 |
+                       |                                 |
+sizeof (struct thread) +---------------------------------+
+                       |              magic              |
+                       |                :                |
+                       |                :                |
+                       |              status             |
+                       |               tid               |
+                  0 kB +---------------------------------+
 @end group
 @end example
 
@@ -271,6 +276,7 @@ if you like.
 @end deftypecv
 
 @deftypecv {Member} {@struct{thread}} {enum thread_status} status
+@anchor{Thread States}
 The thread's state, one of the following:
 
 @defvr {Thread State} @code{THREAD_RUNNING}
@@ -289,7 +295,12 @@ invoked.  Ready threads are kept in a doubly linked list called
 The thread is waiting for something, e.g.@: a lock to become
 available, an interrupt to be invoked.  The thread won't be scheduled
 again until it transitions to the @code{THREAD_READY} state with a
-call to @func{thread_unblock}.
+call to @func{thread_unblock}.  This is most conveniently done
+indirectly, using one of the Pintos synchronization primitives that
+block and unblock threads automatically (@pxref{Synchronization}).
+
+There is no @i{a priori} way to tell what a blocked thread is waiting
+for, but a backtrace can help (@pxref{Backtraces}).
 @end defvr
 
 @defvr {Thread State} @code{THREAD_DYING}
@@ -327,23 +338,24 @@ priority scheduling in project 1 (@pxref{Priority Scheduling}).
 
 @deftypecv {Member} {@struct{thread}} {@struct{list_elem}} elem
 A ``list element'' used to put the thread into doubly linked lists,
-either the list of threads ready to run or a list of threads waiting
-on a semaphore.  Take a look at @file{lib/kernel/list.h} for
-information on how to use Pintos doubly linked lists.
+either @code{ready_list} (the list of threads ready to run) or a list of
+threads waiting on a semaphore in @func{sema_down}.  It can do double
+duty because a thread waiting on a semaphore is not ready, and vice
+versa.
 @end deftypecv
 
 @deftypecv {Member} {@struct{thread}} {uint32_t *} pagedir
-Only present in project 2 and later.
+Only present in project 2 and later.  @xref{Page Tables}.
 @end deftypecv
 
 @deftypecv {Member} {@struct{thread}} {unsigned} magic
-Always set to @code{THREAD_MAGIC}, which is just a random number defined
+Always set to @code{THREAD_MAGIC}, which is just an arbitrary number defined
 in @file{threads/thread.c}, and used to detect stack overflow.
 @func{thread_current} checks that the @code{magic} member of the running
 thread's @struct{thread} is set to @code{THREAD_MAGIC}.  Stack overflow
-will normally change this value, triggering the assertion.  For greatest
-benefit, as you add members to @struct{thread}, leave @code{magic} as
-the final member.
+tends to change this value, triggering the assertion.  For greatest
+benefit, as you add members to @struct{thread}, leave @code{magic} at
+the end.
 @end deftypecv
 
 @node Thread Functions
@@ -391,20 +403,21 @@ Creates and starts a new thread named @var{name} with the given
 
 @func{thread_create} allocates a page for the thread's
 @struct{thread} and stack and initializes its members, then it sets
-up a set of fake stack frames for it (more about this
-later).  The thread is initialized in the blocked state, so the final
-action before returning is to unblock it, which allows the new thread to
-be scheduled.
-@end deftypefun
+up a set of fake stack frames for it (@pxref{Thread Switching}).  The
+thread is initialized in the blocked state, then unblocked just before
+returning, which allows the new thread to
+be scheduled (@pxref{Thread States}).
 
 @deftp {Type} {void thread_func (void *@var{aux})}
-This is the type of a thread function.  Its @var{aux} argument is the
-value passed to @func{thread_create}.
+This is the type of the function passed to @func{thread_create}, whose
+@var{aux} argument is passed along as the function's argument.
 @end deftp
+@end deftypefun
 
 @deftypefun void thread_block (void)
 Transitions the running thread from the running state to the blocked
-state.  The thread will not run again until @func{thread_unblock} is
+state (@pxref{Thread States}).  The thread will not run again until
+@func{thread_unblock} is
 called on it, so you'd better have some way arranged for that to happen.
 Because @func{thread_block} is so low-level, you should prefer to use
 one of the synchronization primitives instead (@pxref{Synchronization}).
@@ -412,8 +425,9 @@ one of the synchronization primitives instead (@pxref{Synchronization}).
 
 @deftypefun void thread_unblock (struct thread *@var{thread})
 Transitions @var{thread}, which must be in the blocked state, to the
-ready state, allowing it to resume running.  This is called when the
-event that the thread is waiting for occurs, e.g.@: when the lock that
+ready state, allowing it to resume running (@pxref{Thread States}).
+This is called when the event that the thread is waiting for occurs,
+e.g.@: when the lock that 
 the thread is waiting on becomes available.
 @end deftypefun
 
@@ -445,20 +459,20 @@ time.
 
 @deftypefun int thread_get_priority (void)
 @deftypefunx void thread_set_priority (int @var{new_priority})
-Skeleton to set and get thread priority.  @xref{Priority Scheduling}.
+Stub to set and get thread priority.  @xref{Priority Scheduling}.
 @end deftypefun
 
 @deftypefun int thread_get_nice (void)
 @deftypefunx void thread_set_nice (int @var{new_nice})
 @deftypefunx int thread_get_recent_cpu (void)
 @deftypefunx int thread_get_load_avg (void)
-Skeletons for the advanced scheduler.  @xref{4.4BSD Scheduler}.
+Stubs for the advanced scheduler.  @xref{4.4BSD Scheduler}.
 @end deftypefun
 
 @node Thread Switching
 @subsection Thread Switching
 
-@func{schedule} is the function responsible for switching threads.  It
+@func{schedule} is responsible for switching threads.  It
 is internal to @file{threads/thread.c} and called only by the three
 public thread functions that need to switch threads:
 @func{thread_block}, @func{thread_exit}, and @func{thread_yield}.
@@ -466,7 +480,7 @@ Before any of these functions call @func{schedule}, they disable
 interrupts (or ensure that they are already disabled) and then change
 the running thread's state to something other than running.
 
-@func{schedule} is simple but tricky.  It records the
+@func{schedule} is short but tricky.  It records the
 current thread in local variable @var{cur}, determines the next thread
 to run as local variable @var{next} (by calling
 @func{next_thread_to_run}), and then calls @func{switch_threads} to do
@@ -481,7 +495,7 @@ CPU's current stack pointer in the current @struct{thread}'s @code{stack}
 member, restores the new thread's @code{stack} into the CPU's stack
 pointer, restores registers from the stack, and returns.
 
-The rest of the scheduler is implemented as @func{schedule_tail}.  It
+The rest of the scheduler is implemented in @func{schedule_tail}.  It
 marks the new thread as running.  If the thread we just switched from
 is in the dying state, then it also frees the page that contained the
 dying thread's @struct{thread} and stack.  These couldn't be freed
@@ -489,7 +503,7 @@ prior to the thread switch because the switch needed to use it.
 
 Running a thread for the first time is a special case.  When
 @func{thread_create} creates a new thread, it goes through a fair
-amount of trouble to get it started properly.  In particular, a new
+amount of trouble to get it started properly.  In particular, the new
 thread hasn't started running yet, so there's no way for it to be
 running inside @func{switch_threads} as the scheduler expects.  To
 solve the problem, @func{thread_create} creates some fake stack frames
@@ -1615,7 +1629,7 @@ defined in @file{threads/vaddr.h}.
 
 You do not need to understand the PTE format to do the Pintos
 projects, unless you wish to incorporate the page table into your
-segment table (@pxref{Managing the Segment Table}).
+supplemental page table (@pxref{Managing the Supplemental Page Table}).
 
 The actual format of a page table entry is summarized below.  For
 complete information, refer to section 3.7, ``Page Translation Using