summaryrefslogtreecommitdiffstats
path: root/vm/mmap.c
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2012-06-21 18:14:58 +0200
committermanuel <manuel@mausz.at>2012-06-21 18:14:58 +0200
commite61e868b265efe2f6d51079373588d639fc54d59 (patch)
tree035fa9afef57c88ed156909d73cd8c4a91fe4435 /vm/mmap.c
parente11b2ef0c606ab516a4344aeea1dbba22cb1fe5d (diff)
downloadprogos-e61e868b265efe2f6d51079373588d639fc54d59.tar.gz
progos-e61e868b265efe2f6d51079373588d639fc54d59.tar.bz2
progos-e61e868b265efe2f6d51079373588d639fc54d59.zip
full mmap implementation
Diffstat (limited to 'vm/mmap.c')
-rw-r--r--vm/mmap.c91
1 files changed, 66 insertions, 25 deletions
diff --git a/vm/mmap.c b/vm/mmap.c
index 9e7ae47..55ee91b 100644
--- a/vm/mmap.c
+++ b/vm/mmap.c
@@ -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 */
27void 29void
28mmap_table_free (struct mmap_table *table) 30mmap_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 */
36mapid_t 40mapid_t
37mmap_table_insert (struct mmap_table *table, void *addr, struct file *file, 41mmap_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 */
86static struct mmap_table_entry * 96static struct mmap_table_entry *
87mmap_table_get (struct mmap_table *table, mapid_t mapid) 97mmap_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 */
94bool 106bool
95mmap_table_remove (struct mmap_table *table, mapid_t mapid) 107mmap_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}