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