xref: /titanic_44/usr/src/lib/libast/common/vmalloc/vmprofile.c (revision 3e14f97f673e8a630f076077de35afdd43dc1587)
1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*3e14f97fSRoger A. Faulkner *          Copyright (c) 1985-2010 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6da2e3ebdSchin *                  Common Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10da2e3ebdSchin *            http://www.opensource.org/licenses/cpl1.0.txt             *
11da2e3ebdSchin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12da2e3ebdSchin *                                                                      *
13da2e3ebdSchin *              Information and Software Systems Research               *
14da2e3ebdSchin *                            AT&T Research                             *
15da2e3ebdSchin *                           Florham Park NJ                            *
16da2e3ebdSchin *                                                                      *
17da2e3ebdSchin *                 Glenn Fowler <gsf@research.att.com>                  *
18da2e3ebdSchin *                  David Korn <dgk@research.att.com>                   *
19da2e3ebdSchin *                   Phong Vo <kpv@research.att.com>                    *
20da2e3ebdSchin *                                                                      *
21da2e3ebdSchin ***********************************************************************/
22da2e3ebdSchin #if defined(_UWIN) && defined(_BLD_ast)
23da2e3ebdSchin 
_STUB_vmprofile()24da2e3ebdSchin void _STUB_vmprofile(){}
25da2e3ebdSchin 
26da2e3ebdSchin #else
27da2e3ebdSchin 
28da2e3ebdSchin #include	"vmhdr.h"
29da2e3ebdSchin 
30da2e3ebdSchin /*	Method to profile space usage.
31da2e3ebdSchin **
32da2e3ebdSchin **	Written by Kiem-Phong Vo, kpv@research.att.com, 03/23/94.
33da2e3ebdSchin */
34da2e3ebdSchin 
35da2e3ebdSchin #define PFHASH(pf)	((pf)->data.data.hash)
36da2e3ebdSchin #define PFVM(pf)	((pf)->data.data.vm)
37da2e3ebdSchin #define PFFILE(pf)	((pf)->data.data.fm.file)
38da2e3ebdSchin #define PFLINE(pf)	((pf)->line)
39da2e3ebdSchin #define PFNAME(pf)	((pf)->data.f)
40da2e3ebdSchin #define PFNALLOC(pf)	((pf)->data.data.nalloc)
41da2e3ebdSchin #define PFALLOC(pf)	((pf)->data.data.alloc)
42da2e3ebdSchin #define PFNFREE(pf)	((pf)->data.data.nfree)
43da2e3ebdSchin #define PFFREE(pf)	((pf)->data.data.free)
44da2e3ebdSchin #define PFREGION(pf)	((pf)->data.data.region)
45da2e3ebdSchin #define PFMAX(pf)	((pf)->data.data.fm.max)
46da2e3ebdSchin 
47da2e3ebdSchin typedef struct _pfdata_s	Pfdata_t;
48da2e3ebdSchin struct _pfdata_s
49da2e3ebdSchin {	Vmulong_t	hash;	/* hash value			*/
50da2e3ebdSchin 	union
51da2e3ebdSchin 	{ char*		file;	/* file name			*/
52da2e3ebdSchin 	  Vmulong_t	max;	/* max busy space for region	*/
53da2e3ebdSchin 	} fm;
54da2e3ebdSchin 	Vmalloc_t*	vm;	/* region alloc from 		*/
55da2e3ebdSchin 	Pfobj_t*	region;	/* pointer to region record	*/
56da2e3ebdSchin 	Vmulong_t	nalloc;	/* number of alloc calls	*/
57da2e3ebdSchin 	Vmulong_t	alloc;	/* amount allocated		*/
58da2e3ebdSchin 	Vmulong_t	nfree;	/* number of free calls		*/
59da2e3ebdSchin 	Vmulong_t	free;	/* amount freed			*/
60da2e3ebdSchin };
61da2e3ebdSchin struct _pfobj_s
62da2e3ebdSchin {	Pfobj_t*	next;	/* next in linked list	*/
63da2e3ebdSchin 	int		line;	/* line #, 0 for name holder	*/
64da2e3ebdSchin 	union
65da2e3ebdSchin 	{
66da2e3ebdSchin 	Pfdata_t	data;
67da2e3ebdSchin 	char		f[1];	/* actual file name		*/
68da2e3ebdSchin 	} data;
69da2e3ebdSchin };
70da2e3ebdSchin 
71da2e3ebdSchin static Pfobj_t**	Pftable;	/* hash table		*/
72da2e3ebdSchin #define PFTABLE		1019		/* table size		*/
73da2e3ebdSchin static Vmalloc_t*	Vmpf;		/* heap for our own use	*/
74da2e3ebdSchin 
75da2e3ebdSchin #if __STD_C
pfsearch(Vmalloc_t * vm,const char * file,int line)76da2e3ebdSchin static Pfobj_t* pfsearch(Vmalloc_t* vm, const char* file, int line)
77da2e3ebdSchin #else
78da2e3ebdSchin static Pfobj_t* pfsearch(vm, file, line)
79da2e3ebdSchin Vmalloc_t*	vm;	/* region allocating from			*/
80da2e3ebdSchin const char*	file;	/* the file issuing the allocation request	*/
81da2e3ebdSchin int		line;	/* line number					*/
82da2e3ebdSchin #endif
83da2e3ebdSchin {
84da2e3ebdSchin 	reg Pfobj_t		*pf, *last;
85da2e3ebdSchin 	reg Vmulong_t		h;
86da2e3ebdSchin 	reg int			n;
87da2e3ebdSchin 	reg const char*		cp;
88da2e3ebdSchin 
89da2e3ebdSchin 	if(!Vmpf && !(Vmpf = vmopen(Vmdcheap,Vmpool,0)) )
90da2e3ebdSchin 		return NIL(Pfobj_t*);
91da2e3ebdSchin 
92da2e3ebdSchin 	/* make hash table; PFTABLE'th slot hold regions' records */
93da2e3ebdSchin 	if(!Pftable)
94da2e3ebdSchin 	{	if(!(Pftable = (Pfobj_t**)vmalloc(Vmheap,(PFTABLE+1)*sizeof(Pfobj_t*))) )
95da2e3ebdSchin 			return NIL(Pfobj_t*);
96da2e3ebdSchin 		for(n = PFTABLE; n >= 0; --n)
97da2e3ebdSchin 			Pftable[n] = NIL(Pfobj_t*);
98da2e3ebdSchin 	}
99da2e3ebdSchin 
100da2e3ebdSchin 	/* see if it's there with a combined hash value of vm,file,line */
101da2e3ebdSchin 	h = line + (((Vmulong_t)vm)>>4);
102da2e3ebdSchin 	for(cp = file; *cp; ++cp)
103da2e3ebdSchin 		h += (h<<7) + ((*cp)&0377) + 987654321L;
104da2e3ebdSchin 	n = (int)(h%PFTABLE);
105da2e3ebdSchin 	for(last = NIL(Pfobj_t*), pf = Pftable[n]; pf; last = pf, pf = pf->next)
106da2e3ebdSchin 		if(PFLINE(pf) == line && PFVM(pf) == vm && strcmp(PFFILE(pf),file) == 0)
107da2e3ebdSchin 			break;
108da2e3ebdSchin 
109da2e3ebdSchin 	/* insert if not there yet */
110da2e3ebdSchin 	if(!pf)
111da2e3ebdSchin 	{	reg Pfobj_t*	fn;
112da2e3ebdSchin 		reg Pfobj_t*	pfvm;
113da2e3ebdSchin 		reg Vmulong_t	hn;
114da2e3ebdSchin 
115da2e3ebdSchin 		/* first get/construct the file name slot */
116da2e3ebdSchin 		hn = 0;
117da2e3ebdSchin 		for(cp = file; *cp; ++cp)
118da2e3ebdSchin 			hn += (hn<<7) + ((*cp)&0377) + 987654321L;
119da2e3ebdSchin 		n = (int)(hn%PFTABLE);
120da2e3ebdSchin 		for(fn = Pftable[n]; fn; fn = fn->next)
121da2e3ebdSchin 			if(PFLINE(fn) < 0 && strcmp(PFNAME(fn),file) == 0)
122da2e3ebdSchin 				break;
123da2e3ebdSchin 		if(!fn)
124da2e3ebdSchin 		{	reg size_t	s;
125da2e3ebdSchin 			s = sizeof(Pfobj_t) - sizeof(Pfdata_t) + strlen(file) + 1;
126da2e3ebdSchin 			if(!(fn = (Pfobj_t*)vmalloc(Vmheap,s)) )
127da2e3ebdSchin 				return NIL(Pfobj_t*);
128da2e3ebdSchin 			fn->next = Pftable[n];
129da2e3ebdSchin 			Pftable[n] = fn;
130da2e3ebdSchin 			PFLINE(fn) = -1;
131da2e3ebdSchin 			strcpy(PFNAME(fn),file);
132da2e3ebdSchin 		}
133da2e3ebdSchin 
134da2e3ebdSchin 		/* get region record; note that these are ordered by vm */
135da2e3ebdSchin 		last = NIL(Pfobj_t*);
136da2e3ebdSchin 		for(pfvm = Pftable[PFTABLE]; pfvm; last = pfvm, pfvm = pfvm->next)
137da2e3ebdSchin 			if(vm >= PFVM(pfvm))
138da2e3ebdSchin 				break;
139da2e3ebdSchin 		if(!pfvm || PFVM(pfvm) > vm)
140da2e3ebdSchin 		{	if(!(pfvm = (Pfobj_t*)vmalloc(Vmpf,sizeof(Pfobj_t))) )
141da2e3ebdSchin 				return NIL(Pfobj_t*);
142da2e3ebdSchin 			if(last)
143da2e3ebdSchin 			{	pfvm->next = last->next;
144da2e3ebdSchin 				last->next = pfvm;
145da2e3ebdSchin 			}
146da2e3ebdSchin 			else
147da2e3ebdSchin 			{	pfvm->next = Pftable[PFTABLE];
148da2e3ebdSchin 				Pftable[PFTABLE] = pfvm;
149da2e3ebdSchin 			}
150da2e3ebdSchin 			PFNALLOC(pfvm) = PFALLOC(pfvm) = 0;
151da2e3ebdSchin 			PFNFREE(pfvm) = PFFREE(pfvm) = 0;
152da2e3ebdSchin 			PFMAX(pfvm) = 0;
153da2e3ebdSchin 			PFVM(pfvm) = vm;
154da2e3ebdSchin 			PFLINE(pfvm) = 0;
155da2e3ebdSchin 		}
156da2e3ebdSchin 
157da2e3ebdSchin 		if(!(pf = (Pfobj_t*)vmalloc(Vmpf,sizeof(Pfobj_t))) )
158da2e3ebdSchin 			return NIL(Pfobj_t*);
159da2e3ebdSchin 		n = (int)(h%PFTABLE);
160da2e3ebdSchin 		pf->next = Pftable[n];
161da2e3ebdSchin 		Pftable[n] = pf;
162da2e3ebdSchin 		PFLINE(pf) = line;
163da2e3ebdSchin 		PFFILE(pf) = PFNAME(fn);
164da2e3ebdSchin 		PFREGION(pf) = pfvm;
165da2e3ebdSchin 		PFVM(pf) = vm;
166da2e3ebdSchin 		PFNALLOC(pf) = 0;
167da2e3ebdSchin 		PFALLOC(pf) = 0;
168da2e3ebdSchin 		PFNFREE(pf) = 0;
169da2e3ebdSchin 		PFFREE(pf) = 0;
170da2e3ebdSchin 		PFHASH(pf) = h;
171da2e3ebdSchin 	}
172da2e3ebdSchin 	else if(last)	/* do a move-to-front */
173da2e3ebdSchin 	{	last->next = pf->next;
174da2e3ebdSchin 		pf->next = Pftable[n];
175da2e3ebdSchin 		Pftable[n] = pf;
176da2e3ebdSchin 	}
177da2e3ebdSchin 
178da2e3ebdSchin 	return pf;
179da2e3ebdSchin }
180da2e3ebdSchin 
181da2e3ebdSchin #if __STD_C
pfclose(Vmalloc_t * vm)182da2e3ebdSchin static void pfclose(Vmalloc_t* vm)
183da2e3ebdSchin #else
184da2e3ebdSchin static void pfclose(vm)
185da2e3ebdSchin Vmalloc_t*	vm;
186da2e3ebdSchin #endif
187da2e3ebdSchin {
188da2e3ebdSchin 	reg int		n;
189da2e3ebdSchin 	reg Pfobj_t	*pf, *next, *last;
190da2e3ebdSchin 
191da2e3ebdSchin 	/* free all records related to region vm */
192da2e3ebdSchin 	for(n = PFTABLE; n >= 0; --n)
193da2e3ebdSchin 	{	for(last = NIL(Pfobj_t*), pf = Pftable[n]; pf; )
194da2e3ebdSchin 		{	next = pf->next;
195da2e3ebdSchin 
196da2e3ebdSchin 			if(PFLINE(pf) >= 0 && PFVM(pf) == vm)
197da2e3ebdSchin 			{	if(last)
198da2e3ebdSchin 					last->next = next;
199da2e3ebdSchin 				else	Pftable[n] = next;
200da2e3ebdSchin 				vmfree(Vmpf,pf);
201da2e3ebdSchin 			}
202da2e3ebdSchin 			else	last = pf;
203da2e3ebdSchin 
204da2e3ebdSchin 			pf = next;
205da2e3ebdSchin 		}
206da2e3ebdSchin 	}
207da2e3ebdSchin }
208da2e3ebdSchin 
209da2e3ebdSchin #if __STD_C
pfsetinfo(Vmalloc_t * vm,Vmuchar_t * data,size_t size,const char * file,int line)210da2e3ebdSchin static void pfsetinfo(Vmalloc_t* vm, Vmuchar_t* data, size_t size, const char* file, int line)
211da2e3ebdSchin #else
212da2e3ebdSchin static void pfsetinfo(vm, data, size, file, line)
213da2e3ebdSchin Vmalloc_t*	vm;
214da2e3ebdSchin Vmuchar_t*	data;
215da2e3ebdSchin size_t		size;
216da2e3ebdSchin const char*	file;
217da2e3ebdSchin int		line;
218da2e3ebdSchin #endif
219da2e3ebdSchin {
220da2e3ebdSchin 	reg Pfobj_t*	pf;
221da2e3ebdSchin 	reg Vmulong_t	s;
222da2e3ebdSchin 
223da2e3ebdSchin 	/* let vmclose knows that there are records for region vm */
224da2e3ebdSchin 	_Vmpfclose = pfclose;
225da2e3ebdSchin 
226da2e3ebdSchin 	if(!file || line <= 0)
227da2e3ebdSchin 	{	file = "";
228da2e3ebdSchin 		line = 0;
229da2e3ebdSchin 	}
230da2e3ebdSchin 
231da2e3ebdSchin 	if((pf = pfsearch(vm,file,line)) )
232da2e3ebdSchin 	{	PFALLOC(pf) += size;
233da2e3ebdSchin 		PFNALLOC(pf) += 1;
234da2e3ebdSchin 	}
235da2e3ebdSchin 	PFOBJ(data) = pf;
236da2e3ebdSchin 	PFSIZE(data) = size;
237da2e3ebdSchin 
238da2e3ebdSchin 	if(pf)
239da2e3ebdSchin 	{	/* update region statistics */
240da2e3ebdSchin 		pf = PFREGION(pf);
241da2e3ebdSchin 		PFALLOC(pf) += size;
242da2e3ebdSchin 		PFNALLOC(pf) += 1;
243da2e3ebdSchin 		if((s = PFALLOC(pf) - PFFREE(pf)) > PFMAX(pf) )
244da2e3ebdSchin 			PFMAX(pf) = s;
245da2e3ebdSchin 	}
246da2e3ebdSchin }
247da2e3ebdSchin 
248da2e3ebdSchin /* sort by file names and line numbers */
249da2e3ebdSchin #if __STD_C
pfsort(Pfobj_t * pf)250da2e3ebdSchin static Pfobj_t* pfsort(Pfobj_t* pf)
251da2e3ebdSchin #else
252da2e3ebdSchin static Pfobj_t* pfsort(pf)
253da2e3ebdSchin Pfobj_t*	pf;
254da2e3ebdSchin #endif
255da2e3ebdSchin {
256da2e3ebdSchin 	reg Pfobj_t	*one, *two, *next;
257da2e3ebdSchin 	reg int		cmp;
258da2e3ebdSchin 
259da2e3ebdSchin 	if(!pf->next)
260da2e3ebdSchin 		return pf;
261da2e3ebdSchin 
262da2e3ebdSchin 	/* partition to two equal size lists */
263da2e3ebdSchin 	one = two = NIL(Pfobj_t*);
264da2e3ebdSchin 	while(pf)
265da2e3ebdSchin 	{	next = pf->next;
266da2e3ebdSchin 		pf->next = one;
267da2e3ebdSchin 		one = pf;
268da2e3ebdSchin 
269da2e3ebdSchin 		if((pf = next) )
270da2e3ebdSchin 		{	next = pf->next;
271da2e3ebdSchin 			pf->next = two;
272da2e3ebdSchin 			two = pf;
273da2e3ebdSchin 			pf = next;
274da2e3ebdSchin 		}
275da2e3ebdSchin 	}
276da2e3ebdSchin 
277da2e3ebdSchin 	/* sort and merge the lists */
278da2e3ebdSchin 	one = pfsort(one);
279da2e3ebdSchin 	two = pfsort(two);
280da2e3ebdSchin 	for(pf = next = NIL(Pfobj_t*);; )
281da2e3ebdSchin 	{	/* make sure that the "<>" file comes first */
282da2e3ebdSchin 		if(PFLINE(one) == 0 && PFLINE(two) == 0)
283da2e3ebdSchin 			cmp = PFVM(one) > PFVM(two) ? 1 : -1;
284da2e3ebdSchin 		else if(PFLINE(one) == 0)
285da2e3ebdSchin 			cmp = -1;
286da2e3ebdSchin 		else if(PFLINE(two) == 0)
287da2e3ebdSchin 			cmp = 1;
288da2e3ebdSchin 		else if((cmp = strcmp(PFFILE(one),PFFILE(two))) == 0)
289da2e3ebdSchin 		{	cmp = PFLINE(one) - PFLINE(two);
290da2e3ebdSchin 			if(cmp == 0)
291da2e3ebdSchin 				cmp = PFVM(one) > PFVM(two) ? 1 : -1;
292da2e3ebdSchin 		}
293da2e3ebdSchin 
294da2e3ebdSchin 		if(cmp < 0)
295da2e3ebdSchin 		{	if(!pf)
296da2e3ebdSchin 				pf = one;
297da2e3ebdSchin 			else	next->next = one;
298da2e3ebdSchin 			next = one;
299da2e3ebdSchin 			if(!(one = one->next) )
300da2e3ebdSchin 			{	if(two)
301da2e3ebdSchin 					next->next = two;
302da2e3ebdSchin 				return pf;
303da2e3ebdSchin 			}
304da2e3ebdSchin 		}
305da2e3ebdSchin 		else
306da2e3ebdSchin 		{	if(!pf)
307da2e3ebdSchin 				pf = two;
308da2e3ebdSchin 			else	next->next = two;
309da2e3ebdSchin 			next = two;
310da2e3ebdSchin 			if(!(two = two->next) )
311da2e3ebdSchin 			{	if(one)
312da2e3ebdSchin 					next->next = one;
313da2e3ebdSchin 				return pf;
314da2e3ebdSchin 			}
315da2e3ebdSchin 		}
316da2e3ebdSchin 	}
317da2e3ebdSchin }
318da2e3ebdSchin 
319da2e3ebdSchin #if __STD_C
pfsummary(char * buf,Vmulong_t na,Vmulong_t sa,Vmulong_t nf,Vmulong_t sf,Vmulong_t max,Vmulong_t size)320da2e3ebdSchin static char* pfsummary(char* buf, Vmulong_t na, Vmulong_t sa,
321da2e3ebdSchin 			Vmulong_t nf, Vmulong_t sf, Vmulong_t max, Vmulong_t size)
322da2e3ebdSchin #else
323da2e3ebdSchin static char* pfsummary(buf, na, sa, nf, sf, max, size)
324da2e3ebdSchin char*		buf;
325da2e3ebdSchin Vmulong_t	na;
326da2e3ebdSchin Vmulong_t	sa;
327da2e3ebdSchin Vmulong_t	nf;
328da2e3ebdSchin Vmulong_t	sf;
329da2e3ebdSchin Vmulong_t	max;
330da2e3ebdSchin Vmulong_t	size;
331da2e3ebdSchin #endif
332da2e3ebdSchin {
333da2e3ebdSchin 	buf = (*_Vmstrcpy)(buf,"n_alloc", '=');
334da2e3ebdSchin 	buf = (*_Vmstrcpy)(buf, (*_Vmitoa)(na,-1), ':');
335da2e3ebdSchin 	buf = (*_Vmstrcpy)(buf,"n_free", '=');
336da2e3ebdSchin 	buf = (*_Vmstrcpy)(buf, (*_Vmitoa)(nf,-1), ':');
337da2e3ebdSchin 	buf = (*_Vmstrcpy)(buf,"s_alloc", '=');
338da2e3ebdSchin 	buf = (*_Vmstrcpy)(buf, (*_Vmitoa)(sa,-1), ':');
339da2e3ebdSchin 	buf = (*_Vmstrcpy)(buf,"s_free", '=');
340da2e3ebdSchin 	buf = (*_Vmstrcpy)(buf, (*_Vmitoa)(sf,-1), ':');
341da2e3ebdSchin 	if(max > 0)
342da2e3ebdSchin 	{	buf = (*_Vmstrcpy)(buf,"max_busy", '=');
343da2e3ebdSchin 		buf = (*_Vmstrcpy)(buf, (*_Vmitoa)(max,-1), ':');
344da2e3ebdSchin 		buf = (*_Vmstrcpy)(buf,"extent", '=');
345da2e3ebdSchin 		buf = (*_Vmstrcpy)(buf, (*_Vmitoa)(size,-1), ':');
346da2e3ebdSchin 	}
347da2e3ebdSchin 	*buf++ = '\n';
348da2e3ebdSchin 
349da2e3ebdSchin 	return buf;
350da2e3ebdSchin }
351da2e3ebdSchin 
352da2e3ebdSchin /* print profile data */
353da2e3ebdSchin #if __STD_C
vmprofile(Vmalloc_t * vm,int fd)354da2e3ebdSchin int vmprofile(Vmalloc_t* vm, int fd)
355da2e3ebdSchin #else
356da2e3ebdSchin int vmprofile(vm, fd)
357da2e3ebdSchin Vmalloc_t*	vm;
358da2e3ebdSchin int		fd;
359da2e3ebdSchin #endif
360da2e3ebdSchin {
361da2e3ebdSchin 	reg Pfobj_t	*pf, *list, *next, *last;
362da2e3ebdSchin 	reg int		n;
363da2e3ebdSchin 	reg Vmulong_t	nalloc, alloc, nfree, free;
364da2e3ebdSchin 	reg Seg_t*	seg;
365da2e3ebdSchin 	char		buf[1024], *bufp, *endbuf;
366da2e3ebdSchin #define INITBUF()	(bufp = buf, endbuf = buf+sizeof(buf)-128)
367da2e3ebdSchin #define CHKBUF()	(bufp >= endbuf ? (write(fd,buf,bufp-buf), bufp=buf) : bufp)
368da2e3ebdSchin #define FLSBUF()	(bufp > buf ? write(fd,buf,bufp-buf) : 0)
369da2e3ebdSchin 
370da2e3ebdSchin 	if(fd < 0)
371da2e3ebdSchin 		return -1;
372da2e3ebdSchin 
373da2e3ebdSchin 	/* initialize functions from vmtrace.c that we use below */
374da2e3ebdSchin 	if((n = vmtrace(-1)) >= 0)
375da2e3ebdSchin 		vmtrace(n);
376da2e3ebdSchin 
377da2e3ebdSchin 	alloc = free = nalloc = nfree = 0;
378da2e3ebdSchin 	list = NIL(Pfobj_t*);
379da2e3ebdSchin 	for(n = PFTABLE-1; n >= 0; --n)
380da2e3ebdSchin 	{	for(pf = Pftable[n], last = NIL(Pfobj_t*); pf; )
381da2e3ebdSchin 		{	next = pf->next;
382da2e3ebdSchin 
383da2e3ebdSchin 			if(PFLINE(pf) < 0  || (vm && vm != PFVM(pf)) )
384da2e3ebdSchin 			{	last = pf;
385da2e3ebdSchin 				goto next_pf;
386da2e3ebdSchin 			}
387da2e3ebdSchin 
388da2e3ebdSchin 			/* remove from hash table */
389da2e3ebdSchin 			if(last)
390da2e3ebdSchin 				last->next = next;
391da2e3ebdSchin 			else	Pftable[n] = next;
392da2e3ebdSchin 
393da2e3ebdSchin 			/* put on output list */
394da2e3ebdSchin 			pf->next = list;
395da2e3ebdSchin 			list = pf;
396da2e3ebdSchin 			nalloc += PFNALLOC(pf);
397da2e3ebdSchin 			alloc += PFALLOC(pf);
398da2e3ebdSchin 			nfree += PFNFREE(pf);
399da2e3ebdSchin 			free += PFFREE(pf);
400da2e3ebdSchin 
401da2e3ebdSchin 		next_pf:
402da2e3ebdSchin 			pf = next;
403da2e3ebdSchin 		}
404da2e3ebdSchin 	}
405da2e3ebdSchin 
406da2e3ebdSchin 	INITBUF();
407da2e3ebdSchin 	bufp = (*_Vmstrcpy)(bufp,"ALLOCATION USAGE SUMMARY", ':');
408da2e3ebdSchin 	bufp = pfsummary(bufp,nalloc,alloc,nfree,free,0,0);
409da2e3ebdSchin 
410da2e3ebdSchin 	/* print regions' summary data */
411da2e3ebdSchin 	for(pf = Pftable[PFTABLE]; pf; pf = pf->next)
412da2e3ebdSchin 	{	if(vm && PFVM(pf) != vm)
413da2e3ebdSchin 			continue;
414da2e3ebdSchin 		alloc = 0;
415da2e3ebdSchin 		for(seg = PFVM(pf)->data->seg; seg; seg = seg->next)
416da2e3ebdSchin 			alloc += seg->extent;
417da2e3ebdSchin 		bufp = (*_Vmstrcpy)(bufp,"region", '=');
418da2e3ebdSchin 		bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(PFVM(pf)),0), ':');
419da2e3ebdSchin 		bufp = pfsummary(bufp,PFNALLOC(pf),PFALLOC(pf),
420da2e3ebdSchin 				 PFNFREE(pf),PFFREE(pf),PFMAX(pf),alloc);
421da2e3ebdSchin 	}
422da2e3ebdSchin 
423da2e3ebdSchin 	/* sort then output detailed profile */
424da2e3ebdSchin 	list = pfsort(list);
425da2e3ebdSchin 	for(pf = list; pf; )
426da2e3ebdSchin 	{	/* compute summary for file */
427da2e3ebdSchin 		alloc = free = nalloc = nfree = 0;
428da2e3ebdSchin 		for(last = pf; last; last = last->next)
429da2e3ebdSchin 		{	if(strcmp(PFFILE(last),PFFILE(pf)) != 0)
430da2e3ebdSchin 				break;
431da2e3ebdSchin 			nalloc += PFNALLOC(pf);
432da2e3ebdSchin 			alloc += PFALLOC(last);
433da2e3ebdSchin 			nfree += PFNFREE(last);
434da2e3ebdSchin 			free += PFFREE(last);
435da2e3ebdSchin 		}
436da2e3ebdSchin 		CHKBUF();
437da2e3ebdSchin 		bufp = (*_Vmstrcpy)(bufp,"file",'=');
438da2e3ebdSchin 		bufp = (*_Vmstrcpy)(bufp,PFFILE(pf)[0] ? PFFILE(pf) : "<>" ,':');
439da2e3ebdSchin 		bufp = pfsummary(bufp,nalloc,alloc,nfree,free,0,0);
440da2e3ebdSchin 
441da2e3ebdSchin 		while(pf != last)	/* detailed data */
442da2e3ebdSchin 		{	CHKBUF();
443da2e3ebdSchin 			bufp = (*_Vmstrcpy)(bufp,"\tline",'=');
444da2e3ebdSchin 			bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(PFLINE(pf),-1), ':');
445da2e3ebdSchin 			bufp = (*_Vmstrcpy)(bufp, "region", '=');
446da2e3ebdSchin 			bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(PFVM(pf)),0), ':');
447da2e3ebdSchin 			bufp = pfsummary(bufp,PFNALLOC(pf),PFALLOC(pf),
448da2e3ebdSchin 					 PFNFREE(pf),PFFREE(pf),0,0);
449da2e3ebdSchin 
450da2e3ebdSchin 			/* reinsert into hash table */
451da2e3ebdSchin 			next = pf->next;
452da2e3ebdSchin 			n = (int)(PFHASH(pf)%PFTABLE);
453da2e3ebdSchin 			pf->next = Pftable[n];
454da2e3ebdSchin 			Pftable[n] = pf;
455da2e3ebdSchin 			pf = next;
456da2e3ebdSchin 		}
457da2e3ebdSchin 	}
458da2e3ebdSchin 
459da2e3ebdSchin 	FLSBUF();
460da2e3ebdSchin 	return 0;
461da2e3ebdSchin }
462da2e3ebdSchin 
463da2e3ebdSchin #if __STD_C
pfalloc(Vmalloc_t * vm,size_t size)464da2e3ebdSchin static Void_t* pfalloc(Vmalloc_t* vm, size_t size)
465da2e3ebdSchin #else
466da2e3ebdSchin static Void_t* pfalloc(vm, size)
467da2e3ebdSchin Vmalloc_t*	vm;
468da2e3ebdSchin size_t		size;
469da2e3ebdSchin #endif
470da2e3ebdSchin {
471da2e3ebdSchin 	reg size_t		s;
472da2e3ebdSchin 	reg Void_t*		data;
473da2e3ebdSchin 	reg char*		file;
4747c2fbfb3SApril Chin 	reg int			line, local, inuse;
475da2e3ebdSchin 	reg Void_t*		func;
476da2e3ebdSchin 	reg Vmdata_t*		vd = vm->data;
477da2e3ebdSchin 
478da2e3ebdSchin 	VMFLF(vm,file,line,func);
4797c2fbfb3SApril Chin 	SETINUSE(vd, inuse);
480da2e3ebdSchin 	if(!(local = vd->mode&VM_TRUST) )
481da2e3ebdSchin 	{	GETLOCAL(vd, local);
482da2e3ebdSchin 		if(ISLOCK(vd, local))
4837c2fbfb3SApril Chin 		{	CLRINUSE(vd, inuse);
484da2e3ebdSchin 			return NIL(Void_t*);
4857c2fbfb3SApril Chin 		}
486da2e3ebdSchin 		SETLOCK(vd, local);
487da2e3ebdSchin 	}
488da2e3ebdSchin 
489da2e3ebdSchin 	s = ROUND(size,ALIGN) + PF_EXTRA;
490da2e3ebdSchin 	if(!(data = KPVALLOC(vm,s,(*(Vmbest->allocf))) ) )
491da2e3ebdSchin 		goto done;
492da2e3ebdSchin 
493da2e3ebdSchin 	pfsetinfo(vm,(Vmuchar_t*)data,size,file,line);
494da2e3ebdSchin 
495da2e3ebdSchin 	if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
496da2e3ebdSchin 	{	vm->file = file; vm->line = line; vm->func = func;
497da2e3ebdSchin 		(*_Vmtrace)(vm,NIL(Vmuchar_t*),(Vmuchar_t*)data,size,0);
498da2e3ebdSchin 	}
499da2e3ebdSchin done:
500da2e3ebdSchin 	CLRLOCK(vd, local);
501da2e3ebdSchin 	ANNOUNCE(local, vm, VM_ALLOC, (Void_t*)data, vm->disc);
5027c2fbfb3SApril Chin 	CLRINUSE(vd, inuse);
503da2e3ebdSchin 	return data;
504da2e3ebdSchin }
505da2e3ebdSchin 
506da2e3ebdSchin #if __STD_C
pffree(Vmalloc_t * vm,Void_t * data)507da2e3ebdSchin static int pffree(Vmalloc_t* vm, Void_t* data)
508da2e3ebdSchin #else
509da2e3ebdSchin static int pffree(vm, data)
510da2e3ebdSchin Vmalloc_t*	vm;
511da2e3ebdSchin Void_t*		data;
512da2e3ebdSchin #endif
513da2e3ebdSchin {
514da2e3ebdSchin 	reg Pfobj_t*		pf;
515da2e3ebdSchin 	reg size_t		s;
516da2e3ebdSchin 	reg char*		file;
5177c2fbfb3SApril Chin 	reg int			line, rv, local, inuse;
518da2e3ebdSchin 	reg Void_t*		func;
519da2e3ebdSchin 	reg Vmdata_t*		vd = vm->data;
520da2e3ebdSchin 
521da2e3ebdSchin 	VMFLF(vm,file,line,func);
522da2e3ebdSchin 
523da2e3ebdSchin 	if(!data)
524da2e3ebdSchin 		return 0;
525da2e3ebdSchin 
5267c2fbfb3SApril Chin 	SETINUSE(vd, inuse);
527da2e3ebdSchin 	if(!(local = vd->mode&VM_TRUST) )
528da2e3ebdSchin 	{	GETLOCAL(vd,local);
529da2e3ebdSchin 		if(ISLOCK(vd,local))
5307c2fbfb3SApril Chin 		{	CLRINUSE(vd, inuse);
531da2e3ebdSchin 			return -1;
5327c2fbfb3SApril Chin 		}
533da2e3ebdSchin 		SETLOCK(vd,local);
534da2e3ebdSchin 	}
535da2e3ebdSchin 
536da2e3ebdSchin 	if(KPVADDR(vm,data,Vmbest->addrf) != 0 )
537da2e3ebdSchin 	{	if(vm->disc->exceptf)
538da2e3ebdSchin 			(void)(*vm->disc->exceptf)(vm,VM_BADADDR,data,vm->disc);
539da2e3ebdSchin 		CLRLOCK(vd,0);
5407c2fbfb3SApril Chin 		CLRINUSE(vd, inuse);
541da2e3ebdSchin 		return -1;
542da2e3ebdSchin 	}
543da2e3ebdSchin 
544da2e3ebdSchin 	pf = PFOBJ(data);
545da2e3ebdSchin 	s = PFSIZE(data);
546da2e3ebdSchin 	if(pf)
547da2e3ebdSchin 	{	PFNFREE(pf) += 1;
548da2e3ebdSchin 		PFFREE(pf) += s;
549da2e3ebdSchin 		pf = PFREGION(pf);
550da2e3ebdSchin 		PFNFREE(pf) += 1;
551da2e3ebdSchin 		PFFREE(pf) += s;
552da2e3ebdSchin 	}
553da2e3ebdSchin 
554da2e3ebdSchin 	if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
555da2e3ebdSchin 	{	vm->file = file; vm->line = line; vm->func = func;
556da2e3ebdSchin 		(*_Vmtrace)(vm,(Vmuchar_t*)data,NIL(Vmuchar_t*),s,0);
557da2e3ebdSchin 	}
558da2e3ebdSchin 
559da2e3ebdSchin 	rv = KPVFREE((vm), (Void_t*)data, (*Vmbest->freef));
560da2e3ebdSchin         CLRLOCK(vd,local);
561da2e3ebdSchin         ANNOUNCE(local, vm, VM_FREE, data, vm->disc);
5627c2fbfb3SApril Chin 	CLRINUSE(vd, inuse);
563da2e3ebdSchin 	return rv;
564da2e3ebdSchin }
565da2e3ebdSchin 
566da2e3ebdSchin #if __STD_C
pfresize(Vmalloc_t * vm,Void_t * data,size_t size,int type)567da2e3ebdSchin static Void_t* pfresize(Vmalloc_t* vm, Void_t* data, size_t size, int type)
568da2e3ebdSchin #else
569da2e3ebdSchin static Void_t* pfresize(vm, data, size, type)
570da2e3ebdSchin Vmalloc_t*	vm;
571da2e3ebdSchin Void_t*		data;
572da2e3ebdSchin size_t		size;
573da2e3ebdSchin int		type;
574da2e3ebdSchin #endif
575da2e3ebdSchin {
576da2e3ebdSchin 	reg Pfobj_t*		pf;
577da2e3ebdSchin 	reg size_t		s;
578da2e3ebdSchin 	reg size_t		news;
579da2e3ebdSchin 	reg Void_t*		addr;
580da2e3ebdSchin 	reg char*		file;
5817c2fbfb3SApril Chin 	reg int			line, local, inuse;
582da2e3ebdSchin 	reg Void_t*		func;
583da2e3ebdSchin 	reg size_t		oldsize;
584da2e3ebdSchin 	reg Vmdata_t*		vd = vm->data;
585da2e3ebdSchin 
5867c2fbfb3SApril Chin 	SETINUSE(vd, inuse);
587da2e3ebdSchin 	if(!data)
588da2e3ebdSchin 	{	oldsize = 0;
589da2e3ebdSchin 		addr = pfalloc(vm,size);
590da2e3ebdSchin 		goto done;
591da2e3ebdSchin 	}
592da2e3ebdSchin 	if(size == 0)
593da2e3ebdSchin 	{	(void)pffree(vm,data);
5947c2fbfb3SApril Chin 		CLRINUSE(vd, inuse);
595da2e3ebdSchin 		return NIL(Void_t*);
596da2e3ebdSchin 	}
597da2e3ebdSchin 
598da2e3ebdSchin 	VMFLF(vm,file,line,func);
599da2e3ebdSchin 	if(!(local = vd->mode&VM_TRUST))
600da2e3ebdSchin 	{	GETLOCAL(vd, local);
601da2e3ebdSchin 		if(ISLOCK(vd, local))
6027c2fbfb3SApril Chin 		{	CLRINUSE(vd, inuse);
603da2e3ebdSchin 			return NIL(Void_t*);
6047c2fbfb3SApril Chin 		}
605da2e3ebdSchin 		SETLOCK(vd, local);
606da2e3ebdSchin 	}
607da2e3ebdSchin 
608da2e3ebdSchin 	if(KPVADDR(vm,data,Vmbest->addrf) != 0 )
609da2e3ebdSchin 	{	if(vm->disc->exceptf)
610da2e3ebdSchin 			(void)(*vm->disc->exceptf)(vm,VM_BADADDR,data,vm->disc);
611da2e3ebdSchin 		CLRLOCK(vd, local);
6127c2fbfb3SApril Chin 		CLRINUSE(vd, inuse);
613da2e3ebdSchin 		return NIL(Void_t*);
614da2e3ebdSchin 	}
615da2e3ebdSchin 
616da2e3ebdSchin 	pf = PFOBJ(data);
617da2e3ebdSchin 	s = oldsize = PFSIZE(data);
618da2e3ebdSchin 
619da2e3ebdSchin 	news = ROUND(size,ALIGN) + PF_EXTRA;
620da2e3ebdSchin 	if((addr = KPVRESIZE(vm,data,news,(type&~VM_RSZERO),Vmbest->resizef)) )
621da2e3ebdSchin 	{	if(pf)
622da2e3ebdSchin 		{	PFFREE(pf) += s;
623da2e3ebdSchin 			PFNFREE(pf) += 1;
624da2e3ebdSchin 			pf = PFREGION(pf);
625da2e3ebdSchin 			PFFREE(pf) += s;
626da2e3ebdSchin 			PFNFREE(pf) += 1;
627da2e3ebdSchin 			pfsetinfo(vm,(Vmuchar_t*)addr,size,file,line);
628da2e3ebdSchin 		}
629da2e3ebdSchin 
630da2e3ebdSchin 		if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
631da2e3ebdSchin 		{	vm->file = file; vm->line = line; vm->func = func;
632da2e3ebdSchin 			(*_Vmtrace)(vm,(Vmuchar_t*)data,(Vmuchar_t*)addr,size,0);
633da2e3ebdSchin 		}
634da2e3ebdSchin 	}
635da2e3ebdSchin 	else if(pf)	/* reset old info */
636da2e3ebdSchin 	{	PFALLOC(pf) -= s;
637da2e3ebdSchin 		PFNALLOC(pf) -= 1;
638da2e3ebdSchin 		pf = PFREGION(pf);
639da2e3ebdSchin 		PFALLOC(pf) -= s;
640da2e3ebdSchin 		PFNALLOC(pf) -= 1;
641da2e3ebdSchin 		file = PFFILE(pf);
642da2e3ebdSchin 		line = PFLINE(pf);
643da2e3ebdSchin 		pfsetinfo(vm,(Vmuchar_t*)data,s,file,line);
644da2e3ebdSchin 	}
645da2e3ebdSchin 
646da2e3ebdSchin 	CLRLOCK(vd, local);
647da2e3ebdSchin 	ANNOUNCE(local, vm, VM_RESIZE, (Void_t*)addr, vm->disc);
648da2e3ebdSchin 
649da2e3ebdSchin done:	if(addr && (type&VM_RSZERO) && oldsize < size)
650da2e3ebdSchin 	{	reg Vmuchar_t *d = (Vmuchar_t*)addr+oldsize, *ed = (Vmuchar_t*)addr+size;
651da2e3ebdSchin 		do { *d++ = 0; } while(d < ed);
652da2e3ebdSchin 	}
653da2e3ebdSchin 
6547c2fbfb3SApril Chin 	CLRINUSE(vd, inuse);
655da2e3ebdSchin 	return addr;
656da2e3ebdSchin }
657da2e3ebdSchin 
658da2e3ebdSchin #if __STD_C
pfsize(Vmalloc_t * vm,Void_t * addr)659da2e3ebdSchin static long pfsize(Vmalloc_t* vm, Void_t* addr)
660da2e3ebdSchin #else
661da2e3ebdSchin static long pfsize(vm, addr)
662da2e3ebdSchin Vmalloc_t*	vm;
663da2e3ebdSchin Void_t*		addr;
664da2e3ebdSchin #endif
665da2e3ebdSchin {
666da2e3ebdSchin 	return (*Vmbest->addrf)(vm,addr) != 0 ? -1L : (long)PFSIZE(addr);
667da2e3ebdSchin }
668da2e3ebdSchin 
669da2e3ebdSchin #if __STD_C
pfaddr(Vmalloc_t * vm,Void_t * addr)670da2e3ebdSchin static long pfaddr(Vmalloc_t* vm, Void_t* addr)
671da2e3ebdSchin #else
672da2e3ebdSchin static long pfaddr(vm, addr)
673da2e3ebdSchin Vmalloc_t*	vm;
674da2e3ebdSchin Void_t*		addr;
675da2e3ebdSchin #endif
676da2e3ebdSchin {
677da2e3ebdSchin 	return (*Vmbest->addrf)(vm,addr);
678da2e3ebdSchin }
679da2e3ebdSchin 
680da2e3ebdSchin #if __STD_C
pfcompact(Vmalloc_t * vm)681da2e3ebdSchin static int pfcompact(Vmalloc_t* vm)
682da2e3ebdSchin #else
683da2e3ebdSchin static int pfcompact(vm)
684da2e3ebdSchin Vmalloc_t*	vm;
685da2e3ebdSchin #endif
686da2e3ebdSchin {
687da2e3ebdSchin 	return (*Vmbest->compactf)(vm);
688da2e3ebdSchin }
689da2e3ebdSchin 
690da2e3ebdSchin #if __STD_C
pfalign(Vmalloc_t * vm,size_t size,size_t align)691da2e3ebdSchin static Void_t* pfalign(Vmalloc_t* vm, size_t size, size_t align)
692da2e3ebdSchin #else
693da2e3ebdSchin static Void_t* pfalign(vm, size, align)
694da2e3ebdSchin Vmalloc_t*	vm;
695da2e3ebdSchin size_t		size;
696da2e3ebdSchin size_t		align;
697da2e3ebdSchin #endif
698da2e3ebdSchin {
699da2e3ebdSchin 	reg size_t		s;
700da2e3ebdSchin 	reg Void_t*		data;
701da2e3ebdSchin 	reg char*		file;
7027c2fbfb3SApril Chin 	reg int			line, local, inuse;
703da2e3ebdSchin 	reg Void_t*		func;
704da2e3ebdSchin 	reg Vmdata_t*		vd = vm->data;
705da2e3ebdSchin 
706da2e3ebdSchin 	VMFLF(vm,file,line,func);
707da2e3ebdSchin 
7087c2fbfb3SApril Chin 	SETINUSE(vd, inuse);
709da2e3ebdSchin 	if(!(local = vd->mode&VM_TRUST) )
710da2e3ebdSchin 	{	GETLOCAL(vd,local);
711da2e3ebdSchin 		if(ISLOCK(vd, local))
7127c2fbfb3SApril Chin 		{	CLRINUSE(vd, inuse);
713da2e3ebdSchin 			return NIL(Void_t*);
7147c2fbfb3SApril Chin 		}
715da2e3ebdSchin 		SETLOCK(vd, local);
716da2e3ebdSchin 	}
717da2e3ebdSchin 
718da2e3ebdSchin 	s = (size <= TINYSIZE ? TINYSIZE : ROUND(size,ALIGN)) + PF_EXTRA;
719da2e3ebdSchin 	if(!(data = KPVALIGN(vm,s,align,Vmbest->alignf)) )
720da2e3ebdSchin 		goto done;
721da2e3ebdSchin 
722da2e3ebdSchin 	pfsetinfo(vm,(Vmuchar_t*)data,size,file,line);
723da2e3ebdSchin 
724da2e3ebdSchin 	if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
725da2e3ebdSchin 	{	vm->file = file; vm->line = line; vm->func = func;
726da2e3ebdSchin 		(*_Vmtrace)(vm,NIL(Vmuchar_t*),(Vmuchar_t*)data,size,align);
727da2e3ebdSchin 	}
728da2e3ebdSchin done:
729da2e3ebdSchin 	CLRLOCK(vd, local);
730da2e3ebdSchin 	ANNOUNCE(local, vm, VM_ALLOC, data, vm->disc);
7317c2fbfb3SApril Chin 	CLRINUSE(vd, inuse);
732da2e3ebdSchin 	return data;
733da2e3ebdSchin }
734da2e3ebdSchin 
735da2e3ebdSchin static Vmethod_t _Vmprofile =
736da2e3ebdSchin {
737da2e3ebdSchin 	pfalloc,
738da2e3ebdSchin 	pfresize,
739da2e3ebdSchin 	pffree,
740da2e3ebdSchin 	pfaddr,
741da2e3ebdSchin 	pfsize,
742da2e3ebdSchin 	pfcompact,
743da2e3ebdSchin 	pfalign,
744da2e3ebdSchin 	VM_MTPROFILE
745da2e3ebdSchin };
746da2e3ebdSchin 
747da2e3ebdSchin __DEFINE__(Vmethod_t*,Vmprofile,&_Vmprofile);
748da2e3ebdSchin 
749da2e3ebdSchin #ifdef NoF
750da2e3ebdSchin NoF(vmprofile)
751da2e3ebdSchin #endif
752da2e3ebdSchin 
753da2e3ebdSchin #endif
754