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 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 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 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