|
|
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.