-@b{Why is pubtest3's FIFO test skipping some threads! I know my scheduler
-is round-robin'ing them like it's supposed to! Our output is like this:}
-
-@example
-Thread 0 goes.
-Thread 2 goes.
-Thread 3 goes.
-Thread 4 goes.
-Thread 0 goes.
-Thread 1 goes.
-Thread 2 goes.
-Thread 3 goes.
-Thread 4 goes.
-@end example
-
-@noindent @b{which repeats 5 times and then}
-
-@example
-Thread 1 goes.
-Thread 1 goes.
-Thread 1 goes.
-Thread 1 goes.
-Thread 1 goes.
-@end example
-
-This happens because context switches are being invoked by the test
-when it explicitly calls @func{thread_yield}. However, the time
-slice timer is still alive and so, every tick (by default), thread 1
-gets switched out (caused by @func{timer_interrupt} calling
-@func{intr_yield_on_return}) before it gets a chance to run its
-mainline. It is by coincidence that Thread 1 is the one that gets
-skipped in our example. If we use a different jitter value, the same
-behavior is seen where a thread gets started and switched out
-completely.
-
-Solution: Increase the value of @code{TIME_SLICE} in
-@file{devices/timer.c} to a very high value, such as 10000, to see
-that the threads will round-robin if they aren't interrupted.
+@b{Why is @file{p1-3.c}'s FIFO test skipping some threads? I know my
+scheduler is round-robin'ing them like it's supposed to. Our output
+starts out okay, but toward the end it starts getting out of order.}
+
+The usual problem is that the serial output buffer fills up. This is
+causing serial_putc() to block in thread @var{A}, so that thread
+@var{B} is scheduled. Thread @var{B} immediately tries to do output
+of its own and blocks on the serial lock (which is held by thread
+@var{A}). Now that we've wasted some time in scheduling and locking,
+typically some characters have been drained out of the serial buffer
+by the interrupt handler, so thread @var{A} can continue its output.
+After it finishes, though, some other thread (not @var{B}) is
+scheduled, because thread @var{B} was already scheduled while we
+waited for the buffer to drain.
+
+There's at least one other possibility. Context switches are being
+invoked by the test when it explicitly calls @func{thread_yield}.
+However, the time slice timer is still alive and so, every tick (by
+default), a thread gets switched out (caused by @func{timer_interrupt}
+calling @func{intr_yield_on_return}) before it gets a chance to run
+@func{printf}, effectively skipping it. If we use a different jitter
+value, the same behavior is seen where a thread gets started and
+switched out completely.
+
+Normally you can fix these problems using the same techniques
+suggested on problem 1-1 (@pxref{Out of Order 1-1}).