Add hints about not doing too much work in timer interrupt.
[pintos-anon] / doc / threads.texi
index 706f76b7f035e5b7c0e17755dc5c7750aed4d34d..1231168e34224ab3aca2ee50479087ceb0abdf46 100644 (file)
@@ -40,7 +40,7 @@ The first step is to read and understand the code for the initial thread
 system.
 Pintos already implements thread creation and thread completion,
 a simple scheduler to switch between threads, and synchronization
-primitives (semaphores, locks, condition variables, and memory
+primitives (semaphores, locks, condition variables, and optimization
 barriers).
 
 Some of this code might seem slightly mysterious.  If
@@ -170,7 +170,7 @@ Infrastructure}, for more information.
 @item synch.c
 @itemx synch.h
 Basic synchronization primitives: semaphores, locks, condition
-variables, and memory barriers.  You will need to use these for
+variables, and optimization barriers.  You will need to use these for
 synchronization in all
 four projects.  @xref{Synchronization}, for more information.
 
@@ -447,7 +447,7 @@ 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
+highest priority waiting thread should be awakened first.  A thread
 may raise or lower its own priority at any time, but lowering its
 priority such that it no longer has the highest priority must cause it
 to immediately yield the CPU.
@@ -522,7 +522,7 @@ policy at Pintos startup time.  By default, the priority scheduler
 must be active, but we must be able to choose the 4.4@acronym{BSD}
 scheduler
 with the @option{-mlfqs} kernel option.  Passing this
-option sets @code{enable_mlfqs}, declared in @file{threads/init.h}, to
+option sets @code{thread_mlfqs}, declared in @file{threads/thread.h}, to
 true when the options are parsed by @func{parse_options}, which happens
 midway through @func{main}.
 
@@ -640,6 +640,45 @@ that happens to follow @func{fail} in memory, which in this case happens
 to be @func{pass}.
 
 @xref{Backtraces}, for more information.
+
+@item How do interrupts get re-enabled in the new thread following @func{schedule}?
+
+Every path into @func{schedule} disables interrupts.  They eventually
+get re-enabled by the next thread to be scheduled.  Consider the
+possibilities: the new thread is running in @func{switch_thread} (but
+see below), which is called by @func{schedule}, which is called by one
+of a few possible functions:
+
+@itemize @bullet
+@item
+@func{thread_exit}, but we'll never switch back into such a thread, so
+it's uninteresting.
+
+@item
+@func{thread_yield}, which immediately restores the interrupt level upon
+return from @func{schedule}.
+
+@item
+@func{thread_block}, which is called from multiple places:
+
+@itemize @minus
+@item
+@func{sema_down}, which restores the interrupt level before returning.
+
+@item
+@func{idle}, which enables interrupts with an explicit assembly STI
+instruction.
+
+@item
+@func{wait} in @file{devices/intq.c}, whose callers are responsible for
+re-enabling interrupts.
+@end itemize
+@end itemize
+
+There is a special case when a newly created thread runs for the first
+time.  Such a thread calls @func{intr_enable} as the first action in
+@func{kernel_thread}, which is at the bottom of the call stack for every
+kernel thread but the first.
 @end table
 
 @menu
@@ -752,4 +791,32 @@ scheduler at the same time.
 
 Yes.  In general, your implementation may differ from the description,
 as long as its behavior is the same.
+
+@item Some scheduler tests fail and I don't understand why.  Help!
+
+If your implementation mysteriously fails some of the advanced
+scheduler tests, try the following:
+
+@itemize
+@item
+Read the source files for the tests that you're failing, to make sure
+that you understand what's going on.  Each one has a comment at the
+top that explains its purpose and expected results.
+
+@item
+Double-check your fixed-point arithmetic routines and your use of them
+in the scheduler routines.
+
+@item
+Consider how much work your implementation does in the timer
+interrupt.  If the timer interrupt handler takes too long, then it
+will take away most of a timer tick from the thread that the timer
+interrupt preempted.  When it returns control to that thread, it
+therefore won't get to do much work before the next timer interrupt
+arrives.  That thread will therefore get blamed for a lot more CPU
+time than it actually got a chance to use.  This raises the
+interrupted thread's recent CPU count, thereby lowering its priority.
+It can cause scheduling decisions to change.  It also raises the load
+average.
+@end itemize
 @end table