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