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