1/*********************************************************************** 2* * 3* This software is part of the ast package * 4* Copyright (c) 1992-2011 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 method=%(method)s flags=%(flags)s 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 25static const char usage[] = 26"[-?\n@(#)$Id: vmstate (AT&T Research) 2010-04-08 $\n]" 27USAGE_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 "[+method?The vmalloc method name.]" 38 "[+flags?The vmalloc method flags.]" 39 "[+size?The total region size.]" 40 "[+segments?The number of segments in the region.]" 41 "[+busy_size?The total busy block size.]" 42 "[+busy_blocks?The number of busy blocks.]" 43 "[+busy_max?The maximum busy block size.]" 44 "[+free_size?The total free block size.]" 45 "[+free_blocks?The number of free blocks.]" 46 "[+free_max?The maximum free block size.]" 47 "}" 48"[+SEE ALSO?\bvmalloc\b(3)]" 49; 50 51#include <cmd.h> 52#include <vmalloc.h> 53 54typedef struct State_s 55{ 56 char* format; 57 Vmalloc_t* vm; 58 Vmstat_t vs; 59 unsigned int regions; 60 Vmalloc_t* region[256]; 61} State_t; 62 63/* 64 * sfkeyprintf() lookup 65 * handle==0 for heading 66 */ 67 68static int 69key(void* handle, Sffmt_t* fp, const char* arg, char** ps, Sflong_t* pn) 70{ 71 register State_t* state = (State_t*)handle; 72 register char* s; 73 74 if (!(s = fp->t_str) || streq(s, "size")) 75 *pn = state->vs.extent; 76 else if (streq(s, "region")) 77 *pn = integralof(state->vm); 78 else if (streq(s, "segments")) 79 *pn = state->vs.n_seg; 80 else if (streq(s, "busy_size")) 81 *pn = state->vs.s_busy; 82 else if (streq(s, "busy_blocks")) 83 *pn = state->vs.n_busy; 84 else if (streq(s, "busy_max")) 85 *pn = state->vs.m_busy; 86 else if (streq(s, "flags")) 87 { 88 *ps = s = fmtbuf(32); 89 if (state->vs.mode & VM_TRUST) 90 s = strcopy(s, "TRUST|"); 91 if (state->vs.mode & VM_TRACE) 92 s = strcopy(s, "TRACE|"); 93 if (state->vs.mode & VM_DBCHECK) 94 s = strcopy(s, "DBCHECK|"); 95 if (state->vs.mode & VM_DBABORT) 96 s = strcopy(s, "DBABORT|"); 97 if (s > *ps) 98 *(s - 1) = 0; 99 else 100 strcpy(s, "0"); 101 } 102 else if (streq(s, "free_size")) 103 *pn = state->vs.s_free; 104 else if (streq(s, "free_blocks")) 105 *pn = state->vs.n_free; 106 else if (streq(s, "free_max")) 107 *pn = state->vs.m_free; 108 else if (streq(s, "format")) 109 *ps = (char*)state->format; 110 else if (streq(s, "method")) 111 { 112 if (state->vs.mode & VM_MTBEST) 113 *ps = "best"; 114 else if (state->vs.mode & VM_MTPOOL) 115 *ps = "pool"; 116 else if (state->vs.mode & VM_MTLAST) 117 *ps = "last"; 118 else if (state->vs.mode & VM_MTDEBUG) 119 *ps = "debug"; 120 else if (state->vs.mode & VM_MTPROFILE) 121 *ps = "profile"; 122 else 123 *ps = "UNKNOWN"; 124 } 125 else 126 { 127 error(2, "%s: unknown format identifier", s); 128 return 0; 129 } 130 return 1; 131} 132 133static int 134visit(Vmalloc_t* vm, void* addr, size_t size, Vmdisc_t* disc, void* handle) 135{ 136 State_t* state = (State_t*)handle; 137 Vmstat_t vs; 138 139 if (vm != state->vm) 140 { 141 state->vm = vm; 142 if (state->regions < elementsof(state->region)) 143 state->region[state->regions++] = vm; 144 } 145 return 0; 146} 147 148int 149b_vmstate(int argc, char** argv, void* context) 150{ 151 register int i; 152 State_t state; 153 154 memset(&state, 0, sizeof(state)); 155 cmdinit(argc, argv, context, ERROR_CATALOG, 0); 156 for (;;) 157 { 158 switch (optget(argv, usage)) 159 { 160 case 'f': 161 state.format = opt_info.arg; 162 continue; 163 case '?': 164 error(ERROR_USAGE|4, "%s", opt_info.arg); 165 break; 166 case ':': 167 error(2, "%s", opt_info.arg); 168 break; 169 } 170 break; 171 } 172 argv += opt_info.index; 173 if (error_info.errors || *argv) 174 error(ERROR_USAGE|4, "%s", optusage(NiL)); 175 if (!state.format) 176 state.format = FORMAT; 177 178 /* 179 * the walk must do no allocations because it locks the regions 180 */ 181 182 vmwalk(NiL, visit, &state); 183 184 /* 185 * now we can compute and list the state of each region 186 */ 187 188 for (i = 0; i < state.regions; i++) 189 { 190 state.vm = state.region[i]; 191 vmstat(state.vm, &state.vs); 192 sfkeyprintf(sfstdout, &state, state.format, key, NiL); 193 sfprintf(sfstdout, "\n"); 194 } 195 return 0; 196} 197