1 /***********************************************************************
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 *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
20 ***********************************************************************/
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)"
25 static const char usage
[] =
26 "[-?\n@(#)$Id: vmstate (AT&T Research) 2010-03-05 $\n]"
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
"]"
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.]"
46 "[+SEE ALSO?\bvmalloc\b(3)]"
52 typedef struct State_s
58 Vmalloc_t
* region
[256];
62 * sfkeyprintf() lookup
63 * handle==0 for heading
67 key(void* handle
, Sffmt_t
* fp
, const char* arg
, char** ps
, Sflong_t
* pn
)
69 register State_t
* state
= (State_t
*)handle
;
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
;
94 error(2, "%s: unknown format identifier", s
);
101 visit(Vmalloc_t
* vm
, void* addr
, size_t size
, Vmdisc_t
* disc
, void* handle
)
103 State_t
* state
= (State_t
*)handle
;
109 if (state
->regions
< elementsof(state
->region
))
110 state
->region
[state
->regions
++] = vm
;
116 b_vmstate(int argc
, char** argv
, void* context
)
121 memset(&state
, 0, sizeof(state
));
122 cmdinit(argc
, argv
, context
, ERROR_CATALOG
, 0);
125 switch (optget(argv
, usage
))
128 state
.format
= opt_info
.arg
;
131 error(ERROR_USAGE
|4, "%s", opt_info
.arg
);
134 error(2, "%s", opt_info
.arg
);
139 argv
+= opt_info
.index
;
140 if (error_info
.errors
|| *argv
)
141 error(ERROR_USAGE
|4, "%s", optusage(NiL
));
143 state
.format
= FORMAT
;
146 * the walk must do no allocations because it locks the regions
149 vmwalk(NiL
, visit
, &state
);
152 * now we can compute and list the state of each region
155 for (i
= 0; i
< state
.regions
; i
++)
157 state
.vm
= state
.region
[i
];
158 vmstat(state
.vm
, &state
.vs
);
159 sfkeyprintf(sfstdout
, &state
, state
.format
, key
, NiL
);
160 sfprintf(sfstdout
, "\n");