1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
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,const char * file,int line)76 static Pfobj_t* pfsearch(Vmalloc_t* vm, const char* file, int line)
77 #else
78 static Pfobj_t* pfsearch(vm, file, line)
79 Vmalloc_t* vm; /* region allocating from */
80 const 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 const 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,const char * file,int line)210 static void pfsetinfo(Vmalloc_t* vm, Vmuchar_t* data, size_t size, const 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 const 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) += 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) += 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 += 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)464 static Void_t* pfalloc(Vmalloc_t* vm, size_t size)
465 #else
466 static Void_t* pfalloc(vm, size)
467 Vmalloc_t* vm;
468 size_t size;
469 #endif
470 {
471 reg size_t s;
472 reg Void_t* data;
473 reg char* file;
474 reg int line, local, inuse;
475 reg Void_t* func;
476 reg Vmdata_t* vd = vm->data;
477
478 VMFLF(vm,file,line,func);
479 SETINUSE(vd, inuse);
480 if(!(local = vd->mode&VM_TRUST) )
481 { GETLOCAL(vd, local);
482 if(ISLOCK(vd, local))
483 { CLRINUSE(vd, inuse);
484 return NIL(Void_t*);
485 }
486 SETLOCK(vd, local);
487 }
488
489 s = ROUND(size,ALIGN) + PF_EXTRA;
490 if(!(data = KPVALLOC(vm,s,(*(Vmbest->allocf))) ) )
491 goto done;
492
493 pfsetinfo(vm,(Vmuchar_t*)data,size,file,line);
494
495 if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
496 { vm->file = file; vm->line = line; vm->func = func;
497 (*_Vmtrace)(vm,NIL(Vmuchar_t*),(Vmuchar_t*)data,size,0);
498 }
499 done:
500 CLRLOCK(vd, local);
501 ANNOUNCE(local, vm, VM_ALLOC, (Void_t*)data, vm->disc);
502 CLRINUSE(vd, inuse);
503 return data;
504 }
505
506 #if __STD_C
pffree(Vmalloc_t * vm,Void_t * data)507 static int pffree(Vmalloc_t* vm, Void_t* data)
508 #else
509 static int pffree(vm, data)
510 Vmalloc_t* vm;
511 Void_t* data;
512 #endif
513 {
514 reg Pfobj_t* pf;
515 reg size_t s;
516 reg char* file;
517 reg int line, rv, local, inuse;
518 reg Void_t* func;
519 reg Vmdata_t* vd = vm->data;
520
521 VMFLF(vm,file,line,func);
522
523 if(!data)
524 return 0;
525
526 SETINUSE(vd, inuse);
527 if(!(local = vd->mode&VM_TRUST) )
528 { GETLOCAL(vd,local);
529 if(ISLOCK(vd,local))
530 { CLRINUSE(vd, inuse);
531 return -1;
532 }
533 SETLOCK(vd,local);
534 }
535
536 if(KPVADDR(vm,data,Vmbest->addrf) != 0 )
537 { if(vm->disc->exceptf)
538 (void)(*vm->disc->exceptf)(vm,VM_BADADDR,data,vm->disc);
539 CLRLOCK(vd,0);
540 CLRINUSE(vd, inuse);
541 return -1;
542 }
543
544 pf = PFOBJ(data);
545 s = PFSIZE(data);
546 if(pf)
547 { PFNFREE(pf) += 1;
548 PFFREE(pf) += s;
549 pf = PFREGION(pf);
550 PFNFREE(pf) += 1;
551 PFFREE(pf) += s;
552 }
553
554 if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
555 { vm->file = file; vm->line = line; vm->func = func;
556 (*_Vmtrace)(vm,(Vmuchar_t*)data,NIL(Vmuchar_t*),s,0);
557 }
558
559 rv = KPVFREE((vm), (Void_t*)data, (*Vmbest->freef));
560 CLRLOCK(vd,local);
561 ANNOUNCE(local, vm, VM_FREE, data, vm->disc);
562 CLRINUSE(vd, inuse);
563 return rv;
564 }
565
566 #if __STD_C
pfresize(Vmalloc_t * vm,Void_t * data,size_t size,int type)567 static Void_t* pfresize(Vmalloc_t* vm, Void_t* data, size_t size, int type)
568 #else
569 static Void_t* pfresize(vm, data, size, type)
570 Vmalloc_t* vm;
571 Void_t* data;
572 size_t size;
573 int type;
574 #endif
575 {
576 reg Pfobj_t* pf;
577 reg size_t s;
578 reg size_t news;
579 reg Void_t* addr;
580 reg char* file;
581 reg int line, local, inuse;
582 reg Void_t* func;
583 reg size_t oldsize;
584 reg Vmdata_t* vd = vm->data;
585
586 SETINUSE(vd, inuse);
587 if(!data)
588 { oldsize = 0;
589 addr = pfalloc(vm,size);
590 goto done;
591 }
592 if(size == 0)
593 { (void)pffree(vm,data);
594 CLRINUSE(vd, inuse);
595 return NIL(Void_t*);
596 }
597
598 VMFLF(vm,file,line,func);
599 if(!(local = vd->mode&VM_TRUST))
600 { GETLOCAL(vd, local);
601 if(ISLOCK(vd, local))
602 { CLRINUSE(vd, inuse);
603 return NIL(Void_t*);
604 }
605 SETLOCK(vd, local);
606 }
607
608 if(KPVADDR(vm,data,Vmbest->addrf) != 0 )
609 { if(vm->disc->exceptf)
610 (void)(*vm->disc->exceptf)(vm,VM_BADADDR,data,vm->disc);
611 CLRLOCK(vd, local);
612 CLRINUSE(vd, inuse);
613 return NIL(Void_t*);
614 }
615
616 pf = PFOBJ(data);
617 s = oldsize = PFSIZE(data);
618
619 news = ROUND(size,ALIGN) + PF_EXTRA;
620 if((addr = KPVRESIZE(vm,data,news,(type&~VM_RSZERO),Vmbest->resizef)) )
621 { if(pf)
622 { PFFREE(pf) += s;
623 PFNFREE(pf) += 1;
624 pf = PFREGION(pf);
625 PFFREE(pf) += s;
626 PFNFREE(pf) += 1;
627 pfsetinfo(vm,(Vmuchar_t*)addr,size,file,line);
628 }
629
630 if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
631 { vm->file = file; vm->line = line; vm->func = func;
632 (*_Vmtrace)(vm,(Vmuchar_t*)data,(Vmuchar_t*)addr,size,0);
633 }
634 }
635 else if(pf) /* reset old info */
636 { PFALLOC(pf) -= s;
637 PFNALLOC(pf) -= 1;
638 pf = PFREGION(pf);
639 PFALLOC(pf) -= s;
640 PFNALLOC(pf) -= 1;
641 file = PFFILE(pf);
642 line = PFLINE(pf);
643 pfsetinfo(vm,(Vmuchar_t*)data,s,file,line);
644 }
645
646 CLRLOCK(vd, local);
647 ANNOUNCE(local, vm, VM_RESIZE, (Void_t*)addr, vm->disc);
648
649 done: if(addr && (type&VM_RSZERO) && oldsize < size)
650 { reg Vmuchar_t *d = (Vmuchar_t*)addr+oldsize, *ed = (Vmuchar_t*)addr+size;
651 do { *d++ = 0; } while(d < ed);
652 }
653
654 CLRINUSE(vd, inuse);
655 return addr;
656 }
657
658 #if __STD_C
pfsize(Vmalloc_t * vm,Void_t * addr)659 static long pfsize(Vmalloc_t* vm, Void_t* addr)
660 #else
661 static long pfsize(vm, addr)
662 Vmalloc_t* vm;
663 Void_t* addr;
664 #endif
665 {
666 return (*Vmbest->addrf)(vm,addr) != 0 ? -1L : (long)PFSIZE(addr);
667 }
668
669 #if __STD_C
pfaddr(Vmalloc_t * vm,Void_t * addr)670 static long pfaddr(Vmalloc_t* vm, Void_t* addr)
671 #else
672 static long pfaddr(vm, addr)
673 Vmalloc_t* vm;
674 Void_t* addr;
675 #endif
676 {
677 return (*Vmbest->addrf)(vm,addr);
678 }
679
680 #if __STD_C
pfcompact(Vmalloc_t * vm)681 static int pfcompact(Vmalloc_t* vm)
682 #else
683 static int pfcompact(vm)
684 Vmalloc_t* vm;
685 #endif
686 {
687 return (*Vmbest->compactf)(vm);
688 }
689
690 #if __STD_C
pfalign(Vmalloc_t * vm,size_t size,size_t align)691 static Void_t* pfalign(Vmalloc_t* vm, size_t size, size_t align)
692 #else
693 static Void_t* pfalign(vm, size, align)
694 Vmalloc_t* vm;
695 size_t size;
696 size_t align;
697 #endif
698 {
699 reg size_t s;
700 reg Void_t* data;
701 reg char* file;
702 reg int line, local, inuse;
703 reg Void_t* func;
704 reg Vmdata_t* vd = vm->data;
705
706 VMFLF(vm,file,line,func);
707
708 SETINUSE(vd, inuse);
709 if(!(local = vd->mode&VM_TRUST) )
710 { GETLOCAL(vd,local);
711 if(ISLOCK(vd, local))
712 { CLRINUSE(vd, inuse);
713 return NIL(Void_t*);
714 }
715 SETLOCK(vd, local);
716 }
717
718 s = (size <= TINYSIZE ? TINYSIZE : ROUND(size,ALIGN)) + PF_EXTRA;
719 if(!(data = KPVALIGN(vm,s,align,Vmbest->alignf)) )
720 goto done;
721
722 pfsetinfo(vm,(Vmuchar_t*)data,size,file,line);
723
724 if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
725 { vm->file = file; vm->line = line; vm->func = func;
726 (*_Vmtrace)(vm,NIL(Vmuchar_t*),(Vmuchar_t*)data,size,align);
727 }
728 done:
729 CLRLOCK(vd, local);
730 ANNOUNCE(local, vm, VM_ALLOC, data, vm->disc);
731 CLRINUSE(vd, inuse);
732 return data;
733 }
734
735 static Vmethod_t _Vmprofile =
736 {
737 pfalloc,
738 pfresize,
739 pffree,
740 pfaddr,
741 pfsize,
742 pfcompact,
743 pfalign,
744 VM_MTPROFILE
745 };
746
747 __DEFINE__(Vmethod_t*,Vmprofile,&_Vmprofile);
748
749 #ifdef NoF
750 NoF(vmprofile)
751 #endif
752
753 #endif
754