xref: /minix3/minix/servers/vm/mem_anon.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1 
2 /* This file implements the methods of anonymous memory.
3  *
4  * Anonymous memory is memory that is for private use to a process
5  * and can not be related to a file (hence anonymous).
6  */
7 
8 #include <assert.h>
9 
10 #include "proto.h"
11 #include "vm.h"
12 #include "region.h"
13 #include "glo.h"
14 
15 /* These functions are static so as to not pollute the
16  * global namespace, and are accessed through their function
17  * pointers.
18  */
19 
20 static void anon_split(struct vmproc *vmp, struct vir_region *vr,
21 			struct vir_region *r1, struct vir_region *r2);
22 static int anon_lowshrink(struct vir_region *vr, vir_bytes len);
23 static int anon_unreference(struct phys_region *pr);
24 static int anon_pagefault(struct vmproc *vmp, struct vir_region *region,
25 	struct phys_region *ph, int write, vfs_callback_t cb, void *state,
26 	int len, int *io);
27 static int anon_sanitycheck(struct phys_region *pr, const char *file, int line);
28 static int anon_writable(struct phys_region *pr);
29 static int anon_resize(struct vmproc *vmp, struct vir_region *vr, vir_bytes l);
30 static u32_t anon_regionid(struct vir_region *region);
31 static int anon_refcount(struct vir_region *vr);
32 static int anon_pt_flags(struct vir_region *vr);
33 
34 struct mem_type mem_type_anon = {
35 	.name = "anonymous memory",
36 	.ev_unreference = anon_unreference,
37 	.ev_pagefault = anon_pagefault,
38 	.ev_resize = anon_resize,
39 	.ev_sanitycheck = anon_sanitycheck,
40 	.ev_lowshrink = anon_lowshrink,
41 	.ev_split = anon_split,
42 	.regionid = anon_regionid,
43 	.writable = anon_writable,
44 	.refcount = anon_refcount,
45 	.pt_flags = anon_pt_flags,
46 };
47 
anon_pt_flags(struct vir_region * vr)48 static int anon_pt_flags(struct vir_region *vr){
49 #if defined(__arm__)
50 	return ARM_VM_PTE_CACHED;
51 #else
52 	return 0;
53 #endif
54 }
55 
anon_unreference(struct phys_region * pr)56 static int anon_unreference(struct phys_region *pr)
57 {
58 	assert(pr->ph->refcount == 0);
59 	if(pr->ph->phys != MAP_NONE)
60 		free_mem(ABS2CLICK(pr->ph->phys), 1);
61 	return OK;
62 }
63 
anon_pagefault(struct vmproc * vmp,struct vir_region * region,struct phys_region * ph,int write,vfs_callback_t cb,void * state,int len,int * io)64 static int anon_pagefault(struct vmproc *vmp, struct vir_region *region,
65 	struct phys_region *ph, int write, vfs_callback_t cb, void *state,
66 	int len, int *io)
67 {
68 	phys_bytes new_page, new_page_cl;
69 	u32_t allocflags;
70 
71 	allocflags = vrallocflags(region->flags);
72 
73 	assert(ph->ph->refcount > 0);
74 
75 	if((new_page_cl = alloc_mem(1, allocflags)) == NO_MEM) {
76 		printf("anon_pagefault: out of memory\n");
77 		return ENOMEM;
78 	}
79 	new_page = CLICK2ABS(new_page_cl);
80 
81 	/* Totally new block? Create it. */
82 	if(ph->ph->phys == MAP_NONE) {
83 		ph->ph->phys = new_page;
84 		assert(ph->ph->phys != MAP_NONE);
85 
86 		return OK;
87 	}
88 
89 	if(ph->ph->refcount < 2 || !write) {
90 		/* memory is ready already */
91 		return OK;
92 	}
93 
94         assert(region->flags & VR_WRITABLE);
95 
96 	return mem_cow(region, ph, new_page_cl, new_page);
97 }
98 
anon_sanitycheck(struct phys_region * pr,const char * file,int line)99 static int anon_sanitycheck(struct phys_region *pr, const char *file, int line)
100 {
101 	MYASSERT(usedpages_add(pr->ph->phys, VM_PAGE_SIZE) == OK);
102 	return OK;
103 }
104 
anon_writable(struct phys_region * pr)105 static int anon_writable(struct phys_region *pr)
106 {
107 	assert(pr->ph->refcount > 0);
108 	if(pr->ph->phys == MAP_NONE)
109 		return 0;
110 	if(pr->parent->remaps > 0)
111 		return 1;
112 	return pr->ph->refcount == 1;
113 }
114 
anon_resize(struct vmproc * vmp,struct vir_region * vr,vir_bytes l)115 static int anon_resize(struct vmproc *vmp, struct vir_region *vr, vir_bytes l)
116 {
117 	/* Shrinking not implemented; silently ignored.
118 	 * (Which is ok for brk().)
119 	 */
120 	if(l <= vr->length)
121 		return OK;
122 
123         assert(vr);
124         assert(vr->flags & VR_ANON);
125         assert(!(l % VM_PAGE_SIZE));
126 
127         USE(vr, vr->length = l;);
128 
129 	return OK;
130 }
131 
anon_regionid(struct vir_region * region)132 static u32_t anon_regionid(struct vir_region *region)
133 {
134 	return region->id;
135 }
136 
anon_lowshrink(struct vir_region * vr,vir_bytes len)137 static int anon_lowshrink(struct vir_region *vr, vir_bytes len)
138 {
139 	return OK;
140 }
141 
anon_refcount(struct vir_region * vr)142 static int anon_refcount(struct vir_region *vr)
143 {
144         return 1 + vr->remaps;
145 }
146 
anon_split(struct vmproc * vmp,struct vir_region * vr,struct vir_region * r1,struct vir_region * r2)147 static void anon_split(struct vmproc *vmp, struct vir_region *vr,
148 			struct vir_region *r1, struct vir_region *r2)
149 {
150 	return;
151 }
152