xref: /titanic_41/usr/src/lib/libcmd/common/vmstate.c (revision cd3e933325e68e23516a196a8fea7f49b1e497c3)
1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *          Copyright (c) 1992-2010 AT&T Intellectual Property          *
5 *                      and is licensed under the                       *
6 *                  Common Public License, Version 1.0                  *
7 *                    by AT&T Intellectual Property                     *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *            http://www.opensource.org/licenses/cpl1.0.txt             *
11 *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12 *                                                                      *
13 *              Information and Software Systems Research               *
14 *                            AT&T Research                             *
15 *                           Florham Park NJ                            *
16 *                                                                      *
17 *                 Glenn Fowler <gsf@research.att.com>                  *
18 *                  David Korn <dgk@research.att.com>                   *
19 *                                                                      *
20 ***********************************************************************/
21 #pragma prototyped
22 
23 #define FORMAT		"region=%(region)p size=%(size)d segments=%(segments)d busy=(%(busy_size)d,%(busy_blocks)d,%(busy_max)d) free=(%(free_size)d,%(free_blocks)d,%(free_max)d)"
24 
25 static const char usage[] =
26 "[-?\n@(#)$Id: vmstate (AT&T Research) 2010-03-05 $\n]"
27 USAGE_LICENSE
28 "[+NAME?vmstate - list the calling process vmalloc region state]"
29 "[+DESCRIPTION?When invoked as a shell builtin, \bvmstate\b lists the "
30     "calling process \bvmalloc\b(3) state for all regions.]"
31 "[f:format?List the ids specified by \aformat\a. \aformat\a follows "
32     "\bprintf\b(3) conventions, except that \bsfio\b(3) inline ids are used "
33     "instead of arguments: "
34     "%[-+]][\awidth\a[.\aprecis\a[.\abase\a]]]]]](\aid\a)\achar\a. The "
35     "supported \aid\as are:]:[format:=" FORMAT "]"
36     "{"
37         "[+size?The total region size.]"
38         "[+segments?The number of segments in the region.]"
39         "[+busy_size?The total busy block size.]"
40         "[+busy_blocks?The number of busy blocks.]"
41         "[+busy_max?The maximum busy block size.]"
42         "[+free_size?The total free block size.]"
43         "[+free_blocks?The number of free blocks.]"
44         "[+free_max?The maximum free block size.]"
45     "}"
46 "[+SEE ALSO?\bvmalloc\b(3)]"
47 ;
48 
49 #include <cmd.h>
50 #include <vmalloc.h>
51 
52 typedef struct State_s
53 {
54 	char*		format;
55 	Vmalloc_t*	vm;
56 	Vmstat_t	vs;
57 	unsigned int	regions;
58 	Vmalloc_t*	region[256];
59 } State_t;
60 
61 /*
62  * sfkeyprintf() lookup
63  * handle==0 for heading
64  */
65 
66 static int
67 key(void* handle, Sffmt_t* fp, const char* arg, char** ps, Sflong_t* pn)
68 {
69 	register State_t*	state = (State_t*)handle;
70 	register char*		s;
71 
72 	if (!(s = fp->t_str) || streq(s, "size"))
73 		*pn = state->vs.extent;
74 	else if (streq(s, "region"))
75 		*pn = integralof(state->vm);
76 	else if (streq(s, "segments"))
77 		*pn = state->vs.n_seg;
78 	else if (streq(s, "busy_size"))
79 		*pn = state->vs.s_busy;
80 	else if (streq(s, "busy_blocks"))
81 		*pn = state->vs.n_busy;
82 	else if (streq(s, "busy_max"))
83 		*pn = state->vs.m_busy;
84 	else if (streq(s, "free_size"))
85 		*pn = state->vs.s_free;
86 	else if (streq(s, "free_blocks"))
87 		*pn = state->vs.n_free;
88 	else if (streq(s, "free_max"))
89 		*pn = state->vs.m_free;
90 	else if (streq(s, "format"))
91 		*ps = (char*)state->format;
92 	else
93 	{
94 		error(2, "%s: unknown format identifier", s);
95 		return 0;
96 	}
97 	return 1;
98 }
99 
100 static int
101 visit(Vmalloc_t* vm, void* addr, size_t size, Vmdisc_t* disc, void* handle)
102 {
103 	State_t*	state = (State_t*)handle;
104 	Vmstat_t	vs;
105 
106 	if (vm != state->vm)
107 	{
108 		state->vm = vm;
109 		if (state->regions < elementsof(state->region))
110 			state->region[state->regions++] = vm;
111 	}
112 	return 0;
113 }
114 
115 int
116 b_vmstate(int argc, char** argv, void* context)
117 {
118 	register int	i;
119 	State_t		state;
120 
121 	memset(&state, 0, sizeof(state));
122 	cmdinit(argc, argv, context, ERROR_CATALOG, 0);
123 	for (;;)
124 	{
125 		switch (optget(argv, usage))
126 		{
127 		case 'f':
128 			state.format = opt_info.arg;
129 			continue;
130 		case '?':
131 			error(ERROR_USAGE|4, "%s", opt_info.arg);
132 			continue;
133 		case ':':
134 			error(2, "%s", opt_info.arg);
135 			continue;
136 		}
137 		break;
138 	}
139 	argv += opt_info.index;
140 	if (error_info.errors || *argv)
141 		error(ERROR_USAGE|4, "%s", optusage(NiL));
142 	if (!state.format)
143 		state.format = FORMAT;
144 
145 	/*
146 	 * the walk must do no allocations because it locks the regions
147 	 */
148 
149 	vmwalk(NiL, visit, &state);
150 
151 	/*
152 	 * now we can compute and list the state of each region
153 	 */
154 
155 	for (i = 0; i < state.regions; i++)
156 	{
157 		state.vm = state.region[i];
158 		vmstat(state.vm, &state.vs);
159 		sfkeyprintf(sfstdout, &state, state.format, key, NiL);
160 		sfprintf(sfstdout, "\n");
161 	}
162 	return 0;
163 }
164