xref: /onnv-gate/usr/src/lib/libast/common/vmalloc/vmprofile.c (revision 12068:08a39a083754)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1985-2010 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
78462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
84887Schin *                                                                      *
94887Schin *                A copy of the License is available at                 *
104887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
114887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
124887Schin *                                                                      *
134887Schin *              Information and Software Systems Research               *
144887Schin *                            AT&T Research                             *
154887Schin *                           Florham Park NJ                            *
164887Schin *                                                                      *
174887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
184887Schin *                  David Korn <dgk@research.att.com>                   *
194887Schin *                   Phong Vo <kpv@research.att.com>                    *
204887Schin *                                                                      *
214887Schin ***********************************************************************/
224887Schin #if defined(_UWIN) && defined(_BLD_ast)
234887Schin 
_STUB_vmprofile()244887Schin void _STUB_vmprofile(){}
254887Schin 
264887Schin #else
274887Schin 
284887Schin #include	"vmhdr.h"
294887Schin 
304887Schin /*	Method to profile space usage.
314887Schin **
324887Schin **	Written by Kiem-Phong Vo, kpv@research.att.com, 03/23/94.
334887Schin */
344887Schin 
354887Schin #define PFHASH(pf)	((pf)->data.data.hash)
364887Schin #define PFVM(pf)	((pf)->data.data.vm)
374887Schin #define PFFILE(pf)	((pf)->data.data.fm.file)
384887Schin #define PFLINE(pf)	((pf)->line)
394887Schin #define PFNAME(pf)	((pf)->data.f)
404887Schin #define PFNALLOC(pf)	((pf)->data.data.nalloc)
414887Schin #define PFALLOC(pf)	((pf)->data.data.alloc)
424887Schin #define PFNFREE(pf)	((pf)->data.data.nfree)
434887Schin #define PFFREE(pf)	((pf)->data.data.free)
444887Schin #define PFREGION(pf)	((pf)->data.data.region)
454887Schin #define PFMAX(pf)	((pf)->data.data.fm.max)
464887Schin 
474887Schin typedef struct _pfdata_s	Pfdata_t;
484887Schin struct _pfdata_s
494887Schin {	Vmulong_t	hash;	/* hash value			*/
504887Schin 	union
514887Schin 	{ char*		file;	/* file name			*/
524887Schin 	  Vmulong_t	max;	/* max busy space for region	*/
534887Schin 	} fm;
544887Schin 	Vmalloc_t*	vm;	/* region alloc from 		*/
554887Schin 	Pfobj_t*	region;	/* pointer to region record	*/
564887Schin 	Vmulong_t	nalloc;	/* number of alloc calls	*/
574887Schin 	Vmulong_t	alloc;	/* amount allocated		*/
584887Schin 	Vmulong_t	nfree;	/* number of free calls		*/
594887Schin 	Vmulong_t	free;	/* amount freed			*/
604887Schin };
614887Schin struct _pfobj_s
624887Schin {	Pfobj_t*	next;	/* next in linked list	*/
634887Schin 	int		line;	/* line #, 0 for name holder	*/
644887Schin 	union
654887Schin 	{
664887Schin 	Pfdata_t	data;
674887Schin 	char		f[1];	/* actual file name		*/
684887Schin 	} data;
694887Schin };
704887Schin 
714887Schin static Pfobj_t**	Pftable;	/* hash table		*/
724887Schin #define PFTABLE		1019		/* table size		*/
734887Schin static Vmalloc_t*	Vmpf;		/* heap for our own use	*/
744887Schin 
754887Schin #if __STD_C
pfsearch(Vmalloc_t * vm,const char * file,int line)764887Schin static Pfobj_t* pfsearch(Vmalloc_t* vm, const char* file, int line)
774887Schin #else
784887Schin static Pfobj_t* pfsearch(vm, file, line)
794887Schin Vmalloc_t*	vm;	/* region allocating from			*/
804887Schin const char*	file;	/* the file issuing the allocation request	*/
814887Schin int		line;	/* line number					*/
824887Schin #endif
834887Schin {
844887Schin 	reg Pfobj_t		*pf, *last;
854887Schin 	reg Vmulong_t		h;
864887Schin 	reg int			n;
874887Schin 	reg const char*		cp;
884887Schin 
894887Schin 	if(!Vmpf && !(Vmpf = vmopen(Vmdcheap,Vmpool,0)) )
904887Schin 		return NIL(Pfobj_t*);
914887Schin 
924887Schin 	/* make hash table; PFTABLE'th slot hold regions' records */
934887Schin 	if(!Pftable)
944887Schin 	{	if(!(Pftable = (Pfobj_t**)vmalloc(Vmheap,(PFTABLE+1)*sizeof(Pfobj_t*))) )
954887Schin 			return NIL(Pfobj_t*);
964887Schin 		for(n = PFTABLE; n >= 0; --n)
974887Schin 			Pftable[n] = NIL(Pfobj_t*);
984887Schin 	}
994887Schin 
1004887Schin 	/* see if it's there with a combined hash value of vm,file,line */
1014887Schin 	h = line + (((Vmulong_t)vm)>>4);
1024887Schin 	for(cp = file; *cp; ++cp)
1034887Schin 		h += (h<<7) + ((*cp)&0377) + 987654321L;
1044887Schin 	n = (int)(h%PFTABLE);
1054887Schin 	for(last = NIL(Pfobj_t*), pf = Pftable[n]; pf; last = pf, pf = pf->next)
1064887Schin 		if(PFLINE(pf) == line && PFVM(pf) == vm && strcmp(PFFILE(pf),file) == 0)
1074887Schin 			break;
1084887Schin 
1094887Schin 	/* insert if not there yet */
1104887Schin 	if(!pf)
1114887Schin 	{	reg Pfobj_t*	fn;
1124887Schin 		reg Pfobj_t*	pfvm;
1134887Schin 		reg Vmulong_t	hn;
1144887Schin 
1154887Schin 		/* first get/construct the file name slot */
1164887Schin 		hn = 0;
1174887Schin 		for(cp = file; *cp; ++cp)
1184887Schin 			hn += (hn<<7) + ((*cp)&0377) + 987654321L;
1194887Schin 		n = (int)(hn%PFTABLE);
1204887Schin 		for(fn = Pftable[n]; fn; fn = fn->next)
1214887Schin 			if(PFLINE(fn) < 0 && strcmp(PFNAME(fn),file) == 0)
1224887Schin 				break;
1234887Schin 		if(!fn)
1244887Schin 		{	reg size_t	s;
1254887Schin 			s = sizeof(Pfobj_t) - sizeof(Pfdata_t) + strlen(file) + 1;
1264887Schin 			if(!(fn = (Pfobj_t*)vmalloc(Vmheap,s)) )
1274887Schin 				return NIL(Pfobj_t*);
1284887Schin 			fn->next = Pftable[n];
1294887Schin 			Pftable[n] = fn;
1304887Schin 			PFLINE(fn) = -1;
1314887Schin 			strcpy(PFNAME(fn),file);
1324887Schin 		}
1334887Schin 
1344887Schin 		/* get region record; note that these are ordered by vm */
1354887Schin 		last = NIL(Pfobj_t*);
1364887Schin 		for(pfvm = Pftable[PFTABLE]; pfvm; last = pfvm, pfvm = pfvm->next)
1374887Schin 			if(vm >= PFVM(pfvm))
1384887Schin 				break;
1394887Schin 		if(!pfvm || PFVM(pfvm) > vm)
1404887Schin 		{	if(!(pfvm = (Pfobj_t*)vmalloc(Vmpf,sizeof(Pfobj_t))) )
1414887Schin 				return NIL(Pfobj_t*);
1424887Schin 			if(last)
1434887Schin 			{	pfvm->next = last->next;
1444887Schin 				last->next = pfvm;
1454887Schin 			}
1464887Schin 			else
1474887Schin 			{	pfvm->next = Pftable[PFTABLE];
1484887Schin 				Pftable[PFTABLE] = pfvm;
1494887Schin 			}
1504887Schin 			PFNALLOC(pfvm) = PFALLOC(pfvm) = 0;
1514887Schin 			PFNFREE(pfvm) = PFFREE(pfvm) = 0;
1524887Schin 			PFMAX(pfvm) = 0;
1534887Schin 			PFVM(pfvm) = vm;
1544887Schin 			PFLINE(pfvm) = 0;
1554887Schin 		}
1564887Schin 
1574887Schin 		if(!(pf = (Pfobj_t*)vmalloc(Vmpf,sizeof(Pfobj_t))) )
1584887Schin 			return NIL(Pfobj_t*);
1594887Schin 		n = (int)(h%PFTABLE);
1604887Schin 		pf->next = Pftable[n];
1614887Schin 		Pftable[n] = pf;
1624887Schin 		PFLINE(pf) = line;
1634887Schin 		PFFILE(pf) = PFNAME(fn);
1644887Schin 		PFREGION(pf) = pfvm;
1654887Schin 		PFVM(pf) = vm;
1664887Schin 		PFNALLOC(pf) = 0;
1674887Schin 		PFALLOC(pf) = 0;
1684887Schin 		PFNFREE(pf) = 0;
1694887Schin 		PFFREE(pf) = 0;
1704887Schin 		PFHASH(pf) = h;
1714887Schin 	}
1724887Schin 	else if(last)	/* do a move-to-front */
1734887Schin 	{	last->next = pf->next;
1744887Schin 		pf->next = Pftable[n];
1754887Schin 		Pftable[n] = pf;
1764887Schin 	}
1774887Schin 
1784887Schin 	return pf;
1794887Schin }
1804887Schin 
1814887Schin #if __STD_C
pfclose(Vmalloc_t * vm)1824887Schin static void pfclose(Vmalloc_t* vm)
1834887Schin #else
1844887Schin static void pfclose(vm)
1854887Schin Vmalloc_t*	vm;
1864887Schin #endif
1874887Schin {
1884887Schin 	reg int		n;
1894887Schin 	reg Pfobj_t	*pf, *next, *last;
1904887Schin 
1914887Schin 	/* free all records related to region vm */
1924887Schin 	for(n = PFTABLE; n >= 0; --n)
1934887Schin 	{	for(last = NIL(Pfobj_t*), pf = Pftable[n]; pf; )
1944887Schin 		{	next = pf->next;
1954887Schin 
1964887Schin 			if(PFLINE(pf) >= 0 && PFVM(pf) == vm)
1974887Schin 			{	if(last)
1984887Schin 					last->next = next;
1994887Schin 				else	Pftable[n] = next;
2004887Schin 				vmfree(Vmpf,pf);
2014887Schin 			}
2024887Schin 			else	last = pf;
2034887Schin 
2044887Schin 			pf = next;
2054887Schin 		}
2064887Schin 	}
2074887Schin }
2084887Schin 
2094887Schin #if __STD_C
pfsetinfo(Vmalloc_t * vm,Vmuchar_t * data,size_t size,const char * file,int line)2104887Schin static void pfsetinfo(Vmalloc_t* vm, Vmuchar_t* data, size_t size, const char* file, int line)
2114887Schin #else
2124887Schin static void pfsetinfo(vm, data, size, file, line)
2134887Schin Vmalloc_t*	vm;
2144887Schin Vmuchar_t*	data;
2154887Schin size_t		size;
2164887Schin const char*	file;
2174887Schin int		line;
2184887Schin #endif
2194887Schin {
2204887Schin 	reg Pfobj_t*	pf;
2214887Schin 	reg Vmulong_t	s;
2224887Schin 
2234887Schin 	/* let vmclose knows that there are records for region vm */
2244887Schin 	_Vmpfclose = pfclose;
2254887Schin 
2264887Schin 	if(!file || line <= 0)
2274887Schin 	{	file = "";
2284887Schin 		line = 0;
2294887Schin 	}
2304887Schin 
2314887Schin 	if((pf = pfsearch(vm,file,line)) )
2324887Schin 	{	PFALLOC(pf) += size;
2334887Schin 		PFNALLOC(pf) += 1;
2344887Schin 	}
2354887Schin 	PFOBJ(data) = pf;
2364887Schin 	PFSIZE(data) = size;
2374887Schin 
2384887Schin 	if(pf)
2394887Schin 	{	/* update region statistics */
2404887Schin 		pf = PFREGION(pf);
2414887Schin 		PFALLOC(pf) += size;
2424887Schin 		PFNALLOC(pf) += 1;
2434887Schin 		if((s = PFALLOC(pf) - PFFREE(pf)) > PFMAX(pf) )
2444887Schin 			PFMAX(pf) = s;
2454887Schin 	}
2464887Schin }
2474887Schin 
2484887Schin /* sort by file names and line numbers */
2494887Schin #if __STD_C
pfsort(Pfobj_t * pf)2504887Schin static Pfobj_t* pfsort(Pfobj_t* pf)
2514887Schin #else
2524887Schin static Pfobj_t* pfsort(pf)
2534887Schin Pfobj_t*	pf;
2544887Schin #endif
2554887Schin {
2564887Schin 	reg Pfobj_t	*one, *two, *next;
2574887Schin 	reg int		cmp;
2584887Schin 
2594887Schin 	if(!pf->next)
2604887Schin 		return pf;
2614887Schin 
2624887Schin 	/* partition to two equal size lists */
2634887Schin 	one = two = NIL(Pfobj_t*);
2644887Schin 	while(pf)
2654887Schin 	{	next = pf->next;
2664887Schin 		pf->next = one;
2674887Schin 		one = pf;
2684887Schin 
2694887Schin 		if((pf = next) )
2704887Schin 		{	next = pf->next;
2714887Schin 			pf->next = two;
2724887Schin 			two = pf;
2734887Schin 			pf = next;
2744887Schin 		}
2754887Schin 	}
2764887Schin 
2774887Schin 	/* sort and merge the lists */
2784887Schin 	one = pfsort(one);
2794887Schin 	two = pfsort(two);
2804887Schin 	for(pf = next = NIL(Pfobj_t*);; )
2814887Schin 	{	/* make sure that the "<>" file comes first */
2824887Schin 		if(PFLINE(one) == 0 && PFLINE(two) == 0)
2834887Schin 			cmp = PFVM(one) > PFVM(two) ? 1 : -1;
2844887Schin 		else if(PFLINE(one) == 0)
2854887Schin 			cmp = -1;
2864887Schin 		else if(PFLINE(two) == 0)
2874887Schin 			cmp = 1;
2884887Schin 		else if((cmp = strcmp(PFFILE(one),PFFILE(two))) == 0)
2894887Schin 		{	cmp = PFLINE(one) - PFLINE(two);
2904887Schin 			if(cmp == 0)
2914887Schin 				cmp = PFVM(one) > PFVM(two) ? 1 : -1;
2924887Schin 		}
2934887Schin 
2944887Schin 		if(cmp < 0)
2954887Schin 		{	if(!pf)
2964887Schin 				pf = one;
2974887Schin 			else	next->next = one;
2984887Schin 			next = one;
2994887Schin 			if(!(one = one->next) )
3004887Schin 			{	if(two)
3014887Schin 					next->next = two;
3024887Schin 				return pf;
3034887Schin 			}
3044887Schin 		}
3054887Schin 		else
3064887Schin 		{	if(!pf)
3074887Schin 				pf = two;
3084887Schin 			else	next->next = two;
3094887Schin 			next = two;
3104887Schin 			if(!(two = two->next) )
3114887Schin 			{	if(one)
3124887Schin 					next->next = one;
3134887Schin 				return pf;
3144887Schin 			}
3154887Schin 		}
3164887Schin 	}
3174887Schin }
3184887Schin 
3194887Schin #if __STD_C
pfsummary(char * buf,Vmulong_t na,Vmulong_t sa,Vmulong_t nf,Vmulong_t sf,Vmulong_t max,Vmulong_t size)3204887Schin static char* pfsummary(char* buf, Vmulong_t na, Vmulong_t sa,
3214887Schin 			Vmulong_t nf, Vmulong_t sf, Vmulong_t max, Vmulong_t size)
3224887Schin #else
3234887Schin static char* pfsummary(buf, na, sa, nf, sf, max, size)
3244887Schin char*		buf;
3254887Schin Vmulong_t	na;
3264887Schin Vmulong_t	sa;
3274887Schin Vmulong_t	nf;
3284887Schin Vmulong_t	sf;
3294887Schin Vmulong_t	max;
3304887Schin Vmulong_t	size;
3314887Schin #endif
3324887Schin {
3334887Schin 	buf = (*_Vmstrcpy)(buf,"n_alloc", '=');
3344887Schin 	buf = (*_Vmstrcpy)(buf, (*_Vmitoa)(na,-1), ':');
3354887Schin 	buf = (*_Vmstrcpy)(buf,"n_free", '=');
3364887Schin 	buf = (*_Vmstrcpy)(buf, (*_Vmitoa)(nf,-1), ':');
3374887Schin 	buf = (*_Vmstrcpy)(buf,"s_alloc", '=');
3384887Schin 	buf = (*_Vmstrcpy)(buf, (*_Vmitoa)(sa,-1), ':');
3394887Schin 	buf = (*_Vmstrcpy)(buf,"s_free", '=');
3404887Schin 	buf = (*_Vmstrcpy)(buf, (*_Vmitoa)(sf,-1), ':');
3414887Schin 	if(max > 0)
3424887Schin 	{	buf = (*_Vmstrcpy)(buf,"max_busy", '=');
3434887Schin 		buf = (*_Vmstrcpy)(buf, (*_Vmitoa)(max,-1), ':');
3444887Schin 		buf = (*_Vmstrcpy)(buf,"extent", '=');
3454887Schin 		buf = (*_Vmstrcpy)(buf, (*_Vmitoa)(size,-1), ':');
3464887Schin 	}
3474887Schin 	*buf++ = '\n';
3484887Schin 
3494887Schin 	return buf;
3504887Schin }
3514887Schin 
3524887Schin /* print profile data */
3534887Schin #if __STD_C
vmprofile(Vmalloc_t * vm,int fd)3544887Schin int vmprofile(Vmalloc_t* vm, int fd)
3554887Schin #else
3564887Schin int vmprofile(vm, fd)
3574887Schin Vmalloc_t*	vm;
3584887Schin int		fd;
3594887Schin #endif
3604887Schin {
3614887Schin 	reg Pfobj_t	*pf, *list, *next, *last;
3624887Schin 	reg int		n;
3634887Schin 	reg Vmulong_t	nalloc, alloc, nfree, free;
3644887Schin 	reg Seg_t*	seg;
3654887Schin 	char		buf[1024], *bufp, *endbuf;
3664887Schin #define INITBUF()	(bufp = buf, endbuf = buf+sizeof(buf)-128)
3674887Schin #define CHKBUF()	(bufp >= endbuf ? (write(fd,buf,bufp-buf), bufp=buf) : bufp)
3684887Schin #define FLSBUF()	(bufp > buf ? write(fd,buf,bufp-buf) : 0)
3694887Schin 
3704887Schin 	if(fd < 0)
3714887Schin 		return -1;
3724887Schin 
3734887Schin 	/* initialize functions from vmtrace.c that we use below */
3744887Schin 	if((n = vmtrace(-1)) >= 0)
3754887Schin 		vmtrace(n);
3764887Schin 
3774887Schin 	alloc = free = nalloc = nfree = 0;
3784887Schin 	list = NIL(Pfobj_t*);
3794887Schin 	for(n = PFTABLE-1; n >= 0; --n)
3804887Schin 	{	for(pf = Pftable[n], last = NIL(Pfobj_t*); pf; )
3814887Schin 		{	next = pf->next;
3824887Schin 
3834887Schin 			if(PFLINE(pf) < 0  || (vm && vm != PFVM(pf)) )
3844887Schin 			{	last = pf;
3854887Schin 				goto next_pf;
3864887Schin 			}
3874887Schin 
3884887Schin 			/* remove from hash table */
3894887Schin 			if(last)
3904887Schin 				last->next = next;
3914887Schin 			else	Pftable[n] = next;
3924887Schin 
3934887Schin 			/* put on output list */
3944887Schin 			pf->next = list;
3954887Schin 			list = pf;
3964887Schin 			nalloc += PFNALLOC(pf);
3974887Schin 			alloc += PFALLOC(pf);
3984887Schin 			nfree += PFNFREE(pf);
3994887Schin 			free += PFFREE(pf);
4004887Schin 
4014887Schin 		next_pf:
4024887Schin 			pf = next;
4034887Schin 		}
4044887Schin 	}
4054887Schin 
4064887Schin 	INITBUF();
4074887Schin 	bufp = (*_Vmstrcpy)(bufp,"ALLOCATION USAGE SUMMARY", ':');
4084887Schin 	bufp = pfsummary(bufp,nalloc,alloc,nfree,free,0,0);
4094887Schin 
4104887Schin 	/* print regions' summary data */
4114887Schin 	for(pf = Pftable[PFTABLE]; pf; pf = pf->next)
4124887Schin 	{	if(vm && PFVM(pf) != vm)
4134887Schin 			continue;
4144887Schin 		alloc = 0;
4154887Schin 		for(seg = PFVM(pf)->data->seg; seg; seg = seg->next)
4164887Schin 			alloc += seg->extent;
4174887Schin 		bufp = (*_Vmstrcpy)(bufp,"region", '=');
4184887Schin 		bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(PFVM(pf)),0), ':');
4194887Schin 		bufp = pfsummary(bufp,PFNALLOC(pf),PFALLOC(pf),
4204887Schin 				 PFNFREE(pf),PFFREE(pf),PFMAX(pf),alloc);
4214887Schin 	}
4224887Schin 
4234887Schin 	/* sort then output detailed profile */
4244887Schin 	list = pfsort(list);
4254887Schin 	for(pf = list; pf; )
4264887Schin 	{	/* compute summary for file */
4274887Schin 		alloc = free = nalloc = nfree = 0;
4284887Schin 		for(last = pf; last; last = last->next)
4294887Schin 		{	if(strcmp(PFFILE(last),PFFILE(pf)) != 0)
4304887Schin 				break;
4314887Schin 			nalloc += PFNALLOC(pf);
4324887Schin 			alloc += PFALLOC(last);
4334887Schin 			nfree += PFNFREE(last);
4344887Schin 			free += PFFREE(last);
4354887Schin 		}
4364887Schin 		CHKBUF();
4374887Schin 		bufp = (*_Vmstrcpy)(bufp,"file",'=');
4384887Schin 		bufp = (*_Vmstrcpy)(bufp,PFFILE(pf)[0] ? PFFILE(pf) : "<>" ,':');
4394887Schin 		bufp = pfsummary(bufp,nalloc,alloc,nfree,free,0,0);
4404887Schin 
4414887Schin 		while(pf != last)	/* detailed data */
4424887Schin 		{	CHKBUF();
4434887Schin 			bufp = (*_Vmstrcpy)(bufp,"\tline",'=');
4444887Schin 			bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(PFLINE(pf),-1), ':');
4454887Schin 			bufp = (*_Vmstrcpy)(bufp, "region", '=');
4464887Schin 			bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(PFVM(pf)),0), ':');
4474887Schin 			bufp = pfsummary(bufp,PFNALLOC(pf),PFALLOC(pf),
4484887Schin 					 PFNFREE(pf),PFFREE(pf),0,0);
4494887Schin 
4504887Schin 			/* reinsert into hash table */
4514887Schin 			next = pf->next;
4524887Schin 			n = (int)(PFHASH(pf)%PFTABLE);
4534887Schin 			pf->next = Pftable[n];
4544887Schin 			Pftable[n] = pf;
4554887Schin 			pf = next;
4564887Schin 		}
4574887Schin 	}
4584887Schin 
4594887Schin 	FLSBUF();
4604887Schin 	return 0;
4614887Schin }
4624887Schin 
4634887Schin #if __STD_C
pfalloc(Vmalloc_t * vm,size_t size)4644887Schin static Void_t* pfalloc(Vmalloc_t* vm, size_t size)
4654887Schin #else
4664887Schin static Void_t* pfalloc(vm, size)
4674887Schin Vmalloc_t*	vm;
4684887Schin size_t		size;
4694887Schin #endif
4704887Schin {
4714887Schin 	reg size_t		s;
4724887Schin 	reg Void_t*		data;
4734887Schin 	reg char*		file;
4748462SApril.Chin@Sun.COM 	reg int			line, local, inuse;
4754887Schin 	reg Void_t*		func;
4764887Schin 	reg Vmdata_t*		vd = vm->data;
4774887Schin 
4784887Schin 	VMFLF(vm,file,line,func);
4798462SApril.Chin@Sun.COM 	SETINUSE(vd, inuse);
4804887Schin 	if(!(local = vd->mode&VM_TRUST) )
4814887Schin 	{	GETLOCAL(vd, local);
4824887Schin 		if(ISLOCK(vd, local))
4838462SApril.Chin@Sun.COM 		{	CLRINUSE(vd, inuse);
4844887Schin 			return NIL(Void_t*);
4858462SApril.Chin@Sun.COM 		}
4864887Schin 		SETLOCK(vd, local);
4874887Schin 	}
4884887Schin 
4894887Schin 	s = ROUND(size,ALIGN) + PF_EXTRA;
4904887Schin 	if(!(data = KPVALLOC(vm,s,(*(Vmbest->allocf))) ) )
4914887Schin 		goto done;
4924887Schin 
4934887Schin 	pfsetinfo(vm,(Vmuchar_t*)data,size,file,line);
4944887Schin 
4954887Schin 	if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
4964887Schin 	{	vm->file = file; vm->line = line; vm->func = func;
4974887Schin 		(*_Vmtrace)(vm,NIL(Vmuchar_t*),(Vmuchar_t*)data,size,0);
4984887Schin 	}
4994887Schin done:
5004887Schin 	CLRLOCK(vd, local);
5014887Schin 	ANNOUNCE(local, vm, VM_ALLOC, (Void_t*)data, vm->disc);
5028462SApril.Chin@Sun.COM 	CLRINUSE(vd, inuse);
5034887Schin 	return data;
5044887Schin }
5054887Schin 
5064887Schin #if __STD_C
pffree(Vmalloc_t * vm,Void_t * data)5074887Schin static int pffree(Vmalloc_t* vm, Void_t* data)
5084887Schin #else
5094887Schin static int pffree(vm, data)
5104887Schin Vmalloc_t*	vm;
5114887Schin Void_t*		data;
5124887Schin #endif
5134887Schin {
5144887Schin 	reg Pfobj_t*		pf;
5154887Schin 	reg size_t		s;
5164887Schin 	reg char*		file;
5178462SApril.Chin@Sun.COM 	reg int			line, rv, local, inuse;
5184887Schin 	reg Void_t*		func;
5194887Schin 	reg Vmdata_t*		vd = vm->data;
5204887Schin 
5214887Schin 	VMFLF(vm,file,line,func);
5224887Schin 
5234887Schin 	if(!data)
5244887Schin 		return 0;
5254887Schin 
5268462SApril.Chin@Sun.COM 	SETINUSE(vd, inuse);
5274887Schin 	if(!(local = vd->mode&VM_TRUST) )
5284887Schin 	{	GETLOCAL(vd,local);
5294887Schin 		if(ISLOCK(vd,local))
5308462SApril.Chin@Sun.COM 		{	CLRINUSE(vd, inuse);
5314887Schin 			return -1;
5328462SApril.Chin@Sun.COM 		}
5334887Schin 		SETLOCK(vd,local);
5344887Schin 	}
5354887Schin 
5364887Schin 	if(KPVADDR(vm,data,Vmbest->addrf) != 0 )
5374887Schin 	{	if(vm->disc->exceptf)
5384887Schin 			(void)(*vm->disc->exceptf)(vm,VM_BADADDR,data,vm->disc);
5394887Schin 		CLRLOCK(vd,0);
5408462SApril.Chin@Sun.COM 		CLRINUSE(vd, inuse);
5414887Schin 		return -1;
5424887Schin 	}
5434887Schin 
5444887Schin 	pf = PFOBJ(data);
5454887Schin 	s = PFSIZE(data);
5464887Schin 	if(pf)
5474887Schin 	{	PFNFREE(pf) += 1;
5484887Schin 		PFFREE(pf) += s;
5494887Schin 		pf = PFREGION(pf);
5504887Schin 		PFNFREE(pf) += 1;
5514887Schin 		PFFREE(pf) += s;
5524887Schin 	}
5534887Schin 
5544887Schin 	if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
5554887Schin 	{	vm->file = file; vm->line = line; vm->func = func;
5564887Schin 		(*_Vmtrace)(vm,(Vmuchar_t*)data,NIL(Vmuchar_t*),s,0);
5574887Schin 	}
5584887Schin 
5594887Schin 	rv = KPVFREE((vm), (Void_t*)data, (*Vmbest->freef));
5604887Schin         CLRLOCK(vd,local);
5614887Schin         ANNOUNCE(local, vm, VM_FREE, data, vm->disc);
5628462SApril.Chin@Sun.COM 	CLRINUSE(vd, inuse);
5634887Schin 	return rv;
5644887Schin }
5654887Schin 
5664887Schin #if __STD_C
pfresize(Vmalloc_t * vm,Void_t * data,size_t size,int type)5674887Schin static Void_t* pfresize(Vmalloc_t* vm, Void_t* data, size_t size, int type)
5684887Schin #else
5694887Schin static Void_t* pfresize(vm, data, size, type)
5704887Schin Vmalloc_t*	vm;
5714887Schin Void_t*		data;
5724887Schin size_t		size;
5734887Schin int		type;
5744887Schin #endif
5754887Schin {
5764887Schin 	reg Pfobj_t*		pf;
5774887Schin 	reg size_t		s;
5784887Schin 	reg size_t		news;
5794887Schin 	reg Void_t*		addr;
5804887Schin 	reg char*		file;
5818462SApril.Chin@Sun.COM 	reg int			line, local, inuse;
5824887Schin 	reg Void_t*		func;
5834887Schin 	reg size_t		oldsize;
5844887Schin 	reg Vmdata_t*		vd = vm->data;
5854887Schin 
5868462SApril.Chin@Sun.COM 	SETINUSE(vd, inuse);
5874887Schin 	if(!data)
5884887Schin 	{	oldsize = 0;
5894887Schin 		addr = pfalloc(vm,size);
5904887Schin 		goto done;
5914887Schin 	}
5924887Schin 	if(size == 0)
5934887Schin 	{	(void)pffree(vm,data);
5948462SApril.Chin@Sun.COM 		CLRINUSE(vd, inuse);
5954887Schin 		return NIL(Void_t*);
5964887Schin 	}
5974887Schin 
5984887Schin 	VMFLF(vm,file,line,func);
5994887Schin 	if(!(local = vd->mode&VM_TRUST))
6004887Schin 	{	GETLOCAL(vd, local);
6014887Schin 		if(ISLOCK(vd, local))
6028462SApril.Chin@Sun.COM 		{	CLRINUSE(vd, inuse);
6034887Schin 			return NIL(Void_t*);
6048462SApril.Chin@Sun.COM 		}
6054887Schin 		SETLOCK(vd, local);
6064887Schin 	}
6074887Schin 
6084887Schin 	if(KPVADDR(vm,data,Vmbest->addrf) != 0 )
6094887Schin 	{	if(vm->disc->exceptf)
6104887Schin 			(void)(*vm->disc->exceptf)(vm,VM_BADADDR,data,vm->disc);
6114887Schin 		CLRLOCK(vd, local);
6128462SApril.Chin@Sun.COM 		CLRINUSE(vd, inuse);
6134887Schin 		return NIL(Void_t*);
6144887Schin 	}
6154887Schin 
6164887Schin 	pf = PFOBJ(data);
6174887Schin 	s = oldsize = PFSIZE(data);
6184887Schin 
6194887Schin 	news = ROUND(size,ALIGN) + PF_EXTRA;
6204887Schin 	if((addr = KPVRESIZE(vm,data,news,(type&~VM_RSZERO),Vmbest->resizef)) )
6214887Schin 	{	if(pf)
6224887Schin 		{	PFFREE(pf) += s;
6234887Schin 			PFNFREE(pf) += 1;
6244887Schin 			pf = PFREGION(pf);
6254887Schin 			PFFREE(pf) += s;
6264887Schin 			PFNFREE(pf) += 1;
6274887Schin 			pfsetinfo(vm,(Vmuchar_t*)addr,size,file,line);
6284887Schin 		}
6294887Schin 
6304887Schin 		if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
6314887Schin 		{	vm->file = file; vm->line = line; vm->func = func;
6324887Schin 			(*_Vmtrace)(vm,(Vmuchar_t*)data,(Vmuchar_t*)addr,size,0);
6334887Schin 		}
6344887Schin 	}
6354887Schin 	else if(pf)	/* reset old info */
6364887Schin 	{	PFALLOC(pf) -= s;
6374887Schin 		PFNALLOC(pf) -= 1;
6384887Schin 		pf = PFREGION(pf);
6394887Schin 		PFALLOC(pf) -= s;
6404887Schin 		PFNALLOC(pf) -= 1;
6414887Schin 		file = PFFILE(pf);
6424887Schin 		line = PFLINE(pf);
6434887Schin 		pfsetinfo(vm,(Vmuchar_t*)data,s,file,line);
6444887Schin 	}
6454887Schin 
6464887Schin 	CLRLOCK(vd, local);
6474887Schin 	ANNOUNCE(local, vm, VM_RESIZE, (Void_t*)addr, vm->disc);
6484887Schin 
6494887Schin done:	if(addr && (type&VM_RSZERO) && oldsize < size)
6504887Schin 	{	reg Vmuchar_t *d = (Vmuchar_t*)addr+oldsize, *ed = (Vmuchar_t*)addr+size;
6514887Schin 		do { *d++ = 0; } while(d < ed);
6524887Schin 	}
6534887Schin 
6548462SApril.Chin@Sun.COM 	CLRINUSE(vd, inuse);
6554887Schin 	return addr;
6564887Schin }
6574887Schin 
6584887Schin #if __STD_C
pfsize(Vmalloc_t * vm,Void_t * addr)6594887Schin static long pfsize(Vmalloc_t* vm, Void_t* addr)
6604887Schin #else
6614887Schin static long pfsize(vm, addr)
6624887Schin Vmalloc_t*	vm;
6634887Schin Void_t*		addr;
6644887Schin #endif
6654887Schin {
6664887Schin 	return (*Vmbest->addrf)(vm,addr) != 0 ? -1L : (long)PFSIZE(addr);
6674887Schin }
6684887Schin 
6694887Schin #if __STD_C
pfaddr(Vmalloc_t * vm,Void_t * addr)6704887Schin static long pfaddr(Vmalloc_t* vm, Void_t* addr)
6714887Schin #else
6724887Schin static long pfaddr(vm, addr)
6734887Schin Vmalloc_t*	vm;
6744887Schin Void_t*		addr;
6754887Schin #endif
6764887Schin {
6774887Schin 	return (*Vmbest->addrf)(vm,addr);
6784887Schin }
6794887Schin 
6804887Schin #if __STD_C
pfcompact(Vmalloc_t * vm)6814887Schin static int pfcompact(Vmalloc_t* vm)
6824887Schin #else
6834887Schin static int pfcompact(vm)
6844887Schin Vmalloc_t*	vm;
6854887Schin #endif
6864887Schin {
6874887Schin 	return (*Vmbest->compactf)(vm);
6884887Schin }
6894887Schin 
6904887Schin #if __STD_C
pfalign(Vmalloc_t * vm,size_t size,size_t align)6914887Schin static Void_t* pfalign(Vmalloc_t* vm, size_t size, size_t align)
6924887Schin #else
6934887Schin static Void_t* pfalign(vm, size, align)
6944887Schin Vmalloc_t*	vm;
6954887Schin size_t		size;
6964887Schin size_t		align;
6974887Schin #endif
6984887Schin {
6994887Schin 	reg size_t		s;
7004887Schin 	reg Void_t*		data;
7014887Schin 	reg char*		file;
7028462SApril.Chin@Sun.COM 	reg int			line, local, inuse;
7034887Schin 	reg Void_t*		func;
7044887Schin 	reg Vmdata_t*		vd = vm->data;
7054887Schin 
7064887Schin 	VMFLF(vm,file,line,func);
7074887Schin 
7088462SApril.Chin@Sun.COM 	SETINUSE(vd, inuse);
7094887Schin 	if(!(local = vd->mode&VM_TRUST) )
7104887Schin 	{	GETLOCAL(vd,local);
7114887Schin 		if(ISLOCK(vd, local))
7128462SApril.Chin@Sun.COM 		{	CLRINUSE(vd, inuse);
7134887Schin 			return NIL(Void_t*);
7148462SApril.Chin@Sun.COM 		}
7154887Schin 		SETLOCK(vd, local);
7164887Schin 	}
7174887Schin 
7184887Schin 	s = (size <= TINYSIZE ? TINYSIZE : ROUND(size,ALIGN)) + PF_EXTRA;
7194887Schin 	if(!(data = KPVALIGN(vm,s,align,Vmbest->alignf)) )
7204887Schin 		goto done;
7214887Schin 
7224887Schin 	pfsetinfo(vm,(Vmuchar_t*)data,size,file,line);
7234887Schin 
7244887Schin 	if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
7254887Schin 	{	vm->file = file; vm->line = line; vm->func = func;
7264887Schin 		(*_Vmtrace)(vm,NIL(Vmuchar_t*),(Vmuchar_t*)data,size,align);
7274887Schin 	}
7284887Schin done:
7294887Schin 	CLRLOCK(vd, local);
7304887Schin 	ANNOUNCE(local, vm, VM_ALLOC, data, vm->disc);
7318462SApril.Chin@Sun.COM 	CLRINUSE(vd, inuse);
7324887Schin 	return data;
7334887Schin }
7344887Schin 
7354887Schin static Vmethod_t _Vmprofile =
7364887Schin {
7374887Schin 	pfalloc,
7384887Schin 	pfresize,
7394887Schin 	pffree,
7404887Schin 	pfaddr,
7414887Schin 	pfsize,
7424887Schin 	pfcompact,
7434887Schin 	pfalign,
7444887Schin 	VM_MTPROFILE
7454887Schin };
7464887Schin 
7474887Schin __DEFINE__(Vmethod_t*,Vmprofile,&_Vmprofile);
7484887Schin 
7494887Schin #ifdef NoF
7504887Schin NoF(vmprofile)
7514887Schin #endif
7524887Schin 
7534887Schin #endif
754