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