process. Whenever the processor needed to look up a translation, it
consulted the page table. As long as the process only accessed
memory that it didn't own, all was well. If the process accessed
-memory it didn't own, it ``page faulted'' and @code{page_fault()}
+memory it didn't own, it ``page faulted'' and @func{page_fault}
terminated the process.
When we implement virtual memory, the rules have to change. A page
@end enumerate
@example
+@group
32 22 12 0
+--------------------------------------------------------------------+
| Page Directory Index | Page Table Index | Page Offset |
1|____________| | 1|____________| | |____________|
0|____________| \__\0|____________| \____\|____________|
/ /
+@end group
@end example
Header @file{threads/mmu.h} has useful functions for various
idea.
@end itemize
-The page fault handler, @code{page_fault()} in
+The page fault handler, @func{page_fault} in
@file{threads/exception.c}, needs to do roughly the following:
@enumerate 1
use your new page table management code to construct the page tables
only as page faults occur for them.
-You should use the @code{palloc_get_page()} function to get the page
+You should use the @func{palloc_get_page} function to get the page
frames that you use for storing user virtual pages. Be sure to pass
the @code{PAL_USER} flag to this function when you do so, because that
allocates pages from a ``user pool'' separate from the ``kernel pool''
-that other calls to @code{palloc_get_page()} make.
+that other calls to @func{palloc_get_page} make.
There are many possible ways to implement virtual memory. The above
is simply an outline of our suggested implementation.
segments won't change.
There are a few special cases. Look at the loop in
-@code{load_segment()} in @file{userprog/process.c}. Each time
+@func{load_segment} in @file{userprog/process.c}. Each time
around the loop, @code{read_bytes} represents the number of bytes to
read from the executable file and @code{zero_bytes} represents the number
of bytes to initialize to zero following the bytes read. The two
to be compatible with the prototypes for @code{hash_hash_func} and
@code{hash_less_func} in @file{lib/kernel/hash.h}.
-Here's a quick example. Suppose you want to put @code{struct thread}s
+Here's a quick example. Suppose you want to put @struct{thread}s
in a hash table. First, add a @code{hash_elem} to the thread
structure by adding a line to its definition:
hash_elem h_elem; /* Hash table element. */
@end example
-We'll choose the @code{tid} member in @code{struct thread} as the key,
+We'll choose the @code{tid} member in @struct{thread} as the key,
and write a hash function and a comparison function:
@example
/* Returns true if A's tid is less than B's tid. */
bool
-thread_less (const hash_elem *a_, const hash_elem *b_, void *aux UNUSED)
+thread_less (const hash_elem *a_, const hash_elem *b_,
+ void *aux UNUSED)
@{
struct thread *a = hash_entry (a_, struct thread, h_elem);
struct thread *b = hash_entry (b_, struct thread, h_elem);
hash_init (&threads, thread_hash, thread_less, NULL);
@end example
-Finally, if @code{@var{t}} is a pointer to a @code{struct thread},
+Finally, if @code{@var{t}} is a pointer to a @struct{thread},
then we can insert it into the hash table with:
@example
for?}
In simple cases you won't have any need for the @var{aux} parameters.
-In these cases you can just pass a null pointer to @code{hash_init()}
+In these cases you can just pass a null pointer to @func{hash_init}
for @var{aux} and ignore the values passed to the hash function and
comparison functions. (You'll get a compiler warning if you don't use
the @var{aux} parameter, but you can turn that off with the
your design document. Please make sure to justify your decision.
@item
-@b{Why do I need to pass @code{PAL_USER} to @code{palloc_get_page()}
-when I allocate physical page frames?}
+@b{Why do I need to pass @code{PAL_USER} to @func{palloc_get_page}
+when I allocate physical page frames?}@anchor{Why PAL_USER?}
-You can layer some other allocator on top of @code{palloc_get_page()}
+You can layer some other allocator on top of @func{palloc_get_page}
if you like, but it should be the underlying mechanism, directly or
indirectly, for two reasons. First, running out of pages in the user
pool just causes user programs to page, but running out of pages in