|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.