X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=doc%2Fthreads.texi;h=e5b087ba349a69f9d5e7f4b02a9fe463033ab878;hb=a8712a8c90c4c47380fc3380a2368b19d8370b3e;hp=04d48d1c0eff50c96f56ecdeeb338382f970da5f;hpb=36088b8cdcd561b472b60ae5e9cf7a5fde9132b9;p=pintos-anon diff --git a/doc/threads.texi b/doc/threads.texi index 04d48d1..e5b087b 100644 --- a/doc/threads.texi +++ b/doc/threads.texi @@ -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 @@ -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