|
|
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: } ! 191: vscount -= CLSIZE; ! 192: if (type == CSTACK) ! 193: pte -= CLSIZE; ! 194: else ! 195: pte += CLSIZE; ! 196: } ! 197: } ! 198: ! 199: vschunk(p, base, size, type, dmp) ! 200: register struct proc *p; ! 201: register int base, size; ! 202: int type; ! 203: struct dmap *dmp; ! 204: { ! 205: register struct pte *pte; ! 206: struct dblock db; ! 207: unsigned v; ! 208: ! 209: if (type == CTEXT) { ! 210: while (size > 0) { ! 211: db.db_size = dmtext - base % dmtext; ! 212: if (db.db_size > size) ! 213: db.db_size = size; ! 214: swap(p, p->p_textp->x_daddr[base/dmtext] + base%dmtext, ! 215: ptob(tptov(p, base)), ctob(db.db_size), ! 216: B_WRITE, 0, swapdev, 0); ! 217: p->p_textp->x_rssize -= ! 218: vmemfree(tptopte(p, base), db.db_size); ! 219: base += db.db_size; ! 220: size -= db.db_size; ! 221: } ! 222: return; ! 223: } ! 224: do { ! 225: vstodb(base, size, dmp, &db, type == CSTACK); ! 226: v = type==CSTACK ? sptov(p, base+db.db_size-1) : dptov(p, base); ! 227: swap(p, db.db_base, ptob(v), ctob(db.db_size), B_WRITE, 0, swapdev, 0); ! 228: pte = type==CSTACK ? sptopte(p, base+db.db_size-1) : dptopte(p, base); ! 229: p->p_rssize -= vmemfree(pte, db.db_size); ! 230: base += db.db_size; ! 231: size -= db.db_size; ! 232: } while (size != 0); ! 233: } ! 234: ! 235: /* ! 236: * Given a base/size pair in virtual swap area, ! 237: * return a physical base/size pair which is the ! 238: * (largest) initial, physically contiguous block. ! 239: */ ! 240: vstodb(vsbase, vssize, dmp, dbp, rev) ! 241: register int vsbase, vssize; ! 242: struct dmap *dmp; ! 243: register struct dblock *dbp; ! 244: { ! 245: register int blk = dmmin; ! 246: register swblk_t *ip = dmp->dm_map; ! 247: extern int queueflag; ! 248: ! 249: if (vsbase < 0 || vssize < 0 || vsbase + vssize > dmp->dm_size) ! 250: panic("vstodb"); ! 251: while (vsbase >= blk) { ! 252: vsbase -= blk; ! 253: if (blk < dmmax) ! 254: blk *= 2; ! 255: ip++; ! 256: } ! 257: dbp->db_size = imin(vssize, blk - vsbase); ! 258: dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase); ! 259: } ! 260: ! 261: /* ! 262: * Convert a virtual page number ! 263: * to its corresponding disk block number. ! 264: * Used in pagein/pageout to initiate single page transfers. ! 265: */ ! 266: swblk_t ! 267: vtod(p, v, dmap, smap) ! 268: register struct proc *p; ! 269: unsigned v; ! 270: struct dmap *dmap, *smap; ! 271: { ! 272: struct dblock db; ! 273: int tp; ! 274: ! 275: if (isatsv(p, v)) { ! 276: tp = vtotp(p, v); ! 277: return (p->p_textp->x_daddr[tp/dmtext] + tp%dmtext); ! 278: } ! 279: if (isassv(p, v)) ! 280: vstodb(vtosp(p, v), 1, smap, &db, 1); ! 281: else ! 282: vstodb(vtodp(p, v), 1, dmap, &db, 0); ! 283: return (db.db_base); ! 284: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.