xref: /titanic_51/usr/src/lib/libast/common/vmalloc/vmtrace.c (revision 33f2fefd46350ca5992567761c46a5b70f864340)
1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *          Copyright (c) 1985-2008 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 *                   Phong Vo <kpv@research.att.com>                    *
20 *                                                                      *
21 ***********************************************************************/
22 #if defined(_UWIN) && defined(_BLD_ast)
23 
24 void _STUB_vmtrace(){}
25 
26 #else
27 
28 #include	"vmhdr.h"
29 
30 /*	Turn on tracing for regions
31 **
32 **	Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
33 */
34 
35 static int	Trfile = -1;
36 static char	Trbuf[128];
37 
38 #if __STD_C
39 static char* trstrcpy(char* to, const char* from, int endc)
40 #else
41 static char* trstrcpy(to, from, endc)
42 char*		to;
43 const char*	from;
44 int		endc;
45 #endif
46 {	reg int	n;
47 
48 	n = strlen(from);
49 	memcpy(to,from,n);
50 	to += n;
51 	if((*to = endc) )
52 		to += 1;
53 	return to;
54 }
55 
56 /* convert a long value to an ascii representation */
57 #if __STD_C
58 static char* tritoa(Vmulong_t v, int type)
59 #else
60 static char* tritoa(v, type)
61 Vmulong_t	v;	/* value to convert					*/
62 int		type;	/* =0 base-16, >0: unsigned base-10, <0: signed base-10	*/
63 #endif
64 {
65 	char*	s;
66 
67 	s = &Trbuf[sizeof(Trbuf) - 1];
68 	*s-- = '\0';
69 
70 	if(type == 0)		/* base-16 */
71 	{	reg char*	digit = "0123456789abcdef";
72 		do
73 		{	*s-- = digit[v&0xf];
74 			v >>= 4;
75 		} while(v);
76 	}
77 	else if(type > 0)	/* unsigned base-10 */
78 	{	do
79 		{	*s-- = (char)('0' + (v%10));
80 			v /= 10;
81 		} while(v);
82 	}
83 	else			/* signed base-10 */
84 	{	int	sign = ((long)v < 0);
85 		if(sign)
86 			v = (Vmulong_t)(-((long)v));
87 		do
88 		{	*s-- = (char)('0' + (v%10));
89 			v /= 10;
90 		} while(v);
91 		if(sign)
92 			*s-- = '-';
93 	}
94 
95 	return s+1;
96 }
97 
98 /* generate a trace of some call */
99 #if __STD_C
100 static void trtrace(Vmalloc_t* vm,
101 		    Vmuchar_t* oldaddr, Vmuchar_t* newaddr, size_t size, size_t align )
102 #else
103 static void trtrace(vm, oldaddr, newaddr, size, align)
104 Vmalloc_t*	vm;		/* region call was made from	*/
105 Vmuchar_t*	oldaddr;	/* old data address		*/
106 Vmuchar_t*	newaddr;	/* new data address		*/
107 size_t		size;		/* size of piece		*/
108 size_t		align;		/* alignment			*/
109 #endif
110 {
111 	char		buf[1024], *bufp, *endbuf;
112 	Vmdata_t*	vd = vm->data;
113 	const char*	file = 0;
114 	int		line = 0;
115 	const Void_t*	func = 0;
116 	int		comma;
117 	int		n;
118 	int		m;
119 
120 	int		type;
121 #define SLOP	64
122 
123 	if(oldaddr == (Vmuchar_t*)(-1)) /* printing busy blocks */
124 	{	type = 0;
125 		oldaddr = NIL(Vmuchar_t*);
126 	}
127 	else
128 	{	type = vd->mode&VM_METHODS;
129 		VMFLF(vm,file,line,func);
130 	}
131 
132 	if(Trfile < 0)
133 		return;
134 
135 	bufp = buf; endbuf = buf+sizeof(buf);
136 	bufp = trstrcpy(bufp, tritoa(oldaddr ? VLONG(oldaddr) : 0L, 0), ':');
137 	bufp = trstrcpy(bufp, tritoa(newaddr ? VLONG(newaddr) : 0L, 0), ':');
138 	bufp = trstrcpy(bufp, tritoa((Vmulong_t)size, 1), ':');
139 	bufp = trstrcpy(bufp, tritoa((Vmulong_t)align, 1), ':');
140 	bufp = trstrcpy(bufp, tritoa(VLONG(vm), 0), ':');
141 	if(type&VM_MTBEST)
142 		bufp = trstrcpy(bufp, "b", ':');
143 	else if(type&VM_MTLAST)
144 		bufp = trstrcpy(bufp, "l", ':');
145 	else if(type&VM_MTPOOL)
146 		bufp = trstrcpy(bufp, "p", ':');
147 	else if(type&VM_MTPROFILE)
148 		bufp = trstrcpy(bufp, "s", ':');
149 	else if(type&VM_MTDEBUG)
150 		bufp = trstrcpy(bufp, "d", ':');
151 	else	bufp = trstrcpy(bufp, "u", ':');
152 
153 	comma = 0;
154 	if(file && file[0] && line > 0)
155 	{	if((bufp + strlen(file) + SLOP) >= endbuf)
156 		{	char*	f;
157 			for(f = bufp + strlen(file); f > file; --f)
158 				if(f[-1] == '/' || f[-1] == '\\')
159 					break;
160 			file = f;
161 		}
162 
163 		bufp = trstrcpy(bufp, "file", '=');
164 		n = endbuf - bufp - SLOP - 3;
165 		m = strlen(file);
166 		if(m > n)
167 		{	file += (m - n);
168 			bufp = trstrcpy(bufp, "..", '.');
169 		}
170 		bufp = trstrcpy(bufp, file, ',');
171 		bufp = trstrcpy(bufp, "line", '=');
172 		bufp = trstrcpy(bufp, tritoa((Vmulong_t)line,1), 0);
173 		comma = 1;
174 	}
175 	if(func)
176 	{	if(comma)
177 			*bufp++ = ',';
178 		bufp = trstrcpy(bufp, "func", '=');
179 #if _PACKAGE_ast
180 		bufp = trstrcpy(bufp, (const char*)func, 0);
181 #else
182 		bufp = trstrcpy(bufp, tritoa((Vmulong_t)func,0), 0);
183 #endif
184 		comma = 1;
185 	}
186 	if(comma)
187 		*bufp++ = ':';
188 
189 	*bufp++ = '\n';
190 	*bufp = '\0';
191 
192 	write(Trfile,buf,(bufp-buf));
193 }
194 
195 #if DEBUG
196 #if __STD_C
197 void _vmmessage(const char* s1, long n1, const char* s2, long n2)
198 #else
199 void _vmmessage(s1, n1, s2, n2)
200 const char*	s1;
201 long		n1;
202 const char*	s2;
203 long		n2;
204 #endif
205 {
206 	char	buf[1024], *bufp;
207 
208 	bufp = buf;
209 	bufp = trstrcpy(bufp, "vmalloc", ':');
210 	if (s1)
211 	{
212 		bufp = trstrcpy(bufp, s1, ':');
213 		if (n1)
214 			bufp = trstrcpy(bufp, tritoa(n1, 1), ':');
215 	}
216 	if (s2)
217 	{
218 		bufp = trstrcpy(bufp, s2, ':');
219 		if (n2)
220 			bufp = trstrcpy(bufp, tritoa(n2, 0), ':');
221 	}
222 	*bufp++ = '\n';
223 	write(2,buf,(bufp-buf));
224 }
225 #endif
226 
227 #if __STD_C
228 int vmtrace(int file)
229 #else
230 int vmtrace(file)
231 int	file;
232 #endif
233 {
234 	int	fd;
235 
236 	_Vmstrcpy = trstrcpy;
237 	_Vmitoa = tritoa;
238 	_Vmtrace = trtrace;
239 
240 	fd = Trfile;
241 	Trfile = file;
242 	return fd;
243 }
244 
245 #if __STD_C
246 int vmtrbusy(Vmalloc_t* vm)
247 #else
248 int vmtrbusy(vm)
249 Vmalloc_t*	vm;
250 #endif
251 {
252 	Seg_t*		seg;
253 	Vmdata_t*	vd = vm->data;
254 
255 	if(Trfile < 0 || !(vd->mode&(VM_MTBEST|VM_MTDEBUG|VM_MTPROFILE)))
256 		return -1;
257 
258 	for(seg = vd->seg; seg; seg = seg->next)
259 	{	Block_t		*b, *endb;
260 		Vmuchar_t*	data;
261 		size_t		s;
262 
263 		for(b = SEGBLOCK(seg), endb = BLOCK(seg->baddr); b < endb; )
264 		{	if(ISJUNK(SIZE(b)) || !ISBUSY(SIZE(b)))
265 				continue;
266 
267 			data = DATA(b);
268 			if(vd->mode&VM_MTDEBUG)
269 			{	data = DB2DEBUG(data);
270 				s = DBSIZE(data);
271 			}
272 			else if(vd->mode&VM_MTPROFILE)
273 				s = PFSIZE(data);
274 			else	s = SIZE(b)&~BITS;
275 
276 			trtrace(vm, (Vmuchar_t*)(-1), data, s, 0);
277 
278 			b = (Block_t*)((Vmuchar_t*)DATA(b) + (SIZE(b)&~BITS) );
279 		}
280 	}
281 
282 	return 0;
283 }
284 
285 #endif
286