summaryrefslogtreecommitdiffstats
path: root/vm
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2012-06-21 16:47:23 +0200
committermanuel <manuel@mausz.at>2012-06-21 16:47:23 +0200
commite11b2ef0c606ab516a4344aeea1dbba22cb1fe5d (patch)
treeb4973f4dca916113c82a4a172f6f729d41cf4430 /vm
parente9e69def589375c3d0e51b532268b27d3d403bbf (diff)
downloadprogos-e11b2ef0c606ab516a4344aeea1dbba22cb1fe5d.tar.gz
progos-e11b2ef0c606ab516a4344aeea1dbba22cb1fe5d.tar.bz2
progos-e11b2ef0c606ab516a4344aeea1dbba22cb1fe5d.zip
initial implementation of memory mapped files
Diffstat (limited to 'vm')
-rw-r--r--vm/mmap.c116
-rw-r--r--vm/mmap.h31
-rw-r--r--vm/page.c43
-rw-r--r--vm/page.h27
4 files changed, 163 insertions, 54 deletions
diff --git a/vm/mmap.c b/vm/mmap.c
new file mode 100644
index 0000000..9e7ae47
--- /dev/null
+++ b/vm/mmap.c
@@ -0,0 +1,116 @@
1#include <string.h>
2#include "filesys/file.h"
3#include "threads/thread.h"
4#include "threads/vaddr.h"
5#include "threads/malloc.h"
6#include "threads/palloc.h"
7#include "vm/mmap.h"
8#include "vm/page.h"
9
10static struct mmap_table_entry *mmap_table_get (struct mmap_table *table,
11 mapid_t mapid);
12
13/* initialize memory mapped files table */
14bool
15mmap_table_init (struct mmap_table *table)
16{
17 table->ids = palloc_get_page (PAL_ZERO);
18 if (table->ids == NULL)
19 return false;
20 table->id_cap = PGSIZE / sizeof (table->ids[0]);
21 table->id_free = 0;
22 table->id_max = -1;
23 return true;
24}
25
26/* frees the content of mmap table */
27void
28mmap_table_free (struct mmap_table *table)
29{
30 //TODO
31 palloc_free_page (table->ids);
32}
33
34/* inserts a new mmap entry in the mmap table
35 returns -1 if entry is invalid or already in the table */
36mapid_t
37mmap_table_insert (struct mmap_table *table, void *addr, struct file *file,
38 off_t len)
39{
40 off_t ofs = 0;
41 size_t page_read_bytes;
42 struct mmap_table_entry *mme;
43 mapid_t mapid;
44
45 /* no more entries left */
46 if (table->id_free >= table->id_cap)
47 return -1;
48
49 mme = malloc (sizeof *mme);
50 if (mme == NULL)
51 return -1;
52
53 mapid = table->id_free++;
54 mme->addr = addr;
55 mme->file = file;
56 table->ids[mapid] = mme;
57
58 /* create needed pages in page table */
59 while (len > 0)
60 {
61 page_read_bytes = (len < PGSIZE) ? len : PGSIZE;
62
63 if (!page_table_insert_segment (&thread_current ()->page_table, file, ofs,
64 addr, page_read_bytes, true))
65 return -1;
66
67 /* Advance. */
68 len -= PGSIZE;
69 ofs += page_read_bytes;
70 addr += PGSIZE;
71 }
72
73 /* update index of free/max mapid index */
74 if (mapid > table->id_max)
75 table->id_max = mapid;
76 while (table->ids[table->id_free] != NULL)
77 {
78 table->id_free++;
79 if (table->id_free >= table->id_cap)
80 break;
81 }
82
83 return mapid;
84}
85
86static struct mmap_table_entry *
87mmap_table_get (struct mmap_table *table, mapid_t mapid)
88{
89 if (mapid < 0 || mapid >= table->id_cap || !table->ids[mapid])
90 return NULL;
91 return table->ids[mapid];
92}
93
94bool
95mmap_table_remove (struct mmap_table *table, mapid_t mapid)
96{
97 struct mmap_table_entry *mme = mmap_table_get(table, mapid);
98 if (mme == NULL)
99 return false;
100
101 table->ids[mapid] = NULL;
102
103 //TODO
104
105 /* update index of free/max file descriptor index */
106 if (mapid < table->id_free)
107 table->id_free = mapid;
108 while (table->ids[table->id_max] == NULL)
109 {
110 table->id_max--;
111 if (table->id_max < 0)
112 break;
113 }
114
115 return true;
116}
diff --git a/vm/mmap.h b/vm/mmap.h
new file mode 100644
index 0000000..bee364e
--- /dev/null
+++ b/vm/mmap.h
@@ -0,0 +1,31 @@
1#ifndef VM_MMAP_H
2#define VM_MMAP_H
3
4#include <debug.h>
5#include "filesys/off_t.h"
6#include "lib/user/syscall.h"
7
8/* we use the same structure as fd_table thus the capacity is fixed to
9 1024 (PGSIZE/4) */
10struct mmap_table
11{
12 struct mmap_table_entry **ids;
13 int id_free; /* lowest-index free */
14 int id_max; /* highest-index used */
15 int id_cap; /* mmap table capacity */
16};
17
18/* a single entry in the mmap table */
19struct mmap_table_entry
20{
21 void *addr;
22 struct file *file;
23};
24
25bool mmap_table_init (struct mmap_table *table);
26void mmap_table_free (struct mmap_table *table);
27mapid_t mmap_table_insert (struct mmap_table *table, void *addr,
28 struct file *file, off_t len);
29bool mmap_table_remove (struct mmap_table *table, mapid_t mapping);
30
31#endif
diff --git a/vm/page.c b/vm/page.c
index 336353e..2853497 100644
--- a/vm/page.c
+++ b/vm/page.c
@@ -2,6 +2,7 @@
2#include "filesys/file.h" 2#include "filesys/file.h"
3#include "userprog/process.h" 3#include "userprog/process.h"
4#include "threads/thread.h" 4#include "threads/thread.h"
5#include "threads/vaddr.h"
5#include "threads/malloc.h" 6#include "threads/malloc.h"
6#include "threads/palloc.h" 7#include "threads/palloc.h"
7#include "vm/page.h" 8#include "vm/page.h"
@@ -11,8 +12,6 @@ static bool page_table_cmp_less (const struct hash_elem *a, const struct hash_el
11 void *aux UNUSED); 12 void *aux UNUSED);
12static void page_table_entry_free (struct hash_elem *e, void *aux UNUSED); 13static 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); 14static bool page_table_insert (struct hash *ht, 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);
16 15
17/* initialize page table structure */ 16/* initialize page table structure */
18void 17void
@@ -69,23 +68,20 @@ page_table_insert (struct hash *ht, struct page_table_entry *pte)
69/* inserts a new entry of type segment into the page table 68/* inserts a new entry of type segment into the page table
70 returns false if entry is invalid or already in the table */ 69 returns false if entry is invalid or already in the table */
71bool 70bool
72page_table_insert_segment (struct file *file, off_t ofs, uint8_t *upage, 71page_table_insert_segment (struct hash *ht, struct file *file, off_t ofs,
73 uint32_t read_bytes, uint32_t zero_bytes, bool writable) 72 uint8_t *upage, uint32_t read_bytes, bool writable)
74{ 73{
75 struct page_table_entry *pte = malloc (sizeof *pte); 74 struct page_table_entry *pte = malloc (sizeof *pte);
76 if (pte == NULL) 75 if (pte == NULL)
77 return false; 76 return false;
78 77
79 pte->upage = upage; 78 pte->upage = upage;
80 pte->type = PAGE_SEGMENT;
81 pte->loaded = false; 79 pte->loaded = false;
82 pte->segment.file = file; 80 pte->segment.file = file;
83 pte->segment.ofs = ofs; 81 pte->segment.ofs = ofs;
84 pte->segment.read_bytes = read_bytes; 82 pte->segment.read_bytes = read_bytes;
85 pte->segment.zero_bytes = zero_bytes;
86 pte->segment.writable = writable; 83 pte->segment.writable = writable;
87 84 return page_table_insert (ht, pte);
88 return page_table_insert (&thread_current ()->page_table, pte);
89} 85}
90 86
91/* fetch an entry from the page table. returns NULL if not found */ 87/* fetch an entry from the page table. returns NULL if not found */
@@ -105,28 +101,11 @@ page_table_fetch (struct hash *ht, void *upage)
105bool 101bool
106page_load (struct page_table_entry *pte) 102page_load (struct page_table_entry *pte)
107{ 103{
104 struct segment *data;
108 if (pte->loaded) 105 if (pte->loaded)
109 return true; 106 return true;
110 107
111 switch (pte->type) 108 data = &pte->segment;
112 {
113 case PAGE_SEGMENT:
114 return page_load_segment (pte);
115 case PAGE_MEMORY_MAPPED_FILE:
116 return page_load_mmf (pte);
117 default:
118 ASSERT (false);
119 break;
120 }
121 return false;
122}
123
124/* load the segment data page */
125static bool
126page_load_segment (struct page_table_entry *pte)
127{
128 struct segment *data = &pte->segment;
129
130 file_seek (data->file, data->ofs); 109 file_seek (data->file, data->ofs);
131 110
132 /* Get a page of memory. */ 111 /* Get a page of memory. */
@@ -141,7 +120,7 @@ page_load_segment (struct page_table_entry *pte)
141 palloc_free_page (kpage); 120 palloc_free_page (kpage);
142 return false; 121 return false;
143 } 122 }
144 memset (kpage + data->read_bytes, 0, data->zero_bytes); 123 memset (kpage + data->read_bytes, 0, PGSIZE - data->read_bytes);
145 124
146 /* Add the page to the process's address space. */ 125 /* Add the page to the process's address space. */
147 if (!process_install_page (pte->upage, kpage, data->writable)) 126 if (!process_install_page (pte->upage, kpage, data->writable))
@@ -153,11 +132,3 @@ page_load_segment (struct page_table_entry *pte)
153 pte->loaded = true; 132 pte->loaded = true;
154 return true; 133 return true;
155} 134}
156
157/* load the memory mappged file page */
158static bool
159page_load_mmf (struct page_table_entry *pte)
160{
161 //TODO: implement
162 return false;
163}
diff --git a/vm/page.h b/vm/page.h
index 9cea048..da1398c 100644
--- a/vm/page.h
+++ b/vm/page.h
@@ -10,24 +10,15 @@ struct page_table_entry
10{ 10{
11 void *upage; /* virtual address of page */ 11 void *upage; /* virtual address of page */
12 bool loaded; /* indicates if page is loaded */ 12 bool loaded; /* indicates if page is loaded */
13 enum
14 {
15 PAGE_SEGMENT,
16 PAGE_MEMORY_MAPPED_FILE,
17 } type; /* type of page */
18 13
19 union 14 /* structure needed for lazy loading of data segments and mmapped files */
15 struct segment
20 { 16 {
21 /* structure needed for lazy loading of data segments */ 17 struct file *file;
22 struct segment 18 off_t ofs;
23 { 19 uint32_t read_bytes;
24 struct file *file; 20 bool writable;
25 off_t ofs; 21 } segment;
26 uint32_t read_bytes;
27 uint32_t zero_bytes;
28 bool writable;
29 } segment;
30 };
31 22
32 struct hash_elem elem; /* Hash element. */ 23 struct hash_elem elem; /* Hash element. */
33}; 24};
@@ -35,8 +26,8 @@ struct page_table_entry
35void page_table_init (struct hash *ht); 26void page_table_init (struct hash *ht);
36void page_table_free (struct hash *ht); 27void page_table_free (struct hash *ht);
37struct page_table_entry *page_table_fetch (struct hash *ht, void *upage); 28struct page_table_entry *page_table_fetch (struct hash *ht, void *upage);
38bool page_table_insert_segment (struct file *file, off_t ofs, uint8_t *upage, 29bool page_table_insert_segment (struct hash *ht, struct file *file, off_t ofs,
39 uint32_t read_bytes, uint32_t zero_bytes, bool writable); 30 uint8_t *upage, uint32_t read_bytes, bool writable);
40bool page_load (struct page_table_entry *pte); 31bool page_load (struct page_table_entry *pte);
41 32
42#endif 33#endif