|
|
1.1 ! root 1: /* vmmem.c 4.7 81/07/09 */ ! 2: ! 3: #include "sys/param.h" ! 4: #include "sys/systm.h" ! 5: #include "sys/pte.h" ! 6: #include "sys/cmap.h" ! 7: #include "sys/user.h" ! 8: #include "sys/proc.h" ! 9: #include "sys/text.h" ! 10: #include "sys/vm.h" ! 11: #include "sys/buf.h" ! 12: #include "sys/map.h" ! 13: ! 14: /* ! 15: * Shared text pages are not totally abandoned when a process ! 16: * exits, but are remembered while in the free list hashed by <mdev,blkno> ! 17: * off the cmhash structure so that they can be reattached ! 18: * if another instance of the program runs again soon. ! 19: */ ! 20: #define CMHSIZ 512 /* SHOULD BE DYNAMIC */ ! 21: #define CMHASH(bn) ((bn)&(CMHSIZ-1)) ! 22: int cmhash[CMHSIZ]; /* make words big enough for c_hlink */ ! 23: ! 24: /* ! 25: * Allocate memory, and always succeed ! 26: * by jolting page-out daemon ! 27: * so as to obtain page frames. ! 28: * To be used in conjunction with vmemfree(). ! 29: */ ! 30: vmemall(pte, size, p, type) ! 31: register struct pte *pte; ! 32: int size; ! 33: struct proc *p; ! 34: { ! 35: register int m; ! 36: ! 37: if (size <= 0 || size > maxmem) ! 38: panic("vmemall size"); ! 39: while (size > 0) { ! 40: if (freemem < desfree) ! 41: wakeup((caddr_t)&proc[PAGEPID]); /* jolt daemon */ ! 42: while (freemem == 0) ! 43: sleep((caddr_t)&freemem, PSWP+2); ! 44: m = imin(size, freemem); ! 45: (void) memall(pte, m, p, type); ! 46: size -= m; ! 47: pte += m; ! 48: } ! 49: if (freemem < desfree) ! 50: wakeup((caddr_t)&proc[PAGEPID]); /* jolt daemon */ ! 51: /* ! 52: * Always succeeds, but return success for ! 53: * vgetu and vgetpt (e.g.) which call either ! 54: * memall or vmemall depending on context. ! 55: */ ! 56: return (1); ! 57: } ! 58: ! 59: /* ! 60: * Free valid and reclaimable page frames belonging to the ! 61: * count pages starting at pte. If a page is valid ! 62: * or reclaimable and locked (but not a system page), then ! 63: * we simply mark the page as c_gone and let the pageout ! 64: * daemon free the page when it is through with it. ! 65: * If a page is reclaimable, and already in the free list, then ! 66: * we mark the page as c_gone, and (of course) don't free it. ! 67: * ! 68: * Determines the largest contiguous cluster of ! 69: * valid pages and frees them in one call to memfree. ! 70: */ ! 71: vmemfree(pte, count) ! 72: register struct pte *pte; ! 73: register int count; ! 74: { ! 75: register struct cmap *c; ! 76: register struct pte *spte; ! 77: register int j; ! 78: int size, pcnt; ! 79: ! 80: if (count % CLSIZE) ! 81: panic("vmemfree"); ! 82: for (size = 0, pcnt = 0; count > 0; pte += CLSIZE, count -= CLSIZE) { ! 83: if (pte->pg_fod == 0 && pte->pg_pfnum) { ! 84: c = &cmap[pgtocm(pte->pg_pfnum)]; ! 85: pcnt += CLSIZE; ! 86: if (c->c_lock && c->c_type != CSYS) { ! 87: for (j = 0; j < CLSIZE; j++) ! 88: *(int *)(pte+j) &= PG_PROT; ! 89: c->c_gone = 1; ! 90: goto free; ! 91: } ! 92: if (c->c_free) { ! 93: pcnt -= CLSIZE; ! 94: for (j = 0; j < CLSIZE; j++) ! 95: *(int *)(pte+j) &= PG_PROT; ! 96: if (c->c_type == CTEXT) ! 97: distpte(&text[c->c_ndx], (int)c->c_page, pte); ! 98: c->c_gone = 1; ! 99: goto free; ! 100: } ! 101: if (size == 0) ! 102: spte = pte; ! 103: size += CLSIZE; ! 104: continue; ! 105: } ! 106: if (pte->pg_fod) { ! 107: for (j = 0; j < CLSIZE; j++) ! 108: *(int *)(pte+j) &= PG_PROT; ! 109: } ! 110: free: ! 111: if (size) { ! 112: memfree(spte, size, 1); ! 113: size = 0; ! 114: } ! 115: } ! 116: if (size) ! 117: memfree(spte, size, 1); ! 118: return (pcnt); ! 119: } ! 120: ! 121: /* ! 122: * Unlink a page frame from the free list - ! 123: * ! 124: * Performed if the page being reclaimed ! 125: * is in the free list. ! 126: */ ! 127: munlink(pf) ! 128: unsigned pf; ! 129: { ! 130: register int next, prev; ! 131: ! 132: next = cmap[pgtocm(pf)].c_next; ! 133: prev = cmap[pgtocm(pf)].c_prev; ! 134: cmap[prev].c_next = next; ! 135: cmap[next].c_prev = prev; ! 136: cmap[pgtocm(pf)].c_free = 0; ! 137: if (freemem < minfree) ! 138: wakeup((caddr_t)&proc[PAGEPID]); /* jolt paging daemon */ ! 139: freemem -= CLSIZE; ! 140: } ! 141: ! 142: /* ! 143: * Allocate memory - ! 144: * ! 145: * The free list appears as a doubly linked list ! 146: * in the core map with cmap[0] serving as a header. ! 147: */ ! 148: memall(pte, size, p, type) ! 149: register struct pte *pte; ! 150: int size; ! 151: struct proc *p; ! 152: { ! 153: register struct cmap *c; ! 154: register struct pte *rpte; ! 155: register struct proc *rp; ! 156: register int i, j; ! 157: int px; ! 158: unsigned pf; ! 159: struct cmap *c1, *c2; ! 160: ! 161: if (size % CLSIZE) ! 162: panic("memall"); ! 163: if (size > freemem) ! 164: return (0); ! 165: px = p - proc; ! 166: for (i = size; i > 0; i -= CLSIZE) { ! 167: c = &cmap[cmap[CMHEAD].c_next]; ! 168: if (c->c_free == 0) ! 169: panic("dup mem alloc"); ! 170: if (c->c_gone == 0 && c->c_type != CSYS) { ! 171: if (c->c_type == CTEXT) ! 172: rp = text[c->c_ndx].x_caddr; ! 173: else ! 174: rp = &proc[c->c_ndx]; ! 175: switch (c->c_type) { ! 176: ! 177: case CTEXT: ! 178: rpte = tptopte(rp, c->c_page); ! 179: break; ! 180: ! 181: case CDATA: ! 182: rpte = dptopte(rp, c->c_page); ! 183: break; ! 184: ! 185: case CSTACK: ! 186: rpte = sptopte(rp, c->c_page); ! 187: break; ! 188: } ! 189: zapcl(rpte, pg_pfnum) = 0; ! 190: if (c->c_type == CTEXT) ! 191: distpte(&text[c->c_ndx], (int)c->c_page, rpte); ! 192: } ! 193: switch (type) { ! 194: ! 195: case CSYS: ! 196: c->c_ndx = px; ! 197: break; ! 198: ! 199: case CTEXT: ! 200: c->c_page = vtotp(p, ptetov(p, pte)); ! 201: c->c_ndx = p->p_textp - &text[0]; ! 202: break; ! 203: ! 204: case CDATA: ! 205: c->c_page = vtodp(p, ptetov(p, pte)); ! 206: c->c_ndx = px; ! 207: break; ! 208: ! 209: case CSTACK: ! 210: c->c_page = vtosp(p, ptetov(p, pte)); ! 211: c->c_ndx = px; ! 212: break; ! 213: } ! 214: if (c->c_blkno) { ! 215: /* ! 216: * This is very like munhash(), except ! 217: * that we really don't want to bother ! 218: * to calculate a dev to pass to it. ! 219: */ ! 220: j = CMHASH(c->c_blkno); ! 221: c1 = &cmap[cmhash[j]]; ! 222: if (c1 == c) ! 223: cmhash[j] = c1->c_hlink; ! 224: else { ! 225: for (;;) { ! 226: if (c1 == ecmap) ! 227: panic("memall ecmap"); ! 228: c2 = c1; ! 229: c1 = &cmap[c2->c_hlink]; ! 230: if (c1 == c) ! 231: break; ! 232: } ! 233: c2->c_hlink = c1->c_hlink; ! 234: } ! 235: if (mfind(c->c_mdev, (daddr_t)c->c_blkno)) ! 236: panic("memall mfind"); ! 237: c1->c_mdev = 0; ! 238: c1->c_blkno = 0; ! 239: c1->c_hlink = 0; ! 240: } ! 241: pf = cmtopg(c - cmap); ! 242: for (j = 0; j < CLSIZE; j++) ! 243: *(int *)pte++ = pf++; ! 244: c->c_free = 0; ! 245: c->c_gone = 0; ! 246: if (c->c_intrans || c->c_want) ! 247: panic("memall intrans|want"); ! 248: c->c_lock = 1; ! 249: c->c_type = type; ! 250: freemem -= CLSIZE; ! 251: j = c->c_next; ! 252: cmap[CMHEAD].c_next = j; ! 253: cmap[j].c_prev = CMHEAD; ! 254: } ! 255: return (size); ! 256: } ! 257: ! 258: /* ! 259: * Free memory - ! 260: * ! 261: * The page frames being returned are inserted ! 262: * to the head/tail of the free list depending ! 263: * on whether there is any possible future use of them. ! 264: * ! 265: * If the freemem count had been zero, ! 266: * the processes sleeping for memory ! 267: * are awakened. ! 268: */ ! 269: memfree(pte, size, detach) ! 270: register struct pte *pte; ! 271: register int size; ! 272: { ! 273: register int i, j, prev, next; ! 274: register struct cmap *c; ! 275: ! 276: if (size % CLSIZE) ! 277: panic("memfree"); ! 278: if (freemem < CLSIZE * KLMAX) ! 279: wakeup((caddr_t)&freemem); ! 280: while (size > 0) { ! 281: size -= CLSIZE; ! 282: i = pte->pg_pfnum; ! 283: if (i < firstfree || i > maxfree) ! 284: panic("bad mem free"); ! 285: i = pgtocm(i); ! 286: c = &cmap[i]; ! 287: if (c->c_free) ! 288: panic("dup mem free"); ! 289: if (detach && c->c_type != CSYS) { ! 290: for (j = 0; j < CLSIZE; j++) ! 291: *(int *)(pte+j) &= PG_PROT; ! 292: c->c_gone = 1; ! 293: } ! 294: if (detach && c->c_blkno == 0) { ! 295: next = cmap[CMHEAD].c_next; ! 296: cmap[next].c_prev = i; ! 297: c->c_prev = CMHEAD; ! 298: c->c_next = next; ! 299: cmap[CMHEAD].c_next = i; ! 300: } else { ! 301: prev = cmap[CMHEAD].c_prev; ! 302: cmap[prev].c_next = i; ! 303: c->c_next = CMHEAD; ! 304: c->c_prev = prev; ! 305: cmap[CMHEAD].c_prev = i; ! 306: } ! 307: c->c_free = 1; ! 308: freemem += CLSIZE; ! 309: pte += CLSIZE; ! 310: } ! 311: } ! 312: ! 313: /* ! 314: * Enter cmap block c on the hash chains. ! 315: * It contains file system block bn from device dev. ! 316: * Dev must either be a mounted file system or the swap device ! 317: * so we panic if getfsx() cannot find it. ! 318: */ ! 319: mhash(c, mdev, bn) ! 320: register struct cmap *c; ! 321: int mdev; ! 322: daddr_t bn; ! 323: { ! 324: register int i = CMHASH(bn); ! 325: ! 326: if (mdev == -1) ! 327: panic("mhash"); ! 328: c->c_hlink = cmhash[i]; ! 329: cmhash[i] = c - cmap; ! 330: c->c_blkno = bn; ! 331: c->c_mdev = mdev; ! 332: } ! 333: ! 334: /* ! 335: * Pull the clist entry of <dev,bn> off the hash chains. ! 336: * We have checked before calling (using mfind) that the ! 337: * entry really needs to be unhashed, so panic if we can't ! 338: * find it (can't happen). ! 339: */ ! 340: munhash(mdev, bn) ! 341: register int mdev; ! 342: daddr_t bn; ! 343: { ! 344: register int i = CMHASH(bn); ! 345: register struct cmap *c1, *c2; ! 346: ! 347: c1 = &cmap[cmhash[i]]; ! 348: if (c1 == ecmap) ! 349: panic("munhash"); ! 350: if (c1->c_blkno == bn && mdev == c1->c_mdev) ! 351: cmhash[i] = c1->c_hlink; ! 352: else { ! 353: for (;;) { ! 354: c2 = c1; ! 355: c1 = &cmap[c2->c_hlink]; ! 356: if (c1 == ecmap) ! 357: panic("munhash"); ! 358: if (c1->c_blkno == bn && mdev == c1->c_mdev) ! 359: break; ! 360: } ! 361: c2->c_hlink = c1->c_hlink; ! 362: } ! 363: if (mfind(mdev, bn)) ! 364: panic("munhash mfind"); ! 365: c1->c_mdev = 0; ! 366: c1->c_blkno = 0; ! 367: c1->c_hlink = 0; ! 368: } ! 369: ! 370: /* ! 371: * Look for block bn of device dev in the free pool. ! 372: * Currently it should not be possible to find it unless it is ! 373: * c_free and c_gone, although this may later not be true. ! 374: * (This is because active texts are locked against file system ! 375: * writes by the system.) ! 376: */ ! 377: struct cmap * ! 378: mfind(mdev, bn) ! 379: register int mdev; ! 380: daddr_t bn; ! 381: { ! 382: register struct cmap *c1 = &cmap[cmhash[CMHASH(bn)]]; ! 383: ! 384: while (c1 != ecmap) { ! 385: if (c1->c_blkno == bn && c1->c_mdev == mdev) ! 386: return (c1); ! 387: c1 = &cmap[c1->c_hlink]; ! 388: } ! 389: return ((struct cmap *)0); ! 390: } ! 391: ! 392: /* ! 393: * Purge blocks from device dev from incore cache ! 394: * before umount(). ! 395: */ ! 396: mpurge(mdev) ! 397: int mdev; ! 398: { ! 399: register struct cmap *c1, *c2; ! 400: register int i; ! 401: ! 402: for (i = 0; i < CMHSIZ; i++) { ! 403: more: ! 404: c1 = &cmap[cmhash[i]]; ! 405: if (c1 == ecmap) ! 406: continue; ! 407: if (c1->c_mdev == mdev) ! 408: cmhash[i] = c1->c_hlink; ! 409: else { ! 410: for (;;) { ! 411: c2 = c1; ! 412: c1 = &cmap[c1->c_hlink]; ! 413: if (c1 == ecmap) ! 414: goto cont; ! 415: if (c1->c_mdev == mdev) ! 416: break; ! 417: } ! 418: c2->c_hlink = c1->c_hlink; ! 419: } ! 420: c1->c_mdev = 0; ! 421: c1->c_blkno = 0; ! 422: c1->c_hlink = 0; ! 423: goto more; ! 424: cont: ! 425: ; ! 426: } ! 427: } ! 428: ! 429: /* ! 430: * Initialize core map ! 431: */ ! 432: meminit(first, last) ! 433: int first, last; ! 434: { ! 435: register int i; ! 436: register struct cmap *c; ! 437: ! 438: firstfree = clrnd(first); ! 439: maxfree = clrnd(last - (CLSIZE - 1)); ! 440: freemem = maxfree - firstfree; ! 441: ecmx = ecmap - cmap; ! 442: if (ecmx < freemem / CLSIZE) ! 443: freemem = ecmx * CLSIZE; ! 444: for (i = 1; i <= freemem / CLSIZE; i++) { ! 445: cmap[i-1].c_next = i; ! 446: c = &cmap[i]; ! 447: c->c_prev = i-1; ! 448: c->c_free = 1; ! 449: c->c_gone = 1; ! 450: c->c_type = CSYS; ! 451: c->c_mdev = 0; ! 452: c->c_blkno = 0; ! 453: } ! 454: cmap[freemem / CLSIZE].c_next = CMHEAD; ! 455: for (i = 0; i < CMHSIZ; i++) ! 456: cmhash[i] = ecmx; ! 457: cmap[CMHEAD].c_prev = freemem / CLSIZE; ! 458: cmap[CMHEAD].c_type = CSYS; ! 459: avefree = freemem; ! 460: } ! 461: ! 462: /* ! 463: * Wait for frame pf to become unlocked ! 464: * if it is currently locked. ! 465: * ! 466: * THIS ROUTINE SHOULD TAKE A CMAP STRUCTURE AS ARGUMENT. ! 467: */ ! 468: mwait(pf) ! 469: unsigned pf; ! 470: { ! 471: ! 472: mlock(pf); ! 473: munlock(pf); ! 474: } ! 475: ! 476: /* ! 477: * Lock a page frame. ! 478: * ! 479: * THIS ROUTINE SHOULD TAKE A CMAP STRUCTURE AS ARGUMENT. ! 480: */ ! 481: mlock(pf) ! 482: unsigned pf; ! 483: { ! 484: register struct cmap *c = &cmap[pgtocm(pf)]; ! 485: ! 486: while (c->c_lock) { ! 487: c->c_want = 1; ! 488: sleep((caddr_t)c, PSWP+1); ! 489: } ! 490: c->c_lock = 1; ! 491: } ! 492: ! 493: /* ! 494: * Unlock a page frame. ! 495: * ! 496: * THIS ROUTINE SHOULD TAKE A CMAP STRUCTURE AS ARGUMENT. ! 497: */ ! 498: munlock(pf) ! 499: unsigned pf; ! 500: { ! 501: register struct cmap *c = &cmap[pgtocm(pf)]; ! 502: ! 503: if (c->c_lock == 0) ! 504: panic("dup page unlock"); ! 505: if (c->c_want) ! 506: wakeup((caddr_t)c); ! 507: c->c_lock = 0; ! 508: c->c_want = 0; ! 509: } ! 510: ! 511: /* ! 512: * Lock a virtual segment. ! 513: * ! 514: * For each cluster of pages, if the cluster is not valid, ! 515: * touch it to fault it in, otherwise just lock page frame. ! 516: * Called from physio to ensure that the pages ! 517: * participating in raw i/o are valid and locked. ! 518: * We use SDLYU to keep pagein from unlocking pages, ! 519: * so they make it safely back here locked. ! 520: */ ! 521: vslock(base, count) ! 522: caddr_t base; ! 523: { ! 524: register unsigned v; ! 525: register int npf; ! 526: register struct pte *pte; ! 527: ! 528: u.u_procp->p_flag |= SDLYU; ! 529: v = btop(base); ! 530: pte = vtopte(u.u_procp, v); ! 531: npf = btoc(count + ((int)base & CLOFSET)); ! 532: while (npf > 0) { ! 533: if (pte->pg_v) ! 534: mlock(pte->pg_pfnum); ! 535: else ! 536: if (fubyte((caddr_t)ctob(v)) < 0) ! 537: panic("vslock"); ! 538: pte += CLSIZE; ! 539: v += CLSIZE; ! 540: npf -= CLSIZE; ! 541: } ! 542: u.u_procp->p_flag &= ~SDLYU; ! 543: } ! 544: ! 545: /* ! 546: * Unlock a virtual segment. ! 547: */ ! 548: vsunlock(base, count, rw) ! 549: caddr_t base; ! 550: { ! 551: register struct pte *pte; ! 552: register int npf; ! 553: ! 554: pte = vtopte(u.u_procp, btop(base)); ! 555: npf = btoc(count + ((int)base & CLOFSET)); ! 556: while (npf > 0) { ! 557: munlock(pte->pg_pfnum); ! 558: if (rw == B_READ) /* Reading from device writes memory */ ! 559: pte->pg_m = 1; ! 560: pte += CLSIZE; ! 561: npf -= CLSIZE; ! 562: } ! 563: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.