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