|
|
1.1 root 1: /* vmswap.c 4.3 81/06/11 */
2:
3: #include "sys/param.h"
4: #include "sys/systm.h"
5: #include "sys/user.h"
6: #include "sys/proc.h"
7: #include "sys/text.h"
8: #include "sys/map.h"
9: #include "sys/buf.h"
10: #include "sys/pte.h"
11: #include "sys/cmap.h"
12: #include "sys/vm.h"
13:
14: struct pte *Swapmap, *Xswapmap, *Xswap2map;
15: struct user *swaputl, *xswaputl, *xswap2utl;
16:
17: /*
18: * Swap a process in.
19: */
20: swapin(p)
21: register struct proc *p;
22: {
23: register struct text *xp;
24: register int i, s;
25:
26: if (xp = p->p_textp)
27: xlock(xp);
28: p->p_szpt = clrnd(ctopt(p->p_ssize+p->p_dsize+p->p_tsize+UPAGES));
29: if (vgetpt(p, memall) == 0)
30: goto nomem;
31: if (vgetu(p, memall, Swapmap, swaputl, (struct user *)0) == 0) {
32: vrelpt(p);
33: goto nomem;
34: }
35:
36: swdspt(p, swaputl, B_READ);
37: /*
38: * Make sure swdspt didn't smash u. pte's
39: */
40: for (i = 0; i < UPAGES; i++) {
41: if (Swapmap[i].pg_pfnum != p->p_addr[i].pg_pfnum)
42: panic("swapin");
43: }
44: vrelswu(p);
45: if (xp) {
46: xlink(p);
47: xunlock(xp);
48: }
49:
50: p->p_rssize = 0;
51: s = spl6();
52: if (p->p_stat == SRUN)
53: setrq(p);
54: p->p_flag |= SLOAD;
55: if (p->p_flag & SSWAP) {
56: swaputl->u_pcb.pcb_sswap = u.u_ssav;
57: p->p_flag &= ~SSWAP;
58: }
59: splx(s);
60: p->p_time = 0;
61: cnt.v_swpin++;
62: if (p->p_flag&SPROCIO) wakeup((caddr_t)&p->p_addr);
63: return (1);
64:
65: nomem:
66: if (xp)
67: xunlock(xp);
68: return (0);
69: }
70:
71: int xswapwant, xswaplock;
72: /*
73: * Swap out process p.
74: * ds and ss are the old data size and the stack size
75: * of the process, and are supplied during page table
76: * expansion swaps.
77: */
78: swapout(p, ds, ss)
79: register struct proc *p;
80: clicks_t ds, ss;
81: {
82: register struct pte *map;
83: register struct user *utl;
84: register int a;
85: int s;
86: int rc = 1;
87:
88: s = 1;
89: map = Xswapmap;
90: utl = xswaputl;
91: if (xswaplock & s)
92: if ((xswaplock & 2) == 0) {
93: s = 2;
94: map = Xswap2map;
95: utl = xswap2utl;
96: }
97: a = spl6();
98: while (xswaplock & s) {
99: xswapwant |= s;
100: sleep((caddr_t)map, PSWP);
101: }
102: xswaplock |= s;
103: splx(a);
104: uaccess(p, map, utl);
105: if (vgetswu(p) == 0) {
106: swkill(p, "swapout");
107: rc = 0;
108: goto out;
109: }
110: utl->u_vm.vm_nswap++;
111: utl->u_odsize = ds;
112: utl->u_ossize = ss;
113: p->p_flag |= SLOCK;
114: if (p->p_textp) {
115: if (p->p_textp->x_ccount == 1)
116: p->p_textp->x_swrss = p->p_textp->x_rssize;
117: xccdec(p->p_textp, p);
118: }
119: p->p_swrss = p->p_rssize;
120: vsswap(p, dptopte(p, 0), CDATA, 0, ds, &utl->u_dmap);
121: vsswap(p, sptopte(p, CLSIZE-1), CSTACK, 0, ss, &utl->u_smap);
122: if (p->p_rssize != 0)
123: panic("swapout rssize");
124:
125: swdspt(p, utl, B_WRITE);
126: vrelu(p, 1);
127: if ((p->p_flag & SLOAD) && (p->p_stat != SRUN || p != u.u_procp))
128: panic("swapout");
129: p->p_flag &= ~SLOAD;
130: vrelpt(p);
131: p->p_flag &= ~SLOCK;
132: p->p_time = 0;
133:
134: cnt.v_swpout++;
135:
136: if(runout) {
137: runout = 0;
138: wakeup((caddr_t)&runout);
139: }
140: out:
141: xswaplock &= ~s;
142: if (xswapwant & s) {
143: xswapwant &= ~s;
144: wakeup((caddr_t)map);
145: }
146: if (rc == 0) {
147: a = spl6();
148: p->p_flag |= SLOAD;
149: if (p != u.u_procp && p->p_stat == SRUN)
150: setrq(p);
151: splx(a);
152: }
153: return (rc);
154: }
155:
156: /*
157: * Swap the data and stack page tables in or out.
158: * Only hard thing is swapping out when new pt size is different than old.
159: * If we are growing new pt pages, then we must spread pages with 2 swaps.
160: * If we are shrinking pt pages, then we must merge stack pte's into last
161: * data page so as not to lose them (and also do two swaps).
162: */
163: swdspt(p, utl, rdwri)
164: register struct proc *p;
165: register struct user *utl;
166: {
167: register int szpt, tsz, ssz;
168: int tdlast, slast, tdsz;
169: register struct pte *pte;
170: register int i;
171:
172: szpt = clrnd(ctopt(p->p_tsize+p->p_dsize+p->p_ssize+UPAGES));
173: tsz = p->p_tsize / NPTEPG;
174: if (szpt == p->p_szpt) {
175: swptstat.pteasy++;
176: swpt(rdwri, p, 0, tsz,
177: (p->p_szpt - tsz) * NBPG - UPAGES * sizeof (struct pte));
178: goto check;
179: }
180: if (szpt < p->p_szpt)
181: swptstat.ptshrink++;
182: else
183: swptstat.ptexpand++;
184: ssz = clrnd(ctopt(utl->u_ossize+UPAGES));
185: if (szpt < p->p_szpt && utl->u_odsize && (utl->u_ossize+UPAGES)) {
186: /*
187: * Page tables shrinking... see if last text+data and
188: * last stack page must be merged... if so, copy
189: * stack pte's from last stack page to end of last
190: * data page, and decrease size of stack pt to be swapped.
191: */
192: tdlast = (p->p_tsize + utl->u_odsize) % (NPTEPG * CLSIZE);
193: slast = (utl->u_ossize + UPAGES) % (NPTEPG * CLSIZE);
194: if (tdlast && slast && tdlast + slast <= (NPTEPG * CLSIZE)) {
195: swptstat.ptpack++;
196: tdsz = clrnd(ctopt(p->p_tsize + utl->u_odsize));
197: bcopy((caddr_t)sptopte(p, utl->u_ossize - 1),
198: (caddr_t)&p->p_p0br[tdsz * NPTEPG - slast],
199: (unsigned)(slast * sizeof (struct pte)));
200: ssz -= CLSIZE;
201: }
202: }
203: if (ssz)
204: swpt(rdwri, p, szpt - ssz - tsz, p->p_szpt - ssz, ssz * NBPG);
205: if (utl->u_odsize)
206: swpt(rdwri, p, 0, tsz,
207: (clrnd(ctopt(p->p_tsize + utl->u_odsize)) - tsz) * NBPG);
208: check:
209: for (i = 0; i < utl->u_odsize; i++) {
210: pte = dptopte(p, i);
211: if (pte->pg_v || pte->pg_fod == 0 && (pte->pg_pfnum||pte->pg_m))
212: panic("swdspt");
213: }
214: for (i = 0; i < utl->u_ossize; i++) {
215: pte = sptopte(p, i);
216: if (pte->pg_v || pte->pg_fod == 0 && (pte->pg_pfnum||pte->pg_m))
217: panic("swdspt");
218: }
219: }
220:
221: swpt(rdwri, p, doff, a, n)
222: int rdwri;
223: struct proc *p;
224: int doff, a, n;
225: {
226:
227: if (n <= 0)
228: return;
229: swap(p, p->p_swaddr + ctod(UPAGES) + doff,
230: (caddr_t)&p->p_p0br[a * NPTEPG], n, rdwri, B_PAGET, swapdev, 0);
231: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.