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
key(void * handle,Sffmt_t * fp,const char * arg,char ** ps,Sflong_t * pn)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
visit(Vmalloc_t * vm,void * addr,size_t size,Vmdisc_t * disc,void * handle)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
b_vmstate(int argc,char ** argv,void * context)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