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