@func{main}, which never returns.
There's one more trick: the Pintos kernel command line
-is in stored the boot loader. The @command{pintos} program actually
+is stored in the boot loader. The @command{pintos} program actually
modifies a copy of the boot loader on disk each time it runs the kernel,
putting
in whatever command line arguments the user supplies to the kernel,
the loader stored it and put it into the @code{ram_pages} variable for
later use.
-Next, @func{thread_init} initializes the thread system. We will defer
-full discussion to our discussion of Pintos threads below. It is
-called so early in initialization because the console, initialized
-just afterward, tries to use locks, and locks in turn require there to be a
-running thread.
-
-Then we initialize the console so that @func{printf} will work.
-@func{main} calls @func{vga_init}, which initializes the VGA text
-display and clears the screen. It also calls @func{serial_init_poll}
-to initialize the first serial port in ``polling mode,'' that is,
-where the kernel busy-waits for the port to be ready for each
-character to be output. (We use polling mode until we're ready to enable
-interrupts, later.) Finally we initialize the console device and
-print a startup message to the console.
-
-@func{main} calls @func{read_command_line} to break the kernel command
+Next, @func{main} calls @func{read_command_line} to break the kernel command
line into arguments, then @func{parse_options} to read any options at
the beginning of the command line. (Actions specified on the
command line execute later.)
-@func{main} calls @func{random_init} to initialize the kernel random
-number generator. If the user specified @option{-rs} on the
-@command{pintos} command line, @func{parse_options} already did
-this, but calling it a second time is harmless.
+@func{thread_init} initializes the thread system. We will defer full
+discussion to our discussion of Pintos threads below. It is called so
+early in initialization because a valid thread structure is a
+prerequisite for acquiring a lock, and lock acquisition in turn is
+important to other Pintos subsystems. Then we initialize the console
+and print a startup message to the console.
-The next block of functions we call initialize the kernel's memory
+The next block of functions we call initializes the kernel's memory
system. @func{palloc_init} sets up the kernel page allocator, which
doles out memory one or more pages at a time (@pxref{Page Allocator}).
@func{malloc_init} sets
priority scheduling in project 1 (@pxref{Priority Scheduling}).
@end deftypecv
+@deftypecv {Member} {@struct{thread}} {@struct{list_elem}} allelem
+This ``list element'' is used to link the thread into the list of all
+threads. Each thread is inserted into this list when it is created
+and removed when it exits. The @func{thread_foreach} function should
+be used to iterate over all threads.
+@end deftypecv
+
@deftypecv {Member} {@struct{thread}} {@struct{list_elem}} elem
A ``list element'' used to put the thread into doubly linked lists,
either @code{ready_list} (the list of threads ready to run) or a list of
time.
@end deftypefun
+@deftypefun void thread_foreach (thread_action_func *@var{action}, void *@var{aux})
+Iterates over all threads @var{t} and invokes @code{action(t, aux)} on each.
+@var{action} must refer to a function that matches the signature
+given by @func{thread_action_func}:
+
+@deftp {Type} {void thread_action_func (struct thread *@var{thread}, void *@var{aux})}
+Performs some action on a thread, given @var{aux}.
+@end deftp
+@end deftypefun
+
@deftypefun int thread_get_priority (void)
@deftypefunx void thread_set_priority (int @var{new_priority})
Stub to set and get thread priority. @xref{Priority Scheduling}.
member, restores the new thread's @code{stack} into the CPU's stack
pointer, restores registers from the stack, and returns.
-The rest of the scheduler is implemented in @func{schedule_tail}. It
+The rest of the scheduler is implemented in @func{thread_schedule_tail}. It
marks the new thread as running. If the thread we just switched from
is in the dying state, then it also frees the page that contained the
dying thread's @struct{thread} and stack. These couldn't be freed
arguments on the stack and the 80@var{x}86 SVR4 calling convention
requires the caller, not the called function, to remove them when the
call is complete. See @bibref{SysV-i386} chapter 3 for details.}
-calls @func{schedule_tail} (this special case is why
-@func{schedule_tail} is separate from @func{schedule}), and returns.
+calls @func{thread_schedule_tail} (this special case is why
+@func{thread_schedule_tail} is separate from @func{schedule}), and returns.
We fill in its stack frame so that it returns into
@func{kernel_thread}, a function in @file{threads/thread.c}.
A @dfn{lock} is like a semaphore with an initial value of 1
(@pxref{Semaphores}). A lock's equivalent of ``up'' is called
-``acquire'', and the ``down'' operation is called ``release''.
+``release'', and the ``down'' operation is called ``acquire''.
Compared to a semaphore, a lock has one added restriction: only the
thread that acquires a lock, called the lock's ``owner'', is allowed to