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