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