|
|
1.1 ! root 1: /* vmdrum.c 4.3 81/03/08 */ ! 2: ! 3: #include "../h/param.h" ! 4: #include "../h/systm.h" ! 5: #include "../h/dir.h" ! 6: #include "../h/user.h" ! 7: #include "../h/proc.h" ! 8: #include "../h/buf.h" ! 9: #include "../h/text.h" ! 10: #include "../h/map.h" ! 11: #include "../h/pte.h" ! 12: #include "../h/vm.h" ! 13: #include "../h/cmap.h" ! 14: ! 15: /* ! 16: * Expand the swap area for both the data and stack segments. ! 17: * If space is not available for both, retract and return 0. ! 18: */ ! 19: swpexpand(ds, ss, dmp, smp) ! 20: size_t ds, ss; ! 21: register struct dmap *dmp, *smp; ! 22: { ! 23: register struct dmap *tmp; ! 24: register int ts; ! 25: size_t ods; ! 26: ! 27: /* ! 28: * If dmap isn't growing, do smap first. ! 29: * This avoids anomalies if smap will try to grow and ! 30: * fail, which otherwise would shrink ds without expanding ! 31: * ss, a rather curious side effect! ! 32: */ ! 33: if (dmp->dm_alloc > ds) { ! 34: tmp = dmp; ts = ds; ! 35: dmp = smp; ds = ss; ! 36: smp = tmp; ss = ts; ! 37: } ! 38: ods = dmp->dm_size; ! 39: if (vsexpand(ds, dmp, 0) == 0) ! 40: goto bad; ! 41: if (vsexpand(ss, smp, 0) == 0) { ! 42: (void) vsexpand(ods, dmp, 1); ! 43: goto bad; ! 44: } ! 45: return (1); ! 46: ! 47: bad: ! 48: u.u_error = ENOMEM; ! 49: return (0); ! 50: } ! 51: ! 52: /* ! 53: * Expand or contract the virtual swap segment mapped ! 54: * by the argument diskmap so as to just allow the given size. ! 55: * ! 56: * FOR NOW CANT RELEASE UNLESS SHRINKING TO ZERO, SINCE PAGEOUTS MAY ! 57: * BE IN PROGRESS... TYPICALLY NEVER SHRINK ANYWAYS, SO DOESNT MATTER MUCH ! 58: */ ! 59: vsexpand(vssize, dmp, canshrink) ! 60: register size_t vssize; ! 61: register struct dmap *dmp; ! 62: { ! 63: register int blk = DMMIN; ! 64: register int vsbase = 0; ! 65: register swblk_t *ip = dmp->dm_map; ! 66: size_t oldsize = dmp->dm_size; ! 67: size_t oldalloc = dmp->dm_alloc; ! 68: ! 69: while (vsbase < oldalloc || vsbase < vssize) { ! 70: if (vsbase >= oldalloc) { ! 71: *ip = rmalloc(swapmap, ctod(blk)); ! 72: if (*ip == 0) { ! 73: dmp->dm_size = vsbase; ! 74: if (vsexpand(oldsize, dmp, 1) == 0) ! 75: panic("vsexpand"); ! 76: return (0); ! 77: } ! 78: dmp->dm_alloc += blk; ! 79: } else if (vssize == 0 || ! 80: vsbase >= vssize && canshrink) { ! 81: rmfree(swapmap, ctod(blk), *ip); ! 82: *ip = 0; ! 83: dmp->dm_alloc -= blk; ! 84: } ! 85: vsbase += blk; ! 86: if (blk < DMMAX) ! 87: blk *= 2; ! 88: ip++; ! 89: if (ip - dmp->dm_map > NDMAP) ! 90: panic("vmdrum NDMAP"); ! 91: } ! 92: dmp->dm_size = vssize; ! 93: return (1); ! 94: } ! 95: ! 96: /* ! 97: * Allocate swap space for a text segment, ! 98: * in chunks of at most DMTEXT pages. ! 99: */ ! 100: vsxalloc(xp) ! 101: struct text *xp; ! 102: { ! 103: register int blk; ! 104: register swblk_t *dp; ! 105: swblk_t vsbase; ! 106: ! 107: if (xp->x_size > NXDAD * DMTEXT) ! 108: panic("vsxalloc"); ! 109: dp = xp->x_daddr; ! 110: for (vsbase = 0; vsbase < xp->x_size; vsbase += DMTEXT) { ! 111: blk = xp->x_size - vsbase; ! 112: if (blk > DMTEXT) ! 113: blk = DMTEXT; ! 114: if ((*dp++ = rmalloc(swapmap, blk)) == 0) { ! 115: vsxfree(xp, vsbase); ! 116: return (0); ! 117: } ! 118: } ! 119: if (xp->x_flag & XPAGI) { ! 120: xp->x_ptdaddr = rmalloc(swapmap, clrnd(ctopt(xp->x_size))); ! 121: if (xp->x_ptdaddr == 0) { ! 122: vsxfree(xp, xp->x_size); ! 123: return (0); ! 124: } ! 125: } ! 126: return (1); ! 127: } ! 128: ! 129: /* ! 130: * Free the swap space of a text segment which ! 131: * has been allocated ts pages. ! 132: */ ! 133: vsxfree(xp, ts) ! 134: struct text *xp; ! 135: int ts; ! 136: { ! 137: register int blk; ! 138: register swblk_t *dp; ! 139: swblk_t vsbase; ! 140: ! 141: dp = xp->x_daddr; ! 142: for (vsbase = 0; vsbase < ts; vsbase += DMTEXT) { ! 143: blk = ts - vsbase; ! 144: if (blk > DMTEXT) ! 145: blk = DMTEXT; ! 146: rmfree(swapmap, blk, *dp); ! 147: *dp++ = 0; ! 148: } ! 149: if ((xp->x_flag&XPAGI) && xp->x_ptdaddr) { ! 150: rmfree(swapmap, clrnd(ctopt(xp->x_size)), xp->x_ptdaddr); ! 151: xp->x_ptdaddr = 0; ! 152: } ! 153: } ! 154: ! 155: /* ! 156: * Swap a segment of virtual memory to disk, ! 157: * by locating the contiguous dirty pte's ! 158: * and calling vschunk with each chunk. ! 159: */ ! 160: vsswap(p, pte, type, vsbase, vscount, dmp) ! 161: struct proc *p; ! 162: register struct pte *pte; ! 163: int type; ! 164: register int vsbase, vscount; ! 165: struct dmap *dmp; ! 166: { ! 167: register int size = 0; ! 168: ! 169: if (vscount % CLSIZE) ! 170: panic("vsswap"); ! 171: for (;;) { ! 172: if (vscount == 0 || !dirtycl(pte)) { ! 173: if (size) { ! 174: vschunk(p, vsbase, size, type, dmp); ! 175: vsbase += size; ! 176: size = 0; ! 177: } ! 178: if (vscount == 0) ! 179: return; ! 180: vsbase += CLSIZE; ! 181: if (pte->pg_fod == 0 && pte->pg_pfnum) ! 182: if (type == CTEXT) ! 183: p->p_textp->x_rssize -= vmemfree(pte, CLSIZE); ! 184: else ! 185: p->p_rssize -= vmemfree(pte, CLSIZE); ! 186: } else { ! 187: size += CLSIZE; ! 188: mwait(pte->pg_pfnum); ! 189: if (anycl(pte, pg_m)) ! 190: zapcl(pte, pg_vreadm) = 1; ! 191: } ! 192: vscount -= CLSIZE; ! 193: if (type == CSTACK) ! 194: pte -= CLSIZE; ! 195: else ! 196: pte += CLSIZE; ! 197: } ! 198: } ! 199: ! 200: vschunk(p, base, size, type, dmp) ! 201: register struct proc *p; ! 202: register int base, size; ! 203: int type; ! 204: struct dmap *dmp; ! 205: { ! 206: register struct pte *pte; ! 207: struct dblock db; ! 208: unsigned v; ! 209: ! 210: if (type == CTEXT) { ! 211: while (size > 0) { ! 212: db.db_size = DMTEXT - base % DMTEXT; ! 213: if (db.db_size > size) ! 214: db.db_size = size; ! 215: swap(p, p->p_textp->x_daddr[base/DMTEXT] + base%DMTEXT, ! 216: ptob(tptov(p, base)), ctob(db.db_size), ! 217: B_WRITE, 0, swapdev, 0); ! 218: p->p_textp->x_rssize -= ! 219: vmemfree(tptopte(p, base), db.db_size); ! 220: base += db.db_size; ! 221: size -= db.db_size; ! 222: } ! 223: return; ! 224: } ! 225: do { ! 226: vstodb(base, size, dmp, &db, type == CSTACK); ! 227: v = type==CSTACK ? sptov(p, base+db.db_size-1) : dptov(p, base); ! 228: swap(p, db.db_base, ptob(v), ctob(db.db_size), B_WRITE, 0, swapdev, 0); ! 229: pte = type==CSTACK ? sptopte(p, base+db.db_size-1) : dptopte(p, base); ! 230: p->p_rssize -= vmemfree(pte, db.db_size); ! 231: base += db.db_size; ! 232: size -= db.db_size; ! 233: } while (size != 0); ! 234: } ! 235: ! 236: /* ! 237: * Given a base/size pair in virtual swap area, ! 238: * return a physical base/size pair which is the ! 239: * (largest) initial, physically contiguous block. ! 240: */ ! 241: vstodb(vsbase, vssize, dmp, dbp, rev) ! 242: register int vsbase, vssize; ! 243: struct dmap *dmp; ! 244: register struct dblock *dbp; ! 245: { ! 246: register int blk = DMMIN; ! 247: register swblk_t *ip = dmp->dm_map; ! 248: extern int queueflag; ! 249: ! 250: if (vsbase < 0 || vssize < 0 || vsbase + vssize > dmp->dm_size) ! 251: panic("vstodb"); ! 252: while (vsbase >= blk) { ! 253: vsbase -= blk; ! 254: if (blk < DMMAX) ! 255: blk *= 2; ! 256: ip++; ! 257: } ! 258: if (*ip + blk > nswap) ! 259: panic("vstodb *ip"); ! 260: dbp->db_size = imin(vssize, blk - vsbase); ! 261: dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase); ! 262: } ! 263: ! 264: /* ! 265: * Convert a virtual page number ! 266: * to its corresponding disk block number. ! 267: * Used in pagein/pageout to initiate single page transfers. ! 268: */ ! 269: swblk_t ! 270: vtod(p, v, dmap, smap) ! 271: register struct proc *p; ! 272: unsigned v; ! 273: struct dmap *dmap, *smap; ! 274: { ! 275: struct dblock db; ! 276: int tp; ! 277: ! 278: if (isatsv(p, v)) { ! 279: tp = vtotp(p, v); ! 280: return (p->p_textp->x_daddr[tp/DMTEXT] + tp%DMTEXT); ! 281: } ! 282: if (isassv(p, v)) ! 283: vstodb(vtosp(p, v), 1, smap, &db, 1); ! 284: else ! 285: vstodb(vtodp(p, v), 1, dmap, &db, 0); ! 286: return (db.db_base); ! 287: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.