Annotation of src/usr.bin/systat/pool.c, Revision 1.11
1.11 ! sthen 1: /* $OpenBSD: pool.c,v 1.10 2015/01/16 00:03:37 deraadt Exp $ */
1.1 canacar 2: /*
3: * Copyright (c) 2008 Can Erkin Acar <canacar@openbsd.org>
4: *
5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
17:
18: #include <sys/types.h>
1.10 deraadt 19: #include <sys/signal.h>
1.1 canacar 20: #include <sys/sysctl.h>
21: #include <sys/pool.h>
22: #include <errno.h>
23: #include <stdlib.h>
1.3 chl 24: #include <string.h>
1.10 deraadt 25: #include <limits.h>
1.1 canacar 26:
27: #include "systat.h"
28:
29: void print_pool(void);
30: int read_pool(void);
31: void sort_pool(void);
32: int select_pool(void);
33: void showpool(int k);
1.8 mpi 34: int pool_keyboard_callback(int);
1.1 canacar 35:
36: /* qsort callbacks */
37: int sort_name_callback(const void *s1, const void *s2);
1.2 canacar 38: int sort_req_callback(const void *s1, const void *s2);
1.4 canacar 39: int sort_psize_callback(const void *s1, const void *s2);
40: int sort_npage_callback(const void *s1, const void *s2);
1.1 canacar 41:
42: struct pool_info {
43: char name[32];
1.7 dlg 44: struct kinfo_pool pool;
1.1 canacar 45: };
46:
47:
1.8 mpi 48: int print_all = 0;
1.1 canacar 49: int num_pools = 0;
50: struct pool_info *pools = NULL;
51:
52:
53: field_def fields_pool[] = {
1.11 ! sthen 54: {"NAME", 12, 32, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
1.1 canacar 55: {"SIZE", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
56: {"REQUESTS", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
57: {"FAIL", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
58: {"INUSE", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
59: {"PGREQ", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
60: {"PGREL", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
61: {"NPAGE", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
62: {"HIWAT", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
63: {"MINPG", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
64: {"MAXPG", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
65: {"IDLE", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}
66: };
67:
68:
1.6 jasper 69: #define FLD_POOL_NAME FIELD_ADDR(fields_pool,0)
70: #define FLD_POOL_SIZE FIELD_ADDR(fields_pool,1)
71: #define FLD_POOL_REQS FIELD_ADDR(fields_pool,2)
72: #define FLD_POOL_FAIL FIELD_ADDR(fields_pool,3)
73: #define FLD_POOL_INUSE FIELD_ADDR(fields_pool,4)
74: #define FLD_POOL_PGREQ FIELD_ADDR(fields_pool,5)
75: #define FLD_POOL_PGREL FIELD_ADDR(fields_pool,6)
76: #define FLD_POOL_NPAGE FIELD_ADDR(fields_pool,7)
77: #define FLD_POOL_HIWAT FIELD_ADDR(fields_pool,8)
78: #define FLD_POOL_MINPG FIELD_ADDR(fields_pool,9)
79: #define FLD_POOL_MAXPG FIELD_ADDR(fields_pool,10)
80: #define FLD_POOL_IDLE FIELD_ADDR(fields_pool,11)
1.1 canacar 81:
82: /* Define views */
83: field_def *view_pool_0[] = {
84: FLD_POOL_NAME, FLD_POOL_SIZE, FLD_POOL_REQS, FLD_POOL_FAIL,
85: FLD_POOL_INUSE, FLD_POOL_PGREQ, FLD_POOL_PGREL, FLD_POOL_NPAGE,
86: FLD_POOL_HIWAT, FLD_POOL_MINPG, FLD_POOL_MAXPG, FLD_POOL_IDLE, NULL
87: };
88:
89: order_type pool_order_list[] = {
1.2 canacar 90: {"name", "name", 'N', sort_name_callback},
91: {"requests", "requests", 'Q', sort_req_callback},
1.4 canacar 92: {"size", "size", 'Z', sort_psize_callback},
93: {"npages", "npages", 'P', sort_npage_callback},
1.1 canacar 94: {NULL, NULL, 0, NULL}
95: };
96:
97: /* Define view managers */
98: struct view_manager pool_mgr = {
99: "Pool", select_pool, read_pool, sort_pool, print_header,
1.8 mpi 100: print_pool, pool_keyboard_callback, pool_order_list, pool_order_list
1.1 canacar 101: };
102:
103: field_view views_pool[] = {
104: {view_pool_0, "pool", '5', &pool_mgr},
105: {NULL, NULL, 0, NULL}
106: };
107:
108:
109: int
110: sort_name_callback(const void *s1, const void *s2)
111: {
112: struct pool_info *p1, *p2;
113: p1 = (struct pool_info *)s1;
114: p2 = (struct pool_info *)s2;
115:
1.2 canacar 116: return strcmp(p1->name, p2->name) * sortdir;
117: }
118:
119: int
120: sort_req_callback(const void *s1, const void *s2)
121: {
122: struct pool_info *p1, *p2;
123: p1 = (struct pool_info *)s1;
124: p2 = (struct pool_info *)s2;
125:
126: if (p1->pool.pr_nget < p2->pool.pr_nget)
127: return sortdir;
128: if (p1->pool.pr_nget > p2->pool.pr_nget)
129: return -sortdir;
130:
131: return sort_name_callback(s1, s2);
1.4 canacar 132: }
133:
134: int
135: sort_npage_callback(const void *s1, const void *s2)
136: {
137: struct pool_info *p1, *p2;
138: p1 = (struct pool_info *)s1;
139: p2 = (struct pool_info *)s2;
140:
141: if (p1->pool.pr_npages < p2->pool.pr_npages)
142: return sortdir;
143: if (p1->pool.pr_npages > p2->pool.pr_npages)
144: return -sortdir;
145:
146: return sort_name_callback(s1, s2);
147: }
148:
149: int
150: sort_psize_callback(const void *s1, const void *s2)
151: {
152: struct pool_info *p1, *p2;
153: size_t ps1, ps2;
154:
155: p1 = (struct pool_info *)s1;
156: p2 = (struct pool_info *)s2;
157:
158: ps1 = (size_t)(p1->pool.pr_nget - p1->pool.pr_nput) *
159: (size_t)p1->pool.pr_size;
160: ps2 = (size_t)(p2->pool.pr_nget - p2->pool.pr_nput) *
161: (size_t)p2->pool.pr_size;
162:
163: if (ps1 < ps2)
164: return sortdir;
165: if (ps1 > ps2)
166: return -sortdir;
167:
168: return sort_npage_callback(s1, s2);
1.1 canacar 169: }
170:
171: void
172: sort_pool(void)
173: {
174: order_type *ordering;
175:
176: if (curr_mgr == NULL)
177: return;
178:
179: ordering = curr_mgr->order_curr;
180:
181: if (ordering == NULL)
182: return;
183: if (ordering->func == NULL)
184: return;
185: if (pools == NULL)
186: return;
187: if (num_pools <= 0)
188: return;
189:
1.2 canacar 190: mergesort(pools, num_pools, sizeof(struct pool_info), ordering->func);
1.1 canacar 191: }
192:
193: int
194: select_pool(void)
195: {
196: num_disp = num_pools;
197: return (0);
198: }
199:
200: int
201: read_pool(void)
202: {
203: int mib[4], np, i;
204: size_t size;
205:
206: mib[0] = CTL_KERN;
207: mib[1] = KERN_POOL;
208: mib[2] = KERN_POOL_NPOOLS;
209: size = sizeof(np);
210:
211: if (sysctl(mib, 3, &np, &size, NULL, 0) < 0) {
212: error("sysctl(npools): %s", strerror(errno));
213: return (-1);
214: }
215:
216: if (np <= 0) {
217: num_pools = 0;
218: return (0);
219: }
220:
221: if (np > num_pools || pools == NULL) {
1.9 doug 222: struct pool_info *p = reallocarray(pools, np, sizeof(*pools));
1.1 canacar 223: if (p == NULL) {
224: error("realloc: %s", strerror(errno));
225: return (-1);
226: }
227: pools = p;
228: num_pools = np;
229: }
230:
1.5 canacar 231: num_disp = num_pools;
232:
1.1 canacar 233: for (i = 0; i < num_pools; i++) {
234: mib[0] = CTL_KERN;
235: mib[1] = KERN_POOL;
236: mib[2] = KERN_POOL_POOL;
237: mib[3] = i + 1;
1.7 dlg 238: size = sizeof(pools[i].pool);
1.1 canacar 239: if (sysctl(mib, 4, &pools[i].pool, &size, NULL, 0) < 0) {
1.5 canacar 240: memset(&pools[i], 0, sizeof(pools[i]));
241: num_disp--;
242: continue;
1.1 canacar 243: }
244: mib[2] = KERN_POOL_NAME;
245: size = sizeof(pools[i].name);
246: if (sysctl(mib, 4, &pools[i].name, &size, NULL, 0) < 0) {
1.5 canacar 247: snprintf(pools[i].name, size, "#%d#", mib[3]);
1.1 canacar 248: }
249: }
250:
251: if (i != num_pools) {
252: memset(pools, 0, sizeof(*pools) * num_pools);
253: return (-1);
254: }
255:
256: return 0;
257: }
258:
259:
260: void
261: print_pool(void)
262: {
1.8 mpi 263: struct pool_info *p;
1.5 canacar 264: int i, n, count = 0;
1.1 canacar 265:
266: if (pools == NULL)
267: return;
268:
1.5 canacar 269: for (n = i = 0; i < num_pools; i++) {
1.8 mpi 270: p = &pools[i];
271: if (p->name[0] == 0)
1.5 canacar 272: continue;
1.8 mpi 273:
274: if (!print_all &&
275: (p->pool.pr_nget == 0 && p->pool.pr_npagealloc == 0))
276: continue;
277:
1.5 canacar 278: if (n++ < dispstart)
279: continue;
280: showpool(i);
1.1 canacar 281: count++;
282: if (maxprint > 0 && count >= maxprint)
283: break;
284: }
285: }
286:
287: int
288: initpool(void)
289: {
290: field_view *v;
291:
292: for (v = views_pool; v->name != NULL; v++)
293: add_view(v);
294:
295: read_pool();
296:
297: return(0);
298: }
299:
300: void
301: showpool(int k)
302: {
303: struct pool_info *p = pools + k;
304:
305: if (k < 0 || k >= num_pools)
306: return;
307:
308: print_fld_str(FLD_POOL_NAME, p->name);
309: print_fld_uint(FLD_POOL_SIZE, p->pool.pr_size);
310:
311: print_fld_size(FLD_POOL_REQS, p->pool.pr_nget);
312: print_fld_size(FLD_POOL_FAIL, p->pool.pr_nfail);
313: print_fld_ssize(FLD_POOL_INUSE, p->pool.pr_nget - p->pool.pr_nput);
314: print_fld_size(FLD_POOL_PGREQ, p->pool.pr_npagealloc);
315: print_fld_size(FLD_POOL_PGREL, p->pool.pr_npagefree);
316:
317: print_fld_size(FLD_POOL_NPAGE, p->pool.pr_npages);
318: print_fld_size(FLD_POOL_HIWAT, p->pool.pr_hiwat);
319: print_fld_size(FLD_POOL_MINPG, p->pool.pr_minpages);
320:
321: if (p->pool.pr_maxpages == UINT_MAX)
322: print_fld_str(FLD_POOL_MAXPG, "inf");
323: else
324: print_fld_size(FLD_POOL_MAXPG, p->pool.pr_maxpages);
325:
326: print_fld_size(FLD_POOL_IDLE, p->pool.pr_nidle);
327:
328: end_line();
1.8 mpi 329: }
330:
331: int
332: pool_keyboard_callback(int ch)
333: {
334: switch (ch) {
335: case 'A':
336: print_all ^= 1;
337: gotsig_alarm = 1;
338: default:
339: return keyboard_callback(ch);
340: };
341:
342: return (1);
1.1 canacar 343: }