diff options
| author | manuel <manuel@mausz.at> | 2012-06-21 18:14:58 +0200 |
|---|---|---|
| committer | manuel <manuel@mausz.at> | 2012-06-21 18:14:58 +0200 |
| commit | e61e868b265efe2f6d51079373588d639fc54d59 (patch) | |
| tree | 035fa9afef57c88ed156909d73cd8c4a91fe4435 /vm/mmap.c | |
| parent | e11b2ef0c606ab516a4344aeea1dbba22cb1fe5d (diff) | |
| download | progos-e61e868b265efe2f6d51079373588d639fc54d59.tar.gz progos-e61e868b265efe2f6d51079373588d639fc54d59.tar.bz2 progos-e61e868b265efe2f6d51079373588d639fc54d59.zip | |
full mmap implementation
Diffstat (limited to 'vm/mmap.c')
| -rw-r--r-- | vm/mmap.c | 91 |
1 files changed, 66 insertions, 25 deletions
| @@ -1,4 +1,6 @@ | |||
| 1 | #include <string.h> | 1 | #include <string.h> |
| 2 | #include "userprog/pagedir.h" | ||
| 3 | #include "userprog/process.h" | ||
| 2 | #include "filesys/file.h" | 4 | #include "filesys/file.h" |
| 3 | #include "threads/thread.h" | 5 | #include "threads/thread.h" |
| 4 | #include "threads/vaddr.h" | 6 | #include "threads/vaddr.h" |
| @@ -23,18 +25,20 @@ mmap_table_init (struct mmap_table *table) | |||
| 23 | return true; | 25 | return true; |
| 24 | } | 26 | } |
| 25 | 27 | ||
| 26 | /* frees the content of mmap table */ | 28 | /* closes all mapped files and frees the content of the table */ |
| 27 | void | 29 | void |
| 28 | mmap_table_free (struct mmap_table *table) | 30 | mmap_table_free (struct mmap_table *table) |
| 29 | { | 31 | { |
| 30 | //TODO | 32 | mapid_t id; |
| 33 | for (id = 0; id <= table->id_max; id++) | ||
| 34 | mmap_table_remove (table, id); | ||
| 31 | palloc_free_page (table->ids); | 35 | palloc_free_page (table->ids); |
| 32 | } | 36 | } |
| 33 | 37 | ||
| 34 | /* inserts a new mmap entry in the mmap table | 38 | /* inserts a new mmap entry in the mmap table. |
| 35 | returns -1 if entry is invalid or already in the table */ | 39 | returns -1 if entry is invalid or already in the table */ |
| 36 | mapid_t | 40 | mapid_t |
| 37 | mmap_table_insert (struct mmap_table *table, void *addr, struct file *file, | 41 | mmap_table_insert (struct mmap_table *table, uint8_t *upage, struct file *file, |
| 38 | off_t len) | 42 | off_t len) |
| 39 | { | 43 | { |
| 40 | off_t ofs = 0; | 44 | off_t ofs = 0; |
| @@ -46,43 +50,49 @@ mmap_table_insert (struct mmap_table *table, void *addr, struct file *file, | |||
| 46 | if (table->id_free >= table->id_cap) | 50 | if (table->id_free >= table->id_cap) |
| 47 | return -1; | 51 | return -1; |
| 48 | 52 | ||
| 53 | /* create mmap table entry */ | ||
| 49 | mme = malloc (sizeof *mme); | 54 | mme = malloc (sizeof *mme); |
| 50 | if (mme == NULL) | 55 | if (mme == NULL) |
| 51 | return -1; | 56 | return -1; |
| 52 | 57 | ||
| 53 | mapid = table->id_free++; | 58 | mme->upage = upage; |
| 54 | mme->addr = addr; | ||
| 55 | mme->file = file; | 59 | mme->file = file; |
| 56 | table->ids[mapid] = mme; | 60 | mme->pages = 0; |
| 57 | 61 | ||
| 58 | /* create needed pages in page table */ | 62 | /* create needed pages in page table */ |
| 59 | while (len > 0) | 63 | while (len > 0) |
| 60 | { | 64 | { |
| 61 | page_read_bytes = (len < PGSIZE) ? len : PGSIZE; | 65 | page_read_bytes = (len < PGSIZE) ? len : PGSIZE; |
| 62 | |||
| 63 | if (!page_table_insert_segment (&thread_current ()->page_table, file, ofs, | 66 | if (!page_table_insert_segment (&thread_current ()->page_table, file, ofs, |
| 64 | addr, page_read_bytes, true)) | 67 | upage, page_read_bytes, true)) |
| 65 | return -1; | 68 | return -1; |
| 66 | 69 | ||
| 67 | /* Advance. */ | 70 | /* Advance. */ |
| 68 | len -= PGSIZE; | 71 | len -= PGSIZE; |
| 69 | ofs += page_read_bytes; | 72 | ofs += page_read_bytes; |
| 70 | addr += PGSIZE; | 73 | upage += PGSIZE; |
| 74 | mme->pages++; | ||
| 71 | } | 75 | } |
| 72 | 76 | ||
| 77 | /* insert entry into our table */ | ||
| 78 | mapid = table->id_free++; | ||
| 79 | table->ids[mapid] = mme; | ||
| 80 | |||
| 73 | /* update index of free/max mapid index */ | 81 | /* update index of free/max mapid index */ |
| 74 | if (mapid > table->id_max) | 82 | if (mapid > table->id_max) |
| 75 | table->id_max = mapid; | 83 | table->id_max = mapid; |
| 76 | while (table->ids[table->id_free] != NULL) | 84 | while (table->ids[table->id_free] != NULL) |
| 77 | { | 85 | { |
| 78 | table->id_free++; | 86 | table->id_free++; |
| 79 | if (table->id_free >= table->id_cap) | 87 | if (table->id_free >= table->id_cap) |
| 80 | break; | 88 | break; |
| 81 | } | 89 | } |
| 82 | 90 | ||
| 83 | return mapid; | 91 | return mapid; |
| 84 | } | 92 | } |
| 85 | 93 | ||
| 94 | /* get the mmap table entry associated with the given map id. | ||
| 95 | return NULL if no mapping is associated with the given id */ | ||
| 86 | static struct mmap_table_entry * | 96 | static struct mmap_table_entry * |
| 87 | mmap_table_get (struct mmap_table *table, mapid_t mapid) | 97 | mmap_table_get (struct mmap_table *table, mapid_t mapid) |
| 88 | { | 98 | { |
| @@ -91,26 +101,57 @@ mmap_table_get (struct mmap_table *table, mapid_t mapid) | |||
| 91 | return table->ids[mapid]; | 101 | return table->ids[mapid]; |
| 92 | } | 102 | } |
| 93 | 103 | ||
| 104 | /* remove the entry associated with the given map id from the mmap table. | ||
| 105 | flushes all dirty/modified pages back to disk. return true if successful */ | ||
| 94 | bool | 106 | bool |
| 95 | mmap_table_remove (struct mmap_table *table, mapid_t mapid) | 107 | mmap_table_remove (struct mmap_table *table, mapid_t mapid) |
| 96 | { | 108 | { |
| 109 | struct page_table_entry *pte; | ||
| 110 | off_t ofs = 0; | ||
| 111 | struct thread *thread = thread_current (); | ||
| 97 | struct mmap_table_entry *mme = mmap_table_get(table, mapid); | 112 | struct mmap_table_entry *mme = mmap_table_get(table, mapid); |
| 98 | if (mme == NULL) | 113 | if (mme == NULL) |
| 99 | return false; | 114 | return false; |
| 100 | 115 | ||
| 101 | table->ids[mapid] = NULL; | 116 | /* fetch pages needed by mapped file and check whether the page is dirty */ |
| 117 | while (mme->pages-- > 0) | ||
| 118 | { | ||
| 119 | pte = page_table_remove (&thread->page_table, mme->upage + ofs); | ||
| 120 | if (pte != NULL && pte->loaded && | ||
| 121 | pagedir_is_dirty (thread->pagedir, pte->upage)) | ||
| 122 | { | ||
| 123 | /* write modified page back to disk */ | ||
| 124 | ASSERT (pte->segment.file == mme->file); | ||
| 125 | process_lock_filesys (); | ||
| 126 | file_seek (pte->segment.file, pte->segment.ofs); | ||
| 127 | file_write (pte->segment.file, pte->upage, pte->segment.read_bytes); | ||
| 128 | process_unlock_filesys (); | ||
| 129 | } | ||
| 130 | |||
| 131 | if (pte != NULL) | ||
| 132 | free (pte); | ||
| 133 | |||
| 134 | ofs += PGSIZE; | ||
| 135 | } | ||
| 136 | |||
| 137 | /* close the file */ | ||
| 138 | process_lock_filesys (); | ||
| 139 | file_close (mme->file); | ||
| 140 | process_unlock_filesys (); | ||
| 102 | 141 | ||
| 103 | //TODO | 142 | /* remove mmap entry from mmap table */ |
| 143 | free (mme); | ||
| 144 | table->ids[mapid] = NULL; | ||
| 104 | 145 | ||
| 105 | /* update index of free/max file descriptor index */ | 146 | /* update index of free/max mapid index */ |
| 106 | if (mapid < table->id_free) | 147 | if (mapid < table->id_free) |
| 107 | table->id_free = mapid; | 148 | table->id_free = mapid; |
| 108 | while (table->ids[table->id_max] == NULL) | 149 | while (table->ids[table->id_max] == NULL) |
| 109 | { | 150 | { |
| 110 | table->id_max--; | 151 | table->id_max--; |
| 111 | if (table->id_max < 0) | 152 | if (table->id_max < 0) |
| 112 | break; | 153 | break; |
| 113 | } | 154 | } |
| 114 | 155 | ||
| 115 | return true; | 156 | return true; |
| 116 | } | 157 | } |
