xref: /original-bsd/usr.bin/systat/swap.c (revision 2301fdfb)
1 /*
2  * Copyright (c) 1980 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 static char sccsid[] = "@(#)swap.c	5.4 (Berkeley) 07/20/86";
9 #endif not lint
10 
11 #include "systat.h"
12 #include <sys/dir.h>
13 #include <sys/user.h>
14 #include <sys/proc.h>
15 #include <sys/text.h>
16 #include <sys/conf.h>
17 #include <sys/vmmac.h>
18 #include <machine/pte.h>
19 
20 WINDOW *
21 openswap()
22 {
23 
24 	return (subwin(stdscr, LINES-5-1, 0, 5, 0));
25 }
26 
27 closeswap(w)
28 	WINDOW *w;
29 {
30 
31 	if (w == NULL)
32 		return;
33 	wclear(w);
34 	wrefresh(w);
35 	delwin(w);
36 }
37 
38 int	dmmin;
39 int	dmmax;
40 int	dmtext;
41 int	nswdev;
42 #define	MAXSWAPDEV	4
43 short	buckets[MAXSWAPDEV][NDMAP];
44 struct	swdevt *swdevt;
45 int	colwidth;
46 
47 extern union {
48         struct  user user;
49         char    upages[UPAGES][NBPG];
50 } user;
51 #define u       user.user
52 
53 showswap()
54 {
55         register int i, j;
56 	register struct proc *pp;
57 	register struct text *xp;
58 	register int row;
59 	register int ts;
60 	register swblk_t *dp;
61 
62 	if (xtext == 0)
63 		return;
64 	for (xp = xtext; xp < &xtext[ntext]; xp++) {
65 		if (xp->x_iptr == NULL)
66 			continue;
67 		ts = ctod(xp->x_size);
68 		dp = xp->x_daddr;
69 		for (i = 0; i < ts; i += dmtext) {
70 			j = ts - i;
71 			if (j > dmtext)
72 				j = dmtext;
73 #define	swatodev(addr)	(((addr) / dmmax) % nswdev)
74 			buckets[swatodev(*dp)][dmtoindex(j)]++;
75 			dp++;
76 		}
77 		if ((xp->x_flag & XPAGI) && xp->x_ptdaddr)
78 			buckets[swatodev(xp->x_ptdaddr)]
79 			    [dmtoindex(ctod(ctopt(xp->x_size)))]++;
80 	}
81 	row = swapdisplay(2, dmtext, 'X');
82 	if (kprocp == NULL)
83 		return;
84         for (i = 0, pp = kprocp; i < nproc; i++, pp++) {
85 		if (pp->p_stat == 0 || pp->p_stat == SZOMB)
86 			continue;
87 		if (pp->p_flag & SSYS)
88 			continue;
89 		if (getu(pp) == 0)
90 			continue;
91 		vsacct(&u.u_dmap);
92 		vsacct(&u.u_smap);
93 #ifdef notdef
94 		if ((pp->p_flag & SLOAD) == 0)
95 			vusize(pp);
96 #endif
97         }
98 	(void) swapdisplay(1+row, dmmax, 'X');
99 }
100 
101 #define	OFFSET	5			/* left hand column */
102 
103 swapdisplay(baserow, dmbound, c)
104 	int baserow, dmbound;
105 	char c;
106 {
107 	register int i, j, k, row;
108 	register short *pb;
109 	char buf[10];
110 
111 	for (row = baserow, i = dmmin; i <= dmbound; i *= 2, row++) {
112 		for (j = 0; j < nswdev; j++) {
113 			pb = &buckets[j][row - baserow];
114 			wmove(wnd, row, OFFSET + j * (1 + colwidth));
115 			k = MIN(*pb, colwidth);
116 			if (*pb > colwidth) {
117 				sprintf(buf, " %d", *pb);
118 				k -= strlen(buf);
119 				while (k--)
120 					waddch(wnd, c);
121 				waddstr(wnd, buf);
122 			} else {
123 				while (k--)
124 					waddch(wnd, c);
125 				k = MAX(colwidth - *pb, 0);
126 				while (k--)
127 					waddch(wnd, ' ');
128 			}
129 			*pb = 0;
130 		}
131 	}
132 	return (row);
133 }
134 
135 vsacct(dmp)
136 	register struct dmap *dmp;
137 {
138 	register swblk_t *ip;
139 	register int blk = dmmin, index = 0;
140 
141 	for (ip = dmp->dm_map; dmp->dm_alloc > 0; ip++) {
142 		if (ip - dmp->dm_map >= NDMAP) {
143 			error("vsacct NDMAP");
144 			break;
145 		}
146 		if (*ip == 0)
147 			error("vsacct *ip == 0");
148 		buckets[swatodev(*ip)][index]++;
149 		dmp->dm_alloc -= blk;
150 		if (blk < dmmax) {
151 			blk *= 2;
152 			index++;
153 		}
154 	}
155 }
156 
157 dmtoindex(dm)
158 	int dm;
159 {
160 	register int i, j;
161 
162 	for (j = 0, i = dmmin; i <= dmmax; i *= 2, j++)
163 		if (dm <= i)
164 			return (j);
165 	error("dmtoindex(%d)", dm);
166 	return (NDMAP - 1);
167 }
168 
169 static struct nlist nlst[] = {
170 #define X_PROC          0
171         { "_proc" },
172 #define X_NPROC         1
173         { "_nproc" },
174 #define X_USRPTMAP      2
175         { "_Usrptmap" },
176 #define X_USRPT         3
177         { "_usrpt" },
178 #define X_NSWAP         4
179         { "_nswap" },
180 #define X_DMMIN         5
181         { "_dmmin" },
182 #define X_DMMAX         6
183         { "_dmmax" },
184 #define	X_DMTEXT	7
185 	{ "_dmtext" },
186 #define X_NSWDEV        8
187         { "_nswdev" },
188 #define	X_SWDEVT	9
189 	{ "_swdevt" },
190 #define	X_NTEXT		10
191 	{ "_ntext" },
192 #define	X_TEXT		11
193 	{ "_text" },
194         { "" }
195 };
196 
197 initswap()
198 {
199 
200 	if (nlst[X_PROC].n_type == 0) {
201 		nlist("/vmunix", nlst);
202 		if (nlst[X_PROC].n_type == 0) {
203 			error("namelist on /vmunix failed");
204 			return(0);
205 		}
206 	}
207         if (nswdev == 0) {
208                 dmmin = getw(nlst[X_DMMIN].n_value);
209                 dmmax = getw(nlst[X_DMMAX].n_value);
210                 dmtext = getw(nlst[X_DMTEXT].n_value);
211                 nswdev = getw(nlst[X_NSWDEV].n_value);
212 		if (nswdev > MAXSWAPDEV)
213 			nswdev = MAXSWAPDEV;
214 		swdevt = (struct swdevt *)calloc(nswdev, sizeof (*swdevt));
215 		klseek(kmem, nlst[X_SWDEVT].n_value, L_SET);
216 		read(kmem, swdevt, nswdev * sizeof (struct swdevt));
217 		ntext = getw(nlst[X_NTEXT].n_value);
218 		textp = getw(nlst[X_TEXT].n_value);
219         }
220         if (procp == NULL) {
221                 procp = getw(nlst[X_PROC].n_value);
222                 nproc = getw(nlst[X_NPROC].n_value);
223         }
224 	if (xtext == NULL)
225 		xtext = (struct text *)calloc(ntext, sizeof (struct text));
226 	if (kprocp == NULL)
227                 kprocp = (struct proc *)calloc(nproc, sizeof (struct proc));
228         if (usrpt != NULL)
229                 return(1);
230 	usrpt = (struct pte *)nlst[X_USRPT].n_value;
231 	Usrptma = (struct pte *)nlst[X_USRPTMAP].n_value;
232 	if (pt == NULL)
233 		pt = (struct p_times *)malloc(nproc * sizeof (struct p_times));
234 	return(1);
235 }
236 
237 fetchswap()
238 {
239 
240 	if (nlst[X_PROC].n_type == 0)
241 		return;
242 	if (kprocp == NULL) {
243                 kprocp = (struct proc *)malloc(sizeof (*kprocp) * nproc);
244 		if (kprocp == NULL)
245 			return;
246 	}
247         lseek(kmem, procp, L_SET);
248         if (read(kmem, kprocp, sizeof (struct proc) * nproc) !=
249 	    sizeof (struct proc) * nproc) {
250 		error("couldn't read proc table");
251 		return;
252 	}
253 	if (xtext == NULL) {
254 		xtext = (struct text *)calloc(ntext, sizeof (struct text));
255 		if (xtext == NULL)
256 			return;
257 	}
258 	lseek(kmem, textp, L_SET);
259 	if (read(kmem, xtext, ntext * sizeof (struct text)) !=
260 	    sizeof (struct text) * ntext)
261 		error("couldn't read text table");
262 }
263 
264 #ifdef vax
265 char	*devnames[] =
266      { "hp", "ht", "up", "rk", "sw", "tm", "ts", "mt", "tu", "ra", "ut",
267        "rb", "rx", "rl" };
268 #endif
269 #ifdef tahoe
270 char	*devnames[] = { "ud", "vd", "xp", "cy", "sw" };
271 #endif
272 
273 labelswap()
274 {
275 	register int row;
276 
277 	if (nswdev == 0) {
278 		error("Don't know how many swap devices.\n");
279 		return;
280 	}
281 	colwidth = (COLS - OFFSET - (nswdev - 1)) / nswdev;
282 	row = swaplabel(0, dmtext, 1);
283 	(void) swaplabel(row, dmmax, 0);
284 }
285 
286 swaplabel(row, dmbound, donames)
287 	register int row;
288 	int dmbound, donames;
289 {
290 	register int i, j;
291 
292 	for (i = 0; i < nswdev; i++) {
293 		if (donames)
294 			mvwprintw(wnd,
295 			    row, OFFSET + i*(1 + colwidth) + (colwidth - 3)/2,
296 			    "%s%d", devnames[major(swdevt[i].sw_dev)],
297 			        minor(swdevt[i].sw_dev) >> 3);
298 		for (j = 0; j + 5 < colwidth; j += 5)
299 			mvwprintw(wnd, row + donames,
300 			    OFFSET + i*(1 + colwidth) + j, "/%-2d  ", j);
301 	}
302 	row += 1 + donames;
303 	for (j = 0, i = dmmin; i <= dmbound; i *= 2, j++, row++) {
304 		int k;
305 
306 		mvwprintw(wnd, row, 0, "%4d|", i);
307 		for (k = 1; k < nswdev; k++)
308 			mvwaddch(wnd, row, OFFSET + k*(1 + colwidth) - 1, '|');
309 	}
310 	return (row);
311 }
312