Use runtime options instead of conditional compilation for MLFQS,
[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. Additionally, you
7 will use at least part of this increased functionality in future
8 assignments.
9
10 You will be working in primarily in the @file{threads} directory for
11 this assignment, with some work in the @file{devices} directory on the
12 side.  Compilation should be done in the @file{threads} directory.
13
14 Before you read the description of this project, you should read all
15 of the following sections: @ref{Introduction}, @ref{Coding Standards},
16 @ref{Project Documentation}, @ref{Debugging Tools}, and
17 @ref{Development Tools}.  You should at least skim the material in
18 @ref{Threads Tour}.  To complete this project you will also need to
19 read @ref{Multilevel Feedback Scheduling}.
20
21 @menu
22 * Understanding Threads::       
23 * Project 1 Code::              
24 * Debugging versus Testing::    
25 * Tips::                        
26 * Problem 1-1 Alarm Clock::     
27 * Problem 1-2 Priority Scheduling::  
28 * Problem 1-3 Advanced Scheduler::  
29 * Threads FAQ::                 
30 @end menu
31
32 @node Understanding Threads
33 @section Understanding Threads
34
35 The first step is to read and understand the initial thread system.
36 Pintos, by default, implements thread creation and thread completion,
37 a simple scheduler to switch between threads, and synchronization
38 primitives (semaphores, locks, and condition variables). 
39
40 However, there's a lot of magic going on in some of this code, so if
41 you haven't already compiled and run the base system, as described in
42 the introduction (@pxref{Introduction}), you should do so now.  You
43 can read through parts of the source code by hand to see what's going
44 on.  If you like, you can add calls to @func{printf} almost
45 anywhere, then recompile and run to see what happens and in what
46 order.  You can also run the kernel in a debugger and set breakpoints
47 at interesting spots, single-step through code and examine data, and
48 so on.  @xref{i386-elf-gdb}, for more information.
49
50 When a thread is created, you are creating a new context to be
51 scheduled. You provide a function to be run in this context as an
52 argument to @func{thread_create}. The first time the thread is
53 scheduled and runs, it will start from the beginning of that function
54 and execute it in the context. When that function returns, that thread
55 completes. Each thread, therefore, acts like a mini-program running
56 inside Pintos, with the function passed to @func{thread_create}
57 acting like @func{main}.
58
59 At any given time, Pintos is running exactly one thread, with the
60 others switched out.  The scheduler decides which thread to run next
61 when it needs to switch between them.  (If no thread is ready to run
62 at any given time, then the special ``idle'' thread runs.)  The
63 synchronization primitives are used to force context switches when one
64 thread needs to wait for another thread to do something.
65
66 The exact mechanics of a context switch are pretty gruesome and have
67 been provided for you in @file{threads/switch.S} (this is 80@var{x}86
68 assembly; don't worry about understanding it).  It involves saving the
69 state of the currently running thread and restoring the state of the
70 thread we're switching to.
71
72 Using the @command{gdb} debugger, slowly trace through a context
73 switch to see what happens (@pxref{i386-elf-gdb}).  You can set a
74 breakpoint on the @func{schedule} function to start out, and then
75 single-step from there.@footnote{@command{gdb} might tell you that
76 @func{schedule} doesn't exist, which is arguably a @command{gdb} bug.
77 You can work around this by setting the breakpoint by filename and
78 line number, e.g.@: @code{break thread.c:@var{ln}} where @var{ln} is
79 the line number of the first declaration in @func{schedule}.}  Be sure
80 to keep track of each thread's address
81 and state, and what procedures are on the call stack for each thread.
82 You will notice that when one thread calls @func{switch_threads},
83 another thread starts running, and the first thing the new thread does
84 is to return from @func{switch_threads}.  We realize this comment will
85 seem cryptic to you at this point, but you will understand threads
86 once you understand why the @func{switch_threads} that gets called is
87 different from the @func{switch_threads} that returns.
88
89 @strong{Warning}: In Pintos, each thread is assigned a small,
90 fixed-size execution stack just under @w{4 kB} in size.  The kernel
91 does try to detect stack overflow, but it cannot always succeed.  You
92 may cause bizarre problems, such as mysterious kernel panics, if you
93 declare large data structures as non-static local variables,
94 e.g. @samp{int buf[1000];}.  Alternatives to stack allocation include
95 the page allocator in @file{threads/palloc.c} and the block allocator
96 in @file{threads/malloc.c}.  Note that the page allocator doles out
97 @w{4 kB} chunks and that @func{malloc} has a @w{2 kB} block size
98 limit.  If you need larger chunks, consider using a linked structure
99 instead.
100
101 @node Project 1 Code
102 @section Code
103
104 Here is a brief overview of the files in the @file{threads}
105 directory.  You will not need to modify most of this code, but the
106 hope is that presenting this overview will give you a start on what
107 code to look at.
108
109 @table @file
110 @item loader.S
111 @itemx loader.h
112 The kernel loader.  Assembles to 512 bytes of code and data that the
113 PC BIOS loads into memory and which in turn loads the kernel into
114 memory, does basic processor initialization, and jumps to the
115 beginning of the kernel.  You should not need to look at this code or
116 modify it.
117
118 @item kernel.lds.S
119 The linker script used to link the kernel.  Sets the load address of
120 the kernel and arranges for @file{start.S} to be at the very beginning
121 of the kernel image.  Again, you should not need to look at this code
122 or modify it, but it's here in case you're curious.
123
124 @item start.S
125 Jumps to @func{main}.
126
127 @item init.c
128 @itemx init.h
129 Kernel initialization, including @func{main}, the kernel's ``main
130 program.''  You should look over @func{main} at least to see what
131 gets initialized.
132
133 @item thread.c
134 @itemx thread.h
135 Basic thread support.  Much of your work will take place in these
136 files.  @file{thread.h} defines @struct{thread}, which you will
137 modify in the first three projects.
138
139 @item switch.S
140 @itemx switch.h
141 Assembly language routine for switching threads.  Already discussed
142 above.
143
144 @item palloc.c
145 @itemx palloc.h
146 Page allocator, which hands out system memory in multiples of 4 kB
147 pages.
148
149 @item malloc.c
150 @itemx malloc.h
151 A very simple implementation of @func{malloc} and @func{free} for
152 the kernel.
153
154 @item interrupt.c
155 @itemx interrupt.h
156 Basic interrupt handling and functions for turning interrupts on and
157 off.
158
159 @item intr-stubs.S
160 @itemx intr-stubs.h
161 Assembly code for low-level interrupt handling.
162
163 @item synch.c
164 @itemx synch.h
165 Basic synchronization primitives: semaphores, locks, and condition
166 variables.  You will need to use these for synchronization through all
167 four projects.
168
169 @item test.c
170 @itemx test.h
171 Test code.  For project 1, you will replace this file with your test
172 cases.
173
174 @item io.h
175 Functions for I/O port access.  This is mostly used by source code in
176 the @file{devices} directory that you won't have to touch.
177
178 @item mmu.h
179 Functions and macros related to memory management, including page
180 directories and page tables.  This will be more important to you in
181 project 3.  For now, you can ignore it.
182 @end table
183
184 @menu
185 * devices code::                
186 * lib files::                   
187 @end menu
188
189 @node devices code
190 @subsection @file{devices} code
191
192 The basic threaded kernel also includes these files in the
193 @file{devices} directory:
194
195 @table @file
196 @item timer.c
197 @itemx timer.h
198 System timer that ticks, by default, 100 times per second.  You will
199 modify this code in Problem 1-1.
200
201 @item vga.c
202 @itemx vga.h
203 VGA display driver.  Responsible for writing text to the screen.
204 You should have no need to look at this code.  @func{printf} will
205 call into the VGA display driver for you, so there's little reason to
206 call this code yourself.
207
208 @item serial.c
209 @itemx serial.h
210 Serial port driver.  Again, @func{printf} calls this code for you,
211 so you don't need to do so yourself.  Feel free to look through it if
212 you're curious.
213
214 @item disk.c
215 @itemx disk.h
216 Supports reading and writing sectors on up to 4 IDE disks.  This won't
217 actually be used until project 2.
218
219 @item intq.c
220 @itemx intq.h
221 Interrupt queue, for managing a circular queue that both kernel
222 threads and interrupt handlers want to access.  Used by the keyboard
223 and serial drivers.
224 @end table
225
226 @node lib files
227 @subsection @file{lib} files
228
229 Finally, @file{lib} and @file{lib/kernel} contain useful library
230 routines.  (@file{lib/user} will be used by user programs, starting in
231 project 2, but it is not part of the kernel.)  Here's a few more
232 details:
233
234 @table @file
235 @item ctype.h
236 @itemx inttypes.h
237 @itemx limits.h
238 @itemx stdarg.h
239 @itemx stdbool.h
240 @itemx stddef.h
241 @itemx stdint.h
242 @itemx stdio.c
243 @itemx stdio.h
244 @itemx stdlib.c
245 @itemx stdlib.h
246 @itemx string.c
247 @itemx string.h
248 Implementation of the standard C library.  @xref{C99}, for information
249 on a few recently introduced pieces of the C library that you might
250 not have encountered before.  @xref{Unsafe String Functions}, for
251 information on what's been intentionally left out for safety.
252
253 @item debug.c
254 @itemx debug.h
255 Functions and macros to aid debugging.  @xref{Debugging Tools}, for
256 more information.
257
258 @item random.c
259 @itemx random.h
260 Pseudo-random number generator.
261
262 @item round.h
263 Macros for rounding.
264
265 @item syscall-nr.h
266 System call numbers.  Not used until project 2.
267
268 @item kernel/list.c
269 @itemx kernel/list.h
270 Doubly linked list implementation.  Used all over the Pintos code, and
271 you'll probably want to use it a few places yourself in project 1.
272
273 @item kernel/bitmap.c
274 @itemx kernel/bitmap.h
275 Bitmap implementation.  You can use this in your code if you like, but
276 you probably won't have any need for project 1.
277
278 @item kernel/hash.c
279 @itemx kernel/hash.h
280 Hash table implementation.  Likely to come in handy for project 3.
281
282 @item kernel/console.c
283 @itemx kernel/console.h
284 Implements @func{printf} and a few other functions.
285 @end table
286
287 @node Debugging versus Testing
288 @section Debugging versus Testing
289
290 When you're debugging code, it's useful to be able to be able to run a
291 program twice and have it do exactly the same thing.  On second and
292 later runs, you can make new observations without having to discard or
293 verify your old observations.  This property is called
294 ``reproducibility.''  The simulator we use, Bochs, can be set up for
295 reproducibility, and that's the way that @command{pintos} invokes it
296 by default.
297
298 Of course, a simulation can only be reproducible from one run to the
299 next if its input is the same each time.  For simulating an entire
300 computer, as we do, this means that every part of the computer must be
301 the same.  For example, you must use the same disks, the same version
302 of Bochs, and you must not hit any keys on the keyboard (because you
303 could not be sure to hit them at exactly the same point each time)
304 during the runs.
305
306 While reproducibility is useful for debugging, it is a problem for
307 testing thread synchronization, an important part of this project.  In
308 particular, when Bochs is set up for reproducibility, timer interrupts
309 will come at perfectly reproducible points, and therefore so will
310 thread switches.  That means that running the same test several times
311 doesn't give you any greater confidence in your code's correctness
312 than does running it only once.
313
314 So, to make your code easier to test, we've added a feature, called
315 ``jitter,'' to Bochs, that makes timer interrupts come at random
316 intervals, but in a perfectly predictable way.  In particular, if you
317 invoke @command{pintos} with the option @option{-j @var{seed}}, timer
318 interrupts will come at irregularly spaced intervals.  Within a single
319 @var{seed} value, execution will still be reproducible, but timer
320 behavior will change as @var{seed} is varied.  Thus, for the highest
321 degree of confidence you should test your code with many seed values.
322
323 On the other hand, when Bochs runs in reproducible mode, timings are not
324 realistic, meaning that a ``one-second'' delay may be much shorter or
325 even much longer than one second.  You can invoke @command{pintos} with
326 a different option, @option{-r}, to make it set up Bochs for realistic
327 timings, in which a one-second delay should take approximately one
328 second of real time.  Simulation in real-time mode is not reproducible,
329 and options @option{-j} and @option{-r} are mutually exclusive.
330
331 @node Tips
332 @section Tips
333
334 @itemize @bullet
335 @item
336 There should be no busy waiting in any of your solutions to this
337 assignment.  We consider a tight loop that calls @func{thread_yield}
338 to be one form of busy waiting.
339
340 @item
341 Proper synchronization is an important part of the solutions to these
342 problems.  It is tempting to synchronize all your code by turning off
343 interrupts with @func{intr_disable} or @func{intr_set_level}, because
344 this eliminates concurrency and thus the possibility for race
345 conditions, but @strong{don't}.  Instead, use semaphores, locks, and
346 condition variables to solve the bulk of your synchronization
347 problems.  Read the tour section on synchronization
348 (@pxref{Synchronization}) or the comments in @file{threads/synch.c} if
349 you're unsure what synchronization primitives may be used in what
350 situations.
351
352 You might run into a few situations where interrupt disabling is the
353 best way to handle synchronization.  If so, you need to explain your
354 rationale in your design documents.  If you're unsure whether a given
355 situation justifies disabling interrupts, talk to the TAs, who can
356 help you decide on the right thing to do.
357
358 Disabling interrupts can be useful for debugging, if you want to make
359 sure that a section of code is not interrupted.  You should remove
360 debugging code before turning in your project.
361
362 @item
363 All parts of this assignment are required if you intend to earn full
364 credit on this project.  Problem 1-1 (Alarm Clock) could be handy for
365 later projects, but it is not strictly required.  Problems 1-2
366 (Priority Scheduling) and 1-3 (Advanced Scheduler) won't be needed for
367 later projects.
368
369 @item
370 Problem 1-3 (MLFQS) builds on the features you implement in Problem
371 1-2.  You should have Problem 1-2 fully working before you begin to
372 tackle Problem 1-3.
373
374 @item
375 In the past, many groups divided the assignment into pieces, then each
376 group member worked on his or her piece until just before the
377 deadline, at which time the group reconvened to combine their code and
378 submit.  @strong{This is a bad idea.  We do not recommend this
379 approach.}  Groups that do this often find that two changes conflict
380 with each other, requiring lots of last-minute debugging.  Some groups
381 who have done this have turned in code that did not even successfully
382 boot.
383
384 Instead, we recommend integrating your team's changes early and often,
385 using a source code control system such as CVS (@pxref{CVS}) or a
386 group collaboration site such as SourceForge (@pxref{SourceForge}).
387 This is less likely to produce surprises, because everyone can see
388 everyone else's code as it is written, instead of just when it is
389 finished.  These systems also make it possible to review changes and,
390 when a change introduces a bug, drop back to working versions of code.
391
392 @item
393 You should expect to run into bugs that you simply don't understand
394 while working on this and subsequent projects.  When you do, go back
395 and reread the appendix on debugging tools, which is filled with
396 useful debugging tips that should help you to get back up to speed
397 (@pxref{Debugging Tools}).  Be sure to read the section on backtraces
398 (@pxref{Backtraces}), which will help you to get the most out of every
399 kernel panic or assertion failure.
400 @end itemize
401
402 @node Problem 1-1 Alarm Clock
403 @section Problem 1-1: Alarm Clock
404
405 Improve the implementation of the timer device defined in
406 @file{devices/timer.c} by reimplementing @func{timer_sleep}.
407 Threads call @code{timer_sleep(@var{x})} to suspend execution until
408 time has advanced by at least @w{@var{x} timer ticks}.  This is
409 useful for threads that operate in real-time, for example, for
410 blinking the cursor once per second.  There is no requirement that
411 threads start running immediately after waking up; just put them on
412 the ready queue after they have waited for approximately the right
413 amount of time.
414
415 A working implementation of this function is provided.  However, the
416 version provided is poor, because it ``busy waits,'' that is, it spins
417 in a tight loop checking the current time until the current time has
418 advanced far enough.  This is undesirable because it wastes time that
419 could potentially be used more profitably by another thread.  Your
420 solution should not busy wait.
421
422 The argument to @func{timer_sleep} is expressed in timer ticks, not in
423 milliseconds or any another unit.  There are @code{TIMER_FREQ} timer
424 ticks per second, where @code{TIMER_FREQ} is a macro defined in
425 @code{devices/timer.h}.
426
427 Separate functions @func{timer_msleep}, @func{timer_usleep}, and
428 @func{timer_nsleep} do exist for sleeping a specific number of
429 milliseconds, microseconds, or nanoseconds, respectively, but these will
430 call @func{timer_sleep} automatically when necessary.  You do not need
431 to modify them.
432
433 If your delays seem too short or too long, reread the explanation of the
434 @option{-r} option to @command{pintos} (@pxref{Debugging versus
435 Testing}).
436
437 @node Problem 1-2 Priority Scheduling
438 @section Problem 1-2: Priority Scheduling
439
440 Implement priority scheduling in Pintos.  Priority scheduling is a key
441 building block for real-time systems.  Implement functions
442 @func{thread_set_priority} to set the priority of the running thread
443 and @func{thread_get_priority} to get the running thread's priority.
444 (This API only allows a thread to examine and modify its own
445 priority.)  There are already prototypes for these functions in
446 @file{threads/thread.h}, which you should not change.
447
448 Thread priority ranges from @code{PRI_MIN} (0) to @code{PRI_MAX} (59).
449 The initial thread priority is passed as an argument to
450 @func{thread_create}.  If there's no reason to choose another
451 priority, use @code{PRI_DEFAULT} (29).  The @code{PRI_} macros are
452 defined in @file{threads/thread.h}, and you should not change their
453 values.
454
455 When a thread is added to the ready list that has a higher priority
456 than the currently running thread, the current thread should
457 immediately yield the processor to the new thread.  Similarly, when
458 threads are waiting for a lock, semaphore or condition variable, the
459 highest priority waiting thread should be woken up first.  A thread
460 may raise or lower its own priority at any time, but lowering its
461 priority such that it no longer has the highest priority must cause it
462 to immediately yield the CPU.
463
464 One issue with priority scheduling is ``priority inversion'': if a
465 high priority thread needs to wait for a low priority thread (for
466 instance, for a lock held by a low priority thread), and a middle priority
467 thread is on the ready list, then the high priority thread will never
468 get the CPU because the low priority thread will not get any CPU time.
469 A partial fix for this problem is to have the waiting thread
470 ``donate'' its priority to the low priority thread while it is holding
471 the lock, then recall the donation once it has acquired the lock.
472 Implement this fix.
473
474 You will need to account for all different orders in which priority
475 donation and inversion can occur.  Be sure to handle multiple
476 donations, in which multiple priorities are donated to a thread.  You
477 must also handle nested donation: given high, medium, and low priority
478 threads @var{H}, @var{M}, and @var{L}, respectively, if @var{H} is
479 waiting on a lock that @var{M} holds and @var{M} is waiting on a lock
480 that @var{L} holds, then both @var{M} and @var{L} should be boosted to
481 @var{H}'s priority.
482
483 You only need to implement priority donation when a thread is waiting
484 for a lock held by a lower-priority thread.  You do not need to
485 implement this fix for semaphores or condition variables
486 although you are welcome to do so.  However, you do need to implement
487 priority scheduling in all cases.
488
489 @node Problem 1-3 Advanced Scheduler
490 @section Problem 1-3: Advanced Scheduler
491
492 Implement Solaris's multilevel feedback queue scheduler (MLFQS) to
493 reduce the average response time for running jobs on your system.
494 @xref{Multilevel Feedback Scheduling}, for a detailed description of
495 the MLFQS requirements.
496
497 Demonstrate that your scheduling algorithm reduces response time
498 relative to the original Pintos scheduling algorithm (round robin) for
499 at least one workload of your own design (i.e.@: in addition to the
500 provided test).
501
502 You must write your code so that we can choose a scheduling algorithm
503 policy at Pintos startup time.  By default, the round-robin scheduler
504 must be active, but we must be able to choose the MLFQS by invoking
505 @command{pintos} with the @option{-o mlfqs} option.  Passing this
506 option sets @code{enable_mlfqs}, declared in @file{threads/init.h}, to
507 true.
508
509 @node Threads FAQ
510 @section FAQ
511
512 @enumerate 1
513 @item
514 @b{I am adding a new @file{.h} or @file{.c} file.  How do I fix the
515 @file{Makefile}s?}@anchor{Adding c or h Files}
516
517 To add a @file{.c} file, edit the top-level @file{Makefile.build}.
518 You'll want to add your file to variable @samp{@var{dir}_SRC}, where
519 @var{dir} is the directory where you added the file.  For this
520 project, that means you should add it to @code{threads_SRC}, or
521 possibly @code{devices_SRC} if you put in the @file{devices}
522 directory.  Then run @code{make}.  If your new file doesn't get
523 compiled, run @code{make clean} and then try again.
524
525 When you modify the top-level @file{Makefile.build}, the modified
526 version should be automatically copied to
527 @file{threads/build/Makefile} when you re-run make.  The opposite is
528 not true, so any changes will be lost the next time you run @code{make
529 clean} from the @file{threads} directory.  Therefore, you should
530 prefer to edit @file{Makefile.build} (unless your changes are meant to
531 be truly temporary).
532
533 There is no need to edit the @file{Makefile}s to add a @file{.h} file.
534
535 @item
536 @b{How do I write my test cases?}
537
538 Test cases should be replacements for the existing @file{test.c}
539 file.  Put them in a @file{threads/testcases} directory.
540 @xref{TESTCASE}, for more information.
541
542 @item
543 @b{Why can't I disable interrupts?}
544
545 Turning off interrupts should only be done for short amounts of time,
546 or else you end up losing important things such as disk or input
547 events.  Turning off interrupts also increases the interrupt handling
548 latency, which can make a machine feel sluggish if taken too far.
549 Therefore, in general, setting the interrupt level should be used
550 sparingly.  Also, any synchronization problem can be easily solved by
551 turning interrupts off, since while interrupts are off, there is no
552 concurrency, so there's no possibility for race conditions.
553
554 To make sure you understand concurrency well, we are discouraging you
555 from taking this shortcut at all in your solution.  If you are unable
556 to solve a particular synchronization problem with semaphores, locks,
557 or conditions, or think that they are inadequate for a particular
558 reason, you may turn to disabling interrupts.  If you want to do this,
559 we require in your design document a complete justification and
560 scenario (i.e.@: exact sequence of events) to show why interrupt
561 manipulation is the best solution.  If you are unsure, the TAs can
562 help you determine if you are using interrupts too haphazardly.  We
563 want to emphasize that there are only limited cases where this is
564 appropriate.
565
566 You might find @file{devices/intq.h} and its users to be an
567 inspiration or source of rationale.
568
569 @item
570 @b{Where might interrupt-level manipulation be appropriate?}
571
572 You might find it necessary in some solutions to the Alarm problem.
573
574 You might want it at one small point for the priority scheduling
575 problem.  Note that it is not required to use interrupts for these
576 problems.  There are other, equally correct solutions that do not
577 require interrupt manipulation.  However, if you do manipulate
578 interrupts and @strong{correctly and fully document it} in your design
579 document, we will allow limited use of interrupt disabling.
580
581 @item
582 @b{What does ``warning: no previous prototype for `@var{function}''
583 mean?}
584
585 It means that you defined a non-@code{static} function without
586 preceding it by a prototype.  Because non-@code{static} functions are
587 intended for use by other @file{.c} files, for safety they should be
588 prototyped in a header file included before their definition.  To fix
589 the problem, add a prototype in a header file that you include, or, if
590 the function isn't actually used by other @file{.c} files, make it
591 @code{static}.
592 @end enumerate
593
594 @menu
595 * Problem 1-1 Alarm Clock FAQ::  
596 * Problem 1-2 Priority Scheduling FAQ::  
597 * Problem 1-3 Advanced Scheduler FAQ::  
598 @end menu
599
600 @node Problem 1-1 Alarm Clock FAQ
601 @subsection Problem 1-1: Alarm Clock FAQ
602
603 @enumerate 1
604 @item
605 @b{Why can't I use most synchronization primitives in an interrupt
606 handler?}
607
608 As you've discovered, you cannot sleep in an external interrupt
609 handler.  Since many lock, semaphore, and condition variable functions
610 attempt to sleep, you won't be able to call those in
611 @func{timer_interrupt}.  You may still use those that never sleep.
612
613 Having said that, you need to make sure that global data does not get
614 updated by multiple threads simultaneously executing
615 @func{timer_sleep}.  Here are some pieces of information to think
616 about:
617
618 @enumerate a
619 @item
620 Interrupts are turned off while @func{timer_interrupt} runs.  This
621 means that @func{timer_interrupt} will not be interrupted by a
622 thread running in @func{timer_sleep}.
623
624 @item
625 A thread in @func{timer_sleep}, however, can be interrupted by a
626 call to @func{timer_interrupt}, except when that thread has turned
627 off interrupts.
628
629 @item
630 Examples of synchronization mechanisms have been presented in lecture.
631 Going over these examples should help you understand when each type is
632 useful or needed.  @xref{Synchronization}, for specific information
633 about synchronization in Pintos.
634 @end enumerate
635
636 @item
637 @b{What about timer overflow due to the fact that times are defined as
638 integers? Do I need to check for that?}
639
640 Don't worry about the possibility of timer values overflowing.  Timer
641 values are expressed as signed 63-bit numbers, which at 100 ticks per
642 second should be good for almost 2,924,712,087 years.
643
644 @item
645 @b{The test program mostly works but reports a few out-of-order
646 wake ups.  I think it's a problem in the test program.  What gives?}
647 @anchor{Out of Order 1-1}
648
649 This test is inherently full of race conditions.  On a real system it
650 wouldn't work perfectly all the time either.  There are a few ways you
651 can help it work more reliably:
652
653 @itemize @bullet
654 @item
655 Make time slices longer by increasing @code{TIME_SLICE} in
656 @file{timer.c} to a large value, such as 100.
657
658 @item
659 Make the timer tick more slowly by decreasing @code{TIMER_FREQ} in
660 @file{timer.h} to its minimum value of 19.
661 @end itemize
662
663 The former two changes are only desirable for testing problem 1-1 and
664 possibly 1-2.  You should revert them before working on other parts
665 of the project or turn in the project.  We will test problem 1-1 with
666 @code{TIME_SLICE} set to 100 and @code{TIMER_FREQ} set to 19, but we
667 will leave them at their defaults for all the other problems.
668
669 @item
670 @b{Should @file{p1-1.c} be expected to work with the MLFQS turned on?}
671
672 No.  The MLFQS will adjust priorities, changing thread ordering.
673 @end enumerate
674
675 @node Problem 1-2 Priority Scheduling FAQ
676 @subsection Problem 1-2: Priority Scheduling FAQ
677
678 @enumerate 1
679 @item
680 @b{Doesn't the priority scheduling lead to starvation? Or do I have to
681 implement some sort of aging?}
682
683 It is true that strict priority scheduling can lead to starvation
684 because thread may not run if a higher-priority thread is runnable.
685 In this problem, don't worry about starvation or any sort of aging
686 technique.  Problem 4 will introduce a mechanism for dynamically
687 changing thread priorities.
688
689 This sort of scheduling is valuable in real-time systems because it
690 offers the programmer more control over which jobs get processing
691 time.  High priorities are generally reserved for time-critical
692 tasks. It's not ``fair,'' but it addresses other concerns not
693 applicable to a general-purpose operating system.
694
695 @item
696 @b{After a lock has been released, does the program need to switch to
697 the highest priority thread that needs the lock (assuming that its
698 priority is higher than that of the current thread)?}
699
700 When a lock is released, the highest priority thread waiting for that
701 lock should be unblocked and put on the ready to run list.  The
702 scheduler should then run the highest priority thread on the ready
703 list.
704
705 @item
706 @b{If a thread calls @func{thread_yield} and then it turns out that
707 it has higher priority than any other threads, does the high-priority
708 thread continue running?}
709
710 Yes.  If there is a single highest-priority thread, it continues
711 running until it blocks or finishes, even if it calls
712 @func{thread_yield}.
713
714 @item
715 @b{If the highest priority thread is added to the ready to run list it
716 should start execution immediately.  Is it immediate enough if I
717 wait until next timer interrupt occurs?}
718
719 The highest priority thread should run as soon as it is runnable,
720 preempting whatever thread is currently running.
721
722 @item
723 @b{What happens to the priority of the donating thread?  Do the priorities
724 get swapped?}
725
726 No.  Priority donation only changes the priority of the low-priority
727 thread.  The donating thread's priority stays unchanged.  Also note
728 that priorities aren't additive: if thread A (with priority 5) donates
729 to thread B (with priority 3), then B's new priority is 5, not 8.
730
731 @item 
732 @b{Can a thread's priority be changed while it is sitting on the ready
733 queue?}
734
735 Yes.  Consider this case: low-priority thread L currently has a lock
736 that high-priority thread H wants.  H donates its priority to L (the
737 lock holder).  L finishes with the lock, and then loses the CPU and is
738 moved to the ready queue.  Now L's old priority is restored while it
739 is in the ready queue.
740
741 @item
742 @b{Can a thread's priority change while it is sitting on the queue of a
743 semaphore?}
744
745 Yes.  Same scenario as above except L gets blocked waiting on a new
746 lock when H restores its priority.
747
748 @item
749 @b{Why is @file{p1-2.c}'s FIFO test skipping some threads?  I know my
750 scheduler is round-robin'ing them like it's supposed to.   Our output
751 starts out okay, but toward the end it starts getting out of order.}
752
753 The usual problem is that the serial output buffer fills up.  This is
754 causing serial_putc() to block in thread @var{A}, so that thread
755 @var{B} is scheduled.  Thread @var{B} immediately tries to do output
756 of its own and blocks on the serial lock (which is held by thread
757 @var{A}).  Now that we've wasted some time in scheduling and locking,
758 typically some characters have been drained out of the serial buffer
759 by the interrupt handler, so thread @var{A} can continue its output.
760 After it finishes, though, some other thread (not @var{B}) is
761 scheduled, because thread @var{B} was already scheduled while we
762 waited for the buffer to drain.
763
764 There's at least one other possibility.  Context switches are being
765 invoked by the test when it explicitly calls @func{thread_yield}.
766 However, the time slice timer is still alive and so, every tick (by
767 default), a thread gets switched out (caused by @func{timer_interrupt}
768 calling @func{intr_yield_on_return}) before it gets a chance to run
769 @func{printf}, effectively skipping it.  If we use a different jitter
770 value, the same behavior is seen where a thread gets started and
771 switched out completely.
772
773 Normally you can fix these problems using the same techniques
774 suggested on problem 1-1 (@pxref{Out of Order 1-1}).
775
776 @item
777 @b{What happens when a thread is added to the ready list which has
778 higher priority than the currently running thread?}
779
780 The correct behavior is to immediately yield the processor.  Your
781 solution must act this way.
782
783 @item
784 @b{What should @func{thread_get_priority} return in a thread while
785 its priority has been increased by a donation?}
786
787 The higher (donated) priority.
788
789 @item
790 @b{Should @file{p1-2.c} be expected to work with the MLFQS turned on?}
791
792 No.  The MLFQS will adjust priorities, changing thread ordering.
793
794 @item
795 @b{@func{printf} in @func{sema_up} or @func{sema_down} makes the
796 system reboot!}
797
798 Yes.  These functions are called before @func{printf} is ready to go.
799 You could add a global flag initialized to false and set it to true
800 just before the first @func{printf} in @func{main}.  Then modify
801 @func{printf} itself to return immediately if the flag isn't set.
802 @end enumerate
803
804 @node Problem 1-3 Advanced Scheduler FAQ
805 @subsection Problem 1-3: Advanced Scheduler FAQ
806
807 @enumerate 1
808 @item
809 @b{What is the interval between timer interrupts?}
810
811 Timer interrupts occur @code{TIMER_FREQ} times per second.  You can
812 adjust this value by editing @file{devices/timer.h}.  The default is
813 100 Hz.
814
815 You can also adjust the number of timer ticks per time slice by
816 modifying @code{TIME_SLICE} in @file{devices/timer.c}.
817
818 @item
819 @b{Do I have to modify the dispatch table?}
820
821 No, although you are allowed to. It is possible to complete
822 this problem (i.e.@: demonstrate response time improvement)
823 without doing so.
824
825 @item
826 @b{When the scheduler changes the priority of a thread, how does this
827 affect priority donation?}
828
829 Short (official) answer: Don't worry about it. Your priority donation
830 code may assume static priority assignment.
831
832 Longer (unofficial) opinion: If you wish to take this into account,
833 however, your design may end up being ``cleaner.''  You have
834 considerable freedom in what actually takes place. I believe what
835 makes the most sense is for scheduler changes to affect the
836 ``original'' (non-donated) priority.  This change may actually be
837 masked by the donated priority.  Priority changes should only
838 propagate with donations, not ``backwards'' from donees to donors.
839
840 @item
841 @b{What is meant by ``static priority''?}
842
843 Once thread A has donated its priority to thread B, if thread A's
844 priority changes (due to the scheduler) while the donation still
845 exists, you do not have to change thread B's donated priority.
846 However, you are free to do so.
847
848 @item
849 @b{Do I have to make my dispatch table user-configurable?}
850
851 No.  Hard-coding the dispatch table values is fine.
852 @end enumerate