|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution is only permitted until one year after the first shipment
6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and
7: * binary forms are permitted provided that: (1) source distributions retain
8: * this entire copyright notice and comment, and (2) distributions including
9: * binaries display the following acknowledgement: This product includes
10: * software developed by the University of California, Berkeley and its
11: * contributors'' in the documentation or other materials provided with the
12: * distribution and in all advertising materials mentioning features or use
13: * of this software. Neither the name of the University nor the names of
14: * its contributors may be used to endorse or promote products derived from
15: * this software without specific prior written permission.
16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19: *
20: * @(#)vm_drum.c 7.8 (Berkeley) 6/28/90
21: */
22:
23: #include "param.h"
24: #include "systm.h"
25: #include "user.h"
26: #include "proc.h"
27: #include "buf.h"
28: #include "text.h"
29: #include "map.h"
30: #include "vm.h"
31: #include "cmap.h"
32: #include "kernel.h"
33:
34: #include "machine/pte.h"
35:
36: /*
37: * Expand the swap area for both the data and stack segments.
38: * If space is not available for both, retract and return ENOMEM.
39: */
40: swpexpand(ds, ss, dmp, smp)
41: segsz_t ds, ss;
42: register struct dmap *dmp, *smp;
43: {
44: register struct dmap *tmp;
45: register int ts;
46: segsz_t ods;
47:
48: /*
49: * If dmap isn't growing, do smap first.
50: * This avoids anomalies if smap will try to grow and
51: * fail, which otherwise would shrink ds without expanding
52: * ss, a rather curious side effect!
53: */
54: if (dmp->dm_alloc > ctod(ds)) {
55: tmp = dmp; ts = ds;
56: dmp = smp; ds = ss;
57: smp = tmp; ss = ts;
58: }
59: ods = dtoc(dmp->dm_size);
60: if (vsexpand(ds, dmp, 0) == 0)
61: return (ENOMEM);
62: if (vsexpand(ss, smp, 0) == 0) {
63: /* flush text cache and try again */
64: if (xpurge() && vsexpand(ss, smp, 0))
65: return (0);
66: (void) vsexpand(ods, dmp, 1);
67: return (ENOMEM);
68: }
69: return (0);
70: }
71:
72: /*
73: * Expand or contract the virtual swap segment mapped
74: * by the argument diskmap so as to just allow the given size.
75: *
76: * FOR NOW CANT RELEASE UNLESS SHRINKING TO ZERO, SINCE PAGEOUTS MAY
77: * BE IN PROGRESS... TYPICALLY NEVER SHRINK ANYWAYS, SO DOESNT MATTER MUCH
78: */
79: vsexpand(vssize, dmp, canshrink)
80: register segsz_t vssize;
81: register struct dmap *dmp;
82: {
83: register long blk = dmmin;
84: register int vsbase = 0;
85: register swblk_t *ip = dmp->dm_map;
86: segsz_t oldsize = dmp->dm_size;
87: segsz_t oldalloc = dmp->dm_alloc;
88:
89: vssize = ctod(vssize);
90: while (vsbase < oldalloc || vsbase < vssize) {
91: if (ip - dmp->dm_map >= NDMAP)
92: panic("vmdrum NDMAP");
93: if (vsbase >= oldalloc) {
94: *ip = rmalloc(swapmap, blk);
95: if (*ip == 0) {
96: dmp->dm_size = vsbase;
97: if (vsexpand(dtoc(oldsize), dmp, 1) == 0)
98: panic("vsexpand");
99: return (0);
100: }
101: dmp->dm_alloc += blk;
102: } else if (vssize == 0 ||
103: vsbase >= vssize && canshrink) {
104: rmfree(swapmap, blk, *ip);
105: *ip = 0;
106: dmp->dm_alloc -= blk;
107: }
108: vsbase += blk;
109: if (blk < dmmax)
110: blk *= 2;
111: ip++;
112: }
113: dmp->dm_size = vssize;
114: return (1);
115: }
116:
117: /*
118: * Allocate swap space for a text segment,
119: * in chunks of at most dmtext pages.
120: */
121: vsxalloc(xp)
122: struct text *xp;
123: {
124: register long blk;
125: register swblk_t *dp;
126: swblk_t vsbase;
127:
128: if (ctod(xp->x_size) > NXDAD * dmtext)
129: return (0);
130: dp = xp->x_daddr;
131: for (vsbase = 0; vsbase < ctod(xp->x_size); vsbase += dmtext) {
132: blk = ctod(xp->x_size) - vsbase;
133: if (blk > dmtext)
134: blk = dmtext;
135: if ((*dp++ = rmalloc(swapmap, blk)) == 0) {
136: vsxfree(xp, dtoc(vsbase));
137: return (0);
138: }
139: }
140: if (xp->x_flag & XPAGV) {
141: xp->x_ptdaddr =
142: rmalloc(swapmap, (long)ctod(clrnd(ctopt(xp->x_size))));
143: if (xp->x_ptdaddr == 0) {
144: vsxfree(xp, (long)xp->x_size);
145: return (0);
146: }
147: }
148: return (1);
149: }
150:
151: /*
152: * Free the swap space of a text segment which
153: * has been allocated ts pages.
154: */
155: vsxfree(xp, ts)
156: struct text *xp;
157: long ts;
158: {
159: register long blk;
160: register swblk_t *dp;
161: swblk_t vsbase;
162:
163: ts = ctod(ts);
164: dp = xp->x_daddr;
165: for (vsbase = 0; vsbase < ts; vsbase += dmtext) {
166: blk = ts - vsbase;
167: if (blk > dmtext)
168: blk = dmtext;
169: rmfree(swapmap, blk, *dp);
170: *dp++ = 0;
171: }
172: if ((xp->x_flag&XPAGV) && xp->x_ptdaddr) {
173: rmfree(swapmap, (long)ctod(clrnd(ctopt(xp->x_size))),
174: xp->x_ptdaddr);
175: xp->x_ptdaddr = 0;
176: }
177: }
178:
179: /*
180: * Swap a segment of virtual memory to disk,
181: * by locating the contiguous dirty pte's
182: * and calling vschunk with each chunk.
183: * We ignore swap errors here because swap()
184: * will panic on an error when writing to disk.
185: */
186: vsswap(p, pte, type, vsbase, vscount, dmp)
187: struct proc *p;
188: register struct pte *pte;
189: int type;
190: register int vsbase, vscount;
191: struct dmap *dmp;
192: {
193: register int size = 0;
194: register struct cmap *c;
195:
196: if (vscount % CLSIZE)
197: panic("vsswap");
198: for (;;) {
199: if (vscount == 0 || pte->pg_fod || pte->pg_pfnum == 0 ||
200: !dirtycl(pte)) {
201: if (size) {
202: vschunk(p, vsbase, size, type, dmp);
203: vsbase += size;
204: size = 0;
205: }
206: if (vscount == 0)
207: return;
208: vsbase += CLSIZE;
209: if (pte->pg_fod == 0 && pte->pg_pfnum)
210: if (type == CTEXT)
211: p->p_textp->x_rssize -= vmemfree(pte, CLSIZE);
212: else
213: p->p_rssize -= vmemfree(pte, CLSIZE);
214: } else {
215: size += CLSIZE;
216: c = &cmap[pgtocm(pte->pg_pfnum)];
217: MLOCK(c);
218: MUNLOCK(c);
219: }
220: vscount -= CLSIZE;
221: if (type == CSTACK)
222: pte -= CLSIZE;
223: else
224: pte += CLSIZE;
225: }
226: }
227:
228: vschunk(p, base, size, type, dmp)
229: register struct proc *p;
230: register int base, size;
231: int type;
232: struct dmap *dmp;
233: {
234: register struct pte *pte;
235: struct dblock db;
236: unsigned v;
237:
238: base = ctod(base);
239: size = ctod(size);
240: if (type == CTEXT) {
241: while (size > 0) {
242: db.db_size = dmtext - base % dmtext;
243: if (db.db_size > size)
244: db.db_size = size;
245: (void)swap(p,
246: p->p_textp->x_daddr[base/dmtext] + base%dmtext,
247: ptob(tptov(p, dtoc(base))), (int)dtob(db.db_size),
248: B_WRITE, 0, swapdev_vp, 0);
249: pte = tptopte(p, dtoc(base));
250: p->p_textp->x_rssize -=
251: vmemfree(pte, (int)dtoc(db.db_size));
252: base += db.db_size;
253: size -= db.db_size;
254: }
255: return;
256: }
257: do {
258: vstodb(base, size, dmp, &db, type == CSTACK);
259: v = type==CSTACK ?
260: sptov(p, dtoc(base+db.db_size)-1) :
261: dptov(p, dtoc(base));
262: (void)swap(p, db.db_base, ptob(v), (int)dtob(db.db_size),
263: B_WRITE, 0, swapdev_vp, 0);
264: pte = type==CSTACK ?
265: sptopte(p, dtoc(base+db.db_size)-1) :
266: dptopte(p, dtoc(base));
267: p->p_rssize -= vmemfree(pte, (int)dtoc(db.db_size));
268: base += db.db_size;
269: size -= db.db_size;
270: } while (size != 0);
271: }
272:
273: /*
274: * Given a base/size pair in virtual swap area,
275: * return a physical base/size pair which is the
276: * (largest) initial, physically contiguous block.
277: */
278: vstodb(vsbase, vssize, dmp, dbp, rev)
279: register int vsbase, vssize;
280: struct dmap *dmp;
281: register struct dblock *dbp;
282: {
283: register int blk = dmmin;
284: register swblk_t *ip = dmp->dm_map;
285:
286: if (vsbase < 0 || vssize < 0 || vsbase + vssize > dmp->dm_size)
287: panic("vstodb");
288: while (vsbase >= blk) {
289: vsbase -= blk;
290: if (blk < dmmax)
291: blk *= 2;
292: ip++;
293: }
294: if (*ip + blk > nswap)
295: panic("vstodb *ip");
296: dbp->db_size = imin(vssize, blk - vsbase);
297: dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase);
298: }
299:
300: /*
301: * Convert a virtual page number
302: * to its corresponding disk block number.
303: * Used in pagein/pageout to initiate single page transfers.
304: * An assumption here is that dmmin >= CLBYTES/DEV_BSIZE
305: * i.e. a page cluster must be stored contiguously in the swap area.
306: */
307: swblk_t
308: vtod(p, v, dmap, smap)
309: register struct proc *p;
310: unsigned v;
311: struct dmap *dmap, *smap;
312: {
313: struct dblock db;
314: int tp;
315:
316: if (isatsv(p, v)) {
317: tp = ctod(vtotp(p, v));
318: return (p->p_textp->x_daddr[tp/dmtext] + tp%dmtext);
319: }
320: if (isassv(p, v))
321: vstodb(ctod(vtosp(p, v)), ctod(1), smap, &db, 1);
322: else
323: vstodb(ctod(vtodp(p, v)), ctod(1), dmap, &db, 0);
324: return (db.db_base);
325: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.