Add some clarifications to address question from "Kevin Hart"
[pintos-anon] / doc / threads.texi
1 @node Project 1--Threads, Project 2--User Programs, Pintos Tour, Top
2 @chapter Project 1: Threads
3
4 In this assignment, we give you a minimally functional thread system.
5 Your job is to extend the functionality of this system to gain a
6 better understanding of synchronization problems.
7
8 You will be working primarily in the @file{threads} directory for
9 this assignment, with some work in the @file{devices} directory on the
10 side.  Compilation should be done in the @file{threads} directory.
11
12 Before you read the description of this project, you should read all of
13 the following sections: @ref{Introduction}, @ref{Coding Standards},
14 @ref{Debugging Tools}, and @ref{Development Tools}.  You should at least
15 skim the material in @ref{Threads Tour} and especially
16 @ref{Synchronization}.  To complete this project you will also need to
17 read @ref{4.4BSD Scheduler}.
18
19 @menu
20 * Project 1 Background::        
21 * Project 1 Requirements::      
22 * Project 1 FAQ::               
23 @end menu
24
25 @node Project 1 Background
26 @section Background
27
28
29 @menu
30 * Understanding Threads::       
31 * Project 1 Source Files::      
32 * Project 1 Synchronization::   
33 * Development Suggestions::     
34 @end menu
35
36 @node Understanding Threads
37 @subsection Understanding Threads
38
39 The first step is to read and understand the code for the initial thread
40 system.
41 Pintos already implements thread creation and thread completion,
42 a simple scheduler to switch between threads, and synchronization
43 primitives (semaphores, locks, condition variables, and memory
44 barriers).
45
46 Some of this code might seem slightly mysterious.  If
47 you haven't already compiled and run the base system, as described in
48 the introduction (@pxref{Introduction}), you should do so now.  You
49 can read through parts of the source code to see what's going
50 on.  If you like, you can add calls to @func{printf} almost
51 anywhere, then recompile and run to see what happens and in what
52 order.  You can also run the kernel in a debugger and set breakpoints
53 at interesting spots, single-step through code and examine data, and
54 so on.
55
56 When a thread is created, you are creating a new context to be
57 scheduled.  You provide a function to be run in this context as an
58 argument to @func{thread_create}.  The first time the thread is
59 scheduled and runs, it starts from the beginning of that function
60 and executes in that context.  When the function returns, the thread
61 terminates.  Each thread, therefore, acts like a mini-program running
62 inside Pintos, with the function passed to @func{thread_create}
63 acting like @func{main}.
64
65 At any given time, exactly one thread runs and the rest, if any,
66 become inactive.  The scheduler decides which thread to
67 run next.  (If no thread is ready to run
68 at any given time, then the special ``idle'' thread, implemented in
69 @func{idle}, runs.)
70 Synchronization primitives can force context switches when one
71 thread needs to wait for another thread to do something.
72
73 The mechanics of a context switch are
74 in @file{threads/switch.S}, which is 80@var{x}86
75 assembly code.  (You don't have to understand it.)  It saves the
76 state of the currently running thread and restores the state of the
77 thread we're switching to.
78
79 Using the @command{gdb} debugger, slowly trace through a context
80 switch to see what happens (@pxref{gdb}).  You can set a
81 breakpoint on @func{schedule} to start out, and then
82 single-step from there.@footnote{@command{gdb} might tell you that
83 @func{schedule} doesn't exist, which is arguably a @command{gdb} bug.
84 You can work around this by setting the breakpoint by filename and
85 line number, e.g.@: @code{break thread.c:@var{ln}} where @var{ln} is
86 the line number of the first declaration in @func{schedule}.}  Be sure
87 to keep track of each thread's address
88 and state, and what procedures are on the call stack for each thread.
89 You will notice that when one thread calls @func{switch_threads},
90 another thread starts running, and the first thing the new thread does
91 is to return from @func{switch_threads}.  You will understand the thread
92 system once you understand why and how the @func{switch_threads} that
93 gets called is different from the @func{switch_threads} that returns.
94 @xref{Thread Switching}, for more information.
95
96 @strong{Warning}: In Pintos, each thread is assigned a small,
97 fixed-size execution stack just under @w{4 kB} in size.  The kernel
98 tries to detect stack overflow, but it cannot do so perfectly.  You
99 may cause bizarre problems, such as mysterious kernel panics, if you
100 declare large data structures as non-static local variables,
101 e.g. @samp{int buf[1000];}.  Alternatives to stack allocation include
102 the page allocator and the block allocator (@pxref{Memory Allocation}).
103
104 @node Project 1 Source Files
105 @subsection Source Files
106
107 Here is a brief overview of the files in the @file{threads}
108 directory.  You will not need to modify most of this code, but the
109 hope is that presenting this overview will give you a start on what
110 code to look at.
111
112 @table @file
113 @item loader.S
114 @itemx loader.h
115 The kernel loader.  Assembles to 512 bytes of code and data that the
116 PC BIOS loads into memory and which in turn loads the kernel into
117 memory, does basic processor initialization, and jumps to the
118 beginning of the kernel.  @xref{Pintos Loader}, for details. You should
119 not need to look at this code or modify it.
120
121 @item kernel.lds.S
122 The linker script used to link the kernel.  Sets the load address of
123 the kernel and arranges for @file{start.S} to be at the very beginning
124 of the kernel image.  @xref{Pintos Loader}, for details. Again, you
125 should not need to look at this code
126 or modify it, but it's here in case you're curious.
127
128 @item start.S
129 Jumps to @func{main}.
130
131 @item init.c
132 @itemx init.h
133 Kernel initialization, including @func{main}, the kernel's ``main
134 program.''  You should look over @func{main} at least to see what
135 gets initialized.  You might want to add your own initialization code
136 here.  @xref{Kernel Initialization}, for details.
137
138 @item thread.c
139 @itemx thread.h
140 Basic thread support.  Much of your work will take place in these
141 files.  @file{thread.h} defines @struct{thread}, which you are likely
142 to modify in all four projects.  See @ref{struct thread} and @ref{Thread
143 Support} for more information.
144
145 @item switch.S
146 @itemx switch.h
147 Assembly language routine for switching threads.  Already discussed
148 above.  @xref{Thread Functions}, for more information.
149
150 @item palloc.c
151 @itemx palloc.h
152 Page allocator, which hands out system memory in multiples of 4 kB
153 pages.  @xref{Page Allocator}, for more information.
154
155 @item malloc.c
156 @itemx malloc.h
157 A simple implementation of @func{malloc} and @func{free} for
158 the kernel.  @xref{Block Allocator}, for more information.
159
160 @item interrupt.c
161 @itemx interrupt.h
162 Basic interrupt handling and functions for turning interrupts on and
163 off.  @xref{Interrupt Handling}, for more information.
164
165 @item intr-stubs.S
166 @itemx intr-stubs.h
167 Assembly code for low-level interrupt handling.  @xref{Interrupt
168 Infrastructure}, for more information.
169
170 @item synch.c
171 @itemx synch.h
172 Basic synchronization primitives: semaphores, locks, condition
173 variables, and memory barriers.  You will need to use these for
174 synchronization in all
175 four projects.  @xref{Synchronization}, for more information.
176
177 @item io.h
178 Functions for I/O port access.  This is mostly used by source code in
179 the @file{devices} directory that you won't have to touch.
180
181 @item mmu.h
182 Functions and macros related to memory management, including page
183 directories and page tables.  This will be more important to you in
184 project 3.  For now, you can ignore it.
185
186 @item flags.h
187 Macros that define a few bits in the 80@var{x}86 ``flags'' register.
188 Probably of no interest.  See @bibref{IA32-v1}, section 3.4.3, for more
189 information.
190 @end table
191
192 @menu
193 * devices code::                
194 * lib files::                   
195 @end menu
196
197 @node devices code
198 @subsubsection @file{devices} code
199
200 The basic threaded kernel also includes these files in the
201 @file{devices} directory:
202
203 @table @file
204 @item timer.c
205 @itemx timer.h
206 System timer that ticks, by default, 100 times per second.  You will
207 modify this code in this project.
208
209 @item vga.c
210 @itemx vga.h
211 VGA display driver.  Responsible for writing text to the screen.
212 You should have no need to look at this code.  @func{printf}
213 calls into the VGA display driver for you, so there's little reason to
214 call this code yourself.
215
216 @item serial.c
217 @itemx serial.h
218 Serial port driver.  Again, @func{printf} calls this code for you,
219 so you don't need to do so yourself.  Feel free to look through it if
220 you're curious.
221
222 @item disk.c
223 @itemx disk.h
224 Supports reading and writing sectors on up to 4 IDE disks.  This won't
225 actually be used until project 2.
226
227 @item intq.c
228 @itemx intq.h
229 Interrupt queue, for managing a circular queue that both kernel
230 threads and interrupt handlers want to access.  Used by the keyboard
231 and serial drivers.
232 @end table
233
234 @node lib files
235 @subsubsection @file{lib} files
236
237 Finally, @file{lib} and @file{lib/kernel} contain useful library
238 routines.  (@file{lib/user} will be used by user programs, starting in
239 project 2, but it is not part of the kernel.)  Here's a few more
240 details:
241
242 @table @file
243 @item ctype.h
244 @itemx inttypes.h
245 @itemx limits.h
246 @itemx stdarg.h
247 @itemx stdbool.h
248 @itemx stddef.h
249 @itemx stdint.h
250 @itemx stdio.c
251 @itemx stdio.h
252 @itemx stdlib.c
253 @itemx stdlib.h
254 @itemx string.c
255 @itemx string.h
256 A subset of the standard C library.  @xref{C99}, for
257 information
258 on a few recently introduced pieces of the C library that you might
259 not have encountered before.  @xref{Unsafe String Functions}, for
260 information on what's been intentionally left out for safety.
261
262 @item debug.c
263 @itemx debug.h
264 Functions and macros to aid debugging.  @xref{Debugging Tools}, for
265 more information.
266
267 @item random.c
268 @itemx random.h
269 Pseudo-random number generator.
270
271 @item round.h
272 Macros for rounding.
273
274 @item syscall-nr.h
275 System call numbers.  Not used until project 2.
276
277 @item kernel/list.c
278 @itemx kernel/list.h
279 Doubly linked list implementation.  Used all over the Pintos code, and
280 you'll probably want to use it a few places yourself in project 1.
281
282 @item kernel/bitmap.c
283 @itemx kernel/bitmap.h
284 Bitmap implementation.  You can use this in your code if you like, but
285 you probably won't have any need for it in project 1.
286
287 @item kernel/hash.c
288 @itemx kernel/hash.h
289 Hash table implementation.  Likely to come in handy for project 3.
290
291 @item kernel/console.c
292 @itemx kernel/console.h
293 @item kernel/stdio.h
294 Implements @func{printf} and a few other functions.
295 @end table
296
297 @node Project 1 Synchronization
298 @subsection Synchronization
299
300 Proper synchronization is an important part of the solutions to these
301 problems.  Any synchronization problem can be easily solved by turning
302 interrupts off: while interrupts are off, there is no concurrency, so
303 there's no possibility for race conditions.  Therefore, it's tempting to
304 solve all synchronization problems this way, but @strong{don't}.
305 Instead, use semaphores, locks, and condition variables to solve the
306 bulk of your synchronization problems.  Read the tour section on
307 synchronization (@pxref{Synchronization}) or the comments in
308 @file{threads/synch.c} if you're unsure what synchronization primitives
309 may be used in what situations.
310
311 In the Pintos projects, the only class of problem best solved by
312 disabling interrupts is coordinating data shared between a kernel thread
313 and an interrupt handler.  Because interrupt handlers can't sleep, they
314 can't acquire locks.  This means that data shared between kernel threads
315 and an interrupt handler must be protected within a kernel thread by
316 turning off interrupts.
317
318 This project only requires accessing a little bit of thread state from
319 interrupt handlers.  For the alarm clock, the timer interrupt needs to
320 wake up sleeping threads.  In the advanced scheduler, the timer
321 interrupt needs to access a few global and per-thread variables.  When
322 you access these variables from kernel threads, you will need to disable
323 interrupts to prevent the timer interrupt from interfering.
324
325 When you do turn off interrupts, take care to do so for the least amount
326 of code possible, or you can end up losing important things such as
327 timer ticks or input events.  Turning off interrupts also increases the
328 interrupt handling latency, which can make a machine feel sluggish if
329 taken too far.
330
331 Disabling interrupts can be useful for debugging, if you want to make
332 sure that a section of code is not interrupted.  You should remove
333 debugging code before turning in your project.
334
335 There should be no busy waiting in your submission.  A tight loop that
336 calls @func{thread_yield} is one form of busy waiting.
337
338 @node Development Suggestions
339 @subsection Development Suggestions
340
341 In the past, many groups divided the assignment into pieces, then each
342 group member worked on his or her piece until just before the
343 deadline, at which time the group reconvened to combine their code and
344 submit.  @strong{This is a bad idea.  We do not recommend this
345 approach.}  Groups that do this often find that two changes conflict
346 with each other, requiring lots of last-minute debugging.  Some groups
347 who have done this have turned in code that did not even compile or
348 boot, much less pass any tests.
349
350 Instead, we recommend integrating your team's changes early and often,
351 using a source code control system such as CVS (@pxref{CVS}) or a
352 group collaboration site such as SourceForge (@pxref{SourceForge}).
353 This is less likely to produce surprises, because everyone can see
354 everyone else's code as it is written, instead of just when it is
355 finished.  These systems also make it possible to review changes and,
356 when a change introduces a bug, drop back to working versions of code.
357
358 You should expect to run into bugs that you simply don't understand
359 while working on this and subsequent projects.  When you do,
360 reread the appendix on debugging tools, which is filled with
361 useful debugging tips that should help you to get back up to speed
362 (@pxref{Debugging Tools}).  Be sure to read the section on backtraces
363 (@pxref{Backtraces}), which will help you to get the most out of every
364 kernel panic or assertion failure.
365
366 @node Project 1 Requirements
367 @section Requirements
368
369 @menu
370 * Project 1 Design Document::   
371 * Alarm Clock::                 
372 * Priority Scheduling::         
373 * Advanced Scheduler::          
374 @end menu
375
376 @node Project 1 Design Document
377 @subsection Design Document
378
379 Before you turn in your project, you must copy @uref{threads.tmpl, , the
380 project 1 design document template} into your source tree under the name
381 @file{pintos/src/threads/DESIGNDOC} and fill it in.  We recommend that
382 you read the design document template before you start working on the
383 project.  @xref{Project Documentation}, for a sample design document
384 that goes along with a fictitious project.
385
386 @node Alarm Clock
387 @subsection Alarm Clock
388
389 Reimplement @func{timer_sleep}, defined in @file{devices/timer.c}.
390 Although a working implementation is provided, it ``busy waits,'' that
391 is, it spins in a loop checking the current time and calling
392 @func{thread_yield} until enough time has gone by.  Reimplement it to
393 avoid busy waiting.
394
395 @deftypefun void timer_sleep (int64_t @var{ticks})
396 Suspends execution of the calling thread until time has advanced by at
397 least @w{@var{x} timer ticks}.  Unless the system is otherwise idle, the
398 thread need not wake up after exactly @var{x} ticks.  Just put it on
399 the ready queue after they have waited for the right amount of time.
400
401 @func{timer_sleep} is useful for threads that operate in real-time,
402 e.g.@: for blinking the cursor once per second.
403
404 The argument to @func{timer_sleep} is expressed in timer ticks, not in
405 milliseconds or any another unit.  There are @code{TIMER_FREQ} timer
406 ticks per second, where @code{TIMER_FREQ} is a macro defined in
407 @code{devices/timer.h}.  The default value is 100.  We don't recommend
408 changing this value, because any change is likely to cause many of
409 the tests to fail.
410 @end deftypefun
411
412 Separate functions @func{timer_msleep}, @func{timer_usleep}, and
413 @func{timer_nsleep} do exist for sleeping a specific number of
414 milliseconds, microseconds, or nanoseconds, respectively, but these will
415 call @func{timer_sleep} automatically when necessary.  You do not need
416 to modify them.
417
418 If your delays seem too short or too long, reread the explanation of the
419 @option{-r} option to @command{pintos} (@pxref{Debugging versus
420 Testing}).
421
422 The alarm clock implementation is not needed for later projects,
423 although it could be useful for project 4.
424
425 @node Priority Scheduling
426 @subsection Priority Scheduling
427
428 Implement priority scheduling in Pintos.
429 When a thread is added to the ready list that has a higher priority
430 than the currently running thread, the current thread should
431 immediately yield the processor to the new thread.  Similarly, when
432 threads are waiting for a lock, semaphore, or condition variable, the
433 highest priority waiting thread should be woken up first.  A thread
434 may raise or lower its own priority at any time, but lowering its
435 priority such that it no longer has the highest priority must cause it
436 to immediately yield the CPU.
437
438 Thread priorities range from @code{PRI_MIN} (0) to @code{PRI_MAX} (63).
439 Lower numbers correspond to @emph{higher} priorities, so that priority 0
440 is the highest priority and priority 63 is the lowest.
441 The initial thread priority is passed as an argument to
442 @func{thread_create}.  If there's no reason to choose another
443 priority, use @code{PRI_DEFAULT} (31).  The @code{PRI_} macros are
444 defined in @file{threads/thread.h}, and you should not change their
445 values.
446
447 One issue with priority scheduling is ``priority inversion''.  Consider
448 high, medium, and low priority threads @var{H}, @var{M}, and @var{L},
449 respectively.  If @var{H} needs to wait for @var{L} (for instance, for a
450 lock held by @var{L}), and @var{M} is on the ready list, then @var{H}
451 will never get the CPU because the low priority thread will not get any
452 CPU time.  A partial fix for this problem is for @var{H} to ``donate''
453 its priority to @var{L} while @var{L} is holding the lock, then recall
454 the donation once @var{L} releases (and thus @var{H} acquires) the lock.
455
456 Implement priority donation.  You will need to account for all different
457 situations in which priority donation is required.  Be sure to handle
458 multiple donations, in which multiple priorities are donated to a single
459 thread.  You must also handle nested donation: if @var{H} is waiting on
460 a lock that @var{M} holds and @var{M} is waiting on a lock that @var{L}
461 holds, then both @var{M} and @var{L} should be boosted to @var{H}'s
462 priority.
463
464 You must implement priority donation for locks.  You need not
465 implement priority donation for semaphores or condition variables
466 (but you are welcome to do so).  You do need to implement
467 priority scheduling in all cases.
468
469 Finally, implement the following functions that allow a thread to
470 examine and modify its own priority.  Skeletons for these functions are
471 provided in @file{threads/thread.c}.
472
473 @deftypefun void thread_set_priority (int @var{new_priority})
474 Sets the current thread's priority to @var{new_priority}.  If the
475 current thread no longer has the highest priority, yields.
476 @end deftypefun
477
478 @deftypefun int thread_get_priority (void)
479 Returns the current thread's priority.  In the presence of priority
480 donation, returns the higher (donated) priority.
481 @end deftypefun
482
483 You need not provide any interface to allow a thread to directly modify
484 other threads' priorities.
485
486 The priority scheduler is not used in any later project.
487
488 @node Advanced Scheduler
489 @subsection Advanced Scheduler
490
491 Implement a multilevel feedback queue scheduler similar to the
492 4.4@acronym{BSD} scheduler to
493 reduce the average response time for running jobs on your system.
494 @xref{4.4BSD Scheduler}, for a detailed description of
495 the MLFQS requirements.
496
497 The advanced scheduler builds on the priority scheduler.  You should
498 have the priority scheduler working, except possibly for priority
499 donation, before you start work on the advanced scheduler.
500
501 You must write your code so that we can choose a scheduling algorithm
502 policy at Pintos startup time.  By default, the round-robin scheduler
503 must be active, but we must be able to choose the 4.4@acronym{BSD}
504 scheduler
505 with the @option{-mlfqs} kernel option.  Passing this
506 option sets @code{enable_mlfqs}, declared in @file{threads/init.h}, to
507 true.
508
509 When the 4.4@acronym{BSD} scheduler is enabled, threads no longer
510 directly control their own priorities.  The @var{priority} argument to
511 @func{thread_create} should be ignored, as well as any calls to
512 @func{thread_set_priority}, and @func{thread_get_priority} should return
513 the thread's current priority as set by the scheduler.
514
515 The advanced scheduler is not used in any later project.
516
517 @node Project 1 FAQ
518 @section FAQ
519
520 @table @b
521 @item How much code will I need to write?
522
523 Here's a summary of our reference solution, produced by the
524 @command{diffstat} program.  The final row gives total lines inserted
525 and deleted; a changed line counts as both an insertion and a deletion.
526
527 @verbatim
528  devices/timer.c       |   42 +++++-
529  threads/fixed-point.h |  120 ++++++++++++++++++
530  threads/synch.c       |   88 ++++++++++++-
531  threads/thread.c      |  196 ++++++++++++++++++++++++++----
532  threads/thread.h      |   23 +++
533  5 files changed, 440 insertions(+), 29 deletions(-)
534 @end verbatim
535
536 @item How do I update the @file{Makefile}s when I add a new source file?
537
538 @anchor{Adding Source Files}
539 To add a @file{.c} file, edit the top-level @file{Makefile.build}.
540 Add the new file to variable @samp{@var{dir}_SRC}, where
541 @var{dir} is the directory where you added the file.  For this
542 project, that means you should add it to @code{threads_SRC} or
543 @code{devices_SRC}.  Then run @code{make}.  If your new file
544 doesn't get
545 compiled, run @code{make clean} and then try again.
546
547 When you modify the top-level @file{Makefile.build} and re-run
548 @command{make}, the modified
549 version should be automatically copied to
550 @file{threads/build/Makefile}.  The converse is
551 not true, so any changes will be lost the next time you run @code{make
552 clean} from the @file{threads} directory.  Unless your changes are
553 truly temporary, you should prefer to edit @file{Makefile.build}.
554
555 A new @file{.h} file does not require editing the @file{Makefile}s.
556
557 @item What does @code{warning: no previous prototype for `@var{func}'} mean?
558
559 It means that you defined a non-@code{static} function without
560 preceding it by a prototype.  Because non-@code{static} functions are
561 intended for use by other @file{.c} files, for safety they should be
562 prototyped in a header file included before their definition.  To fix
563 the problem, add a prototype in a header file that you include, or, if
564 the function isn't actually used by other @file{.c} files, make it
565 @code{static}.
566
567 @item What is the interval between timer interrupts?
568
569 Timer interrupts occur @code{TIMER_FREQ} times per second.  You can
570 adjust this value by editing @file{devices/timer.h}.  The default is
571 100 Hz.
572
573 We don't recommend changing this value, because any changes are likely
574 to cause many of the tests to fail.
575
576 @item How long is a time slice?
577
578 There are @code{TIME_SLICE} ticks per time slice.  This macro is
579 declared in @file{threads/thread.c}.  The default is 4 ticks.
580
581 We don't recommend changing this values, because any changes are likely
582 to cause many of the tests to fail.
583 @end table
584
585 @menu
586 * Alarm Clock FAQ::             
587 * Priority Scheduling FAQ::     
588 * Advanced Scheduler FAQ::      
589 @end menu
590
591 @node Alarm Clock FAQ
592 @subsection Alarm Clock FAQ
593
594 @table @b
595 @item Do I need to account for timer values overflowing?
596
597 Don't worry about the possibility of timer values overflowing.  Timer
598 values are expressed as signed 64-bit numbers, which at 100 ticks per
599 second should be good for almost 2,924,712,087 years.  By then, we
600 expect Pintos to have been phased out of the CS 140 curriculum.
601 @end table
602
603 @node Priority Scheduling FAQ
604 @subsection Priority Scheduling FAQ
605
606 @table @b
607 @item Doesn't priority scheduling lead to starvation?
608
609 Yes, strict priority scheduling can lead to starvation
610 because a thread will not run if any higher-priority thread is runnable.
611 The advanced scheduler introduces a mechanism for dynamically
612 changing thread priorities.
613
614 Strict priority scheduling is valuable in real-time systems because it
615 offers the programmer more control over which jobs get processing
616 time.  High priorities are generally reserved for time-critical
617 tasks. It's not ``fair,'' but it addresses other concerns not
618 applicable to a general-purpose operating system.
619
620 @item What thread should run after a lock has been released?
621
622 When a lock is released, the highest priority thread waiting for that
623 lock should be unblocked and put on the list of ready threads.  The
624 scheduler should then run the highest priority thread on the ready
625 list.
626
627 @item If the highest-priority thread yields, does it continue running?
628
629 Yes.  As long as there is a single highest-priority thread, it continues
630 running until it blocks or finishes, even if it calls
631 @func{thread_yield}.
632 If multiple threads have the same highest priority,
633 @func{thread_yield} should switch among them in ``round robin'' order.
634
635 @item What happens to the priority of a donating thread?
636
637 Priority donation only changes the priority of the donee
638 thread.  The donor thread's priority is unchanged.  
639 Priority donation is not additive: if thread @var{A} (with priority 5) donates
640 to thread @var{B} (with priority 3), then @var{B}'s new priority is 5, not 8.
641
642 @item Can a thread's priority change while it is on the ready queue?
643
644 Yes.  Consider this case: low-priority thread @var{L} holds a
645 lock that high-priority thread @var{H} wants, so @var{H} donates its
646 priority to @var{L}.  @var{L} releases the lock and
647 thus loses the CPU and is moved to the ready queue.  Now @var{L}'s
648 old priority is restored while it is in the ready queue.
649
650 @item Can a thread added to the ready list preempt the processor?
651
652 Yes.  If a thread added to the ready list has higher priority than the
653 running thread, the correct behavior is to immediately yield the
654 processor.  It is not acceptable to wait for the next timer interrupt.
655 The highest priority thread should run as soon as it is runnable,
656 preempting whatever thread is currently running.
657
658 @item How does @func{thread_set_priority} affect a thread receiving donations?
659
660 It should do something sensible, but no particular behavior is
661 required.  None of the test cases call @func{thread_set_priority} from a
662 thread while it is receiving a priority donation.
663
664 @item Calling @func{printf} in @func{sema_up} or @func{sema_down} reboots!
665
666 @anchor{printf Reboots}
667 Yes.  These functions are called before @func{printf} is ready to go.
668 You could add a global flag initialized to false and set it to true
669 just before the first @func{printf} in @func{main}.  Then modify
670 @func{printf} itself to return immediately if the flag isn't set.
671 @end table
672
673 @node Advanced Scheduler FAQ
674 @subsection Advanced Scheduler FAQ
675
676 @table @b
677 @item How does priority donation interact with the advanced scheduler?
678
679 It doesn't have to.  We won't test priority donation and the advanced
680 scheduler at the same time.
681 @end table