FreeBSD/Linux Kernel Cross Reference
sys/port/xalloc.c
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6
7 enum
8 {
9 Chunk = 64*1024,
10 Nhole = 128,
11 Magichole = 0x484F4C45, /* HOLE */
12 };
13
14 typedef struct Hole Hole;
15 typedef struct Xalloc Xalloc;
16 typedef struct Xhdr Xhdr;
17
18 struct Hole
19 {
20 ulong addr;
21 ulong size;
22 ulong top;
23 Hole* link;
24 };
25
26 struct Xhdr
27 {
28 ulong size;
29 ulong magix;
30 char data[];
31 };
32
33 struct Xalloc
34 {
35 Lock;
36 Hole hole[Nhole];
37 Hole* flist;
38 Hole* table;
39 };
40
41 static Xalloc xlists;
42
43 void
44 xinit(void)
45 {
46 int i, n, upages, kpages;
47 ulong maxpages;
48 Confmem *m;
49 Pallocmem *pm;
50 Hole *h, *eh;
51
52 eh = &xlists.hole[Nhole-1];
53 for(h = xlists.hole; h < eh; h++)
54 h->link = h+1;
55
56 xlists.flist = xlists.hole;
57
58 upages = conf.upages;
59 kpages = conf.npage - upages;
60 pm = palloc.mem;
61 for(i=0; i<nelem(conf.mem); i++){
62 m = &conf.mem[i];
63 n = m->npage;
64 if(n > kpages)
65 n = kpages;
66 /* don't try to use non-KADDR-able memory for kernel */
67 maxpages = cankaddr(m->base)/BY2PG;
68 if(n > maxpages)
69 n = maxpages;
70 /* first give to kernel */
71 if(n > 0){
72 m->kbase = (ulong)KADDR(m->base);
73 m->klimit = (ulong)KADDR(m->base+n*BY2PG);
74 xhole(m->base, n*BY2PG);
75 kpages -= n;
76 }
77 /* if anything left over, give to user */
78 if(n < m->npage){
79 if(pm >= palloc.mem+nelem(palloc.mem)){
80 print("xinit: losing %lud pages\n", m->npage-n);
81 continue;
82 }
83 pm->base = m->base+n*BY2PG;
84 pm->npage = m->npage - n;
85 pm++;
86 }
87 }
88 xsummary();
89 }
90
91 void*
92 xspanalloc(ulong size, int align, ulong span)
93 {
94 ulong a, v, t;
95 a = (ulong)xalloc(size+align+span);
96 if(a == 0)
97 panic("xspanalloc: %lud %d %lux\n", size, align, span);
98
99 if(span > 2) {
100 v = (a + span) & ~(span-1);
101 t = v - a;
102 if(t > 0)
103 xhole(PADDR(a), t);
104 t = a + span - v;
105 if(t > 0)
106 xhole(PADDR(v+size+align), t);
107 }
108 else
109 v = a;
110
111 if(align > 1)
112 v = (v + align) & ~(align-1);
113
114 return (void*)v;
115 }
116
117 void*
118 xallocz(ulong size, int zero)
119 {
120 Xhdr *p;
121 Hole *h, **l;
122
123 size += BY2V + offsetof(Xhdr, data[0]);
124 size &= ~(BY2V-1);
125
126 ilock(&xlists);
127 l = &xlists.table;
128 for(h = *l; h; h = h->link) {
129 if(h->size >= size) {
130 p = (Xhdr*)KADDR(h->addr);
131 h->addr += size;
132 h->size -= size;
133 if(h->size == 0) {
134 *l = h->link;
135 h->link = xlists.flist;
136 xlists.flist = h;
137 }
138 iunlock(&xlists);
139 if(zero)
140 memset(p->data, 0, size);
141 p->magix = Magichole;
142 p->size = size;
143 return p->data;
144 }
145 l = &h->link;
146 }
147 iunlock(&xlists);
148 return nil;
149 }
150
151 void*
152 xalloc(ulong size)
153 {
154 return xallocz(size, 1);
155 }
156
157 void
158 xfree(void *p)
159 {
160 Xhdr *x;
161
162 x = (Xhdr*)((ulong)p - offsetof(Xhdr, data[0]));
163 if(x->magix != Magichole) {
164 xsummary();
165 panic("xfree(%#p) %#ux != %#lux", p, Magichole, x->magix);
166 }
167 xhole(PADDR((uintptr)x), x->size);
168 }
169
170 int
171 xmerge(void *vp, void *vq)
172 {
173 Xhdr *p, *q;
174
175 p = (Xhdr*)(((ulong)vp - offsetof(Xhdr, data[0])));
176 q = (Xhdr*)(((ulong)vq - offsetof(Xhdr, data[0])));
177 if(p->magix != Magichole || q->magix != Magichole) {
178 xsummary();
179 panic("xmerge(%#p, %#p) bad magic %#lux, %#lux\n",
180 vp, vq, p->magix, q->magix);
181 }
182 if((uchar*)p+p->size == (uchar*)q) {
183 p->size += q->size;
184 return 1;
185 }
186 return 0;
187 }
188
189 void
190 xhole(ulong addr, ulong size)
191 {
192 ulong top;
193 Hole *h, *c, **l;
194
195 if(size == 0)
196 return;
197
198 top = addr + size;
199 ilock(&xlists);
200 l = &xlists.table;
201 for(h = *l; h; h = h->link) {
202 if(h->top == addr) {
203 h->size += size;
204 h->top = h->addr+h->size;
205 c = h->link;
206 if(c && h->top == c->addr) {
207 h->top += c->size;
208 h->size += c->size;
209 h->link = c->link;
210 c->link = xlists.flist;
211 xlists.flist = c;
212 }
213 iunlock(&xlists);
214 return;
215 }
216 if(h->addr > addr)
217 break;
218 l = &h->link;
219 }
220 if(h && top == h->addr) {
221 h->addr -= size;
222 h->size += size;
223 iunlock(&xlists);
224 return;
225 }
226
227 if(xlists.flist == nil) {
228 iunlock(&xlists);
229 print("xfree: no free holes, leaked %lud bytes\n", size);
230 return;
231 }
232
233 h = xlists.flist;
234 xlists.flist = h->link;
235 h->addr = addr;
236 h->top = top;
237 h->size = size;
238 h->link = *l;
239 *l = h;
240 iunlock(&xlists);
241 }
242
243 void
244 xsummary(void)
245 {
246 int i;
247 Hole *h;
248
249 i = 0;
250 for(h = xlists.flist; h; h = h->link)
251 i++;
252
253 print("%d holes free\n", i);
254 i = 0;
255 for(h = xlists.table; h; h = h->link) {
256 print("%.8lux %.8lux %lud\n", h->addr, h->top, h->size);
257 i += h->size;
258 }
259 print("%d bytes free\n", i);
260 }
Cache object: 6e2abee5e4b1ca5a5093f95ff1a882ab
|