Add VM makefiles.
[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.  There is
12 no new code to get acquainted with for this assignment.  The @file{vm}
13 directory contains only the @file{Makefile}s.  The only change from
14 @file{userprog} is that this new @file{Makefile} turns on the setting
15 @option{-DVM}.  All code you write will either be newly generated
16 files (e.g.@: if you choose to implement your paging code in their own
17 source files), or will be modifications to pre-existing code (e.g.@:
18 you will change the behavior of @file{process.c} significantly).
19
20 You will be building this assignment on the last one.  It will benefit
21 you to get your project 2 in good working order before this assignment
22 so those bugs don't keep haunting you.
23
24 All the test programs from the previous project should also work with
25 this project.  You should also write programs to test the new features
26 introduced in this project.
27
28 @menu
29 * VM Design::                   
30 * Page Faults::                 
31 * Disk as Backing Store::       
32 * Memory Mapped Files::         
33 * Stack::                       
34 * Problem 3-1 Page Table Management::  
35 * Problem 3-2 Paging To and From Disk::  
36 * Problem 3-3 Memory Mapped Files::  
37 * Virtual Memory FAQ::          
38 @end menu
39
40 @node VM Design
41 @section A Word about Design
42
43 It is important for you to note that in addition to getting virtual
44 memory working, this assignment is also meant to be an open-ended
45 design problem.  We will expect you to come up with a design that
46 makes sense.  You will have the freedom to choose how to do software
47 translation on TLB misses, how to represent the swap partition, how to
48 implement paging, etc.  In each case, we will expect you to provide a
49 defensible justification in your design documentation as to why your
50 choices are reasonable.  You should evaluate your design on all the
51 available criteria: speed of handling a page fault, space overhead in
52 memory, minimizing the number of page faults, simplicity, etc.
53
54 In keeping with this, you will find that we are going to say as little
55 as possible about how to do things.  Instead we will focus on what end
56 functionality we require your OS to support.
57
58 @node Page Faults
59 @section Page Faults
60
61 For the last assignment, whenever a context switch occurred, the new
62 process would install its own page table into the machine.  The page
63 table contained all the virtual-to-physical translations for the
64 process.  Whenever the processor needed to look up a translation, it
65 consulted the page table.  As long as the process only accessed
66 memory that it didn't own, all was well.  If the process accessed
67 memory it didn't own, it ``page faulted'' and @code{page_fault()}
68 terminated the process.
69
70 When we implement virtual memory, the rules have to change.  A page
71 fault is no longer necessarily an error, since it might only indicate
72 that the page must be brought in from a disk file or from swap.  You
73 will have to implement a more sophisticated page fault handler to
74 handle these cases.
75
76 On the 80@var{x}86, the page table format is fixed by hardware.  The
77 top-level data structure is a 4 kB page called the ``page directory''
78 (PD) arranged as an array of 1,024 32-bit page directory entries
79 (PDEs), each of which represents 4 MB of virtual memory.  Each PDE may
80 point to the physical address of another 4 kB page called a ``page
81 table'' (PT) arranged in the same fashion as an array of 1,024 32-bit
82 page table entries (PTEs), each of which translates a single 4 kB
83 virtual page into physical memory.
84
85 Thus, translation of a virtual address into a physical address follows
86 the three-step process illustrated in the diagram
87 below:@footnote{Actually, virtual to physical translation on the
88 80@var{x}86 architecture happens via an intermediate ``linear
89 address,'' but Pintos (and most other 80@var{x}86 OSes) set up the CPU
90 so that linear and virtual addresses are one and the same, so that you
91 can effectively ignore this CPU feature.}
92
93 @enumerate 1
94 @item
95 The top 10 bits of the virtual address (bits 22:31) are used to index
96 into the page directory.  If the PDE is marked ``present,'' the
97 physical address of a page table is read from the PDE thus obtained.
98 If the PDE is marked ``not present'' then a page fault occurs.
99
100 @item
101 The next 10 bits of the virtual address (bits 12:21) are used to index
102 into the page table.  If the PTE is marked ``present,'' the physical
103 address of a data page is read from the PTE thus obtained.  If the PTE
104 is marked ``not present'' then a page fault occurs.
105
106
107 @item
108 The bottom 12 bits of the virtual address (bits 0:11) are added to the
109 data page's physical base address, producing the final physical
110 address.
111 @end enumerate
112
113 @example
114 32                    22                     12                      0
115 +--------------------------------------------------------------------+
116 | Page Directory Index |   Page Table Index   |    Page Offset       |
117 +--------------------------------------------------------------------+
118              |                    |                     |
119      _______/             _______/                _____/
120     /                    /                       /
121    /    Page Directory  /      Page Table       /    Data Page
122   /     .____________. /     .____________.    /   .____________.
123   |1,023|____________| |1,023|____________|    |   |____________|
124   |1,022|____________| |1,022|____________|    |   |____________|
125   |1,021|____________| |1,021|____________|    \__\|____________|
126   |1,020|____________| |1,020|____________|       /|____________|
127   |     |            | |     |            |        |            |
128   |     |            | \____\|            |_       |            |
129   |     |      .     |      /|      .     | \      |      .     |
130   \____\|      .     |_      |      .     |  |     |      .     |
131        /|      .     | \     |      .     |  |     |      .     |
132         |      .     |  |    |      .     |  |     |      .     |
133         |            |  |    |            |  |     |            |
134         |____________|  |    |____________|  |     |____________|
135        4|____________|  |   4|____________|  |     |____________|
136        3|____________|  |   3|____________|  |     |____________|
137        2|____________|  |   2|____________|  |     |____________|
138        1|____________|  |   1|____________|  |     |____________|
139        0|____________|  \__\0|____________|  \____\|____________|
140                            /                      /
141 @end example
142
143 Header @file{threads/mmu.h} has useful functions for various
144 operations on virtual addresses.  You should look over the header
145 yourself, but its most important functions include these:
146
147 @table @code
148 @item pd_no(@var{va})
149 Returns the page directory index in virtual address @var{va}.
150
151 @item pt_no(@var{va})
152 Returns the page table index in virtual address @var{va}.
153
154 @item pg_ofs(@var{va})
155 Returns the page offset in virtual address @var{va}.
156
157 @item pg_round_down(@var{va})
158 Returns @var{va} rounded down to the nearest page boundary, that is,
159 @var{va} but with its page offset set to 0.
160
161 @item pg_round_up(@var{va})
162 Returns @var{va} rounded up to the nearest page boundary.
163 @end table
164
165 @node Disk as Backing Store
166 @section Disk as Backing Store
167
168 In VM systems, since memory is less plentiful than disk, you will
169 effectively use memory as a cache for disk.  Looking at it from
170 another angle, you will use disk as a backing store for memory.  This
171 provides the abstraction of an (almost) unlimited virtual memory size.
172 Part of your task in this project is to do this, with the additional
173 constraint that your performance should be close to that provided by
174 physical memory.  You will use the page tables' ``dirty'' bits to
175 denote whether pages need to be written back to disk when they're
176 evicted from main memory and the ``accessed'' bit for page replacement
177 algorithms.  Whenever the hardware writes memory, it sets the dirty
178 bit, and if it reads or writes to the page, it sets the accessed bit.
179
180 As with any caching system, performance depends on the policy used to
181 decide which things are kept in memory and which are only stored on
182 disk.  On a page fault, the kernel must decide which page to replace.
183 Ideally, it will throw out a page that will not be referenced for a
184 long time, keeping in memory those pages that are soon to be
185 referenced.  Another consideration is that if the replaced page has
186 been modified, the page must be first saved to disk before the needed
187 page can be brought in.  Many virtual memory systems avoid this extra
188 overhead by writing modified pages to disk in advance, so that later
189 page faults can be completed more quickly.
190
191 @node Memory Mapped Files
192 @section Memory Mapped Files
193
194 The traditional way to access the file system is via @code{read} and
195 @code{write} system calls, but that requires an extra level of copying
196 between the kernel and the user level.  A secondary interface is
197 simply to ``map'' the file into the virtual address space.  The
198 program can then use load and store instructions directly on the file
199 data.  (An alternative way of viewing the file system is as ``durable
200 memory.''  Files just store data structures.  If you access data
201 structures in memory using load and store instructions, why not access
202 data structures in files the same way?)
203
204 Memory mapped files are typically implemented using system calls.  One
205 system call maps the file to a particular part of the address space.
206 For example, one might map the file @file{foo}, which is 1000 bytes
207 long, starting at address 5000.  Assuming that nothing else is already
208 at virtual addresses 5000@dots{}6000, any memory accesses to these
209 locations will access the corresponding bytes of @file{foo}.
210
211 A consequence of memory mapped files is that address spaces are
212 sparsely populated with lots of segments, one for each memory mapped
213 file (plus one each for code, data, and stack).  You will implement
214 memory mapped files for problem 3 of this assignment, but you should
215 design your solutions to problems 1 and 2 to account for this.
216
217 @node Stack
218 @section Stack
219
220 In project 2, the stack was a single page at the top of the user
221 virtual address space.  The stack's location does not change in this
222 project, but your kernel should allocate additional pages to the stack
223 on demand.  That is, if the stack grows past its current bottom, the
224 system should allocate additional pages for the stack as necessary,
225 unless those pages are unavailable because they are in use by another
226 segment, in which case some sort of fault should occur.
227
228 @node Problem 3-1 Page Table Management
229 @section Problem 3-1: Page Table Management
230
231 Implement page directory and page table management to support virtual
232 memory.  You will need data structures to accomplish the following
233 tasks:
234
235 @itemize @bullet
236 @item
237 Some way of translating in software from virtual page frames to
238 physical page frames (consider using a hash table---note
239 that we provide one in @file{lib/kernel}).
240
241 @item
242 Some way of translating from physical page frames back to virtual
243 page frames, so that when you replace a page, you can invalidate
244 its translation(s).
245
246 @item
247 Some way of finding a page on disk if it is not in memory.  You won't
248 need this data structure until part 2, but planning ahead is a good
249 idea.
250 @end itemize
251
252 You need to do the roughly the following to handle a page fault:
253
254 @enumerate 1
255 @item
256 Determine the location of the physical page backing the virtual
257 address that faulted.  It might be in the file system, in swap,
258 already be in physical memory and just not set up in the page table,
259 or it might be an invalid virtual address.
260
261 If the virtual address is invalid, that is, if there's no physical
262 page backing it, or if the virtual address is above @code{PHYS_BASE},
263 meaning that it belongs to the kernel instead of the user, then the
264 process's memory access must be disallowed.  You should terminate the
265 process at this point, being sure to free all of its resources.
266
267 @item
268 If the physical page is not in physical memory, bring it into memory.
269 If necessary to make room, first evict some other page from memory.
270 (When you do that you need to first remove references to the page from
271 any page table that refers to it.)
272
273 @item
274 Each user process's @code{struct thread} has a @samp{pagedir} member
275 that points to its own per-process page directory.  Read the PDE for
276 the faulting virtual address.
277
278 @item 
279 If the PDE is marked ``not present'' then allocate a new page table
280 page and initialize the PDE to point to the new page table.  As when
281 you allocated a data page, you might have to first evict some other
282 page from memory.
283
284 @item
285 Follow the PDE to the page table.  Point the PTE for the faulting
286 virtual address to the physical page found in step 2.
287 @end enumerate
288
289 You'll need to modify the ELF loader in @file{userprog/process.c} to
290 do page table management according to your new design.  As supplied,
291 it reads all the process's pages from disk and initializes the page
292 tables for them at the same time.  For testing purposes, you'll
293 probably want to leave the code that reads the pages from disk, but
294 use your new page table management code to construct the page tables
295 only as page faults occur for them.
296
297 There are many possible ways to implement virtual memory.  The above
298 is simply an outline of our suggested implementation.  You may choose
299 any implementation you like, as long as it accomplishes the goal.
300
301 @node Problem 3-2 Paging To and From Disk
302 @section Problem 3-2: Paging To and From Disk
303
304 Implement paging to and from disk.
305
306 You will need routines to move a page from memory to disk and from
307 disk to memory.  You may use the Pintos file system for swap space, or
308 you may use the disk on interface @code{hd1:1}, which is otherwise
309 unused.  A swap disk can theoretically be faster than using the file
310 system, because it avoid file system overhead and because the swap
311 disk and file system disk will be on separate hard disk controllers.
312 You will definitely need to be able to retrieve pages from files in
313 any case, so to avoid special cases it may be easier to use a file for
314 swap.  You will still be using the basic file system provided with
315 Pintos.  If you do everything correctly, your VM should still work
316 when you implement your own file system for the next assignment.
317
318 You will need a way to track pages which are used by a process but
319 which are not in physical memory, to fully handle page faults.  Pages
320 that you store on disk should not be constrained to be in sequential
321 order, and consequently your swap file (or swap disk) should not
322 require unused empty space.  You will also need a way to track all of
323 the physical memory pages, in order to find an unused one when needed,
324 or to evict a page when memory is needed but no empty pages are
325 available.  The data structures that you designed in part 1 should do
326 most of the work for you.
327
328 You will need a page replacement algorithm.  The hardware sets the
329 accessed and dirty bits when it accesses memory.  Therefore, you
330 should be able to take advantage of this information to implement some
331 algorithm which attempts to achieve LRU-type behavior.  We expect that
332 your algorithm perform at least as well as a reasonable implementation
333 of the second-chance (clock) algorithm.  You will need to show in your
334 test cases the value of your page replacement algorithm by
335 demonstrating for some workload that it pages less frequently using
336 your algorithm than using some inferior page replacement policy.  The
337 canonical example of a poor page replacement policy is random
338 replacement.
339
340 Since you will already be paging from disk, you should implement a
341 ``lazy'' loading scheme for new processes.  When a process is created,
342 it will not run immediately.  Therefore, it doesn't make sense to load
343 all its code, data, and stack into memory when the process is created,
344 since it might incur additional disk accesses to do so (if it gets
345 paged out before it runs).  When loading a new process, you should
346 leave most pages on disk, and bring them in as demanded when the
347 program begins running.  Your VM system should also use the executable
348 file itself as backing store for read-only segments, since these
349 segments won't change.
350
351 There are a few special cases.  Look at the loop in
352 @code{load_segment()} in @file{userprog/process.c}.  Each time
353 around the loop, @code{read_bytes} represents the number of bytes to
354 read from the executable file and @code{zero_bytes} represents the number
355 of bytes to initialize to zero following the bytes read.  The two
356 always sum to @code{PGSIZE}.  The page handling depends on these
357 variables' values:
358
359 @itemize @bullet
360 @item
361 If @code{read_bytes} equals @code{PGSIZE}, the page should be demand
362 paged from disk on its first access.
363
364 @item 
365 If @code{zero_bytes} equals @code{PGSIZE}, the page does not need to
366 be read from disk at all because it is all zeroes.  You should handle
367 such pages by creating a new page consisting of all zeroes at the
368 first page fault.
369
370 @item
371 If neither @code{read_bytes} nor @code{zero_bytes} equals
372 @code{PGSIZE}, then part of the page is to be read from disk and the
373 remainder zeroed.  This is a special case, which you should handle by
374 reading the partial page from disk at executable load time and zeroing
375 the rest of the page.  It is the only case in which loading should not
376 be ``lazy''; even real OSes such as Linux do not load partial pages
377 lazily.
378 @end itemize
379
380 Incidentally, if you have trouble handling the third case above, you
381 can eliminate it temporarily by linking the test programs with a
382 special ``linker script.''  Read @file{tests/userprog/Makefile} for
383 details.  We will not test your submission with this special linker
384 script, so the code you turn in must properly handle all cases.
385
386 You may optionally implement sharing: when multiple processes are
387 created that use the same executable file, share read-only pages among
388 those processes instead of creating separate copies of read-only
389 segments for each process.  If you carefully designed your data
390 structures in part 1, sharing of read-only pages should not make this
391 part significantly harder.
392
393 @node Problem 3-3 Memory Mapped Files
394 @section Problem 3-3: Memory Mapped Files
395
396 Implement memory mapped files.
397
398 You will need to implement the following system calls:
399
400 @table @asis
401 @item SYS_mmap
402 @itemx bool mmap (int @var{fd}, void *@var{addr}, unsigned @var{length})
403
404 Maps the file open as @var{fd} into the process's address space
405 starting at @var{addr} for @var{length} bytes.  Returns true if
406 successful, false on failure.  
407
408 @item SYS_munmap
409 @itemx bool munmap (void *addr, unsigned length)
410
411 Unmaps the segment specified by id.  This cannot be used to unmap
412 segments mapped by the executable loader.  Returns 0 on success, -1 on
413 failure.  When a file is unmapped, all outstanding changes are written
414 to the file, and the segment's pages are removed from the process's
415 list of used virtual pages.
416 @end table
417
418 Calls to @code{mmap} must fail if the address is not page-aligned, if
419 the length is not positive and a multiple of @var{PGSIZE}.  You also
420 must error check to make sure that the new segment does not overlap
421 already existing segments, and fail if it isn't.  If the length passed
422 to @code{mmap} is less than the file's length, you should only map the
423 first part of the file.  If the length passed to @code{mmap} is longer
424 than the file, the file should grow to the requested length.  Similar
425 to the code segment, your VM system should be able to use the
426 @code{mmap}'d file itself as backing store for the mmap segment, since
427 the changes to the @code{mmap} segment will eventually be written to
428 the file.  (In fact, you may choose to implement executable mappings
429 as a special case of file mappings.)
430
431 @node Virtual Memory FAQ
432 @section FAQ
433
434 @enumerate 1
435 @item
436 @b{Do we need a working HW 2 to implement HW 3?}
437
438 Yes.
439
440 @item
441 @b{How do I use the hash table provided in @file{lib/hash.c}?}
442
443 FIXME
444
445 There are two things you need to use this hashtable:
446
447 1. You need to decide on a key type. The key should be something
448 that is unique for each object as inserting two objects with
449 the same key will cause the second to overwrite the first.
450 (The keys are compared with ==, so you should stick to
451 integers and pointers unless you know how to do operator
452 overloading.) You also need to write a hash function that
453 converts key values to integers, which you will pass into the
454 hash table constructor.
455
456 2. Your key needs to be a field of your object type, and you
457 will need to supply a 'get' function that given an object
458 returns the key.
459
460 Here's a quick example of how to construct a hash table. In
461 this table the keys are Thread pointers and the objects are
462 integers (you will be using different key/value pairs I'm
463 sure). In addition, this hash function is pretty puny. You
464 should probably use a better one.
465
466 @example
467 FIXME
468 @end example
469
470 and to construct the hash table:
471
472 HashTable<Thread *, HashObject *> *htable;
473
474 htable = new HashTable<Thread *, HashObject *>(ExtractKeyFromHashObject,
475                                             MyKeyToHashValue);
476
477 If you have any other questions about hash tables, the CS109
478 and CS161 textbooks have good chapters on them, or you can come
479 to any of the TA's office hours for further clarification.
480
481 @item
482 @b{The current implementation of the hash table does not do something
483 that we need it to do. What gives?}
484
485 You are welcome to modify it.  It is not used by any of the code we
486 provided, so modifying it won't affect any code but yours.  Do
487 whatever it takes to make it work like you want it to.
488
489 @item
490 @b{Is the data segment page-aligned?}
491
492 No.
493
494 @item
495 @b{What controls the layout of user programs?}
496
497 The linker is responsible for the layout of a user program in
498 memory. The linker is directed by a ``linker script'' which tells it
499 the names and locations of the various program segments. The
500 test/script and testvm/script files are the linker scripts for the
501 multiprogramming and virtual memory assignments respectively. You can
502 learn more about linker scripts by reading the ``Scripts'' chapter in
503 the linker manual, accessible via @samp{info ld}.
504
505 @item Page Table Management FAQs
506 @enumerate 1
507 @item
508 @b{How do we manage allocation of pages used for page tables?}
509
510 You can use any reasonable algorithm to do so.  However, you should
511 make sure that memory used for page tables doesn't grow so much that
512 it encroaches deeply on the memory used for data pages.
513
514 Here is one reasonable algorithm.  At OS boot time, reserve some fixed
515 number of pages for page tables.  Then, each time a new page table
516 page is needed, select one of these pages in ``round robin'' fashion.
517 If the page in use, clean up any pointers to it.  Then use it for the
518 new page table page.
519
520 @item
521 @b{Our code handles the PageFault exceptions. However, the number of
522 page faults handled does not show up in the final stats output. Is
523 there a counter that we must increment to correct this problem?}
524
525 FIXME 
526
527 Yes, you'll need to update kernel->stats->numPageFaults when
528 you handle a page fault in your code.
529 @end enumerate
530
531 @item Paging FAQs
532
533 @enumerate 1
534 @item
535 @b{Can we assume (and enforce) that the user's stack will
536 never increase beyond one page?}
537
538 No.  This value was useful for project 2, but for this assignment, you
539 need to implement an extensible stack segment.
540
541 @item
542 @b{Does the virtual memory system need to support growth of the data
543 segment?}
544
545 No.  The size of the data segment is determined by the linker.  We
546 still have no dynamic allocation in Pintos (although it is possible to
547 ``fake'' it at the user level by using memory-mapped files).
548 Implementing @code{sbrk()} has been an extra-credit assignment in
549 previous years, but adds little additional complexity to a
550 well-designed system.
551
552 @item
553 @b{Does the virtual memory system need to support growth of the stack
554 segment?}
555
556 Yes. If a page fault appears just below the last stack segment page,
557 you must add a new page to the bottom of the stack. It is impossible
558 to predict how large the stack will grow at compile time, so we must
559 allocate pages as necessary. You should only allocate additional pages
560 if they ``appear'' to be stack accesses.
561
562 @item
563 @b{But what do you mean by ``appear'' to be stack accesses? How big can a
564 stack growth be?  Under what circumstances do we grow the stack?}
565
566 If it looks like a stack request, then you grow the stack. Yes, that's
567 ambiguous. You need to make a reasonable decision about what looks
568 like a stack request. For example, you could decide a page, or two
569 pages, or ten pages, or more@enddots{}  Or, you could use some other
570 heuristic to figure this out.
571
572 Make a reasonable decision and document it in your code and in
573 your design document.  Please make sure to justify your decision.
574
575 @item
576 @b{How big should the file(s) we're using as a backing store for memory
577 be?}
578
579 These files will need to be able to grow based on the number of pages
580 you're committed to storing on behalf of the processes currently in
581 memory.  They should be able to grow to the full size of the disk.
582 @end enumerate
583
584 @item Memory Mapped File FAQs
585
586 @enumerate 1
587 @item
588 @b{How do we interact with memory-mapped files?}
589
590 Let's say you want to map a file called @file{foo} into your address
591 space at address @t{0x10000000}. You open the file, determine its
592 length, and then use Mmap:
593
594 @example
595 #include <stdio.h>
596 #include <syscall.h>
597
598 int main (void)
599 @{
600     void *addr = (void *) 0x10000000;
601     int fd = open ("foo");
602     int length = filesize (fd);
603     if (mmap (fd, addr, length))
604         printf ("success!\n");
605 @}
606 @end example
607
608 Suppose @file{foo} is a text file and you want to print the first 64
609 bytes on the screen (assuming, of course, that the length of the file
610 is at least 64).  Without @code{mmap}, you'd need to allocate a
611 buffer, use @code{read} to get the data from the file into the buffer,
612 and finally use @code{write} to put the buffer out to the display. But
613 with the file mapped into your address space, you can directly address
614 it like so:
615
616 @example
617 write (addr, 64, STDOUT_FILENO);
618 @end example
619
620 Similarly, if you wanted to replace the first byte of the file,
621 all you need to do is:
622
623 @example
624 addr[0] = 'b';
625 @end example
626
627 When you're done using the memory-mapped file, you simply unmap
628 it:
629
630 @example
631 munmap (addr);
632 @end example
633
634 @item
635 @b{What if two processes memory-map the same file?}
636
637 There is no requirement in Pintos that the two processes see
638 consistent data.  Unix handles this by making the processes share the
639 same physical page, but the @code{mmap} system call also has an
640 argument allowing the client to specify whether the page is shared or
641 private (i.e.@: copy-on-write).
642
643 @item
644 @b{What happens if a user removes a @code{mmap}'d file?}
645
646 @item
647 You should follow the Unix convention and the mapping should still be
648 valid.  This is similar to the question in the User Programs FAQ about
649 a process with a file descriptor to a file that has been removed.
650
651 @item
652 @b{What if a process writes to a page that is memory-mapped, but the
653 location written to in the memory-mapped page is past the end
654 of the memory-mapped file?}
655
656 Can't happen.  @code{mmap} extends the file to the requested length,
657 and Pintos provides no way to shorten a file.  You can remove a file,
658 but the mapping remains valid (see the previous question).
659
660 @item
661 @b{Do we have to handle memory mapping @code{stdin} or @code{stdout}?}
662
663 No.  Memory mapping implies that a file has a length and that a user
664 can seek to any location in the file.  Since the console device has
665 neither of these properties, @code{mmap} should return false when the
666 user attempts to memory map a file descriptor for the console device.
667
668 @item
669 @b{What happens when a process exits with mmap'd files?}
670
671 When a process finishes each of its @code{mmap}'d files is implicitly
672 unmapped.  When a process @code{mmap}s a file and then writes into the
673 area for the file it is making the assumption the changes will be
674 written to the file.
675
676 @item
677 @b{If a user closes a mmaped file, should be automatically unmap it
678 for them?}
679
680 No, once created the mapping is valid until @code{munmap} is called
681 or the process exits.
682 @end enumerate
683 @end enumerate