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 } 261