GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/systat/pool.c Lines: 0 116 0.0 %
Date: 2016-12-06 Branches: 0 68 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: pool.c,v 1.11 2016/03/12 12:45:27 sthen Exp $	*/
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>
19
#include <sys/signal.h>
20
#include <sys/sysctl.h>
21
#include <sys/pool.h>
22
#include <errno.h>
23
#include <stdlib.h>
24
#include <string.h>
25
#include <limits.h>
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);
34
int pool_keyboard_callback(int);
35
36
/* qsort callbacks */
37
int sort_name_callback(const void *s1, const void *s2);
38
int sort_req_callback(const void *s1, const void *s2);
39
int sort_psize_callback(const void *s1, const void *s2);
40
int sort_npage_callback(const void *s1, const void *s2);
41
42
struct pool_info {
43
	char name[32];
44
	struct kinfo_pool pool;
45
};
46
47
48
int print_all = 0;
49
int num_pools = 0;
50
struct pool_info *pools = NULL;
51
52
53
field_def fields_pool[] = {
54
	{"NAME", 12, 32, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
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
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)
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[] = {
90
	{"name", "name", 'N', sort_name_callback},
91
	{"requests", "requests", 'Q', sort_req_callback},
92
	{"size", "size", 'Z', sort_psize_callback},
93
	{"npages", "npages", 'P', sort_npage_callback},
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,
100
	print_pool, pool_keyboard_callback, pool_order_list, pool_order_list
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
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);
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);
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
190
	mergesort(pools, num_pools, sizeof(struct pool_info), ordering->func);
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) {
222
		struct pool_info *p = reallocarray(pools, np, sizeof(*pools));
223
		if (p == NULL) {
224
			error("realloc: %s", strerror(errno));
225
			return (-1);
226
		}
227
		pools = p;
228
		num_pools = np;
229
	}
230
231
	num_disp = num_pools;
232
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;
238
		size = sizeof(pools[i].pool);
239
		if (sysctl(mib, 4, &pools[i].pool, &size, NULL, 0) < 0) {
240
			memset(&pools[i], 0, sizeof(pools[i]));
241
			num_disp--;
242
			continue;
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) {
247
			snprintf(pools[i].name, size, "#%d#", mib[3]);
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
{
263
	struct pool_info *p;
264
	int i, n, count = 0;
265
266
	if (pools == NULL)
267
		return;
268
269
	for (n = i = 0; i < num_pools; i++) {
270
		p = &pools[i];
271
		if (p->name[0] == 0)
272
			continue;
273
274
		if (!print_all &&
275
		   (p->pool.pr_nget == 0 && p->pool.pr_npagealloc == 0))
276
			continue;
277
278
		if (n++ < dispstart)
279
			continue;
280
		showpool(i);
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();
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);
343
}