1/***********************************************************************
2*                                                                      *
3*               This software is part of the ast package               *
4*          Copyright (c) 1985-2011 AT&T Intellectual Property          *
5*                      and is licensed under the                       *
6*                 Eclipse Public License, Version 1.0                  *
7*                    by AT&T Intellectual Property                     *
8*                                                                      *
9*                A copy of the License is available at                 *
10*          http://www.eclipse.org/org/documents/epl-v10.html           *
11*         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
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
24void _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
35static int	Trfile = -1;
36static char	Trbuf[128];
37
38#if __STD_C
39static char* trstrcpy(char* to, const char* from, int endc)
40#else
41static char* trstrcpy(to, from, endc)
42char*		to;
43const char*	from;
44int		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
58static char* tritoa(Vmulong_t v, int type)
59#else
60static char* tritoa(v, type)
61Vmulong_t	v;	/* value to convert					*/
62int		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
100static void trtrace(Vmalloc_t* vm,
101		    Vmuchar_t* oldaddr, Vmuchar_t* newaddr, size_t size, size_t align )
102#else
103static void trtrace(vm, oldaddr, newaddr, size, align)
104Vmalloc_t*	vm;		/* region call was made from	*/
105Vmuchar_t*	oldaddr;	/* old data address		*/
106Vmuchar_t*	newaddr;	/* new data address		*/
107size_t		size;		/* size of piece		*/
108size_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 char*	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 1
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 __STD_C
196void _vmmessage(const char* s1, long n1, const char* s2, long n2)
197#else
198void _vmmessage(s1, n1, s2, n2)
199const char*	s1;
200long		n1;
201const char*	s2;
202long		n2;
203#endif
204{
205	char		buf[1024], *bufp;
206
207	bufp = buf;
208	bufp = trstrcpy(bufp, "vmalloc", ':');
209	if (s1)
210	{
211		bufp = trstrcpy(bufp, s1, ':');
212		if (n1)
213			bufp = trstrcpy(bufp, tritoa(n1, 1), ':');
214	}
215	if (s2)
216	{
217		bufp = trstrcpy(bufp, s2, ':');
218		if (n2)
219			bufp = trstrcpy(bufp, tritoa(n2, 0), ':');
220	}
221
222	bufp = trstrcpy(bufp, tritoa((long)getpid(), 1), ':');
223
224	*bufp++ = '\n';
225	write(2,buf,(bufp-buf));
226}
227
228#if __STD_C
229int vmtrace(int file)
230#else
231int vmtrace(file)
232int	file;
233#endif
234{
235	int	fd;
236
237	_Vmstrcpy = trstrcpy;
238	_Vmitoa = tritoa;
239	_Vmtrace = trtrace;
240
241	fd = Trfile;
242	Trfile = file;
243	return fd;
244}
245
246#if __STD_C
247int vmtrbusy(Vmalloc_t* vm)
248#else
249int vmtrbusy(vm)
250Vmalloc_t*	vm;
251#endif
252{
253	Seg_t*		seg;
254	Vmdata_t*	vd = vm->data;
255
256	if(Trfile < 0 || !(vd->mode&(VM_MTBEST|VM_MTDEBUG|VM_MTPROFILE)))
257		return -1;
258
259	for(seg = vd->seg; seg; seg = seg->next)
260	{	Block_t		*b, *endb;
261		Vmuchar_t*	data;
262		size_t		s;
263
264		for(b = SEGBLOCK(seg), endb = BLOCK(seg->baddr); b < endb; )
265		{	if(ISJUNK(SIZE(b)) || !ISBUSY(SIZE(b)))
266				continue;
267
268			data = DATA(b);
269			if(vd->mode&VM_MTDEBUG)
270			{	data = DB2DEBUG(data);
271				s = DBSIZE(data);
272			}
273			else if(vd->mode&VM_MTPROFILE)
274				s = PFSIZE(data);
275			else	s = SIZE(b)&~BITS;
276
277			trtrace(vm, (Vmuchar_t*)(-1), data, s, 0);
278
279			b = (Block_t*)((Vmuchar_t*)DATA(b) + (SIZE(b)&~BITS) );
280		}
281	}
282
283	return 0;
284}
285
286#endif
287