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