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