vm: allow split of mem_anon_contig region
[minix3.git] / minix / servers / vm / mem_anon.c
blob172e30ed92ed715f794129752e8bfc00f43a8526
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 */
8 #include <assert.h>
10 #include "proto.h"
11 #include "vm.h"
12 #include "region.h"
13 #include "glo.h"
15 /* These functions are static so as to not pollute the
16 * global namespace, and are accessed through their function
17 * pointers.
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);
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,
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
56 static int anon_unreference(struct phys_region *pr)
58 assert(pr->ph->refcount == 0);
59 if(pr->ph->phys != MAP_NONE)
60 free_mem(ABS2CLICK(pr->ph->phys), 1);
61 return OK;
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)
68 phys_bytes new_page, new_page_cl;
69 u32_t allocflags;
71 allocflags = vrallocflags(region->flags);
73 assert(ph->ph->refcount > 0);
75 if((new_page_cl = alloc_mem(1, allocflags)) == NO_MEM) {
76 printf("anon_pagefault: out of memory\n");
77 return ENOMEM;
79 new_page = CLICK2ABS(new_page_cl);
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);
86 return OK;
89 if(ph->ph->refcount < 2 || !write) {
90 /* memory is ready already */
91 return OK;
94 assert(region->flags & VR_WRITABLE);
96 return mem_cow(region, ph, new_page_cl, new_page);
99 static int anon_sanitycheck(struct phys_region *pr, const char *file, int line)
101 MYASSERT(usedpages_add(pr->ph->phys, VM_PAGE_SIZE) == OK);
102 return OK;
105 static int anon_writable(struct phys_region *pr)
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;
115 static int anon_resize(struct vmproc *vmp, struct vir_region *vr, vir_bytes l)
117 /* Shrinking not implemented; silently ignored.
118 * (Which is ok for brk().)
120 if(l <= vr->length)
121 return OK;
123 assert(vr);
124 assert(vr->flags & VR_ANON);
125 assert(!(l % VM_PAGE_SIZE));
127 USE(vr, vr->length = l;);
129 return OK;
132 static u32_t anon_regionid(struct vir_region *region)
134 return region->id;
137 static int anon_lowshrink(struct vir_region *vr, vir_bytes len)
139 return OK;
142 static int anon_refcount(struct vir_region *vr)
144 return 1 + vr->remaps;
147 static void anon_split(struct vmproc *vmp, struct vir_region *vr,
148 struct vir_region *r1, struct vir_region *r2)
150 return;