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