changes designed so that ESIS and ARP may use routing table
[unix-history] / usr / src / usr.bin / systat / swap.c
index 6a8e8f2..91ff969 100644 (file)
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
 #ifndef lint
 #ifndef lint
-static char *sccsid = "@(#)swap.c      1.2 (Lucasfilm) %G%";
-#endif
+static char sccsid[] = "@(#)swap.c     5.7 (Berkeley) %G%";
+#endif not lint
 
 #include "systat.h"
 
 #include "systat.h"
-
-#include <sys/map.h>
+#include <sys/user.h>
+#include <sys/proc.h>
+#include <sys/text.h>
 #include <sys/conf.h>
 #include <sys/conf.h>
+#include <sys/vmmac.h>
+#include <machine/pte.h>
+#include <paths.h>
 
 
-/* these don't belong here */
-#define X_NSWAP         6
-#define X_SWAPMAP       7
-#define X_NSWAPMAP      8
-#define X_DMMIN         9
-#define X_DMMAX         10
-#define X_NSWDEV        11
-#define        X_SWDEVT        12
-
-static  int dmmin;
-static  int dmmax;
-static  int nswdev;
-static  int nswapmap;
-static  int nswap;
-static  struct map *swapmap;
-static short *buckets;
-static short *overflow;
-struct swdevt *swdevt;
-
-fetchswap()
+WINDOW *
+openswap()
 {
 {
+       return (subwin(stdscr, LINES-5-1, 0, 5, 0));
+}
 
 
-        if (nswapmap == 0) {
-                nswapmap = getw(nlst[X_NSWAPMAP].n_value);
-                swapmap = (struct map *)calloc(nswapmap, sizeof (struct map));
-                nswap = getw(nlst[X_NSWAP].n_value);
-                dmmin = getw(nlst[X_DMMIN].n_value);
-                dmmax = getw(nlst[X_DMMAX].n_value);
-                nswdev = getw(nlst[X_NSWDEV].n_value);
-               buckets = (short *)calloc(nswdev, sizeof (short));
-               overflow = (short *)calloc(nswdev, sizeof (short));
-               swdevt = (struct swdevt *)calloc(nswdev, sizeof (*swdevt));
-               klseek(kmem, nlst[X_SWDEVT].n_value, L_SET);
-               read(kmem, swdevt, nswdev * sizeof (struct swdevt));
-               swapmap->m_name = "swap";
-                return;
-        }
-        klseek(kmem, getw(nlst[X_SWAPMAP].n_value), L_SET);
-        read(kmem, swapmap, nswapmap * sizeof (struct map));
+closeswap(w)
+       WINDOW *w;
+{
+       if (w == NULL)
+               return;
+       wclear(w);
+       wrefresh(w);
+       delwin(w);
 }
 
 }
 
-#ifdef vax
-char   *devnames[] =
-     { "hp", "ht", "up", "rk", "sw", "tm", "ts", "mt", "tu", "ra", "ut",
-       "rb", "rx", "rl" };
-#endif
+int    dmmin;
+int    dmmax;
+int    dmtext;
+int    nswdev;
+#define        MAXSWAPDEV      4
+short  buckets[MAXSWAPDEV][NDMAP];
+struct swdevt *swdevt;
 int    colwidth;
 
 int    colwidth;
 
-labelswap()
+extern union {
+       struct  user user;
+       char    upages[UPAGES][NBPG];
+} user;
+#define u       user.user
+
+showswap()
 {
        register int i, j;
 {
        register int i, j;
+       register struct proc *pp;
+       register struct text *xp;
+       register int row;
+       register int ts;
+       register swblk_t *dp;
 
 
-       if (nswdev == 0)
-               fetchswap();
-       if (nswdev == 0) {
-               mvaddstr(22, 0, "Can't find number of swap devices.\n");
+       if (xtext == 0)
                return;
                return;
-       }
-        move(5, 0);
-       colwidth = (70 - (nswdev - 1)) / nswdev;
-       for (i = 0; i < nswdev; i++) {
-               move(5, 5 + i * (1 + colwidth) + (colwidth - 3) / 2);
-               printw("%s%d", devnames[major(swdevt[i].sw_dev)],
-                   minor(swdevt[i].sw_dev) >> 3);
-               for (j = 0; j + 5 < colwidth; j += 5) {
-                       move(6, 5 + i * (1 + colwidth) + j);
-                       printw("/%-2d  ", j);
+       for (xp = xtext; xp < &xtext[ntext]; xp++) {
+               if (xp->x_vptr == NULL)
+                       continue;
+               ts = ctod(xp->x_size);
+               dp = xp->x_daddr;
+               for (i = 0; i < ts; i += dmtext) {
+                       j = ts - i;
+                       if (j > dmtext)
+                               j = dmtext;
+#define        swatodev(addr)  (((addr) / dmmax) % nswdev)
+                       buckets[swatodev(*dp)][dmtoindex(j)]++;
+                       dp++;
                }
                }
+               if ((xp->x_flag & XPAGV) && xp->x_ptdaddr)
+                       buckets[swatodev(xp->x_ptdaddr)]
+                           [dmtoindex(ctod(ctopt(xp->x_size)))]++;
        }
        }
-       for (j = 0, i = dmmax; i >= dmmin; i /= 2, j++) {
-               int k;
-
-               mvprintw(7 + j, 0, "%4d|", i);
-               for (k = 1; k < nswdev; k++)
-                       mvwaddch(wnd, 4 + j, k * (1 + colwidth) - 1, '|');
+       row = swapdisplay(2, dmtext, 'X');
+       if (kprocp == NULL)
+               return;
+       for (i = 0, pp = kprocp; i < nproc; i++, pp++) {
+               if (pp->p_stat == 0 || pp->p_stat == SZOMB)
+                       continue;
+               if (pp->p_flag & SSYS)
+                       continue;
+               if (getu(pp) == 0)
+                       continue;
+               vsacct(&u.u_dmap);
+               vsacct(&u.u_smap);
+#ifdef notdef
+               if ((pp->p_flag & SLOAD) == 0)
+                       vusize(pp);
+#endif
        }
        }
+       (void) swapdisplay(1+row, dmmax, 'X');
 }
 
 }
 
-showswap()
+#define        OFFSET  5                       /* left hand column */
+
+swapdisplay(baserow, dmbound, c)
+       int baserow, dmbound;
+       char c;
 {
 {
-        register int i, j;
-       register int row;
+       register int i, j, k, row;
+       register short *pb;
+       char buf[10];
 
 
-       if (nswdev == 0)
-               return;
-       for (row = 4, i = dmmax; i >= dmmin; i /= 2, row++) {
-move(22, 0); clrtoeol(); printw("size %d", i); refresh();
-               do {
-                       j = rmalloc(swapmap, i);
-                       if (j)
-                               buckets[(j / dmmax) % nswdev]++;
-               } while (j);
+       for (row = baserow, i = dmmin; i <= dmbound; i *= 2, row++) {
                for (j = 0; j < nswdev; j++) {
                for (j = 0; j < nswdev; j++) {
-                       register int k;
-move(21 - j, 0); clrtoeol();
-printw("buckets[%d]=%d", j, buckets[j]);
-refresh();
-                       wmove(wnd, row, j * (1 + colwidth));
-                       k = MIN(buckets[j], colwidth);
-                       while (k--)
-                               waddch(wnd, 'X');
-                       k = MAX(colwidth - buckets[j], 0);
-                       while (k--)
-                               waddch(wnd, ' ');
-                       buckets[j] = 0;
+                       pb = &buckets[j][row - baserow];
+                       wmove(wnd, row, OFFSET + j * (1 + colwidth));
+                       k = MIN(*pb, colwidth);
+                       if (*pb > colwidth) {
+                               sprintf(buf, " %d", *pb);
+                               k -= strlen(buf);
+                               while (k--)
+                                       waddch(wnd, c);
+                               waddstr(wnd, buf);
+                       } else {
+                               while (k--)
+                                       waddch(wnd, c);
+                               k = MAX(colwidth - *pb, 0);
+                               while (k--)
+                                       waddch(wnd, ' ');
+                       }
+                       *pb = 0;
                }
        }
                }
        }
-#ifdef notdef
-       printf("overflow:");
-       for (i = 0; i < nswdev; i++)
-               printf("\t%d", overflow[i]);
-       printf("\n");
-#endif
+       return (row);
 }
 
 }
 
-/*
- * Allocate 'size' units from the given
- * map. Return the base of the allocated space.
- * In a map, the addresses are increasing and the
- * list is terminated by a 0 size.
- *
- * Algorithm is first-fit.
- *
- * This routine knows about the interleaving of the swapmap
- * and handles that.
- */
-long
-rmalloc(mp, size)
-       register struct map *mp;
-       long size;
+vsacct(dmp)
+       register struct dmap *dmp;
 {
 {
-       register struct mapent *ep = (struct mapent *)(mp+1);
-       register int addr;
-       register struct mapent *bp;
-       swblk_t first, rest;
+       register swblk_t *ip;
+       register int blk = dmmin, index = 0;
 
 
-       if (size <= 0 || size > dmmax)
-               return (0);
-       /*
-        * Search for a piece of the resource map which has enough
-        * free space to accomodate the request.
-        */
-       for (bp = ep; bp->m_size; bp++) {
-               if (bp->m_size >= size) {
-                       /*
-                        * If allocating from swapmap,
-                        * then have to respect interleaving
-                        * boundaries.
-                        */
-                       if (nswdev > 1 &&
-                           (first = dmmax - bp->m_addr%dmmax) < bp->m_size) {
-                               if (bp->m_size - first < size)
-                                       continue;
-                               addr = bp->m_addr + first;
-                               rest = bp->m_size - first - size;
-                               bp->m_size = first;
-                               if (rest)
-                                       rmfree(mp, rest, addr+size);
-                               return (addr);
-                       }
-                       /*
-                        * Allocate from the map.
-                        * If there is no space left of the piece
-                        * we allocated from, move the rest of
-                        * the pieces to the left.
-                        */
-                       addr = bp->m_addr;
-                       bp->m_addr += size;
-                       if ((bp->m_size -= size) == 0) {
-                               do {
-                                       bp++;
-                                       (bp-1)->m_addr = bp->m_addr;
-                               } while ((bp-1)->m_size = bp->m_size);
-                       }
-                       if (addr % CLSIZE)
-                               return (0);
-                       return (addr);
+       for (ip = dmp->dm_map; dmp->dm_alloc > 0; ip++) {
+               if (ip - dmp->dm_map >= NDMAP) {
+                       error("vsacct NDMAP");
+                       break;
+               }
+               if (*ip == 0)
+                       error("vsacct *ip == 0");
+               buckets[swatodev(*ip)][index]++;
+               dmp->dm_alloc -= blk;
+               if (blk < dmmax) {
+                       blk *= 2;
+                       index++;
                }
        }
                }
        }
-       return (0);
 }
 
 }
 
-/*
- * Free the previously allocated space at addr
- * of size units into the specified map.
- * Sort addr into map and combine on
- * one or both ends if possible.
- */
-rmfree(mp, size, addr)
-       struct map *mp;
-       long size, addr;
+dmtoindex(dm)
+       int dm;
 {
 {
-       struct mapent *firstbp;
-       register struct mapent *bp;
-       register int t;
+       register int i, j;
 
 
-       /*
-        * Both address and size must be
-        * positive, or the protocol has broken down.
-        */
-       if (addr <= 0 || size <= 0)
-               goto badrmfree;
-       /*
-        * Locate the piece of the map which starts after the
-        * returned space (or the end of the map).
-        */
-       firstbp = bp = (struct mapent *)(mp + 1);
-       for (; bp->m_addr <= addr && bp->m_size != 0; bp++)
-               continue;
-       /*
-        * If the piece on the left abuts us,
-        * then we should combine with it.
-        */
-       if (bp > firstbp && (bp-1)->m_addr+(bp-1)->m_size >= addr) {
-               /*
-                * Check no overlap (internal error).
-                */
-               if ((bp-1)->m_addr+(bp-1)->m_size > addr)
-                       goto badrmfree;
-               /*
-                * Add into piece on the left by increasing its size.
-                */
-               (bp-1)->m_size += size;
-               /*
-                * If the combined piece abuts the piece on
-                * the right now, compress it in also,
-                * by shifting the remaining pieces of the map over.
-                */
-               if (bp->m_addr && addr+size >= bp->m_addr) {
-                       if (addr+size > bp->m_addr)
-                               goto badrmfree;
-                       (bp-1)->m_size += bp->m_size;
-                       while (bp->m_size) {
-                               bp++;
-                               (bp-1)->m_addr = bp->m_addr;
-                               (bp-1)->m_size = bp->m_size;
-                       }
+       for (j = 0, i = dmmin; i <= dmmax; i *= 2, j++)
+               if (dm <= i)
+                       return (j);
+       error("dmtoindex(%d)", dm);
+       return (NDMAP - 1);
+}
+
+static struct nlist nlst[] = {
+#define X_PROC          0
+       { "_proc" },
+#define X_NPROC         1
+       { "_nproc" },
+#define X_USRPTMAP      2
+       { "_Usrptmap" },
+#define X_USRPT         3
+       { "_usrpt" },
+#define X_NSWAP         4
+       { "_nswap" },
+#define X_DMMIN         5
+       { "_dmmin" },
+#define X_DMMAX         6
+       { "_dmmax" },
+#define        X_DMTEXT        7
+       { "_dmtext" },
+#define X_NSWDEV        8
+       { "_nswdev" },
+#define        X_SWDEVT        9
+       { "_swdevt" },
+#define        X_NTEXT         10
+       { "_ntext" },
+#define        X_TEXT          11
+       { "_text" },
+       { "" }
+};
+
+initswap()
+{
+       if (nlst[X_PROC].n_type == 0) {
+               nlist(_PATH_UNIX, nlst);
+               if (nlst[X_PROC].n_type == 0) {
+                       error("namelist on %s failed", _PATH_UNIX);
+                       return(0);
                }
                }
-               goto done;
        }
        }
-       /*
-        * Don't abut on the left, check for abutting on
-        * the right.
-        */
-       if (addr+size >= bp->m_addr && bp->m_size) {
-               if (addr+size > bp->m_addr)
-                       goto badrmfree;
-               bp->m_addr -= size;
-               bp->m_size += size;
-               goto done;
+       if (nswdev == 0) {
+               dmmin = getw(nlst[X_DMMIN].n_value);
+               dmmax = getw(nlst[X_DMMAX].n_value);
+               dmtext = getw(nlst[X_DMTEXT].n_value);
+               nswdev = getw(nlst[X_NSWDEV].n_value);
+               if (nswdev > MAXSWAPDEV)
+                       nswdev = MAXSWAPDEV;
+               swdevt = (struct swdevt *)calloc(nswdev, sizeof (*swdevt));
+               klseek(kmem, nlst[X_SWDEVT].n_value, L_SET);
+               read(kmem, swdevt, nswdev * sizeof (struct swdevt));
+               ntext = getw(nlst[X_NTEXT].n_value);
+               textp = getw(nlst[X_TEXT].n_value);
        }
        }
-       /*
-        * Don't abut at all.  Make a new entry
-        * and check for map overflow.
-        */
-       do {
-               t = bp->m_addr;
-               bp->m_addr = addr;
-               addr = t;
-               t = bp->m_size;
-               bp->m_size = size;
-               bp++;
-       } while (size = t);
-       /*
-        * Segment at bp is to be the delimiter;
-        * If there is not room for it 
-        * then the table is too full
-        * and we must discard something.
-        */
-       if (bp+1 > mp->m_limit) {
-               /*
-                * Back bp up to last available segment.
-                * which contains a segment already and must
-                * be made into the delimiter.
-                * Discard second to last entry,
-                * since it is presumably smaller than the last
-                * and move the last entry back one.
-                */
-               bp--;
-               overflow[((bp-1)->m_addr % dmmax) / nswdev] += 
-                   (bp-1)->m_size;
-#ifdef notdef
-               printf("%s: rmap ovflo, lost [%d,%d)\n", mp->m_name,
-                   (bp-1)->m_addr, (bp-1)->m_addr+(bp-1)->m_size);
+       if (procp == NULL) {
+               procp = getw(nlst[X_PROC].n_value);
+               nproc = getw(nlst[X_NPROC].n_value);
+       }
+       if (xtext == NULL)
+               xtext = (struct text *)calloc(ntext, sizeof (struct text));
+       if (kprocp == NULL)
+               kprocp = (struct proc *)calloc(nproc, sizeof (struct proc));
+       if (usrpt != NULL)
+               return(1);
+       usrpt = (struct pte *)nlst[X_USRPT].n_value;
+       Usrptma = (struct pte *)nlst[X_USRPTMAP].n_value;
+       if (pt == NULL)
+               pt = (struct p_times *)malloc(nproc * sizeof (struct p_times));
+       return(1);
+}
+
+fetchswap()
+{
+       if (nlst[X_PROC].n_type == 0)
+               return;
+       if (kprocp == NULL) {
+               kprocp = (struct proc *)malloc(sizeof (*kprocp) * nproc);
+               if (kprocp == NULL)
+                       return;
+       }
+       lseek(kmem, procp, L_SET);
+       if (read(kmem, kprocp, sizeof (struct proc) * nproc) !=
+           sizeof (struct proc) * nproc) {
+               error("couldn't read proc table");
+               return;
+       }
+       if (xtext == NULL) {
+               xtext = (struct text *)calloc(ntext, sizeof (struct text));
+               if (xtext == NULL)
+                       return;
+       }
+       lseek(kmem, textp, L_SET);
+       if (read(kmem, xtext, ntext * sizeof (struct text)) !=
+           sizeof (struct text) * ntext)
+               error("couldn't read text table");
+}
+
+#ifdef vax
+char   *devnames[] =
+     { "hp", "ht", "up", "rk", "sw", "tm", "ts", "mt", "tu", "ra", "ut",
+       "rb", "rx", "rl" };
 #endif
 #endif
-               bp[-1] = bp[0];
-               bp[0].m_size = bp[0].m_addr = 0;
+#ifdef tahoe
+char   *devnames[] = { "ud", "vd", "xp", "cy", "sw" };
+#endif
+
+labelswap()
+{
+       register int row;
+
+       if (nswdev == 0) {
+               error("Don't know how many swap devices.\n");
+               return;
+       }
+       colwidth = (COLS - OFFSET - (nswdev - 1)) / nswdev;
+       row = swaplabel(0, dmtext, 1);
+       (void) swaplabel(row, dmmax, 0);
+}
+
+swaplabel(row, dmbound, donames)
+       register int row;
+       int dmbound, donames;
+{
+       register int i, j;
+
+       for (i = 0; i < nswdev; i++) {
+               if (donames)
+                       mvwprintw(wnd,
+                           row, OFFSET + i*(1 + colwidth) + (colwidth - 3)/2,
+                           "%s%d", devnames[major(swdevt[i].sw_dev)],
+                               minor(swdevt[i].sw_dev) >> 3);
+               for (j = 0; j + 5 < colwidth; j += 5)
+                       mvwprintw(wnd, row + donames,
+                           OFFSET + i*(1 + colwidth) + j, "/%-2d  ", j);
+       }
+       row += 1 + donames;
+       for (j = 0, i = dmmin; i <= dmbound; i *= 2, j++, row++) {
+               int k;
+
+               mvwprintw(wnd, row, 0, "%4d|", i);
+               for (k = 1; k < nswdev; k++)
+                       mvwaddch(wnd, row, OFFSET + k*(1 + colwidth) - 1, '|');
        }
        }
-done:
-       return;
-badrmfree:
-       printf("bad rmfree\n");
+       return (row);
 }
 }