Update docs.
[pintos-anon] / doc / tour.texi
1 @node Pintos Tour, Project 1--Threads, Introduction, Top
2 @chapter A Tour Through Pintos
3
4 This chapter is a brief tour through the Pintos code.  It covers the
5 entire code base, but you'll only be using Pintos one part at a time,
6 so you may find that you want to read each part as you work on the
7 corresponding project.
8
9 Hint: try using ``tags'' to follow along with references to function
10 and variable names (@pxref{Tags}).
11
12 @menu
13 * Pintos Loading::              
14 * Threads Tour::                
15 @end menu
16
17 @node Pintos Loading
18 @section Loading
19
20 This section covers the Pintos loader and basic kernel
21 initialization.
22
23 @menu
24 * Pintos Loader::               
25 * Kernel Initialization::       
26 @end menu
27
28 @node Pintos Loader
29 @subsection The Loader
30
31 The first part of Pintos that runs is the loader, in
32 @file{threads/loader.S}.  The PC BIOS loads the loader into memory.
33 The loader, in turn, is responsible for initializing the CPU, loading
34 the rest of Pintos into memory, and then jumping to its start.  It's
35 not important to understand exactly what the loader does, but if
36 you're interested, read on.  You should probably read along with the
37 loader's source.  You should also understand the basics of the
38 80@var{x}86 architecture as described by chapter 3 of
39 @bibref{IA32-v1}.
40
41 Because the PC BIOS loads the loader, the loader has to play by the
42 BIOS's rules.  In particular, the BIOS only loads 512 bytes (one disk
43 sector) into memory.  This is a severe restriction and it means that,
44 practically speaking, the loader has to be written in assembly
45 language.
46
47 Pintos' loader first initializes the CPU.  The first important part of
48 this is to enable the A20 line, that is, the CPU's address line
49 numbered 20.  For historical reasons, PCs start out with this address
50 line fixed at 0, which means that attempts to access memory beyond the
51 first 1 MB (2 raised to the 20th power) will fail.  Pintos wants to
52 access more memory than this, so we have to enable it.
53
54 Next, the loader asks the BIOS for the PC's memory size.  Again for
55 historical reasons, the function that we call in the BIOS to do this
56 can only detect up to 64 MB of RAM, so that's the practical limit that
57 Pintos can support.  The memory size is stashed away in a location in
58 the loader that the kernel can read after it boots.
59
60 Third, the loader creates a basic page table.  This page table maps
61 the 64 MB at the base of virtual memory (starting at virtual address
62 0) directly to the identical physical addresses.  It also maps the
63 same physical memory starting at virtual address
64 @code{LOADER_PHYS_BASE}, which defaults to @t{0xc0000000} (3 GB).  The
65 Pintos kernel only wants the latter mapping, but there's a
66 chicken-and-egg problem if we don't include the former: our current
67 virtual address is roughly @t{0x7c00}, the location where the BIOS
68 loaded us, and we can't jump to @t{0xc0007c00} until we turn on the
69 page table, but if we turn on the page table without jumping there,
70 then we've just pulled the rug out from under ourselves.  At any rate,
71 it's necessary.
72
73 After the page table is initialized, we load the CPU's control
74 registers to turn on protected mode and paging, and then we set up the
75 segment registers.  We aren't equipped to handle interrupts in
76 protected mode yet, so we disable interrupts.
77
78 Finally it's time to load the kernel from disk.  We choose a simple,
79 although inflexible, method to do this: we program the IDE disk
80 controller directly.  We assume that the kernel is stored starting
81 from the second sector of the first IDE disk (the first sector
82 contains the boot loader itself).  We also assume that the BIOS has
83 already set up the IDE controller for us.  We read
84 @code{KERNEL_LOAD_PAGES} 4 kB pages of data from the disk directly
85 into virtual memory starting @code{LOADER_KERN_BASE} bytes past
86 @code{LOADER_PHYS_BASE}, which by default means that we load the
87 kernel starting 1 MB into physical memory.
88
89 Then we jump to the start of the compiled kernel image.  Using the
90 ``linker script'' in @file{threads/kernel.lds.S}, the kernel has
91 arranged that it begins with the assembly module
92 @file{threads/start.S}.  This assembly module just calls
93 @func{main}, which never returns.
94
95 There's one more trick to the loader: the Pintos kernel command line
96 is stored in the boot loader.  The @command{pintos} program actually
97 modifies the boot loader on disk each time it runs the kernel, putting
98 in whatever command line arguments the user supplies to the kernel,
99 and then the kernel at boot time reads those arguments out of the boot
100 loader in memory.  This is something of a nasty hack, but it is simple
101 and effective.
102
103 @node Kernel Initialization
104 @subsection Kernel Initialization
105
106 The kernel proper starts with the @func{main} function.  The
107 @func{main} function is written in C, as will be most of the code we
108 encounter in Pintos from here on out.
109
110 When @func{main} starts, the system is in a pretty raw state.  We're
111 in protected mode with paging enabled, but hardly anything else is
112 ready.  Thus, the @func{main} function consists primarily of calls
113 into other Pintos modules' initialization functions.  You should
114 notice that these are usually named @func{@var{module}_init}, where
115 @var{module} is the module's name, @file{@var{module}.c} is the
116 module's source code, and @file{@var{module}.h} is the module's
117 header.
118
119 First we initialize kernel RAM in @func{ram_init}.  The first step
120 is to clear out the kernel's so-called ``BSS'' segment.  The BSS is a
121 segment that should be initialized to all zeros.  In C, whenever you
122 declare a variable outside a function without providing an
123 initializer, that variable goes into the BSS.@footnote{This isn't
124 actually required by the ANSI C standard, but it is the case with most
125 implementations of C on most machines.}  Because it's all zeros, the
126 BSS isn't stored in the image that the loader brought into memory.  We
127 just use @func{memset} to zero it out.  The other task of
128 @func{ram_init} is to read out the machine's memory size from where
129 the loader stored it and put it into the @code{ram_pages} variable for
130 later use.
131
132 Next, @func{thread_init} initializes the thread system.  We will defer
133 full discussion to our discussion of Pintos threads below.  It is
134 called so early in initialization because the console, initialized
135 just below, tries to use locks and locks in turn require there to be a
136 running thread.
137
138 Then we initialize the console so that we can use @func{printf}.
139 @func{main} calls @func{vga_init}, which initializes the VGA text
140 display and clears the screen.  It also calls @func{serial_init_poll}
141 to initialize the first serial port in ``polling mode,'' that is,
142 where the kernel busy-waits for the port to be ready for each
143 character to be output.  (We use polling mode until we're ready to set
144 up interrupts later.)  Finally we initialize the console device and
145 print a startup message to the console.
146
147 @func{main} calls @func{argv_init} to parse the kernel command line.
148 This entails reading the command line out of the loader and updating
149 global variables appropriately.
150
151 The next block of functions we call initialize the kernel's memory
152 system.  @func{palloc_init} sets up the kernel page allocator, which
153 doles out memory one or more pages at a time.  @func{malloc_init} sets
154 up the allocator that handles odd-sized allocations.
155 @func{paging_init} sets up a page table for the kernel.
156
157 In projects 2 and later, @func{main} also calls @func{tss_init} and
158 @func{gdt_init}, but we'll talk about those later.
159
160 @func{main} calls @func{random_init} to initialize the kernel random
161 number generator.  @func{argv_init} might already have done this (if
162 the user specified @option{-rs} on the @command{pintos} command line)
163 but calling it a second time is harmless and has no effect.
164
165 We initialize the interrupt system in the next set of calls.
166 @func{intr_init} sets up the CPU's @dfn{interrupt descriptor table}
167 (IDT) to ready it for interrupt handling, then @func{timer_init} and
168 @func{kbd_init} prepare us to handle timer interrupts and keyboard
169 interrupts, respectively.  In projects 2 and later, we also prepare to
170 handle interrupts caused by user programs using @func{exception_init}
171 and @func{syscall_init}.
172
173 Now that interrupts are set up, we can start preemptively scheduling
174 threads with @func{thread_start}, which also enables interrupts.
175 Interrupt-driven serial port I/O is also possible now, so we use
176 @func{serial_init_queue} to switch to that mode.
177
178 If the filesystem is compiled in, as it will be in project 2 and
179 later, we now initialize the disks with @func{disk_init}, then the
180 filesystem with @func{filesys_init}, and run any operations that were
181 requested on the kernel command line with @func{fsutil_run}.
182
183 Boot is complete, so we print a message.
184
185 For project 1, now we execute @func{test}, which runs whatever test is
186 currently compiled into the kernel.  For later projects, we will
187 instead run a user program and wait for it to complete.
188
189 Finally, if @option{-q} was specified on the kernel command line, we
190 call @func{power_off} to terminate the machine simulator.  Otherwise,
191 @func{main} calls @func{thread_exit}, which allows any other running
192 threads to continue running.
193
194 @node Threads Tour
195 @section Threads
196
197 @menu
198 * struct thread::               
199 @end menu
200
201 @node struct thread
202 @subsection @struct{thread}
203
204 The main Pintos data structure for threads is @struct{thread},
205 declared in @file{threads/thread.h}.  @struct{thread} has these
206 members with the given type:
207
208 @table @code
209 @item tid_t tid;
210 The thread's thread identifier or @dfn{tid}.  Every thread must have a
211 tid that is unique over the entire lifetime of the kernel.  By
212 default, @code{tid_t} is a @code{typedef} for @code{int} and each new
213 thread receives the numerically next higher tid, starting from 1 for
214 the initial process.  You can change the type and the numbering scheme
215 if you like.
216
217 @item enum thread_status status;
218 The thread's state, one of these:
219
220 @table @code
221 @item THREAD_RUNNING
222 The thread is running.  Exactly one thread is running at a given time.
223 @func{thread_current} returns the running thread.
224
225 @item THREAD_READY
226 The thread is ready to run, but it's not running right now.  The
227 thread could be selected to run the next time the scheduler is
228 invoked.  Ready threads are kept in a doubly linked list called
229 @code{ready_list}.
230
231 @item THREAD_BLOCKED
232 The thread is waiting for something, e.g.@: a lock to become
233 available, an interrupt to be invoked.  The thread won't be scheduled
234 again until it transitions to the @code{THREAD_READY} state with a
235 call to @func{thread_unblock}.
236
237 @item THREAD_DYING
238 The thread will be destroyed by the scheduler after switching to the
239 next thread.
240 @end table
241
242 @item char name[16];
243 The thread's name as a string, or at least the first few characters of
244 it.
245
246 @item uint8_t *stack;
247 Every thread has its own stack to keep track of its state.  When the
248 thread is running, the CPU's stack pointer register tracks the top of
249 the stack and this member is unused.  But when the CPU switches to
250 another thread, this member saves the thread's stack pointer.  No
251 other members are needed to save the thread's registers, because the
252 other registers that must be saved are saved on the stack.
253
254 @item int priority;
255 A thread priority, ranging from the lowest possible priority
256 @code{PRI_MIN} (0) to the highest possible priority @code{PRI_MAX}
257 (59).  Pintos as provided ignores thread priorities, but you will
258 implement priority scheduling in problem 1-3 (@pxref{Problem 1-3
259 Priority Scheduling}).
260
261 @item list_elem elem;
262 A ``list element'' used to put the thread into doubly linked lists,
263 either the list of threads ready to run or a list of threads waiting
264 on a semaphore.  Take a look at @file{lib/kernel/list.h} for
265 information on how to use the Pintos doubly linked list ADT.
266
267 @item uint32_t *pagedir;
268 Only present in project 2 and later.
269
270 @item unsigned magic;
271 Always set to @code{THREAD_MAGIC}, which is just a random number
272 defined in @file{threads/thread.c}, and used to detect stack overflow.
273 See below for more information.
274 @end table
275
276 Every @struct{thread} occupies the beginning of its own page of
277 memory.  The rest of the page is used for the thread's stack, which
278 grows downward from the end of the page.  It looks like this:
279
280 @example
281         4 kB +---------------------------------+
282              |          kernel stack           |
283              |                |                |
284              |                |                |
285              |                V                |
286              |         grows downward          |
287              |                                 |
288              |                                 |
289              |                                 |
290              |                                 |
291              |                                 |
292              |                                 |
293              |                                 |
294              |                                 |
295              +---------------------------------+
296              |              magic              |
297              |                :                |
298              |                :                |
299              |               name              |
300              |              status             |
301         0 kB +---------------------------------+
302 @end example
303
304 The upshot of this is twofold.  First, @struct{thread} must not be
305 allowed to grow too big.  If it does, then there will not be enough
306 room for the kernel stack.  Our base @struct{thread} is only a few
307 bytes in size.  It probably should stay well under 1 kB.
308
309 Second, kernel stacks must not be allowed to grow too large.  If a
310 stack overflows, it will corrupt the thread state.  Thus, kernel
311 functions should not allocate large structures or arrays as non-static
312 local variables.  Use dynamic allocation with @func{malloc} or
313 @func{palloc_get_page} instead.
314
315 This brings us to the purpose of @struct{thread}'s @code{magic}
316 member.  If a thread's stack does overflow, then @code{magic} will be
317 the first member of @struct{thread} to be overwritten, because it is
318 closest to the kernel stack.  Thus, some of the thread functions
319 (notably @func{thread_current}) check that @code{magic} has the proper
320 value.
321
322 @node Thread Functions
323 @subsection Thread Functions
324
325 @file{threads/thread.c} implements several public functions for
326 thread support.  Let's take a look at some of them:
327
328 @deftypefun void thread_init (void)
329 Called by @func{main} to initialize the thread system.  Its main
330 purpose is to create a @struct{thread} for Pintos's initial thread.
331 This is possible because the Pintos loader sets up the initial
332 thread's stack at the end of a page.  Before @func{thread_init} runs,
333 @func{thread_current} will fail because the running thread's
334 @code{magic} value is incorrect.  Lots of functions call
335 @func{thread_current} directly or indirectly, including
336 @func{lock_acquire} for locking a lock, so @func{thread_init} is
337 called early in Pintos initialization.
338 @end deftypefun
339
340 @deftypefun void thread_start (void)
341 Called by @func{main} to start the scheduler.  Creates the idle
342 thread, that is, the thread that is scheduled when no other thread is
343 ready.  Then enables interrupts, which enables the scheduler because
344 processes are rescheduled in the return path from the timer
345 interrupt.  FIXME
346 @end deftypefun
347
348 @deftypefun void thread_tick (void)
349 Called by @func{timer_interrupt} on every timer interrupt.  Just
350 increments counters that keep track of how often various kinds of
351 threads run.
352 @end deftypefun
353
354 @deftypefun void thread_print_stats (void)
355 Prints the statistics kept by @func{thread_ticK] to the console.
356 Called when Pintos is terminating.
357 @end deftypefun
358
359 @deftypefun void thread_create (const char *@var{name}, int @var{priority}, @
360             thread_func *@var{func}, void *@var{aux}) Creates and
361 starts a new thread named @var{name} with the given @var{priority},
362 returning the new thread's tid.  The thread executes @var{func},
363 passing @var{aux} as the function's single argument.
364
365 @func{thread_create} works by allocating a page for the thread's
366 @struct{thread} and stack and initializing its members, then setting
367 up a set of fake stack frames for it (we'll talk more about this
368 later).  The thread was initialized in the blocked state, so the final
369 action before returning is to unblock it, allowing the new thread to
370 be scheduled.
371 @end deftypefun