BSD 4 development
authorBill Joy <wnj@ucbvax.Berkeley.EDU>
Sun, 9 Nov 1980 14:43:02 +0000 (06:43 -0800)
committerBill Joy <wnj@ucbvax.Berkeley.EDU>
Sun, 9 Nov 1980 14:43:02 +0000 (06:43 -0800)
Work on file usr/src/sys/sys/vmswap.c

Synthesized-from: CSRG//cd1/4.0

usr/src/sys/sys/vmswap.c [new file with mode: 0644]

diff --git a/usr/src/sys/sys/vmswap.c b/usr/src/sys/sys/vmswap.c
new file mode 100644 (file)
index 0000000..42b3aed
--- /dev/null
@@ -0,0 +1,231 @@
+/*     11/9/80 4.1     11/9/80 */
+
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/proc.h"
+#include "../h/text.h"
+#include "../h/map.h"
+#include "../h/buf.h"
+#include "../h/pte.h"
+#include "../h/mtpr.h"
+#include "../h/cmap.h"
+#include "../h/vm.h"
+
+/*
+ * Swap a process in.
+ */
+swapin(p)
+       register struct proc *p;
+{
+       register struct text *xp;
+       register int i, s;
+
+       if (xp = p->p_textp) 
+               xlock(xp);
+       p->p_szpt = clrnd(ctopt(p->p_ssize+p->p_dsize+p->p_tsize+UPAGES));
+       if (vgetpt(p, memall) == 0)
+               goto nomem;
+       if (vgetu(p, memall, Swapmap, &swaputl, (struct user *)0) == 0) {
+               vrelpt(p);
+               goto nomem;
+       }
+
+       swdspt(p, &swaputl, B_READ);
+       /*
+        * Make sure swdspt didn't smash u. pte's
+        */
+       for (i = 0; i < UPAGES; i++) {
+               if (Swapmap[i].pg_pfnum != p->p_addr[i].pg_pfnum)
+                       panic("swapin");
+       }
+       vrelswu(p, &swaputl);
+       if (xp) {
+               xlink(p);
+               xunlock(xp);
+       }
+
+       p->p_rssize = 0;
+       s = spl6();
+       if (p->p_stat == SRUN)
+               setrq(p);
+       p->p_flag |= SLOAD;
+       if (p->p_flag & SSWAP) {
+               swaputl.u_pcb.pcb_sswap = u.u_ssav;
+               p->p_flag &= ~SSWAP;
+       }
+       splx(s);
+       p->p_time = 0;
+       multprog++;
+       cnt.v_swpin++;
+       return (1);
+
+nomem:
+       if (xp)
+               xunlock(xp);
+       return (0);
+}
+
+int    xswapwant, xswaplock;
+/*
+ * Swap out process p.
+ * ds and ss are the old data size and the stack size
+ * of the process, and are supplied during page table
+ * expansion swaps.
+ */
+swapout(p, ds, ss)
+       register struct proc *p;
+       size_t ds, ss;
+{
+       register struct pte *map;
+       register struct user *utl;
+       register int a;
+       int s;
+       int rc = 1;
+
+       s = 1;
+       map = Xswapmap;
+       utl = &xswaputl;
+       if (xswaplock & s)
+               if ((xswaplock & 2) == 0) {
+                       s = 2;
+                       map = Xswap2map;
+                       utl = &xswap2utl;
+               }
+       a = spl6();
+       while (xswaplock & s) {
+               xswapwant |= s;
+               sleep((caddr_t)map, PSWP);
+       }
+       xswaplock |= s;
+       splx(a);
+       uaccess(p, map, utl);
+       if (vgetswu(p, utl) == 0) {
+               swkill(p, "swapout");
+               rc = 0;
+               goto out;
+       }
+       utl->u_vm.vm_nswap++;
+       utl->u_odsize = ds;
+       utl->u_ossize = ss;
+       p->p_flag |= SLOCK;
+       if (p->p_textp) {
+               if (p->p_textp->x_ccount == 1)
+                       p->p_textp->x_swrss = p->p_textp->x_rssize;
+               xccdec(p->p_textp, p);
+       }
+       p->p_swrss = p->p_rssize;
+       vsswap(p, dptopte(p, 0), CDATA, 0, ds, &utl->u_dmap);
+       vsswap(p, sptopte(p, CLSIZE-1), CSTACK, 0, ss, &utl->u_smap);
+       if (p->p_rssize != 0)
+               panic("swapout rssize");
+
+       swdspt(p, utl, B_WRITE);
+       vrelu(p, 1);
+       if ((p->p_flag & SLOAD) && (p->p_stat != SRUN || p != u.u_procp))
+               panic("swapout");
+       p->p_flag &= ~SLOAD;
+       vrelpt(p);
+       p->p_flag &= ~SLOCK;
+       p->p_time = 0;
+
+       multprog--;
+       cnt.v_swpout++;
+
+       if(runout) {
+               runout = 0;
+               wakeup((caddr_t)&runout);
+       }
+out:
+       xswaplock &= ~s;
+       if (xswapwant & s) {
+               xswapwant &= ~s;
+               wakeup((caddr_t)map);
+       }
+       if (rc == 0) {
+               a = spl6();
+               p->p_flag |= SLOAD;
+               if (p != u.u_procp && p->p_stat == SRUN)
+                       setrq(p);
+               splx(a);
+       }
+       return (rc);
+}
+
+/*
+ * Swap the data and stack page tables in or out.
+ * Only hard thing is swapping out when new pt size is different than old.
+ * If we are growing new pt pages, then we must spread pages with 2 swaps.
+ * If we are shrinking pt pages, then we must merge stack pte's into last
+ * data page so as not to lose them (and also do two swaps).
+ */
+swdspt(p, utl, rdwri)
+       register struct proc *p;
+       register struct user *utl;
+{
+       register int szpt, tsz, ssz;
+       int tdlast, slast, tdsz;
+       register struct pte *pte;
+       register int i;
+
+       szpt = clrnd(ctopt(p->p_tsize+p->p_dsize+p->p_ssize+UPAGES));
+       tsz = p->p_tsize / NPTEPG;
+       if (szpt == p->p_szpt) {
+               swptstat.pteasy++;
+               swpt(rdwri, p, 0, tsz,
+                   (p->p_szpt - tsz) * NBPG - UPAGES * sizeof (struct pte));
+               goto check;
+       }
+       if (szpt < p->p_szpt)
+               swptstat.ptshrink++;
+       else
+               swptstat.ptexpand++;
+       ssz = clrnd(ctopt(utl->u_ossize+UPAGES));
+       if (szpt < p->p_szpt && utl->u_odsize && (utl->u_ossize+UPAGES)) {
+               /*
+                * Page tables shrinking... see if last text+data and
+                * last stack page must be merged... if so, copy
+                * stack pte's from last stack page to end of last
+                * data page, and decrease size of stack pt to be swapped.
+                */
+               tdlast = (p->p_tsize + utl->u_odsize) % (NPTEPG * CLSIZE);
+               slast = (utl->u_ossize + UPAGES) % (NPTEPG * CLSIZE);
+               if (tdlast && slast && tdlast + slast <= (NPTEPG * CLSIZE)) {
+                       swptstat.ptpack++;
+                       tdsz = clrnd(ctopt(p->p_tsize + utl->u_odsize));
+                       bcopy((caddr_t)sptopte(p, utl->u_ossize - 1),
+                           (caddr_t)&p->p_p0br[tdsz * NPTEPG - slast],
+                           (unsigned)(slast * sizeof (struct pte)));
+                       ssz -= CLSIZE;
+               }
+       }
+       if (ssz)
+               swpt(rdwri, p, szpt - ssz - tsz, p->p_szpt - ssz, ssz * NBPG);
+       if (utl->u_odsize)
+               swpt(rdwri, p, 0, tsz,
+                   (clrnd(ctopt(p->p_tsize + utl->u_odsize)) - tsz) * NBPG);
+check:
+       for (i = 0; i < utl->u_odsize; i++) {
+               pte = dptopte(p, i);
+               if (pte->pg_v || pte->pg_fod == 0 && (pte->pg_pfnum||pte->pg_m))
+                       panic("swdspt");
+       }
+       for (i = 0; i < utl->u_ossize; i++) {
+               pte = sptopte(p, i);
+               if (pte->pg_v || pte->pg_fod == 0 && (pte->pg_pfnum||pte->pg_m))
+                       panic("swdspt");
+       }
+}
+
+swpt(rdwri, p, doff, a, n)
+       int rdwri;
+       struct proc *p;
+       int doff, a, n;
+{
+
+       if (n <= 0)
+               return;
+       swap(p, p->p_swaddr + ctod(UPAGES) + doff,
+           (caddr_t)&p->p_p0br[a * NPTEPG], n, rdwri, B_PAGET, swapdev, 0);
+}