AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
vm_object.c
Go to the documentation of this file.
1
7
8#include <core/system.h>
9#include <core/string.h>
10#include <mm/vm.h>
11#include <mm/pmap.h>
12
13static struct vm_pager vnode_pager;
14
16static int vm_page_eq(void *_a, void *_b)
17{
18 struct vm_page *a = (struct vm_page *) _a;
19 size_t *b = (size_t *) _b;
20
21 return a->off == *b;
22}
23
32{
33 if (!vnode)
34 return NULL;
35
36 if (!vnode->vm_object) {
37 struct vm_object *vm_object;
38
39 vm_object = kmalloc(sizeof(struct vm_object), &M_VM_OBJECT, M_ZERO);
40 if (!vm_object) return NULL;
41
43 vm_object->pages = hashmap_new(0, vm_page_eq);
44
45 if (!vm_object->pages) {
47 return NULL;
48 }
49
51 vm_object->p = vnode;
52
54 }
55
56 return vnode->vm_object;
57}
58
68{
69 struct vnode *vnode = (struct vnode *) vm_object->p;
70
71 off = PAGE_ALIGN(off);
72
73 /* read into a buffer of its own, since reading may sleep (on the
74 * disk); a short read leaves zeros, not stale memory */
75 char *buf = kmalloc(PAGE_SIZE, &M_BUFFER, M_ZERO);
76 if (!buf) return NULL;
77
78 /* a page that can't be read isn't mapped as zeros: the fault fails */
79 if (vfs_read(vnode, off, PAGE_SIZE, buf) < 0) {
80 kfree(buf);
81 return NULL;
82 }
83
84 /* another thread may have paged it in meanwhile */
85 hash_t hash = hashmap_digest(&off, sizeof(off));
86 struct hashmap_node *node = hashmap_lookup(vm_object->pages, hash, &off);
87
88 if (node) {
89 kfree(buf);
90 return (struct vm_page *) node->entry;
91 }
92
93 struct vm_page *vm_page = mm_page_alloc();
94
95 if (!vm_page) {
96 kfree(buf);
97 return NULL;
98 }
99
101 vm_page->off = off;
102 vm_page->ref = 1;
103
105 kfree(buf);
106
107 /* no memory to keep it in the object: the fault fails, as with no
108 * memory for the page */
111 return NULL;
112 }
113
114 return vm_page;
115}
116
128void vnode_pages_update(struct vnode *vnode, off_t start, off_t end)
129{
131
132 if (!vm_object || !vm_object->pages->count || end <= start)
133 return;
134
135 char *buf = NULL;
136
137 /* each page is looked up, rather than the map walked: the read may
138 * sleep, and the map change meanwhile (a page that's found stays,
139 * since pages are only freed with the vnode) */
140 for (size_t off = PAGE_ALIGN((size_t) start); off < (size_t) end; off += PAGE_SIZE) {
141 hash_t hash = hashmap_digest(&off, sizeof(off));
142 struct hashmap_node *node = hashmap_lookup(vm_object->pages, hash, &off);
143
144 if (!node)
145 continue;
146
147 struct vm_page *vm_page = (struct vm_page *) node->entry;
148
149 if (!buf && !(buf = kmalloc(PAGE_SIZE, &M_BUFFER, 0))) {
150 printk("vm: no memory to update a file's cached pages\n");
151 return;
152 }
153
154 memset(buf, 0, PAGE_SIZE);
155
156 if (vfs_read(vnode, off, PAGE_SIZE, buf) < 0)
157 continue;
158
160 }
161
162 kfree(buf);
163}
164
173{
175
176 if (!vm_object)
177 return;
178
180 struct hashmap_node *node = (struct hashmap_node *) qnode->value;
181 struct vm_page *vm_page = (struct vm_page *) node->entry;
182
184 }
185
186 hashmap_free(vm_object->pages);
189}
190
191static struct vm_pager vnode_pager = {
192 .in = vnode_page_in,
193 .out = NULL,
194};
#define PAGE_SIZE
Definition system.h:7
static int vm_page_eq(void *a, void *b)
Tells whether a page is at the offset that b points to (for the object's hashmap of pages).
Definition signal.c:56
void vnode_pages_update(struct vnode *vnode, off_t start, off_t end)
Reads a file's cached pages again after a write or a truncation changed a range of it.
Definition vm_object.c:128
void vnode_pages_free(struct vnode *vnode)
Frees a vnode's vm object and its cached pages, when the vnode itself is freed.
Definition vm_object.c:172
struct vm_object * vm_object_vnode(struct vnode *vnode)
Gets a vnode's vm object, making it the first time.
Definition vm_object.c:31
struct vm_page * vnode_page_in(struct vm_object *vm_object, size_t off)
Reads a page of a file into its vm object: the vnode pager's page in.
Definition vm_object.c:67
static struct vm_pager vnode_pager
Definition vm_object.c:13
#define hashmap_for(n, h)
Definition hashmap.h:51
uintptr_t hash_t
Definition hashmap.h:22
#define PAGE_ALIGN(ptr)
Definition mm.h:9
struct vm_page * mm_page_alloc(void)
Allocates a free page of physical memory.
Definition mm.c:78
void mm_page_dealloc(paddr_t paddr)
Frees a page of physical memory, back to the zone it came from.
Definition mm.c:103
void * kmalloc(size_t size, struct malloc_type *type, int flags)
Allocates memory for one of the kernel's structures.
Definition kvmem.c:123
#define M_ZERO
Definition kvmem.h:26
void kfree(void *)
Frees an object that kmalloc() gave.
Definition kvmem.c:146
void * memset(void *dst, int c, size_t n)
Sets n bytes to c.
Definition libc.c:23
int pmap_page_write(paddr_t paddr, off_t off, size_t size, void *buf)
Writes to a page of physical memory, through the kernel's mapping.
Definition pmap.c:452
int printk(const char *fmt,...)
Writes a kernel message, to the message buffer and the consoles.
Definition printk.c:249
ssize_t vfs_read(struct vnode *vnode, off_t off, size_t size, void *buf)
Reads from a vnode into a kernel buffer.
Definition read.c:52
#define NULL
Definition stddef.h:27
__SIZE_TYPE__ size_t
Definition stddef.h:7
A hash table's node: an entry, with its key's hash.
Definition hashmap.h:43
hash_t hash
Definition hashmap.h:44
void * entry
Definition hashmap.h:45
size_t count
Definition hashmap.h:33
A queue's node, holding one entry.
Definition queue.h:19
void * value
Definition queue.h:20
A vm object: what a mapping's pages come from (a file), and its pages that have been read in.
Definition vm.h:132
void * p
the pager's own data (a file's vnode)
Definition vm.h:146
int type
its kind (VMOBJ_*)
Definition vm.h:137
struct vm_pager * pager
its pager
Definition vm.h:143
struct hashmap * pages
its pages that have been read in, by their offset
Definition vm.h:134
A page of physical memory (pages[] has one for every page of RAM).
Definition vm.h:150
size_t off
its offset in its object or anon
Definition vm.h:155
size_t ref
how many references it has
Definition vm.h:157
struct vm_object * vm_object
the object it belongs to, or NULL
Definition vm.h:153
paddr_t paddr
its physical address
Definition vm.h:151
A vm object's pager: reads its pages in, and writes them out.
Definition vm.h:94
A file in memory (a vnode): what its inode says, and the kernel's own state.
Definition vfs.h:113
struct vm_object * vm_object
its vm object: its pages, read in (the page cache)
Definition vfs.h:140
long int off_t
Definition types.h:10
#define VMOBJ_FILE
a file's pages
Definition vm.h:60
int vm_object_page_insert(struct vm_object *vm_object, struct vm_page *vm_page)
Adds a page to a vm object, at the page's offset (vm_page->off).
Definition vm_object.c:52