Adjust wording of "static priority" comment.
[pintos-anon] / doc / threads.texi
index 04d48d1c0eff50c96f56ecdeeb338382f970da5f..1e379710c65c3d38f06a6e168b3fb6a6d5b80814 100644 (file)
@@ -15,9 +15,8 @@ Before you read the description of this project, you should read all
 of the following sections: @ref{Introduction}, @ref{Coding Standards},
 @ref{Project Documentation}, @ref{Debugging Tools}, and
 @ref{Development Tools}.  You should at least skim the material in
-@ref{Threads Tour}, but there's no need to fret over the details.  To
-complete this project you will also need to read @ref{Multilevel
-Feedback Scheduling}.
+@ref{Threads Tour}.  To complete this project you will also need to
+read @ref{Multilevel Feedback Scheduling}.
 
 @menu
 * Understanding Threads::       
@@ -74,15 +73,21 @@ thread we're switching to.
 Using the @command{gdb} debugger, slowly trace through a context
 switch to see what happens (@pxref{i386-elf-gdb}).  You can set a
 breakpoint on the @func{schedule} function to start out, and then
-single-step from there.  Be sure to keep track of each thread's
-address and state, and what procedures are on the call stack for each
-thread.  You will notice that when one thread calls
-@func{switch_threads}, another thread starts running, and the first
-thing the new thread does is to return from
-@func{switch_threads}.  We realize this comment will seem cryptic to
-you at this point, but you will understand threads once you understand
-why the @func{switch_threads} that gets called is different from the
-@func{switch_threads} that returns.
+single-step from there.@footnote{@command{gdb} might tell you that
+@func{schedule} doesn't exist, which is arguably a @command{gdb} bug.
+You can work around this by setting the breakpoint by filename and
+line number, e.g.@: @code{break thread.c:@var{ln}} where @var{ln} is
+the line number of the first declaration in @func{schedule}.
+Alternatively you can recompile with optimization turned off, by
+removing @samp{-O3} from the @code{CFLAGS} line in
+@file{Make.config}.}  Be sure to keep track of each thread's address
+and state, and what procedures are on the call stack for each thread.
+You will notice that when one thread calls @func{switch_threads},
+another thread starts running, and the first thing the new thread does
+is to return from @func{switch_threads}.  We realize this comment will
+seem cryptic to you at this point, but you will understand threads
+once you understand why the @func{switch_threads} that gets called is
+different from the @func{switch_threads} that returns.
 
 @strong{Warning}: In Pintos, each thread is assigned a small,
 fixed-size execution stack just under @w{4 kB} in size.  The kernel
@@ -131,7 +136,7 @@ gets initialized.
 @item thread.c
 @itemx thread.h
 Basic thread support.  Much of your work will take place in these
-files.  @file{thread.h} defines @code{struct thread}, which you will
+files.  @file{thread.h} defines @struct{thread}, which you will
 modify in the first three projects.
 
 @item switch.S
@@ -407,7 +412,7 @@ should implement @func{thread_join} to have the same restriction.
 That is, a thread may only join its immediate children.
 
 A thread need not ever be joined.  Your solution should properly free
-all of a thread's resources, including its @code{struct thread},
+all of a thread's resources, including its @struct{thread},
 whether it is ever joined or not, and regardless of whether the child
 exits before or after its parent.  That is, a thread should be freed
 exactly once in all cases.
@@ -442,9 +447,9 @@ Implement priority scheduling in Pintos.  Priority scheduling is a key
 building block for real-time systems.  Implement functions
 @func{thread_set_priority} to set the priority of the running thread
 and @func{thread_get_priority} to get the running thread's priority.
-(A thread can examine and modify only its own priority.)  There are
-already prototypes for these functions in @file{threads/thread.h},
-which you should not change.
+(This API only allows a thread to examine and modify its own
+priority.)  There are already prototypes for these functions in
+@file{threads/thread.h}, which you should not change.
 
 Thread priority ranges from @code{PRI_MIN} (0) to @code{PRI_MAX} (59).
 The initial thread priority is passed as an argument to
@@ -457,9 +462,8 @@ When a thread is added to the ready list that has a higher priority
 than the currently running thread, the current thread should
 immediately yield the processor to the new thread.  Similarly, when
 threads are waiting for a lock, semaphore or condition variable, the
-highest priority waiting thread should be woken up first.  A thread's
-priority may be set at any time, including while the thread is waiting
-on a lock, semaphore, or condition variable.
+highest priority waiting thread should be woken up first.  A thread
+may set its priority at any time.
 
 One issue with priority scheduling is ``priority inversion'': if a
 high priority thread needs to wait for a low priority thread (for
@@ -486,6 +490,10 @@ for a lock held by a lower-priority thread.  You do not need to
 implement this fix for semaphores, condition variables or joins.
 However, you do need to implement priority scheduling in all cases.
 
+You may assume a static priority for priority donation, that is, it is
+not necessary to ``re-donate'' a thread's priority if it changes
+(although you are free to do so).
+
 @node Problem 1-4 Advanced Scheduler
 @section Problem 1-4: Advanced Scheduler
 
@@ -499,10 +507,6 @@ relative to the original Pintos scheduling algorithm (round robin) for
 at least one workload of your own design (i.e.@: in addition to the
 provided test).
 
-You may assume a static priority for this problem. It is not necessary
-to ``re-donate'' a thread's priority if it changes (although you are
-free to do so).
-
 You must write your code so that we can turn the MLFQS on and off at
 compile time.  By default, it must be off, but we must be able to turn
 it on by inserting the line @code{#define MLFQS 1} in
@@ -642,6 +646,34 @@ integers? Do I need to check for that?}
 Don't worry about the possibility of timer values overflowing.  Timer
 values are expressed as signed 63-bit numbers, which at 100 ticks per
 second should be good for almost 2,924,712,087 years.
+
+@item
+@b{The test program mostly works but reports a few out-of-order
+wake ups.  I think it's a problem in the test program.  What gives?}
+
+This test is inherently full of race conditions.  On a real system it
+wouldn't work perfectly all the time either.  However, you can help it
+work more reliably:
+
+@itemize @bullet
+@item
+Make time slices longer by increasing @code{TIME_SLICE} in
+@file{timer.c} to a large value, such as 100.
+
+@item
+Make the timer tick more slowly by decreasing @code{TIMER_FREQ} in
+@file{timer.h} to its minimum value of 19.
+
+@item
+Increase the serial output speed to the maximum of 115,200 bps by
+modifying the call to @func{set_serial} in @func{serial_init_poll} in
+@file{devices/serial.c}.
+@end itemize
+
+The former two changes are only desirable for testing problem 1-1.  You
+should revert them before working on other parts of the project or turn
+in the project.  The latter is harmless, so you can retain it or revert
+it at your option.
 @end enumerate
 
 @node Problem 1-2 Join FAQ