file reorg, pathnames.h, paths.h
[unix-history] / usr / src / usr.bin / systat / swap.c
index f719f49..94602f4 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.1 (Lucasfilm) %G%";
-#endif
+static char sccsid[] = "@(#)swap.c     5.4 (Berkeley) %G%";
+#endif not lint
 
 #include "systat.h"
 
 #include "systat.h"
-
-#include <sys/map.h>
+#include <sys/dir.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>
 
 
-/* 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
-
-static  int dmmin;
-static  int dmmax;
-static  int nswdev;
-static  int nswapmap;
-static  int nswap;
-static  struct map *swapmap;
-
-fetchswap()
+WINDOW *
+openswap()
 {
 
 {
 
-        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);
-                return;
-        }
-        klseek(kmem, getw(nlst[X_SWAPMAP].n_value), L_SET);
-        read(kmem, swapmap, nswapmap * sizeof (struct map));
-        swapmap->m_name = "swap";
+       return (subwin(stdscr, LINES-5-1, 0, 5, 0));
 }
 
 }
 
-labelswap()
+closeswap(w)
+       WINDOW *w;
 {
 
 {
 
-        move(5, 0);
-        clrtoeol();
-        mvaddstr(5, 20, "/0   /5   /10  /15  /20  /25  /30  /35  /40  /45  /50");
+       if (w == NULL)
+               return;
+       wclear(w);
+       wrefresh(w);
+       delwin(w);
 }
 
 }
 
+int    dmmin;
+int    dmmax;
+int    dmtext;
+int    nswdev;
+#define        MAXSWAPDEV      4
+short  buckets[MAXSWAPDEV][NDMAP];
+struct swdevt *swdevt;
+int    colwidth;
+
+extern union {
+        struct  user user;
+        char    upages[UPAGES][NBPG];
+} user;
+#define u       user.user
+
 showswap()
 {
 showswap()
 {
+        register int i, j;
+       register struct proc *pp;
+       register struct text *xp;
        register int row;
        register int row;
-        register int i, j, free;
-#ifdef notdef
-        register struct mapent *me;
+       register int ts;
+       register swblk_t *dp;
 
 
-        free = 0;
-        for (me = (struct mapent *)(swapmap+1);
-            me < (struct mapent *)&swapmap[nswapmap]; me++)
-                free += me->m_size;
-        free /= nswdev;
-        for (i = 0; i < nswdev; i++)
-                for (space = free; space > 0; space -= j) {
-                        j = rmalloc(swapmap, dev));
-                        if (j == 0)
-                                break;
-                }
-#else
-       for (row = 5, i = dmmax; i >= dmmin; i /= 2, row++) {
-               j = 0;
-               while (rmalloc(swapmap, i) != 0)
-                       j++;
-                mvwprintw(wnd, row, 10, "%5d", i);
-                wmove(wnd, row, 15);
-                wclrtoeol(wnd);
-                while (j--)
-                        waddch(wnd, 'X');
-        }
+       if (xtext == 0)
+               return;
+       for (xp = xtext; xp < &xtext[ntext]; xp++) {
+               if (xp->x_iptr == 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 & XPAGI) && xp->x_ptdaddr)
+                       buckets[swatodev(xp->x_ptdaddr)]
+                           [dmtoindex(ctod(ctopt(xp->x_size)))]++;
+       }
+       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
 #endif
+        }
+       (void) swapdisplay(1+row, dmmax, 'X');
 }
 
 }
 
-#ifdef notdef
-up(size)
-        register int size;
+#define        OFFSET  5                       /* left hand column */
+
+swapdisplay(baserow, dmbound, c)
+       int baserow, dmbound;
+       char c;
 {
 {
-        register int i, block;
+       register int i, j, k, row;
+       register short *pb;
+       char buf[10];
 
 
-        i = 0;
-        block = dmmin;
-        while (i < size) {
-                i += block;
-                if (block < dmmax)
-                        block *= 2;
-        }
-        return (i);
+       for (row = baserow, i = dmmin; i <= dmbound; i *= 2, row++) {
+               for (j = 0; j < nswdev; j++) {
+                       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;
+               }
+       }
+       return (row);
 }
 }
-#endif
 
 
-/*
- * 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);
-                }
-        }
-        return (0);
+       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++;
+               }
+       }
 }
 
 }
 
-/*
- * 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;
-                        }
-                }
-                goto done;
+       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("/vmunix", nlst);
+               if (nlst[X_PROC].n_type == 0) {
+                       error("namelist on /vmunix failed");
+                       return(0);
+               }
+       }
+        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 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 (procp == NULL) {
+                procp = getw(nlst[X_PROC].n_value);
+                nproc = getw(nlst[X_NPROC].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--;
-#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 (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;
-        }
-done:
-        return;
-badrmfree:
-        ;
-#ifdef notdef
-        printf("bad rmfree\n");
+#ifdef tahoe
+char   *devnames[] = { "ud", "vd", "xp", "cy", "sw" };
 #endif
 #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, '|');
+       }
+       return (row);
 }
 }