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_malloc()24 void _STUB_malloc(){}
25
26 #else
27
28 #if _UWIN
29
30 #define calloc ______calloc
31 #define _ast_free ______free
32 #define malloc ______malloc
33 #define mallinfo ______mallinfo
34 #define mallopt ______mallopt
35 #define mstats ______mstats
36 #define realloc ______realloc
37
38 #define _STDLIB_H_ 1
39
40 extern int atexit(void(*)(void));
41 extern char* getenv(const char*);
42
43 #endif
44
45 #include "vmhdr.h"
46 #include <errno.h>
47
48 #if _UWIN
49
50 #include <malloc.h>
51
52 #define _map_malloc 1
53 #define _mal_alloca 1
54
55 #undef calloc
56 #define calloc _ast_calloc
57 #undef _ast_free
58 #define free _ast_free
59 #undef malloc
60 #define malloc _ast_malloc
61 #undef mallinfo
62 typedef struct ______mallinfo Mallinfo_t;
63 #undef mallopt
64 #undef mstats
65 typedef struct ______mstats Mstats_t;
66 #undef realloc
67 #define realloc _ast_realloc
68
69 #endif
70
71 #if __STD_C
72 #define F0(f,t0) f(t0)
73 #define F1(f,t1,a1) f(t1 a1)
74 #define F2(f,t1,a1,t2,a2) f(t1 a1, t2 a2)
75 #else
76 #define F0(f,t0) f()
77 #define F1(f,t1,a1) f(a1) t1 a1;
78 #define F2(f,t1,a1,t2,a2) f(a1, a2) t1 a1; t2 a2;
79 #endif
80
81 /*
82 * define _AST_std_malloc=1 to force the standard malloc
83 * if _map_malloc is also defined then _ast_malloc etc.
84 * will simply call malloc etc.
85 */
86
87 #if !defined(_AST_std_malloc) && __CYGWIN__
88 #define _AST_std_malloc 1
89 #endif
90
91 /* malloc compatibility functions
92 **
93 ** These are aware of debugging/profiling and are driven by the
94 ** VMALLOC_OPTIONS environment variable which is a space-separated
95 ** list of [no]name[=value] options:
96 **
97 ** abort if Vmregion==Vmdebug then VM_DBABORT is set,
98 ** otherwise _BLD_debug enabled assertions abort()
99 ** on failure
100 ** check if Vmregion==Vmbest then the region is checked every op
101 ** method=m sets Vmregion=m if not defined, m (Vm prefix optional)
102 ** may be one of { best debug last profile }
103 ** mmap prefer mmap() over brk() for region allocation
104 ** period=n sets Vmregion=Vmdebug if not defined, if
105 ** Vmregion==Vmdebug the region is checked every n ops
106 ** profile=f sets Vmregion=Vmprofile if not set, if
107 ** Vmregion==Vmprofile then profile info printed to file f
108 ** region if Vmregion==Vmbest then block free verifies
109 ** that the block belongs to the region
110 ** start=n sets Vmregion=Vmdebug if not defined, if
111 ** Vmregion==Vmdebug region checking starts after n ops
112 ** trace=f enables tracing to file f
113 ** warn=f sets Vmregion=Vmdebug if not defined, if
114 ** Vmregion==Vmdebug then warnings printed to file f
115 ** watch=a sets Vmregion=Vmdebug if not defined, if
116 ** Vmregion==Vmdebug then address a is watched
117 **
118 ** Output files are created if they don't exist. &n and /dev/fd/n name
119 ** the file descriptor n which must be open for writing. The pattern %p
120 ** in a file name is replaced by the process ID.
121 **
122 ** VMALLOC_OPTIONS combines the features of these previously used env vars:
123 ** { VMDEBUG VMETHOD VMPROFILE VMTRACE }
124 **
125 ** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
126 */
127
128 #if _sys_stat
129 #include <sys/stat.h>
130 #endif
131 #include <fcntl.h>
132
133 #ifdef S_IRUSR
134 #define CREAT_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
135 #else
136 #define CREAT_MODE 0644
137 #endif
138
139 static Vmulong_t _Vmdbstart = 0;
140 static Vmulong_t _Vmdbcheck = 0;
141 static Vmulong_t _Vmdbtime = 0;
142 static int _Vmpffd = -1;
143
144 #if ( !_std_malloc || !_BLD_ast ) && !_AST_std_malloc
145
146 #if !_map_malloc
147 #undef calloc
148 #undef cfree
149 #undef free
150 #undef mallinfo
151 #undef malloc
152 #undef mallopt
153 #undef memalign
154 #undef mstats
155 #undef realloc
156 #undef valloc
157 #endif
158
159 #if _WINIX
160
161 #include <ast_windows.h>
162
163 #if _UWIN
164
165 #define VMRECORD(p) _vmrecord(p)
166 #define VMBLOCK { int _vmblock = _sigblock();
167 #define VMUNBLOCK _sigunblock(_vmblock); }
168
169 extern int _sigblock(void);
170 extern void _sigunblock(int);
171 extern unsigned long _record[2048];
172
_vmrecord(Void_t * p)173 __inline Void_t* _vmrecord(Void_t* p)
174 {
175 register unsigned long v = ((unsigned long)p)>>16;
176
177 _record[v>>5] |= 1<<((v&0x1f));
178 return p;
179 }
180
181 #else
182
183 #define getenv(s) lcl_getenv(s)
184
185 static char*
lcl_getenv(const char * s)186 lcl_getenv(const char* s)
187 {
188 int n;
189 static char buf[512];
190
191 if (!(n = GetEnvironmentVariable(s, buf, sizeof(buf))) || n > sizeof(buf))
192 return 0;
193 return buf;
194 }
195
196 #endif /* _UWIN */
197
198 #endif /* _WINIX */
199
200 #ifndef VMRECORD
201 #define VMRECORD(p) (p)
202 #define VMBLOCK
203 #define VMUNBLOCK
204 #endif
205
206 #if defined(__EXPORT__)
207 #define extern extern __EXPORT__
208 #endif
209
210 static int _Vmflinit = 0;
211 #define VMFLINIT() \
212 { if(!_Vmflinit) vmflinit(); \
213 if(_Vmdbcheck) \
214 { if(_Vmdbtime < _Vmdbstart) _Vmdbtime += 1; \
215 else if((_Vmdbtime += 1) < _Vmdbstart) _Vmdbtime = _Vmdbstart; \
216 if(_Vmdbtime >= _Vmdbstart && (_Vmdbtime % _Vmdbcheck) == 0 && \
217 Vmregion->meth.meth == VM_MTDEBUG) \
218 vmdbcheck(Vmregion); \
219 } \
220 }
221
222 #if __STD_C
vmflinit(void)223 static int vmflinit(void)
224 #else
225 static int vmflinit()
226 #endif
227 {
228 char* file;
229 int line;
230 Void_t* func;
231
232 /* this must be done now to avoid any inadvertent recursion (more below) */
233 _Vmflinit = 1;
234 VMFLF(Vmregion,file,line,func);
235
236 /* if getenv() calls malloc(), the options may not affect the eventual region */
237 VMOPTIONS();
238
239 /* reset file and line number to correct values for the call */
240 Vmregion->file = file;
241 Vmregion->line = line;
242 Vmregion->func = func;
243
244 return 0;
245 }
246
247 #if __STD_C
calloc(reg size_t n_obj,reg size_t s_obj)248 extern Void_t* calloc(reg size_t n_obj, reg size_t s_obj)
249 #else
250 extern Void_t* calloc(n_obj, s_obj)
251 reg size_t n_obj;
252 reg size_t s_obj;
253 #endif
254 {
255 VMFLINIT();
256 return VMRECORD((*Vmregion->meth.resizef)(Vmregion,NIL(Void_t*),n_obj*s_obj,VM_RSZERO));
257 }
258
259 #if __STD_C
malloc(reg size_t size)260 extern Void_t* malloc(reg size_t size)
261 #else
262 extern Void_t* malloc(size)
263 reg size_t size;
264 #endif
265 {
266 VMFLINIT();
267 return VMRECORD((*Vmregion->meth.allocf)(Vmregion,size));
268 }
269
270 #if __STD_C
realloc(reg Void_t * data,reg size_t size)271 extern Void_t* realloc(reg Void_t* data, reg size_t size)
272 #else
273 extern Void_t* realloc(data,size)
274 reg Void_t* data; /* block to be reallocated */
275 reg size_t size; /* new size */
276 #endif
277 {
278 #if USE_NATIVE
279 #undef realloc
280 #if __STD_C
281 extern Void_t* realloc(Void_t*, size_t);
282 #else
283 extern Void_t* realloc();
284 #endif
285 #endif
286
287 VMFLINIT();
288
289 #if _PACKAGE_ast
290 if(data && Vmregion->meth.meth != VM_MTDEBUG &&
291 #if !USE_NATIVE
292 !(Vmregion->data->mode&VM_TRUST) &&
293 #endif
294 (*Vmregion->meth.addrf)(Vmregion,data) != 0 )
295 {
296 #if USE_NATIVE
297 return realloc(data, size);
298 #else
299 Void_t* newdata;
300 if((newdata = (*Vmregion->meth.allocf)(Vmregion,size)) )
301 memcpy(newdata,data,size);
302 return VMRECORD(newdata);
303 #endif
304 }
305 #endif
306
307 #if USE_NATIVE
308 { Void_t* newdata;
309 if (newdata = (*Vmregion->meth.resizef)(Vmregion,data,size,VM_RSCOPY|VM_RSMOVE))
310 return newdata;
311 return VMRECORD(realloc(data, size));
312 }
313 #else
314 return VMRECORD((*Vmregion->meth.resizef)(Vmregion,data,size,VM_RSCOPY|VM_RSMOVE));
315 #endif
316 }
317
318 #if __STD_C
free(reg Void_t * data)319 extern void free(reg Void_t* data)
320 #else
321 extern void free(data)
322 reg Void_t* data;
323 #endif
324 {
325 #if USE_NATIVE
326 #undef free
327 #if __STD_C
328 extern void free(Void_t*);
329 #else
330 extern void free();
331 #endif
332 #endif
333
334 VMFLINIT();
335
336 #if _PACKAGE_ast
337 if(data && Vmregion->meth.meth != VM_MTDEBUG &&
338 #if !USE_NATIVE
339 !(Vmregion->data->mode&VM_TRUST) &&
340 #endif
341 (*Vmregion->meth.addrf)(Vmregion,data) != 0)
342 {
343 #if USE_NATIVE
344 free(data);
345 #endif
346 return;
347 }
348 #endif
349
350 #if USE_NATIVE
351 if ((*Vmregion->meth.freef)(Vmregion,data) != 0)
352 free(data);
353 #else
354 (void)(*Vmregion->meth.freef)(Vmregion,data);
355 #endif
356 }
357
358 #if __STD_C
cfree(reg Void_t * data)359 extern void cfree(reg Void_t* data)
360 #else
361 extern void cfree(data)
362 reg Void_t* data;
363 #endif
364 {
365 free(data);
366 }
367
368 #if __STD_C
memalign(reg size_t align,reg size_t size)369 extern Void_t* memalign(reg size_t align, reg size_t size)
370 #else
371 extern Void_t* memalign(align, size)
372 reg size_t align;
373 reg size_t size;
374 #endif
375 {
376 Void_t* addr;
377
378 VMFLINIT();
379 VMBLOCK
380 addr = VMRECORD((*Vmregion->meth.alignf)(Vmregion,size,align));
381 VMUNBLOCK
382 return addr;
383 }
384
385 #if __STD_C
posix_memalign(reg Void_t ** memptr,reg size_t align,reg size_t size)386 extern int posix_memalign(reg Void_t **memptr, reg size_t align, reg size_t size)
387 #else
388 extern int posix_memalign(memptr, align, size)
389 reg Void_t** memptr;
390 reg size_t align;
391 reg size_t size;
392 #endif
393 {
394 Void_t *mem;
395
396 if(align == 0 || (align%sizeof(Void_t*)) != 0 || ((align-1)&align) != 0 )
397 return EINVAL;
398
399 if(!(mem = memalign(align, size)) )
400 return ENOMEM;
401
402 *memptr = mem;
403 return 0;
404 }
405
406 #if __STD_C
valloc(reg size_t size)407 extern Void_t* valloc(reg size_t size)
408 #else
409 extern Void_t* valloc(size)
410 reg size_t size;
411 #endif
412 {
413 VMFLINIT();
414 GETPAGESIZE(_Vmpagesize);
415 return VMRECORD((*Vmregion->meth.alignf)(Vmregion,size,_Vmpagesize));
416 }
417
418 #if __STD_C
pvalloc(reg size_t size)419 extern Void_t* pvalloc(reg size_t size)
420 #else
421 extern Void_t* pvalloc(size)
422 reg size_t size;
423 #endif
424 {
425 VMFLINIT();
426 GETPAGESIZE(_Vmpagesize);
427 return VMRECORD((*Vmregion->meth.alignf)(Vmregion,ROUND(size,_Vmpagesize),_Vmpagesize));
428 }
429
430 #if !_PACKAGE_ast
431 #if __STD_C
strdup(const char * s)432 char* strdup(const char* s)
433 #else
434 char* strdup(s)
435 char* s;
436 #endif
437 {
438 char *ns;
439 size_t n;
440
441 if(!s)
442 return NIL(char*);
443 else
444 { n = strlen(s);
445 if((ns = malloc(n+1)) )
446 memcpy(ns,s,n+1);
447 return ns;
448 }
449 }
450 #endif /* _PACKAGE_ast */
451
452 #if !_lib_alloca || _mal_alloca
453 #ifndef _stk_down
454 #define _stk_down 0
455 #endif
456 typedef struct _alloca_s Alloca_t;
457 union _alloca_u
458 { struct
459 { char* addr;
460 Alloca_t* next;
461 } head;
462 char array[ALIGN];
463 };
464 struct _alloca_s
465 { union _alloca_u head;
466 Vmuchar_t data[1];
467 };
468
469 #if __STD_C
alloca(size_t size)470 extern Void_t* alloca(size_t size)
471 #else
472 extern Void_t* alloca(size)
473 size_t size;
474 #endif
475 { char array[ALIGN];
476 char* file;
477 int line;
478 Void_t* func;
479 reg Alloca_t* f;
480 static Alloca_t* Frame;
481
482 VMFLINIT();
483 VMFLF(Vmregion,file,line,func);
484 while(Frame)
485 { if(( _stk_down && &array[0] > Frame->head.head.addr) ||
486 (!_stk_down && &array[0] < Frame->head.head.addr) )
487 { f = Frame;
488 Frame = f->head.head.next;
489 (void)(*Vmregion->meth.freef)(Vmregion,f);
490 }
491 else break;
492 }
493
494 Vmregion->file = file;
495 Vmregion->line = line;
496 Vmregion->func = func;
497 f = (Alloca_t*)(*Vmregion->meth.allocf)(Vmregion,size+sizeof(Alloca_t)-1);
498
499 f->head.head.addr = &array[0];
500 f->head.head.next = Frame;
501 Frame = f;
502
503 return (Void_t*)f->data;
504 }
505 #endif /*!_lib_alloca || _mal_alloca*/
506
507 #if _map_malloc
508
509 /* not sure of all the implications -- 0 is conservative for now */
510 #define USE_NATIVE 0 /* native free/realloc on non-vmalloc ptrs */
511
512 #else
513
514 /* intercept _* __* __libc_* variants */
515
516 #if __lib__malloc
F2(_calloc,size_t,n,size_t,m)517 extern Void_t* F2(_calloc, size_t,n, size_t,m) { return calloc(n, m); }
F1(_cfree,Void_t *,p)518 extern Void_t F1(_cfree, Void_t*,p) { free(p); }
F1(_free,Void_t *,p)519 extern Void_t F1(_free, Void_t*,p) { free(p); }
F1(_malloc,size_t,n)520 extern Void_t* F1(_malloc, size_t,n) { return malloc(n); }
521 #if _lib_memalign
F2(_memalign,size_t,a,size_t,n)522 extern Void_t* F2(_memalign, size_t,a, size_t,n) { return memalign(a, n); }
523 #endif
524 #if _lib_pvalloc
F1(_pvalloc,size_t,n)525 extern Void_t* F1(_pvalloc, size_t,n) { return pvalloc(n); }
526 #endif
F2(_realloc,Void_t *,p,size_t,n)527 extern Void_t* F2(_realloc, Void_t*,p, size_t,n) { return realloc(p, n); }
528 #if _lib_valloc
F1(_valloc,size_t,n)529 extern Void_t* F1(_valloc, size_t,n) { return valloc(n); }
530 #endif
531 #endif
532
533 #if _lib___malloc
F2(__calloc,size_t,n,size_t,m)534 extern Void_t* F2(__calloc, size_t,n, size_t,m) { return calloc(n, m); }
F1(__cfree,Void_t *,p)535 extern Void_t F1(__cfree, Void_t*,p) { free(p); }
F1(__free,Void_t *,p)536 extern Void_t F1(__free, Void_t*,p) { free(p); }
F1(__malloc,size_t,n)537 extern Void_t* F1(__malloc, size_t,n) { return malloc(n); }
538 #if _lib_memalign
F2(__memalign,size_t,a,size_t,n)539 extern Void_t* F2(__memalign, size_t,a, size_t,n) { return memalign(a, n); }
540 #endif
541 #if _lib_pvalloc
F1(__pvalloc,size_t,n)542 extern Void_t* F1(__pvalloc, size_t,n) { return pvalloc(n); }
543 #endif
F2(__realloc,Void_t *,p,size_t,n)544 extern Void_t* F2(__realloc, Void_t*,p, size_t,n) { return realloc(p, n); }
545 #if _lib_valloc
F1(__valloc,size_t,n)546 extern Void_t* F1(__valloc, size_t,n) { return valloc(n); }
547 #endif
548 #endif
549
550 #if _lib___libc_malloc
F2(__libc_calloc,size_t,n,size_t,m)551 extern Void_t* F2(__libc_calloc, size_t,n, size_t,m) { return calloc(n, m); }
F1(__libc_cfree,Void_t *,p)552 extern Void_t F1(__libc_cfree, Void_t*,p) { free(p); }
F1(__libc_free,Void_t *,p)553 extern Void_t F1(__libc_free, Void_t*,p) { free(p); }
F1(__libc_malloc,size_t,n)554 extern Void_t* F1(__libc_malloc, size_t,n) { return malloc(n); }
555 #if _lib_memalign
F2(__libc_memalign,size_t,a,size_t,n)556 extern Void_t* F2(__libc_memalign, size_t,a, size_t,n) { return memalign(a, n); }
557 #endif
558 #if _lib_pvalloc
F1(__libc_pvalloc,size_t,n)559 extern Void_t* F1(__libc_pvalloc, size_t,n) { return pvalloc(n); }
560 #endif
F2(__libc_realloc,Void_t *,p,size_t,n)561 extern Void_t* F2(__libc_realloc, Void_t*,p, size_t,n) { return realloc(p, n); }
562 #if _lib_valloc
F1(__libc_valloc,size_t,n)563 extern Void_t* F1(__libc_valloc, size_t,n) { return valloc(n); }
564 #endif
565 #endif
566
567 #endif /* _map_malloc */
568
569 #undef extern
570
571 #if _hdr_malloc /* need the mallint interface for statistics, etc. */
572
573 #undef calloc
574 #define calloc ______calloc
575 #undef cfree
576 #define cfree ______cfree
577 #undef free
578 #define free ______free
579 #undef malloc
580 #define malloc ______malloc
581 #undef pvalloc
582 #define pvalloc ______pvalloc
583 #undef realloc
584 #define realloc ______realloc
585 #undef valloc
586 #define valloc ______valloc
587
588 #if !_UWIN
589
590 #include <malloc.h>
591
592 typedef struct mallinfo Mallinfo_t;
593 typedef struct mstats Mstats_t;
594
595 #endif
596
597 #if defined(__EXPORT__)
598 #define extern __EXPORT__
599 #endif
600
601 #if _lib_mallopt
602 #if __STD_C
mallopt(int cmd,int value)603 extern int mallopt(int cmd, int value)
604 #else
605 extern int mallopt(cmd, value)
606 int cmd;
607 int value;
608 #endif
609 {
610 VMFLINIT();
611 return 0;
612 }
613 #endif /*_lib_mallopt*/
614
615 #if _lib_mallinfo && _mem_arena_mallinfo
616 #if __STD_C
mallinfo(void)617 extern Mallinfo_t mallinfo(void)
618 #else
619 extern Mallinfo_t mallinfo()
620 #endif
621 {
622 Vmstat_t sb;
623 Mallinfo_t mi;
624
625 VMFLINIT();
626 memset(&mi,0,sizeof(mi));
627 if(vmstat(Vmregion,&sb) >= 0)
628 { mi.arena = sb.extent;
629 mi.ordblks = sb.n_busy+sb.n_free;
630 mi.uordblks = sb.s_busy;
631 mi.fordblks = sb.s_free;
632 }
633 return mi;
634 }
635 #endif /* _lib_mallinfo */
636
637 #if _lib_mstats && _mem_bytes_total_mstats
638 #if __STD_C
mstats(void)639 extern Mstats_t mstats(void)
640 #else
641 extern Mstats_t mstats()
642 #endif
643 {
644 Vmstat_t sb;
645 Mstats_t ms;
646
647 VMFLINIT();
648 memset(&ms,0,sizeof(ms));
649 if(vmstat(Vmregion,&sb) >= 0)
650 { ms.bytes_total = sb.extent;
651 ms.chunks_used = sb.n_busy;
652 ms.bytes_used = sb.s_busy;
653 ms.chunks_free = sb.n_free;
654 ms.bytes_free = sb.s_free;
655 }
656 return ms;
657 }
658 #endif /*_lib_mstats*/
659
660 #undef extern
661
662 #endif/*_hdr_malloc*/
663
664 #else
665
666 /*
667 * even though there is no malloc override, still provide
668 * _ast_* counterparts for object compatibility
669 */
670
671 #undef calloc
672 extern Void_t* calloc _ARG_((size_t, size_t));
673
674 #undef cfree
675 extern void cfree _ARG_((Void_t*));
676
677 #undef free
678 extern void free _ARG_((Void_t*));
679
680 #undef malloc
681 extern Void_t* malloc _ARG_((size_t));
682
683 #if _lib_memalign
684 #undef memalign
685 extern Void_t* memalign _ARG_((size_t, size_t));
686 #endif
687
688 #if _lib_pvalloc
689 #undef pvalloc
690 extern Void_t* pvalloc _ARG_((size_t));
691 #endif
692
693 #undef realloc
694 extern Void_t* realloc _ARG_((Void_t*, size_t));
695
696 #if _lib_valloc
697 #undef valloc
698 extern Void_t* valloc _ARG_((size_t));
699 #endif
700
701 #if defined(__EXPORT__)
702 #define extern __EXPORT__
703 #endif
704
F2(_ast_calloc,size_t,n,size_t,m)705 extern Void_t* F2(_ast_calloc, size_t,n, size_t,m) { return calloc(n, m); }
F1(_ast_cfree,Void_t *,p)706 extern Void_t F1(_ast_cfree, Void_t*,p) { free(p); }
F1(_ast_free,Void_t *,p)707 extern Void_t F1(_ast_free, Void_t*,p) { free(p); }
F1(_ast_malloc,size_t,n)708 extern Void_t* F1(_ast_malloc, size_t,n) { return malloc(n); }
709 #if _lib_memalign
F2(_ast_memalign,size_t,a,size_t,n)710 extern Void_t* F2(_ast_memalign, size_t,a, size_t,n) { return memalign(a, n); }
711 #endif
712 #if _lib_pvalloc
F1(_ast_pvalloc,size_t,n)713 extern Void_t* F1(_ast_pvalloc, size_t,n) { return pvalloc(n); }
714 #endif
F2(_ast_realloc,Void_t *,p,size_t,n)715 extern Void_t* F2(_ast_realloc, Void_t*,p, size_t,n) { return realloc(p, n); }
716 #if _lib_valloc
F1(_ast_valloc,size_t,n)717 extern Void_t* F1(_ast_valloc, size_t,n) { return valloc(n); }
718 #endif
719
720 #undef extern
721
722 #if _hdr_malloc
723
724 #undef mallinfo
725 #undef mallopt
726 #undef mstats
727
728 #define calloc ______calloc
729 #define cfree ______cfree
730 #define free ______free
731 #define malloc ______malloc
732 #define pvalloc ______pvalloc
733 #define realloc ______realloc
734 #define valloc ______valloc
735
736 #if !_UWIN
737
738 #include <malloc.h>
739
740 typedef struct mallinfo Mallinfo_t;
741 typedef struct mstats Mstats_t;
742
743 #endif
744
745 #if defined(__EXPORT__)
746 #define extern __EXPORT__
747 #endif
748
749 #if _lib_mallopt
F2(_ast_mallopt,int,cmd,int,value)750 extern int F2(_ast_mallopt, int,cmd, int,value) { return mallopt(cmd, value); }
751 #endif
752
753 #if _lib_mallinfo && _mem_arena_mallinfo
F0(_ast_mallinfo,void)754 extern Mallinfo_t F0(_ast_mallinfo, void) { return mallinfo(); }
755 #endif
756
757 #if _lib_mstats && _mem_bytes_total_mstats
F0(_ast_mstats,void)758 extern Mstats_t F0(_ast_mstats, void) { return mstats(); }
759 #endif
760
761 #undef extern
762
763 #endif /*_hdr_malloc*/
764
765 #endif /*!_std_malloc*/
766
767 #if __STD_C
atou(char ** sp)768 static Vmulong_t atou(char** sp)
769 #else
770 static Vmulong_t atou(sp)
771 char** sp;
772 #endif
773 {
774 char* s = *sp;
775 Vmulong_t v = 0;
776
777 if(s[0] == '0' && (s[1] == 'x' || s[1] == 'X') )
778 { for(s += 2; *s; ++s)
779 { if(*s >= '0' && *s <= '9')
780 v = (v << 4) + (*s - '0');
781 else if(*s >= 'a' && *s <= 'f')
782 v = (v << 4) + (*s - 'a') + 10;
783 else if(*s >= 'A' && *s <= 'F')
784 v = (v << 4) + (*s - 'A') + 10;
785 else break;
786 }
787 }
788 else
789 { for(; *s; ++s)
790 { if(*s >= '0' && *s <= '9')
791 v = v*10 + (*s - '0');
792 else break;
793 }
794 }
795
796 *sp = s;
797 return v;
798 }
799
800 #if __STD_C
insertpid(char * begs,char * ends)801 static char* insertpid(char* begs, char* ends)
802 #else
803 static char* insertpid(begs,ends)
804 char* begs;
805 char* ends;
806 #endif
807 { int pid;
808 char* s;
809
810 if((pid = getpid()) < 0)
811 return NIL(char*);
812
813 s = ends;
814 do
815 { if(s == begs)
816 return NIL(char*);
817 *--s = '0' + pid%10;
818 } while((pid /= 10) > 0);
819 while(s < ends)
820 *begs++ = *s++;
821
822 return begs;
823 }
824
825 #if __STD_C
createfile(char * file)826 static int createfile(char* file)
827 #else
828 static int createfile(file)
829 char* file;
830 #endif
831 {
832 char buf[1024];
833 char *next, *endb;
834 int fd;
835
836 next = buf;
837 endb = buf + sizeof(buf);
838 while(*file)
839 { if(*file == '%')
840 { switch(file[1])
841 {
842 case 'p' :
843 if(!(next = insertpid(next,endb)) )
844 return -1;
845 file += 2;
846 break;
847 default :
848 goto copy;
849 }
850 }
851 else
852 { copy:
853 *next++ = *file++;
854 }
855
856 if(next >= endb)
857 return -1;
858 }
859
860 *next = '\0';
861 file = buf;
862 if (*file == '&' && *(file += 1) || strncmp(file, "/dev/fd/", 8) == 0 && *(file += 8))
863 fd = dup((int)atou(&file));
864 else if (*file)
865 #if _PACKAGE_ast
866 fd = open(file, O_WRONLY|O_CREAT|O_TRUNC, CREAT_MODE);
867 #else
868 fd = creat(file, CREAT_MODE);
869 #endif
870 else
871 return -1;
872 #if _PACKAGE_ast
873 #ifdef FD_CLOEXEC
874 if (fd >= 0)
875 fcntl(fd, F_SETFD, FD_CLOEXEC);
876 #endif
877 #endif
878 return fd;
879 }
880
881 #if __STD_C
pfprint(void)882 static void pfprint(void)
883 #else
884 static void pfprint()
885 #endif
886 {
887 if(Vmregion->meth.meth == VM_MTPROFILE)
888 vmprofile(Vmregion,_Vmpffd);
889 }
890
891 /*
892 * initialize runtime options from the VMALLOC_OPTIONS env var
893 */
894
895 #define COPY(t,e,f) while ((*t = *f++) && t < e) t++
896
897 #if __STD_C
_vmoptions(void)898 void _vmoptions(void)
899 #else
900 void _vmoptions()
901 #endif
902 {
903 Vmalloc_t* vm = 0;
904 char* trace = 0;
905 char* s;
906 char* t;
907 char* v;
908 Vmulong_t n;
909 int fd;
910 char buf[1024];
911
912 _Vmoptions = 1;
913 t = buf;
914 v = &buf[sizeof(buf)-1];
915 if (s = getenv("VMALLOC_OPTIONS"))
916 COPY(t, v, s);
917 #if 1 /* backwards compatibility until 2011 */
918 else
919 {
920 char* p;
921
922 if (s = getenv("VMDEBUG"))
923 {
924 switch (*s++)
925 {
926 case 0:
927 break;
928 case 'a':
929 p = " abort";
930 COPY(t, v, p);
931 break;
932 case 'w':
933 p = " warn";
934 COPY(t, v, p);
935 break;
936 case '0':
937 if (*s-- == 'x')
938 {
939 p = " watch=";
940 COPY(t, v, p);
941 COPY(t, v, s);
942 break;
943 }
944 /*FALLTHROUGH*/
945 default:
946 p = " period=";
947 COPY(t, v, p);
948 COPY(t, v, s);
949 break;
950 }
951 }
952 if ((s = getenv("VMETHOD")) && *s)
953 {
954 p = " method=";
955 COPY(t, v, p);
956 COPY(t, v, s);
957 }
958 if ((s = getenv("VMPROFILE")) && *s)
959 {
960 p = " profile=";
961 COPY(t, v, p);
962 COPY(t, v, s);
963 }
964 if ((s = getenv("VMTRACE")) && *s)
965 {
966 p = " trace=";
967 COPY(t, v, p);
968 COPY(t, v, s);
969 }
970 }
971 #endif
972 if (t > buf)
973 {
974 *t = 0;
975 s = buf;
976 for (;;)
977 {
978 while (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n')
979 s++;
980 if (!*(t = s))
981 break;
982 v = 0;
983 while (*s)
984 if (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n')
985 {
986 *s++ = 0;
987 break;
988 }
989 else if (!v && *s == '=')
990 {
991 *s++ = 0;
992 if (!*(v = s))
993 v = 0;
994 }
995 else
996 s++;
997 if (t[0] == 'n' && t[1] == 'o')
998 continue;
999 switch (t[0])
1000 {
1001 case 'a': /* abort */
1002 if (!vm)
1003 vm = vmopen(Vmdcsbrk, Vmdebug, 0);
1004 if (vm && vm->meth.meth == VM_MTDEBUG)
1005 vmset(vm, VM_DBABORT, 1);
1006 else
1007 _Vmassert |= VM_abort;
1008 break;
1009 case 'c': /* check */
1010 _Vmassert |= VM_check;
1011 break;
1012 case 'm':
1013 switch (t[1])
1014 {
1015 case 'e': /* method=<method> */
1016 if (v && !vm)
1017 {
1018 if ((v[0] == 'V' || v[0] == 'v') && (v[1] == 'M' || v[1] == 'm'))
1019 v += 2;
1020 if (strcmp(v, "debug") == 0)
1021 vm = vmopen(Vmdcsbrk, Vmdebug, 0);
1022 else if (strcmp(v, "profile") == 0)
1023 vm = vmopen(Vmdcsbrk, Vmprofile, 0);
1024 else if (strcmp(v, "last") == 0)
1025 vm = vmopen(Vmdcsbrk, Vmlast, 0);
1026 else if (strcmp(v, "best") == 0)
1027 vm = Vmheap;
1028 }
1029 break;
1030 case 'm': /* mmap */
1031 #if _mem_mmap_anon || _mem_mmap_zero
1032 _Vmassert |= VM_mmap;
1033 #endif
1034 break;
1035 }
1036 break;
1037 case 'p':
1038 if (v)
1039 switch (t[1])
1040 {
1041 case 'e': /* period=<count> */
1042 if (!vm)
1043 vm = vmopen(Vmdcsbrk, Vmdebug, 0);
1044 if (vm && vm->meth.meth == VM_MTDEBUG)
1045 _Vmdbcheck = atou(&v);
1046 break;
1047 case 'r': /* profile=<path> */
1048 if (!vm)
1049 vm = vmopen(Vmdcsbrk, Vmprofile, 0);
1050 if (v && vm && vm->meth.meth == VM_MTPROFILE)
1051 _Vmpffd = createfile(v);
1052 break;
1053 }
1054 break;
1055 case 'r': /* region */
1056 _Vmassert |= VM_region;
1057 break;
1058 case 's': /* start=<count> */
1059 if (!vm)
1060 vm = vmopen(Vmdcsbrk, Vmdebug, 0);
1061 if (v && vm && vm->meth.meth == VM_MTDEBUG)
1062 _Vmdbstart = atou(&v);
1063 break;
1064 case 't': /* trace=<path> */
1065 trace = v;
1066 break;
1067 case 'w':
1068 if (t[1] == 'a')
1069 switch (t[2])
1070 {
1071 case 'r': /* warn=<path> */
1072 if (!vm)
1073 vm = vmopen(Vmdcsbrk, Vmdebug, 0);
1074 if (v && vm && vm->meth.meth == VM_MTDEBUG && (fd = createfile(v)) >= 0)
1075 vmdebug(fd);
1076 break;
1077 case 't': /* watch=<addr> */
1078 if (!vm)
1079 vm = vmopen(Vmdcsbrk, Vmdebug, 0);
1080 if (v && vm && vm->meth.meth == VM_MTDEBUG && (n = atou(&v)) >= 0)
1081 vmdbwatch((Void_t*)n);
1082 break;
1083 }
1084 break;
1085 }
1086 }
1087 }
1088
1089 /* slip in the new region now so that malloc() will work fine */
1090
1091 if (vm)
1092 {
1093 if (vm->meth.meth == VM_MTDEBUG)
1094 _Vmdbcheck = 1;
1095 Vmregion = vm;
1096 }
1097
1098 /* enable tracing */
1099
1100 if (trace && (fd = createfile(trace)) >= 0)
1101 {
1102 vmset(Vmregion, VM_TRACE, 1);
1103 vmtrace(fd);
1104 }
1105
1106 /* make sure that profile data is output upon exiting */
1107
1108 if (vm && vm->meth.meth == VM_MTPROFILE)
1109 {
1110 if (_Vmpffd < 0)
1111 _Vmpffd = 2;
1112 /* this may wind up calling malloc(), but region is ok now */
1113 atexit(pfprint);
1114 }
1115 else if (_Vmpffd >= 0)
1116 {
1117 close(_Vmpffd);
1118 _Vmpffd = -1;
1119 }
1120 }
1121
1122 #endif /*_UWIN*/
1123