1 #include "u.h" 2 #include "../port/lib.h" 3 #include "mem.h" 4 #include "dat.h" 5 #include "fns.h" 6 #include "../port/error.h" 7 8 #define pghash(daddr) palloc.hash[(daddr>>PGSHIFT)&(PGHSIZE-1)] 9 10 static Lock pglock; 11 struct Palloc palloc; 12 13 void 14 pageinit(void) 15 { 16 Page *p; 17 ulong np, hw, hr, vmem, pmem; 18 19 np = palloc.np0+palloc.np1; 20 palloc.head = xalloc(np*sizeof(Page)); 21 if(palloc.head == 0) 22 panic("pageinit"); 23 24 p = palloc.head; 25 while(palloc.np0 > 0) { 26 p->prev = p-1; 27 p->next = p+1; 28 p->pa = palloc.p0; 29 palloc.p0 += BY2PG; 30 palloc.np0--; 31 p++; 32 } 33 while(palloc.np1 > 0) { 34 p->prev = p-1; 35 p->next = p+1; 36 p->pa = palloc.p1; 37 palloc.p1 += BY2PG; 38 palloc.np1--; 39 p++; 40 } 41 palloc.tail = p - 1; 42 palloc.head->prev = 0; 43 palloc.tail->next = 0; 44 45 palloc.user = p - palloc.head; 46 palloc.freecount = palloc.user; 47 pmem = palloc.user*BY2PG/1024; 48 vmem = pmem + (conf.nswap*BY2PG)/1024; 49 50 /* Pageing numbers */ 51 swapalloc.highwater = (palloc.freecount*5)/100; 52 swapalloc.headroom = swapalloc.highwater + (swapalloc.highwater/4); 53 54 hw = swapalloc.highwater*BY2PG; 55 hr = swapalloc.headroom*BY2PG; 56 57 print("%lud free pages, %dK bytes, swap %dK, highwater %dK, headroom %dK\n", 58 palloc.user, pmem, vmem, hw/1024, hr/1024);/**/ 59 } 60 61 Page* 62 newpage(int clear, Segment **s, ulong va) 63 { 64 Page *p; 65 KMap *k; 66 int hw, i, dontalloc; 67 68 retry: 69 lock(&palloc); 70 71 hw = swapalloc.highwater; 72 while((palloc.freecount < hw && u->p->kp == 0) || palloc.freecount == 0) { 73 palloc.wanted++; 74 unlock(&palloc); 75 dontalloc = 0; 76 if(s && *s) { 77 qunlock(&((*s)->lk)); 78 *s = 0; 79 dontalloc = 1; 80 } 81 qlock(&palloc.pwait); /* Hold memory requesters here */ 82 83 while(waserror()) /* Ignore interrupts */ 84 ; 85 86 kickpager(); 87 tsleep(&palloc.r, ispages, 0, 1000); 88 89 poperror(); 90 91 qunlock(&palloc.pwait); 92 93 /* 94 * If called from fault and we lost the segment from underneath 95 * don't waste time allocating and freeing a page. Fault will call 96 * newpage again when it has reacquired the segment locks 97 */ 98 if(dontalloc) 99 return 0; 100 101 lock(&palloc); 102 palloc.wanted--; 103 } 104 105 p = palloc.head; 106 if(palloc.head = p->next) /* = Assign */ 107 palloc.head->prev = 0; 108 else 109 palloc.tail = 0; 110 111 palloc.freecount--; 112 unlock(&palloc); 113 114 lock(p); 115 if(p->ref != 0) { /* lookpage has priority on steal */ 116 unlock(p); 117 goto retry; 118 } 119 uncachepage(p); 120 p->ref++; 121 p->va = va; 122 p->modref = 0; 123 for(i = 0; i < MAXMACH; i++) 124 p->cachectl[i] = PG_NOFLUSH; 125 mmunewpage(p); 126 unlock(p); 127 128 if(clear){ 129 k = kmap(p); 130 memset((void*)VA(k), 0, BY2PG); 131 kunmap(k); 132 } 133 134 return p; 135 } 136 137 int 138 ispages(void *p) 139 { 140 USED(p); 141 return palloc.freecount >= swapalloc.highwater; 142 } 143 144 void 145 putpage(Page *p) 146 { 147 if(onswap(p)) { 148 putswap(p); 149 return; 150 } 151 152 lock(p); 153 if(--p->ref == 0) { 154 lock(&palloc); 155 if(p->image && p->image != &swapimage) { 156 if(palloc.tail) { 157 p->prev = palloc.tail; 158 palloc.tail->next = p; 159 } 160 else { 161 palloc.head = p; 162 p->prev = 0; 163 } 164 palloc.tail = p; 165 p->next = 0; 166 } 167 else { 168 if(palloc.head) { 169 p->next = palloc.head; 170 palloc.head->prev = p; 171 } 172 else { 173 palloc.tail = p; 174 p->next = 0; 175 } 176 palloc.head = p; 177 p->prev = 0; 178 } 179 180 palloc.freecount++; /* Release people waiting for memory */ 181 if(palloc.r.p != 0) 182 wakeup(&palloc.r); 183 unlock(&palloc); 184 } 185 unlock(p); 186 } 187 188 void 189 simpleputpage(Page *pg) /* Always call with palloc locked */ 190 { 191 if(pg->ref != 1) 192 panic("simpleputpage"); 193 pg->ref = 0; 194 palloc.freecount++; 195 if(palloc.head == 0) { 196 palloc.head = palloc.tail = pg; 197 pg->prev = pg->next = 0; 198 return; 199 } 200 pg->next = palloc.head; 201 palloc.head->prev = pg; 202 pg->prev = 0; 203 palloc.head = pg; 204 } 205 206 void 207 duppage(Page *p) /* Always call with p locked */ 208 { 209 Page *np; 210 211 /* No dup for swap pages */ 212 if(p->image == &swapimage) { 213 uncachepage(p); 214 return; 215 } 216 217 lock(&palloc); 218 /* No freelist cache when memory is very low */ 219 if(palloc.freecount < swapalloc.highwater) { 220 unlock(&palloc); 221 uncachepage(p); 222 return; 223 } 224 225 np = palloc.head; /* Allocate a new page from freelist */ 226 if(palloc.head = np->next) /* = Assign */ 227 palloc.head->prev = 0; 228 else 229 palloc.tail = 0; 230 231 if(palloc.tail) { /* Link back onto tail to give us lru */ 232 np->prev = palloc.tail; 233 palloc.tail->next = np; 234 np->next = 0; 235 palloc.tail = np; 236 } 237 else { 238 palloc.head = palloc.tail = np; 239 np->prev = np->next = 0; 240 } 241 242 unlock(&palloc); 243 244 lock(np); /* Cache the new version */ 245 if(np->ref != 0) { /* Stolen by lookpage */ 246 uncachepage(p); 247 unlock(np); 248 return; 249 } 250 251 uncachepage(np); 252 np->va = p->va; 253 np->daddr = p->daddr; 254 mmunewpage(np); 255 copypage(p, np); 256 cachepage(np, p->image); 257 unlock(np); 258 uncachepage(p); 259 } 260 261 void 262 copypage(Page *f, Page *t) 263 { 264 KMap *ks, *kd; 265 266 ks = kmap(f); 267 kd = kmap(t); 268 memmove((void*)VA(kd), (void*)VA(ks), BY2PG); 269 kunmap(ks); 270 kunmap(kd); 271 } 272 273 void 274 uncachepage(Page *p) /* Always called with a locked page */ 275 { 276 Page **l, *f; 277 278 if(p->image == 0) 279 return; 280 281 lock(&palloc.hashlock); 282 l = &pghash(p->daddr); 283 for(f = *l; f; f = f->hash) { 284 if(f == p) { 285 *l = p->hash; 286 break; 287 } 288 l = &f->hash; 289 } 290 unlock(&palloc.hashlock); 291 putimage(p->image); 292 p->image = 0; 293 } 294 295 void 296 cachepage(Page *p, Image *i) 297 { 298 Page **l; 299 300 /* If this ever happens it should be fixed by calling 301 * uncachepage instead of panic. I think there is a race 302 * with pio in which this can happen. Calling uncachepage is 303 * correct - I just wanted to see if we got here. 304 */ 305 if(p->image) 306 panic("cachepage"); 307 308 incref(i); 309 lock(&palloc.hashlock); 310 p->image = i; 311 l = &pghash(p->daddr); 312 p->hash = *l; 313 *l = p; 314 unlock(&palloc.hashlock); 315 } 316 317 void 318 cachedel(Image *i, ulong daddr) 319 { 320 Page *f, **l; 321 322 lock(&palloc.hashlock); 323 l = &pghash(daddr); 324 for(f = *l; f; f = f->hash) { 325 if(f->image == i && f->daddr == daddr) { 326 *l = f->hash; 327 break; 328 } 329 l = &f->hash; 330 } 331 unlock(&palloc.hashlock); 332 } 333 334 Page * 335 lookpage(Image *i, ulong daddr) 336 { 337 Page *f; 338 339 lock(&palloc.hashlock); 340 for(f = pghash(daddr); f; f = f->hash) { 341 if(f->image == i && f->daddr == daddr) { 342 unlock(&palloc.hashlock); 343 344 lock(f); 345 if(f->image != i || f->daddr != daddr) { 346 unlock(f); 347 return 0; 348 } 349 350 lock(&palloc); 351 if(++f->ref == 1) { 352 if(f->prev) 353 f->prev->next = f->next; 354 else 355 palloc.head = f->next; 356 357 if(f->next) 358 f->next->prev = f->prev; 359 else 360 palloc.tail = f->prev; 361 palloc.freecount--; 362 } 363 unlock(&palloc); 364 365 unlock(f); 366 return f; 367 } 368 } 369 unlock(&palloc.hashlock); 370 return 0; 371 } 372 373 Pte* 374 ptecpy(Pte *old) 375 { 376 Pte *new; 377 Page **src, **dst; 378 379 new = ptealloc(); 380 dst = &new->pages[old->first-old->pages]; 381 new->first = dst; 382 for(src = old->first; src <= old->last; src++, dst++) 383 if(*src) { 384 if(onswap(*src)) 385 dupswap(*src); 386 else { 387 lock(*src); 388 (*src)->ref++; 389 unlock(*src); 390 } 391 new->last = dst; 392 *dst = *src; 393 } 394 395 return new; 396 } 397 398 Pte* 399 ptealloc(void) 400 { 401 Pte *new; 402 403 new = smalloc(sizeof(Pte)); 404 new->first = &new->pages[PTEPERTAB]; 405 new->last = new->pages; 406 return new; 407 } 408 409 void 410 freepte(Segment *s, Pte *p) 411 { 412 int ref; 413 Page *pt, **pg, **ptop; 414 void (*fn)(Page*); 415 416 switch(s->type&SG_TYPE) { 417 case SG_PHYSICAL: 418 fn = s->pseg->pgfree; 419 ptop = &p->pages[PTEPERTAB]; 420 if(fn) { 421 for(pg = p->pages; pg < ptop; pg++) { 422 if(*pg == 0) 423 continue; 424 (*fn)(*pg); 425 *pg = 0; 426 } 427 break; 428 } 429 for(pg = p->pages; pg < ptop; pg++) { 430 pt = *pg; 431 if(pt == 0) 432 continue; 433 lock(pt); 434 ref = --pt->ref; 435 unlock(pt); 436 if(ref == 0) 437 free(pt); 438 } 439 break; 440 default: 441 for(pg = p->first; pg <= p->last; pg++) 442 if(*pg) { 443 putpage(*pg); 444 *pg = 0; 445 } 446 } 447 free(p); 448 } 449