Fix typo.
[pintos-anon] / doc / vm.texi
1 @node Project 3--Virtual Memory, Project 4--File Systems, Project 2--User Programs, Top
2 @chapter Project 3: Virtual Memory
3
4 By now you should be familiar with the inner workings of Pintos.
5 You've already come a long way: your OS can properly handle multiple
6 threads of execution with proper synchronization, and can load
7 multiple user programs at once.  However, when loading user programs,
8 your OS is limited by how much main memory the simulated machine has.
9 In this assignment, you will remove that limitation.
10
11 You will be using the @file{vm} directory for this project.  The
12 @file{vm} directory contains only the @file{Makefile}s.  The only
13 change from @file{userprog} is that this new @file{Makefile} turns on
14 the setting @option{-DVM}.  All code you write will either be newly
15 generated files (e.g.@: if you choose to implement your paging code in
16 their own source files), or will be modifications to pre-existing code
17 (e.g.@: you will change the behavior of @file{process.c}
18 significantly).
19
20 There are only a couple of source files you will probably be
21 encountering for the first time:
22
23 @table @file
24 @item devices/disk.h
25 @itemx devices/disk.c
26 Provides access to the physical disk, abstracting away the rather
27 awful IDE interface.
28 @end table
29
30 You will be building this assignment on the last one.  It will benefit
31 you to get your project 2 in good working order before this assignment
32 so those bugs don't keep haunting you.
33
34 All the test programs from the previous project should also work with
35 this project.  You should also write programs to test the new features
36 introduced in this project.
37
38 You will continue to handle Pintos disks and file systems the same way
39 you did in the previous assignment (@pxref{Using the File System}).
40
41 @menu
42 * VM Design::                   
43 * Page Faults::                 
44 * Disk as Backing Store::       
45 * Memory Mapped Files::         
46 * Stack::                       
47 * Problem 3-1 Page Table Management::  
48 * Problem 3-2 Paging To and From Disk::  
49 * Problem 3-3 Memory Mapped Files::  
50 * Virtual Memory FAQ::          
51 @end menu
52
53 @node VM Design
54 @section A Word about Design
55
56 It is important for you to note that in addition to getting virtual
57 memory working, this assignment is also meant to be an open-ended
58 design problem.  We will expect you to come up with a design that
59 makes sense.  You will have the freedom to choose how to handle page
60 faults, how to organize the swap disk, how to implement paging, etc.
61 In each case, we will expect you to provide a defensible justification
62 in your design documentation as to why your choices are reasonable.
63 You should evaluate your design on all the available criteria: speed
64 of handling a page fault, space overhead in memory, minimizing the
65 number of page faults, simplicity, etc.
66
67 In keeping with this, you will find that we are going to say as little
68 as possible about how to do things.  Instead we will focus on what end
69 functionality we require your OS to support.
70
71 @node Page Faults
72 @section Page Faults
73
74 For the last assignment, whenever a context switch occurred, the new
75 process would install its own page table into the machine.  The page
76 table contained all the virtual-to-physical translations for the
77 process.  Whenever the processor needed to look up a translation, it
78 consulted the page table.  As long as the process only accessed
79 memory that it owned, all was well.  If the process accessed
80 memory it didn't own, it ``page faulted'' and @func{page_fault}
81 terminated the process.
82
83 When we implement virtual memory, the rules have to change.  A page
84 fault is no longer necessarily an error, since it might only indicate
85 that the page must be brought in from a disk file or from swap.  You
86 will have to implement a more sophisticated page fault handler to
87 handle these cases.
88
89 On the 80@var{x}86, the page table format is fixed by hardware.  We
90 have provided code for managing page tables for you to use in
91 @file{userprog/pagedir.c}.  The functions in there should provide an
92 abstract interface to all the page table functionality that you need
93 to complete the project.  However, you may still find it worthwhile to
94 understand a little about the hardware page table format, so we'll go
95 into a little of detail about that in this section.
96
97 The top-level paging data structure is a 4 kB page called the ``page
98 directory'' (PD) arranged as an array of 1,024 32-bit page directory
99 entries (PDEs), each of which represents 4 MB of virtual memory.  Each
100 PDE may point to the physical address of another 4 kB page called a
101 ``page table'' (PT) arranged in the same fashion as an array of 1,024
102 32-bit page table entries (PTEs), each of which translates a single 4
103 kB virtual page into physical memory.
104
105 Thus, translation of a virtual address into a physical address follows
106 the three-step process illustrated in the diagram
107 below:@footnote{Actually, virtual to physical translation on the
108 80@var{x}86 architecture happens via an intermediate ``linear
109 address,'' but Pintos (and most other 80@var{x}86 OSes) set up the CPU
110 so that linear and virtual addresses are one and the same, so that you
111 can effectively ignore this CPU feature.}
112
113 @enumerate 1
114 @item
115 The top 10 bits of the virtual address (bits 22:32) are used to index
116 into the page directory.  If the PDE is marked ``present,'' the
117 physical address of a page table is read from the PDE thus obtained.
118 If the PDE is marked ``not present'' then a page fault occurs.
119
120 @item
121 The next 10 bits of the virtual address (bits 12:22) are used to index
122 into the page table.  If the PTE is marked ``present,'' the physical
123 address of a data page is read from the PTE thus obtained.  If the PTE
124 is marked ``not present'' then a page fault occurs.
125
126
127 @item
128 The bottom 12 bits of the virtual address (bits 0:12) are added to the
129 data page's physical base address, producing the final physical
130 address.
131 @end enumerate
132
133 @example
134 @group
135 32                    22                     12                      0
136 +--------------------------------------------------------------------+
137 | Page Directory Index |   Page Table Index   |    Page Offset       |
138 +--------------------------------------------------------------------+
139              |                    |                     |
140      _______/             _______/                _____/
141     /                    /                       /
142    /    Page Directory  /      Page Table       /    Data Page
143   /     .____________. /     .____________.    /   .____________.
144   |1,023|____________| |1,023|____________|    |   |____________|
145   |1,022|____________| |1,022|____________|    |   |____________|
146   |1,021|____________| |1,021|____________|    \__\|____________|
147   |1,020|____________| |1,020|____________|       /|____________|
148   |     |            | |     |            |        |            |
149   |     |            | \____\|            |_       |            |
150   |     |      .     |      /|      .     | \      |      .     |
151   \____\|      .     |_      |      .     |  |     |      .     |
152        /|      .     | \     |      .     |  |     |      .     |
153         |      .     |  |    |      .     |  |     |      .     |
154         |            |  |    |            |  |     |            |
155         |____________|  |    |____________|  |     |____________|
156        4|____________|  |   4|____________|  |     |____________|
157        3|____________|  |   3|____________|  |     |____________|
158        2|____________|  |   2|____________|  |     |____________|
159        1|____________|  |   1|____________|  |     |____________|
160        0|____________|  \__\0|____________|  \____\|____________|
161                            /                      /
162 @end group
163 @end example
164
165 Header @file{threads/mmu.h} has useful functions for various
166 operations on virtual addresses.  You should look over the header
167 yourself, but its most important functions include these:
168
169 @table @code
170 @item pd_no(@var{va})
171 Returns the page directory index in virtual address @var{va}.
172
173 @item pt_no(@var{va})
174 Returns the page table index in virtual address @var{va}.
175
176 @item pg_ofs(@var{va})
177 Returns the page offset in virtual address @var{va}.
178
179 @item pg_round_down(@var{va})
180 Returns @var{va} rounded down to the nearest page boundary, that is,
181 @var{va} but with its page offset set to 0.
182
183 @item pg_round_up(@var{va})
184 Returns @var{va} rounded up to the nearest page boundary.
185 @end table
186
187 @node Disk as Backing Store
188 @section Disk as Backing Store
189
190 In VM systems, since memory is less plentiful than disk, you will
191 effectively use memory as a cache for disk.  Looking at it from
192 another angle, you will use disk as a backing store for memory.  This
193 provides the abstraction of an (almost) unlimited virtual memory size.
194 Part of your task in this project is to do this, with the additional
195 constraint that your performance should be close to that provided by
196 physical memory.  You will use the page tables' ``dirty'' bits to
197 denote whether pages need to be written back to disk when they're
198 evicted from main memory and the ``accessed'' bit for page replacement
199 algorithms.  Whenever the hardware writes memory, it sets the dirty
200 bit, and if it reads or writes to the page, it sets the accessed bit.
201
202 As with any caching system, performance depends on the policy used to
203 decide which things are kept in memory and which are only stored on
204 disk.  On a page fault, the kernel must decide which page to replace.
205 Ideally, it will throw out a page that will not be referenced for a
206 long time, keeping in memory those pages that are soon to be
207 referenced.  Another consideration is that if the replaced page has
208 been modified, the page must be first saved to disk before the needed
209 page can be brought in.  Many virtual memory systems avoid this extra
210 overhead by writing modified pages to disk in advance, so that later
211 page faults can be completed more quickly (but you do not have to
212 implement this optimization).
213
214 @node Memory Mapped Files
215 @section Memory Mapped Files
216
217 The traditional way to access the file system is via @code{read} and
218 @code{write} system calls, but that requires an extra level of copying
219 between the kernel and the user level.  A secondary interface is
220 simply to ``map'' the file into the virtual address space.  The
221 program can then use load and store instructions directly on the file
222 data.  (An alternative way of viewing the file system is as ``durable
223 memory.''  Files just store data structures.  If you access data
224 structures in memory using load and store instructions, why not access
225 data structures in files the same way?)
226
227 Memory mapped files are typically implemented using system calls.  One
228 system call maps the file to a particular part of the address space.
229 For example, one might conceptually map the file @file{foo}, which is
230 1000 bytes
231 long, starting at address 5000.  Assuming that nothing else is already
232 at virtual addresses 5000@dots{}6000, any memory accesses to these
233 locations will access the corresponding bytes of @file{foo}.
234
235 A consequence of memory mapped files is that address spaces are
236 sparsely populated with lots of segments, one for each memory mapped
237 file (plus one each for code, data, and stack).  You will implement
238 memory mapped files in problem 3-3.  You should
239 design your solutions to problems 3-1 and 3-2 to anticipate this.
240
241 @node Stack
242 @section Stack
243
244 In project 2, the stack was a single page at the top of the user
245 virtual address space.  The stack's location does not change in this
246 project, but your kernel should allocate additional pages to the stack
247 on demand.  That is, if the stack grows past its current bottom, the
248 system should allocate additional pages for the stack as necessary
249 (unless those pages are unavailable because they are in use by another
250 segment).
251
252 It is impossible to predict how large the stack will grow at compile
253 time, so we must allocate pages as necessary.  You should only allocate
254 additional pages if they ``appear'' to be stack accesses.  You must
255 devise a heuristic that attempts to distinguish stack accesses from
256 other accesses.  Document and explain the heuristic in your
257 design documentation.
258
259 The first stack page need not be loaded lazily.  You can initialize it
260 with the command line at load time, with no need to wait for it to be
261 faulted in.  Even if you did wait, the very first instruction in the
262 user program is likely to be one that faults in the page.
263
264 Stack facts:
265
266 @itemize
267 @item
268 The user program's current stack pointer is in the @struct{intr_frame}'s
269 @code{esp} member.
270
271 @item
272 Only buggy user programs write to memory within the stack but below the
273 stack pointer.  This is because more advanced OSes may interrupt a
274 process at any time to deliver a ``signal'' and this uses the stack.
275
276 @item
277 The 80@var{x}86 @code{push} instruction may cause a page fault 4 bytes
278 below the stack pointer, because it checks access permissions before it
279 adjusts the stack pointer.  (Otherwise, the instruction would not be
280 restartable in a straightforward fashion.)
281
282 @item
283 Similarly, the 80@var{x}86 @code{pusha} instruction, which pushes all 32
284 bytes of the 8 general-purpose registers at once, may cause a page fault
285 32 bytes below the stack pointer.
286
287 @item
288 Most OSes impose some sort of limit on the stack size.  Sometimes it is
289 user-adjustable.
290 @end itemize
291
292 @node Problem 3-1 Page Table Management
293 @section Problem 3-1: Page Table Management
294
295 Implement page directory and page table management to support virtual
296 memory.  You will need data structures to accomplish the following
297 tasks:
298
299 @itemize @bullet
300 @item
301 Some way of translating in software from virtual page frames to
302 physical page frames.  Consider using a hash table (@pxref{Hash
303 Table}).
304
305 It is possible to do this translation without adding a new data
306 structure, by modifying the code in @file{userprog/pagedir.c}.  However,
307 if you do that you'll need to carefully study and understand section 3.7
308 in @bibref{IA32-v3}, and in practice it is probably easier to add a new
309 data structure.
310
311 @item
312 Some way of finding a page on disk if it is not in memory.  You won't
313 need this data structure until problem 3-2, but planning ahead is a
314 good idea.
315
316 You can generalize the virtual-to-physical page table, so that it allows
317 you to locate a page wherever it is in physical memory or on disk, or
318 you can make this a separate table.
319
320 @item
321 Some way of translating from physical page frames back to virtual page
322 frames, so that when you evict a physical page from its frame, you can
323 invalidate its translation(s).
324 @end itemize
325
326 The page fault handler, @func{page_fault} in
327 @file{threads/exception.c}, needs to do roughly the following:
328
329 @enumerate 1
330 @item
331 Locate the page backing the virtual
332 address that faulted.  It might be in the file system, in swap,
333 or it might be an invalid virtual address.
334 If you implement sharing, it might even
335 already be in physical memory and just not set up in the page table,
336
337 If the virtual address is invalid, that is, if there's nothing
338 assigned to go there, or if the virtual address is above
339 @code{PHYS_BASE}, meaning that it belongs to the kernel instead of the
340 user, then the process's memory access must be disallowed.  You should
341 terminate the process at this point, being sure to free all of its
342 resources.
343
344 @item
345 If the page is not in physical memory, fetch it by appropriate means.
346 If necessary to make room, first evict some other page from memory.
347 (When you do that you need to first remove references to the page from
348 any page table that refers to it.)
349
350 @item
351 Point the page table entry for the faulting virtual address to the
352 physical page.  You can use the functions in @file{userprog/pagedir.c}.
353 @end enumerate
354
355 You'll need to modify the ELF loader in @file{userprog/process.c} to
356 do page table management according to your new design.  As supplied,
357 it reads all the process's pages from disk and initializes the page
358 tables for them at the same time.  For testing purposes, you'll
359 probably want to leave the code that reads the pages from disk, but
360 use your new page table management code to construct the page tables
361 only as page faults occur for them.
362
363 You should use the @func{palloc_get_page} function to get the page
364 frames that you use for storing user virtual pages.  Be sure to pass
365 the @code{PAL_USER} flag to this function when you do so, because that
366 allocates pages from a ``user pool'' separate from the ``kernel pool''
367 that other calls to @func{palloc_get_page} make.
368
369 There are many possible ways to implement virtual memory.  The above
370 is simply an outline of our suggested implementation.
371
372 @node Problem 3-2 Paging To and From Disk
373 @section Problem 3-2: Paging To and From Disk
374
375 Implement paging to and from files and the swap disk.  You may use the
376 disk on interface @code{hd1:1} as the swap disk, using the disk
377 interface prototyped in @code{devices/disk.h}.  From the @file{vm/build}
378 directory, use the command @code{pintos make-disk swap.dsk @var{n}} to
379 create an @var{n} MB swap disk named @file{swap.dsk}.  Afterward,
380 @file{swap.dsk} will automatically be attached when you run
381 @command{pintos}.
382
383 You will need routines to move a page from memory to disk and from
384 disk to memory, where ``disk'' is either a file or the swap disk.  If
385 you do everything correctly, your VM should still work when you
386 implement your own file system for the next assignment.
387
388 You will need a way to track pages which are used by a process but
389 which are not in physical memory, to fully handle page faults.  Pages
390 that you write to swap should not be constrained to be in sequential
391 order.  You will also need a way to track all of the physical memory
392 pages, to find an unused one when needed, or to evict a page
393 when memory is needed but no empty pages are available.  The data
394 structures that you designed for problem 3-1 should do most of the work for
395 you.
396
397 You will need a page replacement algorithm.  The hardware sets the
398 accessed and dirty bits when it accesses memory.  You can gain access
399 to this information using the functions prototyped in
400 @file{userprog/pagedir.h}.  You should be able to take advantage of
401 this information to implement some algorithm which attempts to achieve
402 LRU-type behavior.  We expect that your algorithm perform at least as
403 well as a reasonable implementation of the second-chance (clock)
404 algorithm.  You will need to show in your test cases the value of your
405 page replacement algorithm by demonstrating for some workload that it
406 pages less frequently using your algorithm than using some inferior
407 page replacement policy.  The canonical example of a poor page
408 replacement policy is random replacement.
409
410 You must write your code so that we can choose a page replacement policy
411 at compile time.  By default, the LRU-like algorithm must be in effect,
412 but we must be able to choose random replacement by inserting the line
413 @code{#define RANDOM_REPLACEMENT 1} in @file{constants.h}.
414 @xref{Conditional Compilation}, for details.
415
416 Since you will already be paging from disk, you should implement a
417 ``lazy'' loading scheme for new processes.  When a process is created,
418 it will not run immediately.  Therefore, it doesn't make sense to load
419 all its code, data, and stack into memory when the process is created,
420 since it might incur additional disk accesses to do so (if it gets
421 paged out before it runs).  When loading a new process, you should
422 leave most pages on disk, and bring them in as demanded when the
423 program begins running.  Your VM system should also use the executable
424 file itself as backing store for read-only segments, since these
425 segments won't change.
426
427 There are a few special cases.  Look at the loop in
428 @func{load_segment} in @file{userprog/process.c}.  Each time
429 around the loop, @code{read_bytes} represents the number of bytes to
430 read from the executable file and @code{zero_bytes} represents the number
431 of bytes to initialize to zero following the bytes read.  The two
432 always sum to @code{PGSIZE}.  The page handling depends on these
433 variables' values:
434
435 @itemize @bullet
436 @item
437 If @code{read_bytes} equals @code{PGSIZE}, the page should be demand
438 paged from disk on its first access.
439
440 @item 
441 If @code{zero_bytes} equals @code{PGSIZE}, the page does not need to
442 be read from disk at all because it is all zeroes.  You should handle
443 such pages by creating a new page consisting of all zeroes at the
444 first page fault.
445
446 @item
447 If neither @code{read_bytes} nor @code{zero_bytes} equals
448 @code{PGSIZE}, then part of the page is to be read from disk and the
449 remainder zeroed.  This is a special case.  You are allowed to handle
450 it by reading the partial page from disk at executable load time and
451 zeroing the rest of the page.  This is the only case in which we will
452 allow you to load a page in a non-``lazy'' fashion.  Many real OSes
453 such as Linux do not load partial pages lazily.
454 @end itemize
455
456 Incidentally, if you have trouble handling the third case above, you
457 can eliminate it temporarily by linking the test programs with a
458 special ``linker script.''  Read @file{tests/userprog/Makefile} for
459 details.  We will not test your submission with this special linker
460 script, so the code you turn in must properly handle all cases.
461
462 For extra credit, you may implement sharing: when multiple processes
463 are created that use the same executable file, share read-only pages
464 among those processes instead of creating separate copies of read-only
465 segments for each process.  If you carefully designed your data
466 structures in problem 3-1, sharing of read-only pages should not make this
467 part significantly harder.
468
469 @node Problem 3-3 Memory Mapped Files
470 @section Problem 3-3: Memory Mapped Files
471
472 Implement memory mapped files.
473
474 You will need to implement the following system calls:
475
476 @table @code
477 @item SYS_mmap
478 @itemx bool mmap (int @var{fd}, void *@var{addr}, unsigned @var{length})
479
480 Maps the file open as @var{fd} into the process's address space
481 starting at @var{addr} for @var{length} bytes.  Returns true if
482 successful, false on failure.  Failure cases include the following:
483
484 @itemize @bullet
485 @item
486 @var{addr} is not page-aligned.
487
488 @item
489 @var{length} is not positive.
490
491 @item
492 The range of pages mapped overlaps any existing set of mapped pages,
493 including the stack or pages mapped at executable load time.
494 @end itemize
495
496 @var{length} is treated as if it were rounded up to the nearest
497 multiple of the page size, that is, as if the first statement in the
498 system call's implementation were
499 @example
500 length = ROUND_UP (length, PGSIZE);
501 @end example
502 (The @code{ROUND_UP} macro is defined in @file{<round.h>}.)
503 The remainder of this description assumes that this has been done.
504
505 If @var{length} is less than @var{fd}'s length, you should only map
506 the first @var{length} bytes of the file.  If @var{length} is greater
507 than @var{fd}'s length, when the file's length is also rounded up to a
508 page multiple, the call should fail.  Ideally it would extend the
509 file, but our file system does not yet support growing files.
510
511 If @var{length} is greater than @var{fd}'s (unrounded) length, then some
512 bytes in the final mapped page ``stick out'' beyond the end of the
513 file.  Set these bytes to zero when the page is faulted in from
514 disk, and discard them when the page is written back to disk.
515
516 Your VM system should use the @code{mmap}'d file itself as
517 backing store for the mapped segment.  That is, to evict a page mapped by
518 @code{mmap} must be evicted, write it to the file it was mapped from.
519 (In fact, you may choose to implement executable mappings as a special
520 case of file mappings.)
521
522 @item SYS_munmap
523 @itemx bool munmap (void *addr, unsigned length)
524
525 Unmaps @var{length} bytes starting at @var{addr}.  Returns true on
526 success, false on failure.  Failure cases include the following:
527
528 @itemize @bullet
529 @item
530 @var{addr} is not page-aligned.
531
532 @item
533 @var{length} is not positive.
534
535 @item
536 One or more pages within the range to be unmapped were not mapped
537 using the @code{mmap} system call.
538 @end itemize
539
540 As with @code{mmap}, @var{length} is treated as if it were rounded up
541 to the nearest multiple of the page size.
542
543 It is valid to unmap only some of the pages that were mapped in a
544 previous system call.
545 @end table
546
547 All mappings are implicitly unmapped when a process exits, whether via
548 @code{exit} or by any other means.  When a file is unmapped, whether
549 implicitly or explicitly, all outstanding changes are written to the
550 file, and the pages are removed from the process's list of used
551 virtual pages.
552
553 @node Virtual Memory FAQ
554 @section FAQ
555
556 @enumerate 1
557 @item
558 @b{Do we need a working HW 2 to implement HW 3?}
559
560 Yes.
561
562 @item
563 @anchor{Hash Table}
564 @b{How do I use the hash table provided in @file{lib/kernel/hash.c}?}
565
566 First, you need to embed a @code{hash_elem} object as a member of the
567 object that the hash table will contain.  Each @code{hash_elem} allows
568 the object to a member of at most one hash table at a given time.  All
569 the hash table functions that deal with hash table items actually use
570 the address of a @code{hash_elem}.  You can convert a pointer to a
571 @code{hash_elem} member into a pointer to the structure in which
572 member is embedded using the @code{hash_entry} macro.
573
574 Second, you need to decide on a key type.  The key should be something
575 that is unique for each object, because a given hash table may not
576 contain two objects with equal keys.  Then you need to write two
577 functions.  The first is a @dfn{hash function} that converts a key
578 into an integer.  Some sample hash functions that you can use or just
579 examine are given in @file{lib/kernel/hash.c}.  The second function
580 needed is a @dfn{comparison function} that compares a pair and returns
581 true if the first is less than the second.  These two functions have
582 to be compatible with the prototypes for @code{hash_hash_func} and
583 @code{hash_less_func} in @file{lib/kernel/hash.h}.
584
585 Here's a quick example.  Suppose you want to put @struct{thread}s
586 in a hash table.  First, add a @code{hash_elem} to the thread
587 structure by adding a line to its definition:
588
589 @example
590 hash_elem h_elem;               /* Hash table element. */
591 @end example
592
593 We'll choose the @code{tid} member in @struct{thread} as the key,
594 and write a hash function and a comparison function:
595
596 @example
597 /* Returns a hash for E. */
598 unsigned
599 thread_hash (const hash_elem *e, void *aux UNUSED)
600 @{
601   struct thread *t = hash_entry (e, struct thread, h_elem);
602   return hash_int (t->tid);
603 @}
604
605 /* Returns true if A's tid is less than B's tid. */
606 bool
607 thread_less (const hash_elem *a_, const hash_elem *b_, 
608              void *aux UNUSED)
609 @{
610   struct thread *a = hash_entry (a_, struct thread, h_elem);
611   struct thread *b = hash_entry (b_, struct thread, h_elem);
612   return a->tid < b->tid;
613 @}
614 @end example
615
616 Then we can create a hash table like this:
617
618 @example
619 struct hash threads;
620
621 hash_init (&threads, thread_hash, thread_less, NULL);
622 @end example
623
624 Finally, if @code{@var{t}} is a pointer to a @struct{thread},
625 then we can insert it into the hash table with:
626
627 @example
628 hash_insert (&threads, &@var{t}->h_elem);
629 @end example
630
631 If you have any other questions about hash tables, the CS109
632 and CS161 textbooks have good chapters on them, or you can come
633 to any of the TA's office hours for further clarification.
634
635 @item
636 @b{What are the @var{aux} parameters to the hash table functions good
637 for?}
638
639 In simple cases you won't have any need for the @var{aux} parameters.
640 In these cases you can just pass a null pointer to @func{hash_init}
641 for @var{aux} and ignore the values passed to the hash function and
642 comparison functions.  (You'll get a compiler warning if you don't use
643 the @var{aux} parameter, but you can turn that off with the
644 @code{UNUSED} macro, as shown above, or you can just ignore it.)
645
646 @var{aux} is useful when you have some property of the data in the
647 hash table that's both constant and needed for hashing or comparisons,
648 but which is not stored in the data items themselves.  For example, if
649 the items in a hash table contain fixed-length strings, but the items
650 themselves don't indicate what that fixed length is, you could pass
651 the length as an @var{aux} parameter.
652
653 @item
654 @b{The current implementation of the hash table does not do something
655 that we need it to do. What gives?}
656
657 You are welcome to modify it.  It is not used by any of the code we
658 provided, so modifying it won't affect any code but yours.  Do
659 whatever it takes to make it work the way you want.
660
661 @item
662 @b{What controls the layout of user programs?}
663
664 The linker is responsible for the layout of a user program in
665 memory. The linker is directed by a ``linker script'' which tells it
666 the names and locations of the various program segments.  You can
667 learn more about linker scripts by reading the ``Scripts'' chapter in
668 the linker manual, accessible via @samp{info ld}.
669 @end enumerate
670
671 @menu
672 * Problem 3-1 and 3-2 FAQ::    
673 * Problem 3-3 Memory Mapped File FAQ::  
674 @end menu
675
676 @node Problem 3-1 and 3-2 FAQ
677 @subsection Problem 3-1 and 3-2 FAQ
678
679 @enumerate 1
680 @item
681 @b{Does the virtual memory system need to support growth of the data
682 segment?}
683
684 No.  The size of the data segment is determined by the linker.  We
685 still have no dynamic allocation in Pintos (although it is possible to
686 ``fake'' it at the user level by using memory-mapped files).  However,
687 implementing it would add little additional complexity to a
688 well-designed system.
689
690 @item
691 @b{Why do I need to pass @code{PAL_USER} to @func{palloc_get_page}
692 when I allocate physical page frames?}@anchor{Why PAL_USER?}
693
694 You can layer some other allocator on top of @func{palloc_get_page}
695 if you like, but it should be the underlying mechanism, directly or
696 indirectly, for two reasons.  First, running out of pages in the user
697 pool just causes user programs to page, but running out of pages in
698 the kernel pool will cause all kinds of problems, because many kernel
699 functions depend on being able to allocate memory.  Second, you can
700 use the @option{-ul} option to @command{pintos} to limit the size of
701 the user pool, which makes it easy to test your VM implementation with
702 various user memory sizes.
703 @end enumerate
704
705 @node Problem 3-3 Memory Mapped File FAQ
706 @subsection Problem 3-3: Memory Mapped File FAQ
707
708 @enumerate 1
709 @item
710 @b{How do we interact with memory-mapped files?}
711
712 Let's say you want to map a file called @file{foo} into your address
713 space at address @t{0x10000000}. You open the file, determine its
714 length, and then use @code{mmap}:
715
716 @example
717 #include <stdio.h>
718 #include <syscall.h>
719
720 int main (void)
721 @{
722     void *addr = (void *) 0x10000000;
723     int fd = open ("foo");
724     int length = filesize (fd);
725     if (mmap (fd, addr, length))
726         printf ("success!\n");
727 @}
728 @end example
729
730 Suppose @file{foo} is a text file and you want to print the first 64
731 bytes on the screen (assuming, of course, that the length of the file
732 is at least 64).  Without @code{mmap}, you'd need to allocate a
733 buffer, use @code{read} to get the data from the file into the buffer,
734 and finally use @code{write} to put the buffer out to the display. But
735 with the file mapped into your address space, you can directly address
736 it like so:
737
738 @example
739 write (addr, 64, STDOUT_FILENO);
740 @end example
741
742 Similarly, if you wanted to replace the first byte of the file,
743 all you need to do is:
744
745 @example
746 addr[0] = 'b';
747 @end example
748
749 When you're done using the memory-mapped file, you simply unmap
750 it:
751
752 @example
753 munmap (addr, length);
754 @end example
755
756 @item
757 @b{What if two processes memory-map the same file?}
758
759 There is no requirement in Pintos that the two processes see
760 consistent data.  Unix handles this by making the processes share the
761 same physical page, but the @code{mmap} system call also has an
762 argument allowing the client to specify whether the page is shared or
763 private (i.e.@: copy-on-write).
764
765 @item
766 @b{What happens if a user removes a @code{mmap}'d file?}
767
768 You should follow the Unix convention and the mapping should still be
769 valid.  @xref{Removing an Open File}, for more information.
770
771 @item
772 @b{What if a process writes to a page that is memory-mapped, but the
773 location written to in the memory-mapped page is past the end
774 of the memory-mapped file?}
775
776 Can't happen.  @code{mmap} checks that the mapped region is within the
777 file's length and Pintos provides no way to shorten a file.  (Until
778 project 4, there's no way to extend a file either.)  You can remove a
779 file, but the mapping remains valid (see the previous question).
780
781 @item
782 @b{Do we have to handle memory mapping @code{stdin} or @code{stdout}?}
783
784 No.  Memory mapping implies that a file has a length and that a user
785 can seek to any location in the file.  Since the console device has
786 neither of these properties, @code{mmap} should return false when the
787 user attempts to memory map a file descriptor for the console device.
788
789 @item
790 @b{What happens when a process exits with mapped files?}
791
792 When a process finishes, each of its mapped files is implicitly
793 unmapped.  When a process @code{mmap}s a file and then writes into the
794 area for the file it is making the assumption the changes will be
795 written to the file.
796
797 @item
798 @b{If a user closes a mapped file, should it be automatically
799 unmapped?}
800
801 No, once created the mapping is valid until @code{munmap} is called
802 or the process exits.
803 @end enumerate