Now that interrupts are set up, we can start preemptively scheduling
threads with @func{thread_start}, which also enables interrupts.
Interrupt-driven serial port I/O is also possible now, so we use
-@func{serial_init_queue} to switch to that mode.
+@func{serial_init_queue} to switch to that mode. Finally,
+@func{timer_calibrate} calibrates the timer for accurate short delays.
If the filesystem is compiled in, as it will be in project 2 and
later, we now initialize the disks with @func{disk_init}, then the
@end menu
@node struct thread
-@subsection @struct{thread}
+@subsection @code{struct thread}
The main Pintos data structure for threads is @struct{thread},
declared in @file{threads/thread.h}. @struct{thread} has these
grows downward from the end of the page. It looks like this:
@example
+@group
4 kB +---------------------------------+
| kernel stack |
| | |
| name |
| status |
0 kB +---------------------------------+
+@end group
@end example
The upshot of this is twofold. First, @struct{thread} must not be
Called by @func{main} to start the scheduler. Creates the idle
thread, that is, the thread that is scheduled when no other thread is
ready. Then enables interrupts, which enables the scheduler because
-processes are rescheduled in the return path from the timer
-interrupt. FIXME
+processes are rescheduled on return from the timer interrupt, using
+@func{intr_yield_on_return} (@pxref{External Interrupt Handling}).
@end deftypefun
@deftypefun void thread_create (const char *@var{name}, int @var{priority}, thread_func *@var{func}, void *@var{aux})