|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: *
6: * @(#)vm_swap.c 7.7 (Berkeley) 6/30/90
7: */
8:
9: #include "param.h"
10: #include "systm.h"
11: #include "user.h"
12: #include "proc.h"
13: #include "text.h"
14: #include "map.h"
15: #include "buf.h"
16: #include "cmap.h"
17: #include "vm.h"
18:
19: #include "machine/cpu.h"
20: #include "machine/pte.h"
21: #include "machine/mtpr.h"
22:
23: /*
24: * Swap a process in.
25: */
26: swapin(p)
27: register struct proc *p;
28: {
29: register struct text *xp;
30: register int i, s;
31:
32: if (xp = p->p_textp)
33: xlock(xp);
34: p->p_szpt = ptsize(p);
35: if (vgetpt(p, memall) == 0)
36: goto nomem;
37: if (vgetu(p, memall, Swapmap, &swaputl, (struct user *)0) == 0) {
38: vrelpt(p);
39: goto nomem;
40: }
41:
42: #if defined(tahoe)
43: for (i = 0; i < UPAGES; i++)
44: mtpr(P1DC, (caddr_t)&u+i*NBPG);
45: #endif
46: swdspt(p, &swaputl, B_READ);
47: /*
48: * Make sure swdspt didn't smash u. pte's
49: */
50: for (i = 0; i < UPAGES; i++) {
51: if (Swapmap[i].pg_pfnum != p->p_addr[i].pg_pfnum)
52: panic("swapin");
53: }
54: vrelswu(p, &swaputl);
55: if (xp) {
56: xlink(p);
57: xunlock(xp);
58: }
59:
60: p->p_rssize = 0;
61: s = splclock();
62: if (p->p_stat == SRUN)
63: setrq(p);
64: p->p_flag |= SLOAD;
65: if (p->p_flag & SSWAP) {
66: swaputl.u_pcb.pcb_sswap = (int *)&u.u_ssave;
67: p->p_flag &= ~SSWAP;
68: }
69: splx(s);
70: p->p_time = 0;
71: multprog++;
72: cnt.v_swpin++;
73: return (1);
74:
75: nomem:
76: if (xp)
77: xunlock(xp);
78: return (0);
79: }
80:
81: int xswapwant, xswaplock;
82: /*
83: * Swap out process p.
84: * ds and ss are the old data size and the stack size
85: * of the process, and are supplied during page table
86: * expansion swaps.
87: */
88: swapout(p, ds, mms, ss)
89: register struct proc *p;
90: segsz_t ds, mms, ss;
91: {
92: register struct pte *map;
93: register struct user *utl;
94: int s;
95: int rc = 1;
96:
97: s = 1;
98: map = Xswapmap;
99: utl = &xswaputl;
100: if (xswaplock & s)
101: if ((xswaplock & 2) == 0) {
102: s = 2;
103: map = Xswap2map;
104: utl = &xswap2utl;
105: }
106: while (xswaplock & s) {
107: xswapwant |= s;
108: sleep((caddr_t)map, PSWP);
109: }
110: xswaplock |= s;
111: uaccess(p, map, utl);
112: if (vgetswu(p, utl) == 0) {
113: p->p_flag |= SLOAD;
114: rc = 0;
115: goto out;
116: }
117: #if defined(tahoe)
118: { int i;
119: for (i = 0; i < UPAGES; i++)
120: mtpr(P1DC, (caddr_t)&u+i*NBPG);
121: }
122: #endif
123: utl->u_ru.ru_nswap++;
124: utl->u_odsize = ds + mms;
125: utl->u_ossize = ss;
126: p->p_flag |= SLOCK;
127: if (p->p_textp) {
128: if (p->p_textp->x_ccount == 1)
129: p->p_textp->x_swrss = p->p_textp->x_rssize;
130: xdetach(p->p_textp, p);
131: }
132: p->p_swrss = p->p_rssize;
133: vsswap(p, dptopte(p, 0), CDATA, 0, (int)ds, &utl->u_dmap);
134: vsswap(p, sptopte(p, CLSIZE-1), CSTACK, 0, (int)ss, &utl->u_smap);
135: if (p->p_rssize != 0)
136: panic("swapout rssize");
137:
138: swdspt(p, utl, B_WRITE);
139: /*
140: * If freeing the user structure and kernel stack
141: * for the current process, have to run a bit longer
142: * using the pages which are about to be freed...
143: * vrelu will then block memory allocation by raising ipl.
144: */
145: vrelu(p, 1);
146: if ((p->p_flag & SLOAD) && (p->p_stat != SRUN || p != u.u_procp))
147: panic("swapout");
148: p->p_flag &= ~SLOAD;
149: vrelpt(p);
150: p->p_flag &= ~SLOCK;
151: p->p_time = 0;
152:
153: multprog--;
154: cnt.v_swpout++;
155:
156: if (runout) {
157: runout = 0;
158: wakeup((caddr_t)&runout);
159: }
160: out:
161: xswaplock &= ~s;
162: if (xswapwant & s) {
163: xswapwant &= ~s;
164: wakeup((caddr_t)map);
165: }
166: return (rc);
167: }
168:
169: /*
170: * Swap the data and stack page tables in or out.
171: * Only hard thing is swapping out when new pt size is different than old.
172: * If we are growing new pt pages, then we must spread pages with 2 swaps.
173: * If we are shrinking pt pages, then we must merge stack pte's into last
174: * data page so as not to lose them (and also do two swaps).
175: */
176: swdspt(p, utl, rdwri)
177: register struct proc *p;
178: register struct user *utl;
179: {
180: register int szpt, tsz, ssz;
181: register struct pte *pte;
182: register int i;
183:
184: szpt = ptsize(p);
185: tsz = p->p_tsize / NPTEPG;
186: if (szpt == p->p_szpt) {
187: swptstat.pteasy++;
188: swpt(rdwri, p, 0, tsz,
189: (p->p_szpt - tsz) * NBPG - HIGHPAGES * sizeof (struct pte));
190: goto check;
191: }
192: if (szpt < p->p_szpt)
193: swptstat.ptshrink++;
194: else
195: swptstat.ptexpand++;
196: ssz = clrnd(ctopt(utl->u_ossize+HIGHPAGES));
197: #if !defined(hp300) && !defined(i386)
198: if (szpt < p->p_szpt && utl->u_odsize && (utl->u_ossize+HIGHPAGES)) {
199: int tdlast, slast, tdsz;
200:
201: /*
202: * Page tables shrinking... see if last text+data and
203: * last stack page must be merged... if so, copy
204: * stack pte's from last stack page to end of last
205: * data page, and decrease size of stack pt to be swapped.
206: */
207: tdlast = (p->p_tsize + utl->u_odsize) % (NPTEPG * CLSIZE);
208: slast = (utl->u_ossize + HIGHPAGES) % (NPTEPG * CLSIZE);
209: if (tdlast && slast && tdlast + slast <= (NPTEPG * CLSIZE)) {
210: swptstat.ptpack++;
211: tdsz = clrnd(ctopt(p->p_tsize + utl->u_odsize));
212: bcopy((caddr_t)sptopte(p, utl->u_ossize - 1),
213: (caddr_t)&p->p_p0br[tdsz * NPTEPG - slast],
214: (unsigned)(slast * sizeof (struct pte)));
215: ssz -= CLSIZE;
216: }
217: }
218: #endif
219: if (ssz)
220: swpt(rdwri, p, szpt - ssz - tsz, p->p_szpt - ssz, ssz * NBPG);
221: if (utl->u_odsize)
222: swpt(rdwri, p, 0, tsz,
223: (int)(clrnd(ctopt(p->p_tsize + utl->u_odsize)) - tsz) * NBPG);
224: check:
225: for (i = 0; i < utl->u_odsize; i++) {
226: pte = dptopte(p, i);
227: #if defined(tahoe)
228: uncache(pte);
229: #endif
230: #ifdef MAPMEM
231: if (pte->pg_v && pte->pg_fod) /* mapped page */
232: continue;
233: #endif
234: if (pte->pg_v || pte->pg_fod == 0 && (pte->pg_pfnum||pte->pg_m))
235: panic("swdspt");
236: }
237: for (i = 0; i < utl->u_ossize; i++) {
238: pte = sptopte(p, i);
239: #if defined(tahoe)
240: uncache(pte);
241: #endif
242: #ifdef MAPMEM
243: if (pte->pg_v && pte->pg_fod) /* mapped page */
244: continue;
245: #endif
246: if (pte->pg_v || pte->pg_fod == 0 && (pte->pg_pfnum||pte->pg_m))
247: panic("swdspt");
248: }
249: }
250:
251: /*
252: * Swap a section of the page tables.
253: * Errors are handled at a lower level (by doing a panic).
254: */
255: swpt(rdwri, p, doff, a, n)
256: int rdwri;
257: struct proc *p;
258: int doff, a, n;
259: {
260:
261: if (n <= 0)
262: return;
263: (void) swap(p, p->p_swaddr + ctod(UPAGES) + ctod(doff),
264: (caddr_t)&p->p_p0br[a * NPTEPG], n, rdwri, B_PAGET, swapdev_vp, 0);
265: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.