|
|
1.1 root 1: /* vmswap.c 4.3 81/06/11 */
2:
3: #include "../h/param.h"
4: #include "../h/systm.h"
5: #include "../h/dir.h"
6: #include "../h/user.h"
7: #include "../h/proc.h"
8: #include "../h/text.h"
9: #include "../h/map.h"
10: #include "../h/buf.h"
11: #include "../h/pte.h"
12: #include "../h/mtpr.h"
13: #include "../h/cmap.h"
14: #include "../h/vm.h"
15:
16: /*
17: * Swap a process in.
18: */
19: swapin(p)
20: register struct proc *p;
21: {
22: register struct text *xp;
23: register int i, s;
24:
25: if (xp = p->p_textp)
26: xlock(xp);
27: p->p_szpt = clrnd(ctopt(p->p_ssize+p->p_dsize+p->p_tsize+UPAGES));
28: if (vgetpt(p, memall) == 0)
29: goto nomem;
30: if (vgetu(p, memall, Swapmap, &swaputl, (struct user *)0) == 0) {
31: vrelpt(p);
32: goto nomem;
33: }
34:
35: swdspt(p, &swaputl, B_READ);
36: /*
37: * Make sure swdspt didn't smash u. pte's
38: */
39: for (i = 0; i < UPAGES; i++) {
40: if (Swapmap[i].pg_pfnum != p->p_addr[i].pg_pfnum)
41: panic("swapin");
42: }
43: vrelswu(p, &swaputl);
44: if (xp) {
45: xlink(p);
46: xunlock(xp);
47: }
48:
49: p->p_rssize = 0;
50: s = spl6();
51: if (p->p_stat == SRUN)
52: setrq(p);
53: p->p_flag |= SLOAD;
54: if (p->p_flag & SSWAP) {
55: swaputl.u_pcb.pcb_sswap = u.u_ssav;
56: p->p_flag &= ~SSWAP;
57: }
58: splx(s);
59: p->p_time = 0;
60: multprog++;
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: size_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, utl) == 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: multprog--;
135: cnt.v_swpout++;
136:
137: if(runout) {
138: runout = 0;
139: wakeup((caddr_t)&runout);
140: }
141: out:
142: xswaplock &= ~s;
143: if (xswapwant & s) {
144: xswapwant &= ~s;
145: wakeup((caddr_t)map);
146: }
147: if (rc == 0) {
148: a = spl6();
149: p->p_flag |= SLOAD;
150: if (p != u.u_procp && p->p_stat == SRUN)
151: setrq(p);
152: splx(a);
153: }
154: return (rc);
155: }
156:
157: /*
158: * Swap the data and stack page tables in or out.
159: * Only hard thing is swapping out when new pt size is different than old.
160: * If we are growing new pt pages, then we must spread pages with 2 swaps.
161: * If we are shrinking pt pages, then we must merge stack pte's into last
162: * data page so as not to lose them (and also do two swaps).
163: */
164: swdspt(p, utl, rdwri)
165: register struct proc *p;
166: register struct user *utl;
167: {
168: register int szpt, tsz, ssz;
169: int tdlast, slast, tdsz;
170: register struct pte *pte;
171: register int i;
172:
173: szpt = clrnd(ctopt(p->p_tsize+p->p_dsize+p->p_ssize+UPAGES));
174: tsz = p->p_tsize / NPTEPG;
175: if (szpt == p->p_szpt) {
176: swptstat.pteasy++;
177: swpt(rdwri, p, 0, tsz,
178: (p->p_szpt - tsz) * NBPG - UPAGES * sizeof (struct pte));
179: goto check;
180: }
181: if (szpt < p->p_szpt)
182: swptstat.ptshrink++;
183: else
184: swptstat.ptexpand++;
185: ssz = clrnd(ctopt(utl->u_ossize+UPAGES));
186: if (szpt < p->p_szpt && utl->u_odsize && (utl->u_ossize+UPAGES)) {
187: /*
188: * Page tables shrinking... see if last text+data and
189: * last stack page must be merged... if so, copy
190: * stack pte's from last stack page to end of last
191: * data page, and decrease size of stack pt to be swapped.
192: */
193: tdlast = (p->p_tsize + utl->u_odsize) % (NPTEPG * CLSIZE);
194: slast = (utl->u_ossize + UPAGES) % (NPTEPG * CLSIZE);
195: if (tdlast && slast && tdlast + slast <= (NPTEPG * CLSIZE)) {
196: swptstat.ptpack++;
197: tdsz = clrnd(ctopt(p->p_tsize + utl->u_odsize));
198: bcopy((caddr_t)sptopte(p, utl->u_ossize - 1),
199: (caddr_t)&p->p_p0br[tdsz * NPTEPG - slast],
200: (unsigned)(slast * sizeof (struct pte)));
201: ssz -= CLSIZE;
202: }
203: }
204: if (ssz)
205: swpt(rdwri, p, szpt - ssz - tsz, p->p_szpt - ssz, ssz * NBPG);
206: if (utl->u_odsize)
207: swpt(rdwri, p, 0, tsz,
208: (clrnd(ctopt(p->p_tsize + utl->u_odsize)) - tsz) * NBPG);
209: check:
210: for (i = 0; i < utl->u_odsize; i++) {
211: pte = dptopte(p, i);
212: if (pte->pg_v || pte->pg_fod == 0 && (pte->pg_pfnum||pte->pg_m))
213: panic("swdspt");
214: }
215: for (i = 0; i < utl->u_ossize; i++) {
216: pte = sptopte(p, i);
217: if (pte->pg_v || pte->pg_fod == 0 && (pte->pg_pfnum||pte->pg_m))
218: panic("swdspt");
219: }
220: }
221:
222: swpt(rdwri, p, doff, a, n)
223: int rdwri;
224: struct proc *p;
225: int doff, a, n;
226: {
227:
228: if (n <= 0)
229: return;
230: swap(p, p->p_swaddr + ctod(UPAGES) + doff,
231: (caddr_t)&p->p_p0br[a * NPTEPG], n, rdwri, B_PAGET, swapdev, 0);
232: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.