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