diff options
| author | manuel <manuel@mausz.at> | 2012-06-19 23:31:28 +0200 |
|---|---|---|
| committer | manuel <manuel@mausz.at> | 2012-06-19 23:31:28 +0200 |
| commit | abd273ce0a9ae9267f8b0a144ea9b56d8912f9b5 (patch) | |
| tree | 15bf5622a6bf7665dfb53a3f557dfaa246f108aa /vm/page.c | |
| parent | e88a8c4c379d721e9901752d440a05295087da11 (diff) | |
| download | progos-abd273ce0a9ae9267f8b0a144ea9b56d8912f9b5.tar.gz progos-abd273ce0a9ae9267f8b0a144ea9b56d8912f9b5.tar.bz2 progos-abd273ce0a9ae9267f8b0a144ea9b56d8912f9b5.zip | |
add dynamic stack growing
Diffstat (limited to 'vm/page.c')
| -rw-r--r-- | vm/page.c | 76 |
1 files changed, 46 insertions, 30 deletions
| @@ -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 | ||
| 9 | static void page_table_entry_free (struct hash_elem *e, void *aux UNUSED); | ||
| 10 | static unsigned page_table_hash (const struct hash_elem *e, void *aux UNUSED); | 9 | static unsigned page_table_hash (const struct hash_elem *e, void *aux UNUSED); |
| 11 | static bool page_table_cmp_less (const struct hash_elem *a, const struct hash_elem *b, | 10 | static bool page_table_cmp_less (const struct hash_elem *a, const struct hash_elem *b, |
| 12 | void *aux UNUSED); | 11 | void *aux UNUSED); |
| 12 | static void page_table_entry_free (struct hash_elem *e, void *aux UNUSED); | ||
| 13 | static bool page_table_insert (struct hash *ht, struct page_table_entry *pte); | 13 | static bool page_table_insert (struct hash *ht, struct page_table_entry *pte); |
| 14 | static bool page_load_segment (struct page_table_entry *pte); | 14 | static bool page_load_segment (struct page_table_entry *pte); |
| 15 | static bool page_load_mmf (struct page_table_entry *pte); | 15 | static bool page_load_mmf (struct page_table_entry *pte); |
| 16 | 16 | ||
| 17 | /* initialize page table structure */ | ||
| 17 | void | 18 | void |
| 18 | page_table_init (struct hash *ht) | 19 | page_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 | ||
| 23 | unsigned | 24 | /* calulcates and returns the hash used as key of the hash/page table */ |
| 25 | static unsigned | ||
| 24 | page_table_hash (const struct hash_elem *e, void *aux UNUSED) | 26 | page_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 | ||
| 30 | bool | 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 */ | ||
| 35 | static bool | ||
| 31 | page_table_cmp_less (const struct hash_elem *a, const struct hash_elem *b, | 36 | page_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 */ | ||
| 39 | void | 45 | void |
| 40 | page_table_free (struct hash *ht) | 46 | page_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 | ||
| 45 | void | 51 | /* frees a single page table entry */ |
| 52 | static void | ||
| 46 | page_table_entry_free (struct hash_elem *e, void *aux UNUSED) | 53 | page_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 | ||
| 52 | bool | 59 | /* inserts a new entry into the page table |
| 60 | returns false if entry is invalid or already in the table */ | ||
| 61 | static bool | ||
| 53 | page_table_insert (struct hash *ht, struct page_table_entry *pte) | 62 | page_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 */ | ||
| 60 | bool | 71 | bool |
| 61 | page_table_insert_segment (struct file *file, off_t ofs, uint8_t *upage, | 72 | page_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 */ | ||
| 80 | struct page_table_entry * | 92 | struct page_table_entry * |
| 81 | page_table_fetch (struct hash *ht, void *uvaddr) | 93 | page_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 */ | ||
| 91 | bool | 105 | bool |
| 92 | page_load (struct page_table_entry *pte) | 106 | page_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 | ||
| 110 | bool | 124 | /* load the segment data page */ |
| 125 | static bool | ||
| 111 | page_load_segment (struct page_table_entry *pte) | 126 | page_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 | ||
| 142 | bool | 157 | /* load the memory mappged file page */ |
| 158 | static bool | ||
| 143 | page_load_mmf (struct page_table_entry *pte) | 159 | page_load_mmf (struct page_table_entry *pte) |
| 144 | { | 160 | { |
| 145 | //TODO: implement | 161 | //TODO: implement |
