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