summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2012-06-19 23:31:28 +0200
committermanuel <manuel@mausz.at>2012-06-19 23:31:28 +0200
commitabd273ce0a9ae9267f8b0a144ea9b56d8912f9b5 (patch)
tree15bf5622a6bf7665dfb53a3f557dfaa246f108aa
parente88a8c4c379d721e9901752d440a05295087da11 (diff)
downloadprogos-abd273ce0a9ae9267f8b0a144ea9b56d8912f9b5.tar.gz
progos-abd273ce0a9ae9267f8b0a144ea9b56d8912f9b5.tar.bz2
progos-abd273ce0a9ae9267f8b0a144ea9b56d8912f9b5.zip
add dynamic stack growing
-rw-r--r--proj2.txt137
-rw-r--r--threads/thread.h2
-rw-r--r--userprog/exception.c80
-rw-r--r--userprog/process.c54
-rw-r--r--userprog/process.h3
-rw-r--r--userprog/syscall.c9
-rw-r--r--userprog/syscall.h2
-rw-r--r--vm/page.c76
-rw-r--r--vm/page.h35
9 files changed, 300 insertions, 98 deletions
diff --git a/proj2.txt b/proj2.txt
new file mode 100644
index 0000000..5405336
--- /dev/null
+++ b/proj2.txt
@@ -0,0 +1,137 @@
1 +---------------------------+
2 | ProgOS |
3 | PROJECT 2: VIRTUAL MEMORY |
4 | DESIGN DOCUMENT |
5 +---------------------------+
6
7---- GROUP ----
8
9>> Fill in the names and email addresses of your group members.
10
11Peter Ketscher <e9651415@mail.student.tuwien.ac.at>
12Karoline Knoth <e0326266@student.tuwien.ac.at>
13Manuel Mausz <manuel-uni@mausz.at>
14
15---- PRELIMINARIES ----
16
17>> If you have any preliminary comments on your submission, notes for the
18>> TAs, or extra credit, please give them here.
19
20>> Please cite any offline or online sources you consulted while
21>> preparing your submission, other than the Pintos documentation, course
22>> text, lecture notes, and course staff.
23
24 PAGE TABLE MANAGEMENT
25 =====================
26---- DATA STRUCTURES ----
27
28>> A1: Copy here the declaration of each new or changed `struct' or
29>> `struct' member, global or static variable, `typedef', or
30>> enumeration. Identify the purpose of each in 25 words or less.
31
32struct thread:
33 struct hash page_table ...page table of thread
34
35struct page_table_entry:
36 void *upage ...virtual address of page
37 bool loaded ...indicates if page is loaded
38 enum type ...type of page
39 union struct segment ...structure needed for lazy loading of data segments
40 struct hash_elem elem ...Hash element.
41
42---- IMPLEMENTATION ----
43>> A2: Describe how you implemented lazy page loading. How do you
44>> determine the file and file offset corresponding to a virtual
45>> address?
46
47TODO
48
49---- SYNCHRONIZATION ----
50>> A3: How do you deal with or prevent page faults in file system
51>> routines. Argue why your solution is deadlock free.
52
53TODO
54
55 STACK GROWTH
56 ============
57
58---- DATA STRUCTURES ----
59
60>> B1: Copy here the declaration of each new or changed `struct' or
61>> `struct' member, global or static variable, `typedef', or
62>> enumeration. Identify the purpose of each in 25 words or less.
63
64extern void *syscall_sp ...stored stack pointer for the "page fault inside
65 syscall/kernel"-case
66
67---- IMPLEMENTATION ----
68>> B2: Describe how you integrated the (potentially growing) stack segment
69>> into your page table management implementation.
70
71TODO
72
73---- ALGORITHMS ----
74>> B3: Explain how you detect a page fault which should trigger a
75>> stack growth. What asssumptions are needed for your implementation
76>> to work?
77
78TODO
79
80 MEMORY MAPPED FILES
81 ===================
82
83---- DATA STRUCTURES ----
84
85>> C1: Copy here the declaration of each new or changed `struct' or
86>> `struct' member, global or static variable, `typedef', or
87>> enumeration. Identify the purpose of each in 25 words or less.
88
89struct page_table_entry:
90 union struct TODO ...structure needed for loading of memory mapped files
91
92---- ALGORITHMS ----
93
94>> C2: Describe how memory mapped files integrate into your virtual
95>> memory subsystem.
96
97TODO
98
99>> C3: Explain how you determine whether a new file mapping overlaps
100>> any existing segment.
101
102TODO
103
104---- RATIONALE ----
105
106>> C4: Mappings created with "mmap" have similar semantics to those of
107>> data demand-paged from executables, except that "mmap" mappings are
108>> written back to their original files, not to swap. This implies
109>> that much of their implementation can be shared. Explain why your
110>> implementation either does or does not share much of the code for
111>> the two situations.
112
113TODO
114
115 SURVEY QUESTIONS
116 ================
117
118Answering these questions is optional, but it will help us improve the
119course in future quarters. Feel free to tell us anything you
120want--these questions are just to spur your thoughts. You may also
121choose to respond anonymously in the course evaluations at the end of
122the quarter.
123
124>> In your opinion, was this assignment, or any one of the three problems
125>> in it, too easy or too hard? Did it take too long or too little time?
126
127>> Did you find that working on a particular part of the assignment gave
128>> you greater insight into some aspect of OS design?
129
130>> Is there some particular fact or hint we should give students in
131>> future quarters to help them solve the problems? Conversely, did you
132>> find any of our guidance to be misleading?
133
134>> Do you have any suggestions for the TAs to more effectively assist
135>> students, either for future quarters or the remaining projects?
136
137>> Any other comments?
diff --git a/threads/thread.h b/threads/thread.h
index 293d14f..ed591f4 100644
--- a/threads/thread.h
+++ b/threads/thread.h
@@ -114,7 +114,7 @@ struct thread
114 struct list locks; /* list of locks the thread currently holds */ 114 struct list locks; /* list of locks the thread currently holds */
115 struct lock *blocked_lock; /* the lock the thread currently tries to acquire (but hasn't yet) */ 115 struct lock *blocked_lock; /* the lock the thread currently tries to acquire (but hasn't yet) */
116 116
117 struct hash page_table; 117 struct hash page_table; /* page table of thread */
118 }; 118 };
119 119
120/* If false (default), use round-robin scheduler. 120/* If false (default), use round-robin scheduler.
diff --git a/userprog/exception.c b/userprog/exception.c
index 54621fa..debe7f0 100644
--- a/userprog/exception.c
+++ b/userprog/exception.c
@@ -2,6 +2,8 @@
2#include <inttypes.h> 2#include <inttypes.h>
3#include <stdio.h> 3#include <stdio.h>
4#include "userprog/gdt.h" 4#include "userprog/gdt.h"
5#include "userprog/process.h"
6#include "userprog/syscall.h"
5#include "threads/interrupt.h" 7#include "threads/interrupt.h"
6#include "threads/thread.h" 8#include "threads/thread.h"
7#include "threads/vaddr.h" 9#include "threads/vaddr.h"
@@ -128,7 +130,8 @@ page_fault (struct intr_frame *f)
128 bool write; /* True: access was write, false: access was read. */ 130 bool write; /* True: access was write, false: access was read. */
129 bool user; /* True: access by user, false: access by kernel. */ 131 bool user; /* True: access by user, false: access by kernel. */
130 void *fault_addr; /* Fault address. */ 132 void *fault_addr; /* Fault address. */
131 struct page_table_entry *pte; 133 void *sp; /* Stack pointer. */
134 struct page_table_entry *pte; /* Page table entry. */
132 135
133 /* Obtain faulting address, the virtual address that was 136 /* Obtain faulting address, the virtual address that was
134 accessed to cause the fault. It may point to code or to 137 accessed to cause the fault. It may point to code or to
@@ -151,38 +154,57 @@ page_fault (struct intr_frame *f)
151 write = (f->error_code & PF_W) != 0; 154 write = (f->error_code & PF_W) != 0;
152 user = (f->error_code & PF_U) != 0; 155 user = (f->error_code & PF_U) != 0;
153 156
154 /* To implement virtual memory, adapt the rest of the function 157 /* accessing r/o page is always wrong */
155 body, adding code that brings in the page to 158 if (!not_present)
156 which fault_addr refers. */ 159 thread_exit ();
157 if (is_user_vaddr(fault_addr)) { 160
158 pte = page_table_fetch (&thread_current ()->page_table, pg_round_down (fault_addr)); 161 if (is_user_vaddr (fault_addr))
159 if (pte != NULL)
160 page_load (pte);
161 else
162 { 162 {
163 printf ("Page fault %p\n", pte); 163 /* if page fault occurs during syscall, use saved stack pointer */
164 kill (f); 164 sp = (!user) ? syscall_sp : f->esp;
165 } 165
166 /* try to fetch page entry */
167 pte = page_table_fetch (&thread_current ()->page_table,
168 pg_round_down (fault_addr));
169
170 /* we got a page entry so try to load the page */
171 if (pte != NULL)
172 {
173 if (page_load (pte))
174 return;
175 printf ("Unable to load page at %p in %s context.\n",
176 fault_addr, user ? "user" : "kernel");
177 }
178 /* there's no page in our page table but we might still have an valid
179 stack access and need to expand our stack. so just check for that.
180 the maxium offset we consider as a valid access is caused by the PUSHA
181 instruction. it's 32 bytes below the current stack pointer */
182 else if (fault_addr >= (sp - 32) && (PHYS_BASE - fault_addr) <= STACK_SIZE)
183 {
184 if (process_grow_stack (pg_round_down (fault_addr)))
185 return;
186 printf ("Unable to grow stack %p in %s context.\n",
187 fault_addr, user ? "user" : "kernel");
188 }
166 189
167 //TODO
168#if 0
169 if (! user) {
170 /* syscall exception; set eax and eip */ 190 /* syscall exception; set eax and eip */
171 f->eip = (void*)f->eax; 191 if (!user)
172 f->eax = 0xFFFFFFFF; 192 {
173 return; 193 f->eip = (void*)f->eax;
174 } else { 194 f->eax = 0xFFFFFFFF;
195 return;
196 }
197
175 /* user process access violation */ 198 /* user process access violation */
176 thread_exit(); 199 thread_exit ();
200 return;
177 } 201 }
178#endif 202
179 } else { 203 printf ("Page fault at %p: %s error %s page in %s context.\n",
180 printf ("Page fault at %p: %s error %s page in %s context.\n", 204 fault_addr,
181 fault_addr, 205 not_present ? "not present" : "rights violation",
182 not_present ? "not present" : "rights violation", 206 write ? "writing" : "reading",
183 write ? "writing" : "reading", 207 user ? "user" : "kernel");
184 user ? "user" : "kernel"); 208 kill (f);
185 kill (f);
186 }
187} 209}
188 210
diff --git a/userprog/process.c b/userprog/process.c
index 15883d9..2771e76 100644
--- a/userprog/process.c
+++ b/userprog/process.c
@@ -552,24 +552,24 @@ load_segment (struct file *file, off_t ofs, uint8_t *upage,
552 552
553 file_seek (file, ofs); 553 file_seek (file, ofs);
554 while (read_bytes > 0 || zero_bytes > 0) 554 while (read_bytes > 0 || zero_bytes > 0)
555 { 555 {
556 /* Calculate how to fill this page. 556 /* Calculate how to fill this page.
557 We will read PAGE_READ_BYTES bytes from FILE 557 We will read PAGE_READ_BYTES bytes from FILE
558 and zero the final PAGE_ZERO_BYTES bytes. */ 558 and zero the final PAGE_ZERO_BYTES bytes. */
559 size_t page_read_bytes = read_bytes < PGSIZE ? read_bytes : PGSIZE; 559 size_t page_read_bytes = read_bytes < PGSIZE ? read_bytes : PGSIZE;
560 size_t page_zero_bytes = PGSIZE - page_read_bytes; 560 size_t page_zero_bytes = PGSIZE - page_read_bytes;
561 561
562 /* add segment to page table for on demand loading */ 562 /* add segment to page table for on demand loading */
563 if (!page_table_insert_segment (file, ofs, upage, page_read_bytes, 563 if (!page_table_insert_segment (file, ofs, upage, page_read_bytes,
564 page_zero_bytes, writable)) 564 page_zero_bytes, writable))
565 return false; 565 return false;
566 566
567 /* Advance. */ 567 /* Advance. */
568 read_bytes -= page_read_bytes; 568 read_bytes -= page_read_bytes;
569 zero_bytes -= page_zero_bytes; 569 zero_bytes -= page_zero_bytes;
570 ofs += page_read_bytes; 570 ofs += page_read_bytes;
571 upage += PGSIZE; 571 upage += PGSIZE;
572 } 572 }
573 return true; 573 return true;
574} 574}
575 575
@@ -686,6 +686,24 @@ setup_stack (uint32_t **esp, const char *args)
686 return true; 686 return true;
687} 687}
688 688
689/* expand the stack of the process by one new page
690 which will be installed at the address of UPAGE */
691bool
692process_grow_stack (void *upage)
693{
694 uint8_t *kpage = palloc_get_page (PAL_USER | PAL_ZERO);
695 if (kpage == NULL)
696 return false;
697
698 if (!process_install_page (upage, kpage, true))
699 {
700 palloc_free_page (kpage);
701 return false;
702 }
703
704 return true;
705}
706
689/* Adds a mapping from user virtual address UPAGE to kernel 707/* Adds a mapping from user virtual address UPAGE to kernel
690 virtual address KPAGE to the page table. 708 virtual address KPAGE to the page table.
691 If WRITABLE is true, the user process may modify the page; 709 If WRITABLE is true, the user process may modify the page;
diff --git a/userprog/process.h b/userprog/process.h
index b7bca5d..ccb94cb 100644
--- a/userprog/process.h
+++ b/userprog/process.h
@@ -3,6 +3,8 @@
3 3
4#include "threads/thread.h" 4#include "threads/thread.h"
5 5
6#define STACK_SIZE (1 << 23) /* 8MB maxiumum stack size */
7
6/* In the current implementation, the capacity is fixed to 1024 (PGSIZE/4) */ 8/* In the current implementation, the capacity is fixed to 1024 (PGSIZE/4) */
7struct fd_table { 9struct fd_table {
8 struct file** fds; 10 struct file** fds;
@@ -37,6 +39,7 @@ tid_t process_execute (const char *file_name);
37int process_wait (tid_t); 39int process_wait (tid_t);
38void process_exit (void); 40void process_exit (void);
39void process_activate (void); 41void process_activate (void);
42bool process_grow_stack (void *upage);
40bool process_install_page (void *upage, void *kpage, bool writable); 43bool process_install_page (void *upage, void *kpage, bool writable);
41 44
42int process_open_file(const char* fname); 45int process_open_file(const char* fname);
diff --git a/userprog/syscall.c b/userprog/syscall.c
index f8e0197..541668d 100644
--- a/userprog/syscall.c
+++ b/userprog/syscall.c
@@ -17,6 +17,9 @@
17 17
18#define STACK_SLOT_SIZE sizeof(int) 18#define STACK_SLOT_SIZE sizeof(int)
19 19
20/* stored stack pointer for the "page fault inside syscall/kernel"-case */
21void *syscall_sp;
22
20/* Prototypes for Utilities */ 23/* Prototypes for Utilities */
21static int get_user (const uint8_t *uaddr); 24static int get_user (const uint8_t *uaddr);
22static bool put_user (uint8_t *udst, uint8_t byte); 25static bool put_user (uint8_t *udst, uint8_t byte);
@@ -195,10 +198,10 @@ syscall_handler (struct intr_frame *f)
195 handler* fp; 198 handler* fp;
196 bool segfault = false; 199 bool segfault = false;
197 int result; 200 int result;
198 void *sp = f->esp; 201 syscall_sp = f->esp;
199 202
200 /* The system call number and the arguments are on the stack */ 203 /* The system call number and the arguments are on the stack */
201 if (! copy_from_user (&syscall_nr,sp)) 204 if (! copy_from_user (&syscall_nr,syscall_sp))
202 goto fail; 205 goto fail;
203 switch (syscall_nr) { 206 switch (syscall_nr) {
204 case SYS_HALT: fp = syscall_halt; break; 207 case SYS_HALT: fp = syscall_halt; break;
@@ -217,7 +220,7 @@ syscall_handler (struct intr_frame *f)
217 default: 220 default:
218 goto fail; 221 goto fail;
219 } 222 }
220 result = fp (sp, &segfault); 223 result = fp (syscall_sp, &segfault);
221 if (segfault) 224 if (segfault)
222 goto fail; 225 goto fail;
223 f->eax = result; 226 f->eax = result;
diff --git a/userprog/syscall.h b/userprog/syscall.h
index f7ab2f3..987ceaa 100644
--- a/userprog/syscall.h
+++ b/userprog/syscall.h
@@ -2,4 +2,6 @@
2#define USERPROG_SYSCALL_H 2#define USERPROG_SYSCALL_H
3 3
4void syscall_init (void); 4void syscall_init (void);
5extern void *syscall_sp;
6
5#endif /* userprog/syscall.h */ 7#endif /* userprog/syscall.h */
diff --git a/vm/page.c b/vm/page.c
index fa2433d..336353e 100644
--- a/vm/page.c
+++ b/vm/page.c
@@ -6,50 +6,59 @@
6#include "threads/palloc.h" 6#include "threads/palloc.h"
7#include "vm/page.h" 7#include "vm/page.h"
8 8
9static void page_table_entry_free (struct hash_elem *e, void *aux UNUSED);
10static unsigned page_table_hash (const struct hash_elem *e, void *aux UNUSED); 9static unsigned page_table_hash (const struct hash_elem *e, void *aux UNUSED);
11static bool page_table_cmp_less (const struct hash_elem *a, const struct hash_elem *b, 10static bool page_table_cmp_less (const struct hash_elem *a, const struct hash_elem *b,
12 void *aux UNUSED); 11 void *aux UNUSED);
12static void page_table_entry_free (struct hash_elem *e, void *aux UNUSED);
13static bool page_table_insert (struct hash *ht, struct page_table_entry *pte); 13static bool page_table_insert (struct hash *ht, struct page_table_entry *pte);
14static bool page_load_segment (struct page_table_entry *pte); 14static bool page_load_segment (struct page_table_entry *pte);
15static bool page_load_mmf (struct page_table_entry *pte); 15static bool page_load_mmf (struct page_table_entry *pte);
16 16
17/* initialize page table structure */
17void 18void
18page_table_init (struct hash *ht) 19page_table_init (struct hash *ht)
19{ 20{
20 hash_init (ht, page_table_hash, page_table_cmp_less, NULL); 21 hash_init (ht, page_table_hash, page_table_cmp_less, NULL);
21} 22}
22 23
23unsigned 24/* calulcates and returns the hash used as key of the hash/page table */
25static unsigned
24page_table_hash (const struct hash_elem *e, void *aux UNUSED) 26page_table_hash (const struct hash_elem *e, void *aux UNUSED)
25{ 27{
26 const struct page_table_entry *pte = hash_entry (e, struct page_table_entry, elem); 28 const struct page_table_entry *pte = hash_entry (e, struct page_table_entry, elem);
27 return hash_bytes (&pte->uvaddr, sizeof pte->uvaddr); 29 return hash_bytes (&pte->upage, sizeof pte->upage);
28} 30}
29 31
30bool 32/* page table comperator needed by the hash table implementation
33 returns true if A is less than B, or false if A is greater than
34 or equal to B */
35static bool
31page_table_cmp_less (const struct hash_elem *a, const struct hash_elem *b, 36page_table_cmp_less (const struct hash_elem *a, const struct hash_elem *b,
32 void *aux UNUSED) 37 void *aux UNUSED)
33{ 38{
34 const struct page_table_entry *pte1 = hash_entry (a, struct page_table_entry, elem); 39 const struct page_table_entry *pte1 = hash_entry (a, struct page_table_entry, elem);
35 const struct page_table_entry *pte2 = hash_entry (b, struct page_table_entry, elem); 40 const struct page_table_entry *pte2 = hash_entry (b, struct page_table_entry, elem);
36 return (pte1->uvaddr < pte2->uvaddr); 41 return (pte1->upage < pte2->upage);
37} 42}
38 43
44/* frees the content of page table */
39void 45void
40page_table_free (struct hash *ht) 46page_table_free (struct hash *ht)
41{ 47{
42 hash_destroy (ht, page_table_entry_free); 48 hash_destroy (ht, page_table_entry_free);
43} 49}
44 50
45void 51/* frees a single page table entry */
52static void
46page_table_entry_free (struct hash_elem *e, void *aux UNUSED) 53page_table_entry_free (struct hash_elem *e, void *aux UNUSED)
47{ 54{
48 struct page_table_entry *pte = hash_entry (e, struct page_table_entry, elem); 55 struct page_table_entry *pte = hash_entry (e, struct page_table_entry, elem);
49 free (pte); 56 free (pte);
50} 57}
51 58
52bool 59/* inserts a new entry into the page table
60 returns false if entry is invalid or already in the table */
61static bool
53page_table_insert (struct hash *ht, struct page_table_entry *pte) 62page_table_insert (struct hash *ht, struct page_table_entry *pte)
54{ 63{
55 if (pte == NULL) 64 if (pte == NULL)
@@ -57,6 +66,8 @@ page_table_insert (struct hash *ht, struct page_table_entry *pte)
57 return (hash_insert (ht, &pte->elem) == NULL); 66 return (hash_insert (ht, &pte->elem) == NULL);
58} 67}
59 68
69/* inserts a new entry of type segment into the page table
70 returns false if entry is invalid or already in the table */
60bool 71bool
61page_table_insert_segment (struct file *file, off_t ofs, uint8_t *upage, 72page_table_insert_segment (struct file *file, off_t ofs, uint8_t *upage,
62 uint32_t read_bytes, uint32_t zero_bytes, bool writable) 73 uint32_t read_bytes, uint32_t zero_bytes, bool writable)
@@ -65,7 +76,7 @@ page_table_insert_segment (struct file *file, off_t ofs, uint8_t *upage,
65 if (pte == NULL) 76 if (pte == NULL)
66 return false; 77 return false;
67 78
68 pte->uvaddr = upage; 79 pte->upage = upage;
69 pte->type = PAGE_SEGMENT; 80 pte->type = PAGE_SEGMENT;
70 pte->loaded = false; 81 pte->loaded = false;
71 pte->segment.file = file; 82 pte->segment.file = file;
@@ -77,17 +88,20 @@ page_table_insert_segment (struct file *file, off_t ofs, uint8_t *upage,
77 return page_table_insert (&thread_current ()->page_table, pte); 88 return page_table_insert (&thread_current ()->page_table, pte);
78} 89}
79 90
91/* fetch an entry from the page table. returns NULL if not found */
80struct page_table_entry * 92struct page_table_entry *
81page_table_fetch (struct hash *ht, void *uvaddr) 93page_table_fetch (struct hash *ht, void *upage)
82{ 94{
83 struct page_table_entry pte; 95 struct page_table_entry pte;
84 struct hash_elem *e; 96 struct hash_elem *e;
85 97
86 pte.uvaddr = uvaddr; 98 pte.upage = upage;
87 e = hash_find (ht, &pte.elem); 99 e = hash_find (ht, &pte.elem);
88 return ((e != NULL) ? hash_entry (e, struct page_table_entry, elem) : NULL); 100 return ((e != NULL) ? hash_entry (e, struct page_table_entry, elem) : NULL);
89} 101}
90 102
103/* load the page referenced by the page table entry
104 returns true on success or already loaded, false otherwise */
91bool 105bool
92page_load (struct page_table_entry *pte) 106page_load (struct page_table_entry *pte)
93{ 107{
@@ -95,19 +109,20 @@ page_load (struct page_table_entry *pte)
95 return true; 109 return true;
96 110
97 switch (pte->type) 111 switch (pte->type)
98 { 112 {
99 case PAGE_SEGMENT: 113 case PAGE_SEGMENT:
100 return page_load_segment (pte); 114 return page_load_segment (pte);
101 case PAGE_MEMORY_MAPPED_FILE: 115 case PAGE_MEMORY_MAPPED_FILE:
102 return page_load_mmf (pte); 116 return page_load_mmf (pte);
103 default: 117 default:
104 ASSERT (false); 118 ASSERT (false);
105 break; 119 break;
106 } 120 }
107 return false; 121 return false;
108} 122}
109 123
110bool 124/* load the segment data page */
125static bool
111page_load_segment (struct page_table_entry *pte) 126page_load_segment (struct page_table_entry *pte)
112{ 127{
113 struct segment *data = &pte->segment; 128 struct segment *data = &pte->segment;
@@ -122,24 +137,25 @@ page_load_segment (struct page_table_entry *pte)
122 /* Load this page. */ 137 /* Load this page. */
123 if (file_read (data->file, kpage, data->read_bytes) 138 if (file_read (data->file, kpage, data->read_bytes)
124 != (int) data->read_bytes) 139 != (int) data->read_bytes)
125 { 140 {
126 palloc_free_page (kpage); 141 palloc_free_page (kpage);
127 return false; 142 return false;
128 } 143 }
129 memset (kpage + data->read_bytes, 0, data->zero_bytes); 144 memset (kpage + data->read_bytes, 0, data->zero_bytes);
130 145
131 /* Add the page to the process's address space. */ 146 /* Add the page to the process's address space. */
132 if (!process_install_page (pte->uvaddr, kpage, data->writable)) 147 if (!process_install_page (pte->upage, kpage, data->writable))
133 { 148 {
134 palloc_free_page (kpage); 149 palloc_free_page (kpage);
135 return false; 150 return false;
136 } 151 }
137 152
138 pte->loaded = true; 153 pte->loaded = true;
139 return true; 154 return true;
140} 155}
141 156
142bool 157/* load the memory mappged file page */
158static bool
143page_load_mmf (struct page_table_entry *pte) 159page_load_mmf (struct page_table_entry *pte)
144{ 160{
145 //TODO: implement 161 //TODO: implement
diff --git a/vm/page.h b/vm/page.h
index 29159fb..9cea048 100644
--- a/vm/page.h
+++ b/vm/page.h
@@ -8,32 +8,33 @@
8/* supplemental page table entry */ 8/* supplemental page table entry */
9struct page_table_entry 9struct page_table_entry
10{ 10{
11 void *uvaddr; 11 void *upage; /* virtual address of page */
12 bool loaded; 12 bool loaded; /* indicates if page is loaded */
13 enum 13 enum
14 { 14 {
15 PAGE_SEGMENT, 15 PAGE_SEGMENT,
16 PAGE_MEMORY_MAPPED_FILE, 16 PAGE_MEMORY_MAPPED_FILE,
17 } type; 17 } type; /* type of page */
18 18
19 union 19 union
20 {
21 struct segment
22 { 20 {
23 struct file *file; 21 /* structure needed for lazy loading of data segments */
24 off_t ofs; 22 struct segment
25 uint32_t read_bytes; 23 {
26 uint32_t zero_bytes; 24 struct file *file;
27 bool writable; 25 off_t ofs;
28 } segment; 26 uint32_t read_bytes;
29 }; 27 uint32_t zero_bytes;
28 bool writable;
29 } segment;
30 };
30 31
31 struct hash_elem elem; 32 struct hash_elem elem; /* Hash element. */
32}; 33};
33 34
34void page_table_init (struct hash *ht); 35void page_table_init (struct hash *ht);
35void page_table_free (struct hash *ht); 36void page_table_free (struct hash *ht);
36struct page_table_entry *page_table_fetch (struct hash *ht, void *uvaddr); 37struct page_table_entry *page_table_fetch (struct hash *ht, void *upage);
37bool page_table_insert_segment (struct file *file, off_t ofs, uint8_t *upage, 38bool page_table_insert_segment (struct file *file, off_t ofs, uint8_t *upage,
38 uint32_t read_bytes, uint32_t zero_bytes, bool writable); 39 uint32_t read_bytes, uint32_t zero_bytes, bool writable);
39bool page_load (struct page_table_entry *pte); 40bool page_load (struct page_table_entry *pte);