AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
vm_anon.c
Go to the documentation of this file.
1
10
11#include <core/system.h>
12#include <core/panic.h>
13#include <mm/vm.h>
14
15MALLOC_DEFINE(M_VM_ANON, "vm-anon", "anonymous virtual memory object");
16
19static int vm_aref_eq(void *_a, void *_b)
20{
21 struct vm_aref *a = (struct vm_aref *) _a;
22
23 if (!a->vm_page)
24 return 0;
25
26 size_t *b = (size_t *) _b;
27
28 return a->vm_page->off == *b;
29}
30
36struct vm_anon *vm_anon_new(void)
37{
38 struct vm_anon *vm_anon = kmalloc(sizeof(struct vm_anon), &M_VM_ANON, M_ZERO);
39 if (!vm_anon) goto error;
40
41 vm_anon->arefs = hashmap_new(0, vm_aref_eq);
42
43 if (!vm_anon->arefs)
44 goto error;
45
46 return vm_anon;
47
48error:
49 if (vm_anon) {
50 if (vm_anon->arefs)
51 hashmap_free(vm_anon->arefs);
53 }
54
55 return NULL;
56}
57
65{
66 /* nothing to do */
67}
68
75{
76 vm_aref->ref--;
77}
78
86{
87 if (!vm_anon) return;
88
89 struct hashmap *arefs = vm_anon->arefs;
90
91 if (!arefs)
92 return;
93
95 struct hashmap_node *hnode = (struct hashmap_node *) qnode->value;
96 struct vm_aref *aref = (struct vm_aref *) hnode->entry;
97
98 vm_aref_decref(aref);
99
100 if (!aref->ref) {
101 if (aref->vm_page) {
103 }
104
105 kfree(aref);
106 }
107 }
108
109 hashmap_free(vm_anon->arefs);
110}
111
118{
119 if (!vm_anon)
120 return;
121
122 vm_anon->ref++;
123}
124
131{
132 if (!vm_anon)
133 return;
134
135 vm_anon->ref--;
136
137 if (!vm_anon->ref) {
139 kfree(vm_anon);
140 }
141}
142
147static int vm_anon_copy_arefs(struct vm_anon *src, struct vm_anon *dst)
148{
149 if (!src || !dst || !src->arefs || !dst->arefs)
150 return -EINVAL;
151
152 hashmap_for (qnode, src->arefs) {
153 struct hashmap_node *node = (struct hashmap_node *) qnode->value;
154 struct vm_aref *aref = (struct vm_aref *) node->entry;
155
156 if (hashmap_insert(dst->arefs, node->hash, aref))
157 return -ENOMEM;
158
159 aref->ref++;
160 }
161
162 return 0;
163}
164
175{
176 if (!vm_anon)
177 return NULL;
178
179 struct vm_anon *new_anon = vm_anon_new();
180
181 if (!new_anon)
182 return NULL;
183
184 new_anon->flags = vm_anon->flags & ~VM_COPY;
185 new_anon->ref = 1;
186
187 /* on failure, the arefs copied so far give back their references,
188 * and the hashmap goes */
189 if (vm_anon_copy_arefs(vm_anon, new_anon)) {
190 vm_anon_destroy(new_anon);
191 kfree(new_anon);
192 return NULL;
193 }
194
195 return new_anon;
196}
#define hashmap_for(n, h)
Definition hashmap.h:51
void mm_page_dealloc(paddr_t paddr)
Frees a page of physical memory, back to the zone it came from.
Definition mm.c:103
#define MALLOC_DEFINE(type, _name, _desc)
Definition kvmem.h:30
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
#define NULL
Definition stddef.h:27
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
A hash table.
Definition hashmap.h:32
A queue's node, holding one entry.
Definition queue.h:19
void * value
Definition queue.h:20
An anon: a mapping's private pages, those the process wrote to.
Definition vm.h:119
struct hashmap * arefs
its arefs, by the offset of their page in the mapping
Definition vm.h:121
int flags
its flags (VM_COPY: to be copied before it's written to)
Definition vm.h:127
size_t ref
how many mappings share the anon
Definition vm.h:124
An anon's reference to a page (an aref).
Definition vm.h:107
size_t ref
how many anons have the aref
Definition vm.h:112
struct vm_page * vm_page
the page
Definition vm.h:109
size_t off
its offset in its object or anon
Definition vm.h:155
paddr_t paddr
its physical address
Definition vm.h:151
#define VM_COPY
to be copied before it's written to
Definition vm.h:47
void vm_anon_destroy(struct vm_anon *vm_anon)
Releases an anon's arefs, and the pages of those that no other anon shares.
Definition vm_anon.c:85
void vm_anon_incref(struct vm_anon *vm_anon)
Adds a reference to an anon: another mapping shares it (a fork).
Definition vm_anon.c:117
struct vm_anon * vm_anon_new(void)
Makes a new, empty anon.
Definition vm_anon.c:36
struct vm_anon * vm_anon_copy(struct vm_anon *vm_anon)
Makes a copy of an anon that shares its arefs, and so its pages, when a mapping's shared anon is writ...
Definition vm_anon.c:174
void vm_anon_decref(struct vm_anon *vm_anon)
Drops a reference to an anon, and frees it with the last one.
Definition vm_anon.c:130
void vm_aref_decref(struct vm_aref *vm_aref)
Drops a reference to an aref.
Definition vm_anon.c:74
static int vm_anon_copy_arefs(struct vm_anon *src, struct vm_anon *dst)
Puts all of src's arefs in dst as well, shared: each gets one more reference.
Definition vm_anon.c:147
static int vm_aref_eq(void *_a, void *_b)
Says whether an aref is the one for an offset (_b, a size_t *), for the anon's hashmap.
Definition vm_anon.c:19
void vm_aref_destroy(struct vm_aref *vm_aref)
Releases what an aref holds.
Definition vm_anon.c:64