1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
4*b30d1939SAndy Fiddaman * Copyright (c) 1985-2012 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6*b30d1939SAndy Fiddaman * Eclipse Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * A copy of the License is available at *
10*b30d1939SAndy Fiddaman * http://www.eclipse.org/org/documents/epl-v10.html *
11*b30d1939SAndy Fiddaman * (with md5 checksum b35adb5213ca9657e911e9befb180842) *
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_malloc()24da2e3ebdSchin void _STUB_malloc(){}
25da2e3ebdSchin
26da2e3ebdSchin #else
27da2e3ebdSchin
28da2e3ebdSchin #if _UWIN
29da2e3ebdSchin
30da2e3ebdSchin #define calloc ______calloc
31da2e3ebdSchin #define _ast_free ______free
32da2e3ebdSchin #define malloc ______malloc
33da2e3ebdSchin #define mallinfo ______mallinfo
34da2e3ebdSchin #define mallopt ______mallopt
35da2e3ebdSchin #define mstats ______mstats
36da2e3ebdSchin #define realloc ______realloc
37da2e3ebdSchin
38da2e3ebdSchin #define _STDLIB_H_ 1
39da2e3ebdSchin
40da2e3ebdSchin extern int atexit(void(*)(void));
41da2e3ebdSchin extern char* getenv(const char*);
42da2e3ebdSchin
43da2e3ebdSchin #endif
44da2e3ebdSchin
45da2e3ebdSchin #include "vmhdr.h"
4634f9b3eeSRoland Mainz #include <errno.h>
47da2e3ebdSchin
48da2e3ebdSchin #if _UWIN
49da2e3ebdSchin
50da2e3ebdSchin #include <malloc.h>
51da2e3ebdSchin
52da2e3ebdSchin #define _map_malloc 1
53da2e3ebdSchin #define _mal_alloca 1
54da2e3ebdSchin
55da2e3ebdSchin #undef calloc
56da2e3ebdSchin #define calloc _ast_calloc
57da2e3ebdSchin #undef _ast_free
58da2e3ebdSchin #define free _ast_free
59da2e3ebdSchin #undef malloc
60da2e3ebdSchin #define malloc _ast_malloc
61da2e3ebdSchin #undef mallinfo
62da2e3ebdSchin typedef struct ______mallinfo Mallinfo_t;
63da2e3ebdSchin #undef mallopt
64da2e3ebdSchin #undef mstats
65da2e3ebdSchin typedef struct ______mstats Mstats_t;
66da2e3ebdSchin #undef realloc
67da2e3ebdSchin #define realloc _ast_realloc
68da2e3ebdSchin
69da2e3ebdSchin #endif
70da2e3ebdSchin
71da2e3ebdSchin #if __STD_C
72da2e3ebdSchin #define F0(f,t0) f(t0)
73da2e3ebdSchin #define F1(f,t1,a1) f(t1 a1)
74da2e3ebdSchin #define F2(f,t1,a1,t2,a2) f(t1 a1, t2 a2)
75da2e3ebdSchin #else
76da2e3ebdSchin #define F0(f,t0) f()
77da2e3ebdSchin #define F1(f,t1,a1) f(a1) t1 a1;
78da2e3ebdSchin #define F2(f,t1,a1,t2,a2) f(a1, a2) t1 a1; t2 a2;
79da2e3ebdSchin #endif
80da2e3ebdSchin
81da2e3ebdSchin /*
82da2e3ebdSchin * define _AST_std_malloc=1 to force the standard malloc
83da2e3ebdSchin * if _map_malloc is also defined then _ast_malloc etc.
84da2e3ebdSchin * will simply call malloc etc.
85da2e3ebdSchin */
86da2e3ebdSchin
87da2e3ebdSchin #if !defined(_AST_std_malloc) && __CYGWIN__
88da2e3ebdSchin #define _AST_std_malloc 1
89da2e3ebdSchin #endif
90da2e3ebdSchin
913e14f97fSRoger A. Faulkner /* malloc compatibility functions
923e14f97fSRoger A. Faulkner **
933e14f97fSRoger A. Faulkner ** These are aware of debugging/profiling and are driven by the
94*b30d1939SAndy Fiddaman ** VMALLOC_OPTIONS environment variable which is a comma or space
95*b30d1939SAndy Fiddaman ** separated list of [no]name[=value] options:
96da2e3ebdSchin **
973e14f97fSRoger A. Faulkner ** abort if Vmregion==Vmdebug then VM_DBABORT is set,
98*b30d1939SAndy Fiddaman ** otherwise _BLD_DEBUG enabled assertions abort()
993e14f97fSRoger A. Faulkner ** on failure
100*b30d1939SAndy Fiddaman ** break try sbrk() block allocator first
1013e14f97fSRoger A. Faulkner ** check if Vmregion==Vmbest then the region is checked every op
102*b30d1939SAndy Fiddaman ** free disable addfreelist()
103*b30d1939SAndy Fiddaman ** keep disable free -- if code works with this enabled then it
104*b30d1939SAndy Fiddaman ** probably accesses free'd data
1053e14f97fSRoger A. Faulkner ** method=m sets Vmregion=m if not defined, m (Vm prefix optional)
1063e14f97fSRoger A. Faulkner ** may be one of { best debug last profile }
107*b30d1939SAndy Fiddaman ** mmap try mmap() block allocator first
1083e14f97fSRoger A. Faulkner ** period=n sets Vmregion=Vmdebug if not defined, if
1093e14f97fSRoger A. Faulkner ** Vmregion==Vmdebug the region is checked every n ops
1103e14f97fSRoger A. Faulkner ** profile=f sets Vmregion=Vmprofile if not set, if
1113e14f97fSRoger A. Faulkner ** Vmregion==Vmprofile then profile info printed to file f
1123e14f97fSRoger A. Faulkner ** start=n sets Vmregion=Vmdebug if not defined, if
1133e14f97fSRoger A. Faulkner ** Vmregion==Vmdebug region checking starts after n ops
1143e14f97fSRoger A. Faulkner ** trace=f enables tracing to file f
1153e14f97fSRoger A. Faulkner ** warn=f sets Vmregion=Vmdebug if not defined, if
1163e14f97fSRoger A. Faulkner ** Vmregion==Vmdebug then warnings printed to file f
1173e14f97fSRoger A. Faulkner ** watch=a sets Vmregion=Vmdebug if not defined, if
1183e14f97fSRoger A. Faulkner ** Vmregion==Vmdebug then address a is watched
119da2e3ebdSchin **
1203e14f97fSRoger A. Faulkner ** Output files are created if they don't exist. &n and /dev/fd/n name
1213e14f97fSRoger A. Faulkner ** the file descriptor n which must be open for writing. The pattern %p
1223e14f97fSRoger A. Faulkner ** in a file name is replaced by the process ID.
1233e14f97fSRoger A. Faulkner **
1243e14f97fSRoger A. Faulkner ** VMALLOC_OPTIONS combines the features of these previously used env vars:
125*b30d1939SAndy Fiddaman ** { VMCHECK VMDEBUG VMETHOD VMPROFILE VMTRACE }
126da2e3ebdSchin **
127da2e3ebdSchin ** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
128da2e3ebdSchin */
129da2e3ebdSchin
130da2e3ebdSchin #if _sys_stat
131da2e3ebdSchin #include <sys/stat.h>
132da2e3ebdSchin #endif
133da2e3ebdSchin #include <fcntl.h>
134da2e3ebdSchin
135da2e3ebdSchin #ifdef S_IRUSR
136da2e3ebdSchin #define CREAT_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
137da2e3ebdSchin #else
138da2e3ebdSchin #define CREAT_MODE 0644
139da2e3ebdSchin #endif
140da2e3ebdSchin
1413e14f97fSRoger A. Faulkner static Vmulong_t _Vmdbstart = 0;
1423e14f97fSRoger A. Faulkner static Vmulong_t _Vmdbcheck = 0;
1433e14f97fSRoger A. Faulkner static Vmulong_t _Vmdbtime = 0;
1443e14f97fSRoger A. Faulkner static int _Vmpffd = -1;
1453e14f97fSRoger A. Faulkner
1463e14f97fSRoger A. Faulkner #if ( !_std_malloc || !_BLD_ast ) && !_AST_std_malloc
1473e14f97fSRoger A. Faulkner
148da2e3ebdSchin #if !_map_malloc
149da2e3ebdSchin #undef calloc
150da2e3ebdSchin #undef cfree
151da2e3ebdSchin #undef free
152da2e3ebdSchin #undef mallinfo
153da2e3ebdSchin #undef malloc
154da2e3ebdSchin #undef mallopt
155da2e3ebdSchin #undef memalign
156da2e3ebdSchin #undef mstats
157da2e3ebdSchin #undef realloc
158da2e3ebdSchin #undef valloc
159*b30d1939SAndy Fiddaman
160*b30d1939SAndy Fiddaman #if _malloc_hook
161*b30d1939SAndy Fiddaman
162*b30d1939SAndy Fiddaman #include <malloc.h>
163*b30d1939SAndy Fiddaman
164*b30d1939SAndy Fiddaman #undef calloc
165*b30d1939SAndy Fiddaman #undef cfree
166*b30d1939SAndy Fiddaman #undef free
167*b30d1939SAndy Fiddaman #undef malloc
168*b30d1939SAndy Fiddaman #undef memalign
169*b30d1939SAndy Fiddaman #undef realloc
170*b30d1939SAndy Fiddaman
171*b30d1939SAndy Fiddaman #define calloc _ast_calloc
172*b30d1939SAndy Fiddaman #define cfree _ast_cfree
173*b30d1939SAndy Fiddaman #define free _ast_free
174*b30d1939SAndy Fiddaman #define malloc _ast_malloc
175*b30d1939SAndy Fiddaman #define memalign _ast_memalign
176*b30d1939SAndy Fiddaman #define realloc _ast_realloc
177*b30d1939SAndy Fiddaman
178*b30d1939SAndy Fiddaman #endif
179*b30d1939SAndy Fiddaman
180da2e3ebdSchin #endif
181da2e3ebdSchin
182da2e3ebdSchin #if _WINIX
183da2e3ebdSchin
184da2e3ebdSchin #include <ast_windows.h>
185da2e3ebdSchin
186da2e3ebdSchin #if _UWIN
187da2e3ebdSchin
188da2e3ebdSchin #define VMRECORD(p) _vmrecord(p)
189da2e3ebdSchin #define VMBLOCK { int _vmblock = _sigblock();
190da2e3ebdSchin #define VMUNBLOCK _sigunblock(_vmblock); }
191da2e3ebdSchin
192da2e3ebdSchin extern int _sigblock(void);
193da2e3ebdSchin extern void _sigunblock(int);
194da2e3ebdSchin extern unsigned long _record[2048];
195da2e3ebdSchin
_vmrecord(Void_t * p)196da2e3ebdSchin __inline Void_t* _vmrecord(Void_t* p)
197da2e3ebdSchin {
198da2e3ebdSchin register unsigned long v = ((unsigned long)p)>>16;
199da2e3ebdSchin
200da2e3ebdSchin _record[v>>5] |= 1<<((v&0x1f));
201da2e3ebdSchin return p;
202da2e3ebdSchin }
203da2e3ebdSchin
204da2e3ebdSchin #else
205da2e3ebdSchin
206da2e3ebdSchin #define getenv(s) lcl_getenv(s)
207da2e3ebdSchin
208da2e3ebdSchin static char*
lcl_getenv(const char * s)209da2e3ebdSchin lcl_getenv(const char* s)
210da2e3ebdSchin {
211da2e3ebdSchin int n;
212da2e3ebdSchin static char buf[512];
213da2e3ebdSchin
214da2e3ebdSchin if (!(n = GetEnvironmentVariable(s, buf, sizeof(buf))) || n > sizeof(buf))
215da2e3ebdSchin return 0;
216da2e3ebdSchin return buf;
217da2e3ebdSchin }
218da2e3ebdSchin
219da2e3ebdSchin #endif /* _UWIN */
220da2e3ebdSchin
221da2e3ebdSchin #endif /* _WINIX */
222da2e3ebdSchin
223da2e3ebdSchin #ifndef VMRECORD
224da2e3ebdSchin #define VMRECORD(p) (p)
225da2e3ebdSchin #define VMBLOCK
226da2e3ebdSchin #define VMUNBLOCK
227da2e3ebdSchin #endif
228da2e3ebdSchin
229da2e3ebdSchin #if defined(__EXPORT__)
230da2e3ebdSchin #define extern extern __EXPORT__
231da2e3ebdSchin #endif
232da2e3ebdSchin
233da2e3ebdSchin static int _Vmflinit = 0;
234da2e3ebdSchin #define VMFLINIT() \
235da2e3ebdSchin { if(!_Vmflinit) vmflinit(); \
236da2e3ebdSchin if(_Vmdbcheck) \
237da2e3ebdSchin { if(_Vmdbtime < _Vmdbstart) _Vmdbtime += 1; \
238da2e3ebdSchin else if((_Vmdbtime += 1) < _Vmdbstart) _Vmdbtime = _Vmdbstart; \
239da2e3ebdSchin if(_Vmdbtime >= _Vmdbstart && (_Vmdbtime % _Vmdbcheck) == 0 && \
240da2e3ebdSchin Vmregion->meth.meth == VM_MTDEBUG) \
241da2e3ebdSchin vmdbcheck(Vmregion); \
242da2e3ebdSchin } \
243da2e3ebdSchin }
244da2e3ebdSchin
245da2e3ebdSchin #if __STD_C
vmflinit(void)246da2e3ebdSchin static int vmflinit(void)
247da2e3ebdSchin #else
248da2e3ebdSchin static int vmflinit()
249da2e3ebdSchin #endif
250da2e3ebdSchin {
251da2e3ebdSchin char* file;
252da2e3ebdSchin int line;
253da2e3ebdSchin Void_t* func;
254da2e3ebdSchin
255da2e3ebdSchin /* this must be done now to avoid any inadvertent recursion (more below) */
256da2e3ebdSchin _Vmflinit = 1;
257da2e3ebdSchin VMFLF(Vmregion,file,line,func);
258da2e3ebdSchin
2593e14f97fSRoger A. Faulkner /* if getenv() calls malloc(), the options may not affect the eventual region */
2603e14f97fSRoger A. Faulkner VMOPTIONS();
261da2e3ebdSchin
262da2e3ebdSchin /* reset file and line number to correct values for the call */
263da2e3ebdSchin Vmregion->file = file;
264da2e3ebdSchin Vmregion->line = line;
265da2e3ebdSchin Vmregion->func = func;
266da2e3ebdSchin
267da2e3ebdSchin return 0;
268da2e3ebdSchin }
269da2e3ebdSchin
270*b30d1939SAndy Fiddaman /* use multiple regions to reduce blocking by concurrent threads */
271*b30d1939SAndy Fiddaman #if _mem_mmap_anon || _mem_mmap_zero
272*b30d1939SAndy Fiddaman static Vmalloc_t *Region[64]; /* list of concurrent regions */
273*b30d1939SAndy Fiddaman static unsigned int Regmax = 64; /* max number of regions */
274*b30d1939SAndy Fiddaman #else
275*b30d1939SAndy Fiddaman static Vmalloc_t* Region[1]; /* list of concurrent regions */
276*b30d1939SAndy Fiddaman static unsigned int Regmax = 0;
277*b30d1939SAndy Fiddaman #endif
278*b30d1939SAndy Fiddaman static unsigned int Regnum = 0; /* current #concurrent regions */
279*b30d1939SAndy Fiddaman
280*b30d1939SAndy Fiddaman /* statistics */
281*b30d1939SAndy Fiddaman static unsigned int Regopen = 0; /* #allocation calls opened */
282*b30d1939SAndy Fiddaman static unsigned int Reglock = 0; /* #allocation calls locked */
283*b30d1939SAndy Fiddaman static unsigned int Regprobe = 0; /* #probes to find a region */
284*b30d1939SAndy Fiddaman
setregmax(int regmax)285*b30d1939SAndy Fiddaman int setregmax(int regmax)
286*b30d1939SAndy Fiddaman {
287*b30d1939SAndy Fiddaman int oldmax = Regmax;
288*b30d1939SAndy Fiddaman
289*b30d1939SAndy Fiddaman if(regmax >= Regnum && regmax <= sizeof(Region)/sizeof(Region[0]))
290*b30d1939SAndy Fiddaman Regmax = regmax;
291*b30d1939SAndy Fiddaman
292*b30d1939SAndy Fiddaman return oldmax;
293*b30d1939SAndy Fiddaman }
294*b30d1939SAndy Fiddaman
295*b30d1939SAndy Fiddaman /* return statistics */
_mallocstat(Vmstat_t * st)296*b30d1939SAndy Fiddaman int _mallocstat(Vmstat_t* st)
297*b30d1939SAndy Fiddaman {
298*b30d1939SAndy Fiddaman Vmstat_t vmst;
299*b30d1939SAndy Fiddaman int k;
300*b30d1939SAndy Fiddaman
301*b30d1939SAndy Fiddaman if(vmstat(Vmregion, st) < 0) /* add up all stats */
302*b30d1939SAndy Fiddaman return -1;
303*b30d1939SAndy Fiddaman for(k = 0; k < Regnum; ++k)
304*b30d1939SAndy Fiddaman { if(!Region[k])
305*b30d1939SAndy Fiddaman continue;
306*b30d1939SAndy Fiddaman if(vmstat(Region[k], &vmst) < 0 )
307*b30d1939SAndy Fiddaman return -1;
308*b30d1939SAndy Fiddaman st->n_busy += vmst.n_busy;
309*b30d1939SAndy Fiddaman st->n_free += vmst.n_free;
310*b30d1939SAndy Fiddaman st->s_busy += vmst.s_busy;
311*b30d1939SAndy Fiddaman st->s_free += vmst.s_free;
312*b30d1939SAndy Fiddaman st->m_busy += vmst.m_busy;
313*b30d1939SAndy Fiddaman st->m_free += vmst.m_free;
314*b30d1939SAndy Fiddaman st->n_seg += vmst.n_seg;
315*b30d1939SAndy Fiddaman st->extent += vmst.extent;
316*b30d1939SAndy Fiddaman }
317*b30d1939SAndy Fiddaman
318*b30d1939SAndy Fiddaman st->n_region = Regnum+1;
319*b30d1939SAndy Fiddaman st->n_open = Regopen;
320*b30d1939SAndy Fiddaman st->n_lock = Reglock;
321*b30d1939SAndy Fiddaman st->n_probe = Regprobe;
322*b30d1939SAndy Fiddaman
323*b30d1939SAndy Fiddaman return 0;
324*b30d1939SAndy Fiddaman }
325*b30d1939SAndy Fiddaman
326*b30d1939SAndy Fiddaman /* find the region that a block was allocated from */
regionof(Void_t * addr)327*b30d1939SAndy Fiddaman static Vmalloc_t* regionof(Void_t* addr)
328*b30d1939SAndy Fiddaman {
329*b30d1939SAndy Fiddaman int k;
330*b30d1939SAndy Fiddaman
331*b30d1939SAndy Fiddaman #if USE_NATIVE
332*b30d1939SAndy Fiddaman #define CAUTIOUS 1
333*b30d1939SAndy Fiddaman #else
334*b30d1939SAndy Fiddaman #define CAUTIOUS 0
335*b30d1939SAndy Fiddaman #endif
336*b30d1939SAndy Fiddaman if(CAUTIOUS || Vmregion->meth.meth != VM_MTBEST )
337*b30d1939SAndy Fiddaman { /* addr will not be dereferenced here */
338*b30d1939SAndy Fiddaman if(vmaddr(Vmregion,addr) == 0 )
339*b30d1939SAndy Fiddaman return Vmregion;
340*b30d1939SAndy Fiddaman for(k = 0; k < Regnum; ++k)
341*b30d1939SAndy Fiddaman if(Region[k] && vmaddr(Region[k], addr) == 0 )
342*b30d1939SAndy Fiddaman return Region[k];
343*b30d1939SAndy Fiddaman return NIL(Vmalloc_t*);
344*b30d1939SAndy Fiddaman }
345*b30d1939SAndy Fiddaman else
346*b30d1939SAndy Fiddaman { /* fast, but susceptible to bad data */
347*b30d1939SAndy Fiddaman Vmdata_t *vd = SEG(BLOCK(addr))->vmdt;
348*b30d1939SAndy Fiddaman if(Vmregion->data == vd )
349*b30d1939SAndy Fiddaman return Vmregion;
350*b30d1939SAndy Fiddaman for(k = 0; k < Regnum; ++k)
351*b30d1939SAndy Fiddaman if(Region[k] && Region[k]->data == vd)
352*b30d1939SAndy Fiddaman return Region[k];
353*b30d1939SAndy Fiddaman return NIL(Vmalloc_t*);
354*b30d1939SAndy Fiddaman }
355*b30d1939SAndy Fiddaman }
356*b30d1939SAndy Fiddaman
357*b30d1939SAndy Fiddaman /* manage a cache of free objects */
358*b30d1939SAndy Fiddaman typedef struct _regfree_s
359*b30d1939SAndy Fiddaman { struct _regfree_s* next;
360*b30d1939SAndy Fiddaman } Regfree_t;
361*b30d1939SAndy Fiddaman static Regfree_t *Regfree;
362*b30d1939SAndy Fiddaman
addfreelist(Regfree_t * data)363*b30d1939SAndy Fiddaman static void addfreelist(Regfree_t* data)
364*b30d1939SAndy Fiddaman {
365*b30d1939SAndy Fiddaman unsigned int k;
366*b30d1939SAndy Fiddaman Regfree_t *head;
367*b30d1939SAndy Fiddaman
368*b30d1939SAndy Fiddaman for(k = 0;; ASOLOOP(k) )
369*b30d1939SAndy Fiddaman { data->next = head = Regfree;
370*b30d1939SAndy Fiddaman if(asocasptr(&Regfree, head, data) == (Void_t*)head )
371*b30d1939SAndy Fiddaman return;
372*b30d1939SAndy Fiddaman }
373*b30d1939SAndy Fiddaman }
374*b30d1939SAndy Fiddaman
clrfreelist()375*b30d1939SAndy Fiddaman static void clrfreelist()
376*b30d1939SAndy Fiddaman {
377*b30d1939SAndy Fiddaman Regfree_t *list, *next;
378*b30d1939SAndy Fiddaman Vmalloc_t *vm;
379*b30d1939SAndy Fiddaman
380*b30d1939SAndy Fiddaman if(!(list = Regfree) )
381*b30d1939SAndy Fiddaman return; /* nothing to do */
382*b30d1939SAndy Fiddaman
383*b30d1939SAndy Fiddaman if(asocasptr(&Regfree, list, NIL(Regfree_t*)) != list )
384*b30d1939SAndy Fiddaman return; /* somebody else is doing it */
385*b30d1939SAndy Fiddaman
386*b30d1939SAndy Fiddaman for(; list; list = next)
387*b30d1939SAndy Fiddaman { next = list->next;
388*b30d1939SAndy Fiddaman if(vm = regionof((Void_t*)list))
389*b30d1939SAndy Fiddaman { if(asocasint(&vm->data->lock, 0, 1) == 0) /* can free this now */
390*b30d1939SAndy Fiddaman { (void)(*vm->meth.freef)(vm, (Void_t*)list, 1);
391*b30d1939SAndy Fiddaman vm->data->lock = 0;
392*b30d1939SAndy Fiddaman }
393*b30d1939SAndy Fiddaman else addfreelist(list); /* ah well, back in the queue */
394*b30d1939SAndy Fiddaman }
395*b30d1939SAndy Fiddaman }
396*b30d1939SAndy Fiddaman }
397*b30d1939SAndy Fiddaman
398*b30d1939SAndy Fiddaman /* get a suitable region to allocate from */
399*b30d1939SAndy Fiddaman typedef struct _regdisc_s
400*b30d1939SAndy Fiddaman { Vmdisc_t disc;
401*b30d1939SAndy Fiddaman char slop[64]; /* to absorb any extra data in Vmdcsystem */
402*b30d1939SAndy Fiddaman } Regdisc_t;
403*b30d1939SAndy Fiddaman
regexcept(Vmalloc_t * vm,int type,Void_t * data,Vmdisc_t * disc)404*b30d1939SAndy Fiddaman static int regexcept(Vmalloc_t* vm, int type, Void_t* data, Vmdisc_t* disc)
405*b30d1939SAndy Fiddaman {
406*b30d1939SAndy Fiddaman if(type == VM_OPEN)
407*b30d1939SAndy Fiddaman { if(data) /* make vmopen allocate all memory using discipline */
408*b30d1939SAndy Fiddaman *(Void_t**)data = data; /* just make it non-NULL */
409*b30d1939SAndy Fiddaman return 0;
410*b30d1939SAndy Fiddaman }
411*b30d1939SAndy Fiddaman return 0;
412*b30d1939SAndy Fiddaman }
413*b30d1939SAndy Fiddaman
getregion(int * local)414*b30d1939SAndy Fiddaman static Vmalloc_t* getregion(int* local)
415*b30d1939SAndy Fiddaman {
416*b30d1939SAndy Fiddaman Vmalloc_t *vm;
417*b30d1939SAndy Fiddaman int p, pos;
418*b30d1939SAndy Fiddaman
419*b30d1939SAndy Fiddaman static unsigned int Rand = 0xdeadbeef; /* a cheap prng */
420*b30d1939SAndy Fiddaman #define RAND() (Rand = Rand*16777617 + 3)
421*b30d1939SAndy Fiddaman
422*b30d1939SAndy Fiddaman clrfreelist();
423*b30d1939SAndy Fiddaman
424*b30d1939SAndy Fiddaman if(Regmax <= 0 )
425*b30d1939SAndy Fiddaman { /* uni-process/thread */
426*b30d1939SAndy Fiddaman *local = 1;
427*b30d1939SAndy Fiddaman Vmregion->data->lock = 1;
428*b30d1939SAndy Fiddaman return Vmregion;
429*b30d1939SAndy Fiddaman }
430*b30d1939SAndy Fiddaman else if(asocasint(&Vmregion->data->lock, 0, 1) == 0 )
431*b30d1939SAndy Fiddaman { /* Vmregion is open, so use it */
432*b30d1939SAndy Fiddaman *local = 1;
433*b30d1939SAndy Fiddaman asoincint(&Regopen);
434*b30d1939SAndy Fiddaman return Vmregion;
435*b30d1939SAndy Fiddaman }
436*b30d1939SAndy Fiddaman
437*b30d1939SAndy Fiddaman asoincint(&Regprobe); /* probe Region[] to find an open region */
438*b30d1939SAndy Fiddaman if(Regnum == 0)
439*b30d1939SAndy Fiddaman pos = 0;
440*b30d1939SAndy Fiddaman else for(pos = p = RAND()%Regnum;; )
441*b30d1939SAndy Fiddaman { if(Region[p] && asocasint(&Region[p]->data->lock, 0, 1) == 0 )
442*b30d1939SAndy Fiddaman { *local = 1;
443*b30d1939SAndy Fiddaman asoincint(&Regopen);
444*b30d1939SAndy Fiddaman return Region[p];
445*b30d1939SAndy Fiddaman }
446*b30d1939SAndy Fiddaman if((p = (p+1)%Regnum) == pos )
447*b30d1939SAndy Fiddaman break;
448*b30d1939SAndy Fiddaman }
449*b30d1939SAndy Fiddaman
450*b30d1939SAndy Fiddaman /* grab the next open slot for a new region */
451*b30d1939SAndy Fiddaman while((p = Regnum) < Regmax)
452*b30d1939SAndy Fiddaman if(asocasint(&Regnum, p, p+1) == p )
453*b30d1939SAndy Fiddaman break;
454*b30d1939SAndy Fiddaman if(p < Regmax) /* this slot is now ours */
455*b30d1939SAndy Fiddaman { static Regdisc_t Regdisc;
456*b30d1939SAndy Fiddaman if(!Regdisc.disc.exceptf) /* one time initialization */
457*b30d1939SAndy Fiddaman { GETPAGESIZE(_Vmpagesize);
458*b30d1939SAndy Fiddaman memcpy(&Regdisc, Vmdcsystem, Vmdcsystem->size);
459*b30d1939SAndy Fiddaman Regdisc.disc.round = ROUND(_Vmpagesize, 64*1024);
460*b30d1939SAndy Fiddaman Regdisc.disc.exceptf = regexcept;
461*b30d1939SAndy Fiddaman }
462*b30d1939SAndy Fiddaman
463*b30d1939SAndy Fiddaman /**/ASSERT(Region[p] == NIL(Vmalloc_t*));
464*b30d1939SAndy Fiddaman if((vm = vmopen(&Regdisc.disc, Vmbest, VM_SHARE)) != NIL(Vmalloc_t*) )
465*b30d1939SAndy Fiddaman { vm->data->lock = 1; /* lock new region now */
466*b30d1939SAndy Fiddaman *local = 1;
467*b30d1939SAndy Fiddaman asoincint(&Regopen);
468*b30d1939SAndy Fiddaman return (Region[p] = vm);
469*b30d1939SAndy Fiddaman }
470*b30d1939SAndy Fiddaman else Region[p] = Vmregion; /* better than nothing */
471*b30d1939SAndy Fiddaman }
472*b30d1939SAndy Fiddaman
473*b30d1939SAndy Fiddaman /* must return something */
474*b30d1939SAndy Fiddaman vm = Region[pos] ? Region[pos] : Vmregion;
475*b30d1939SAndy Fiddaman if(asocasint(&vm->data->lock, 0, 1) == 0)
476*b30d1939SAndy Fiddaman { *local = 1;
477*b30d1939SAndy Fiddaman asoincint(&Regopen);
478*b30d1939SAndy Fiddaman }
479*b30d1939SAndy Fiddaman else
480*b30d1939SAndy Fiddaman { *local = 0;
481*b30d1939SAndy Fiddaman asoincint(&Reglock);
482*b30d1939SAndy Fiddaman }
483*b30d1939SAndy Fiddaman return vm;
484*b30d1939SAndy Fiddaman }
485*b30d1939SAndy Fiddaman
486da2e3ebdSchin #if __STD_C
calloc(reg size_t n_obj,reg size_t s_obj)487da2e3ebdSchin extern Void_t* calloc(reg size_t n_obj, reg size_t s_obj)
488da2e3ebdSchin #else
489da2e3ebdSchin extern Void_t* calloc(n_obj, s_obj)
490da2e3ebdSchin reg size_t n_obj;
491da2e3ebdSchin reg size_t s_obj;
492da2e3ebdSchin #endif
493da2e3ebdSchin {
494*b30d1939SAndy Fiddaman Void_t *addr;
495*b30d1939SAndy Fiddaman Vmalloc_t *vm;
496*b30d1939SAndy Fiddaman int local = 0;
497da2e3ebdSchin VMFLINIT();
498*b30d1939SAndy Fiddaman
499*b30d1939SAndy Fiddaman vm = getregion(&local);
500*b30d1939SAndy Fiddaman addr = (*vm->meth.resizef)(vm, NIL(Void_t*), n_obj*s_obj, VM_RSZERO, local);
501*b30d1939SAndy Fiddaman if(local)
502*b30d1939SAndy Fiddaman { /**/ASSERT(vm->data->lock == 1);
503*b30d1939SAndy Fiddaman vm->data->lock = 0;
504*b30d1939SAndy Fiddaman }
505*b30d1939SAndy Fiddaman return VMRECORD(addr);
506da2e3ebdSchin }
507da2e3ebdSchin
508da2e3ebdSchin #if __STD_C
malloc(reg size_t size)509da2e3ebdSchin extern Void_t* malloc(reg size_t size)
510da2e3ebdSchin #else
511da2e3ebdSchin extern Void_t* malloc(size)
512da2e3ebdSchin reg size_t size;
513da2e3ebdSchin #endif
514da2e3ebdSchin {
515*b30d1939SAndy Fiddaman Void_t *addr;
516*b30d1939SAndy Fiddaman Vmalloc_t *vm;
517*b30d1939SAndy Fiddaman int local = 0;
518da2e3ebdSchin VMFLINIT();
519*b30d1939SAndy Fiddaman
520*b30d1939SAndy Fiddaman vm = getregion(&local);
521*b30d1939SAndy Fiddaman addr = (*vm->meth.allocf)(vm, size, local);
522*b30d1939SAndy Fiddaman if(local)
523*b30d1939SAndy Fiddaman { /**/ASSERT(vm->data->lock == 1);
524*b30d1939SAndy Fiddaman vm->data->lock = 0;
525*b30d1939SAndy Fiddaman }
526*b30d1939SAndy Fiddaman return VMRECORD(addr);
527da2e3ebdSchin }
528da2e3ebdSchin
529da2e3ebdSchin #if __STD_C
realloc(reg Void_t * data,reg size_t size)530da2e3ebdSchin extern Void_t* realloc(reg Void_t* data, reg size_t size)
531da2e3ebdSchin #else
532da2e3ebdSchin extern Void_t* realloc(data,size)
533da2e3ebdSchin reg Void_t* data; /* block to be reallocated */
534da2e3ebdSchin reg size_t size; /* new size */
535da2e3ebdSchin #endif
536da2e3ebdSchin {
537*b30d1939SAndy Fiddaman ssize_t copy;
538*b30d1939SAndy Fiddaman Void_t *addr;
539*b30d1939SAndy Fiddaman Vmalloc_t *vm;
540da2e3ebdSchin VMFLINIT();
541da2e3ebdSchin
542*b30d1939SAndy Fiddaman if(!data)
543*b30d1939SAndy Fiddaman return malloc(size);
544*b30d1939SAndy Fiddaman else if((vm = regionof(data)) )
545*b30d1939SAndy Fiddaman { if(vm == Vmregion && vm != Vmheap) /* no multiple region usage here */
546*b30d1939SAndy Fiddaman { addr = (*vm->meth.resizef)(vm, data, size, VM_RSCOPY|VM_RSMOVE, 0);
547*b30d1939SAndy Fiddaman return VMRECORD(addr);
548*b30d1939SAndy Fiddaman }
549*b30d1939SAndy Fiddaman if(asocasint(&vm->data->lock, 0, 1) == 0 ) /* region is open */
550*b30d1939SAndy Fiddaman { addr = (*vm->meth.resizef)(vm, data, size, VM_RSCOPY|VM_RSMOVE, 1);
551*b30d1939SAndy Fiddaman vm->data->lock = 0;
552*b30d1939SAndy Fiddaman return VMRECORD(addr);
553*b30d1939SAndy Fiddaman }
554*b30d1939SAndy Fiddaman else if(Regmax > 0 && Vmregion == Vmheap && (addr = malloc(size)) )
555*b30d1939SAndy Fiddaman { if((copy = SIZE(BLOCK(data))&~BITS) > size )
556*b30d1939SAndy Fiddaman copy = size;
557*b30d1939SAndy Fiddaman memcpy(addr, data, copy);
558*b30d1939SAndy Fiddaman addfreelist((Regfree_t*)data);
559*b30d1939SAndy Fiddaman return VMRECORD(addr);
560*b30d1939SAndy Fiddaman }
561*b30d1939SAndy Fiddaman else /* this may block but it is the best that we can do now */
562*b30d1939SAndy Fiddaman { addr = (*vm->meth.resizef)(vm, data, size, VM_RSCOPY|VM_RSMOVE, 0);
563*b30d1939SAndy Fiddaman return VMRECORD(addr);
564*b30d1939SAndy Fiddaman }
565*b30d1939SAndy Fiddaman }
566*b30d1939SAndy Fiddaman else /* not our data */
567*b30d1939SAndy Fiddaman {
568da2e3ebdSchin #if USE_NATIVE
569*b30d1939SAndy Fiddaman #undef realloc /* let the native realloc() take care of it */
570*b30d1939SAndy Fiddaman #if __STD_C
571*b30d1939SAndy Fiddaman extern Void_t* realloc(Void_t*, size_t);
572da2e3ebdSchin #else
573*b30d1939SAndy Fiddaman extern Void_t* realloc();
574da2e3ebdSchin #endif
575*b30d1939SAndy Fiddaman return realloc(data, size);
576*b30d1939SAndy Fiddaman #else
577*b30d1939SAndy Fiddaman return NIL(Void_t*);
578da2e3ebdSchin #endif
579da2e3ebdSchin }
580da2e3ebdSchin }
581da2e3ebdSchin
582da2e3ebdSchin #if __STD_C
free(reg Void_t * data)583da2e3ebdSchin extern void free(reg Void_t* data)
584da2e3ebdSchin #else
585da2e3ebdSchin extern void free(data)
586da2e3ebdSchin reg Void_t* data;
587da2e3ebdSchin #endif
588da2e3ebdSchin {
589*b30d1939SAndy Fiddaman Vmalloc_t *vm;
590da2e3ebdSchin VMFLINIT();
591da2e3ebdSchin
592*b30d1939SAndy Fiddaman if(!data || (_Vmassert & VM_keep))
593*b30d1939SAndy Fiddaman return;
594*b30d1939SAndy Fiddaman else if((vm = regionof(data)) )
595*b30d1939SAndy Fiddaman {
596*b30d1939SAndy Fiddaman if(vm == Vmregion && Vmregion != Vmheap || (_Vmassert & VM_free))
597*b30d1939SAndy Fiddaman (void)(*vm->meth.freef)(vm, data, 0);
598*b30d1939SAndy Fiddaman else addfreelist((Regfree_t*)data);
599*b30d1939SAndy Fiddaman return;
600*b30d1939SAndy Fiddaman }
601*b30d1939SAndy Fiddaman else /* not our data */
602da2e3ebdSchin {
603da2e3ebdSchin #if USE_NATIVE
604*b30d1939SAndy Fiddaman #undef free /* let the native free() take care of it */
605*b30d1939SAndy Fiddaman #if __STD_C
606*b30d1939SAndy Fiddaman extern void free(Void_t*);
607*b30d1939SAndy Fiddaman #else
608*b30d1939SAndy Fiddaman extern void free();
609*b30d1939SAndy Fiddaman #endif
610da2e3ebdSchin free(data);
611da2e3ebdSchin #endif
612da2e3ebdSchin return;
613da2e3ebdSchin }
614da2e3ebdSchin }
615da2e3ebdSchin
616da2e3ebdSchin #if __STD_C
cfree(reg Void_t * data)617da2e3ebdSchin extern void cfree(reg Void_t* data)
618da2e3ebdSchin #else
619da2e3ebdSchin extern void cfree(data)
620da2e3ebdSchin reg Void_t* data;
621da2e3ebdSchin #endif
622da2e3ebdSchin {
623da2e3ebdSchin free(data);
624da2e3ebdSchin }
625da2e3ebdSchin
626da2e3ebdSchin #if __STD_C
memalign(reg size_t align,reg size_t size)627da2e3ebdSchin extern Void_t* memalign(reg size_t align, reg size_t size)
628da2e3ebdSchin #else
629da2e3ebdSchin extern Void_t* memalign(align, size)
630da2e3ebdSchin reg size_t align;
631da2e3ebdSchin reg size_t size;
632da2e3ebdSchin #endif
633da2e3ebdSchin {
634*b30d1939SAndy Fiddaman Void_t *addr;
635*b30d1939SAndy Fiddaman Vmalloc_t *vm;
636*b30d1939SAndy Fiddaman int local = 0;
637da2e3ebdSchin VMFLINIT();
638*b30d1939SAndy Fiddaman
639*b30d1939SAndy Fiddaman vm = getregion(&local);
640da2e3ebdSchin VMBLOCK
641*b30d1939SAndy Fiddaman addr = (*vm->meth.alignf)(vm, size, align, local);
642*b30d1939SAndy Fiddaman if(local)
643*b30d1939SAndy Fiddaman { /**/ASSERT(vm->data->lock == 1);
644*b30d1939SAndy Fiddaman vm->data->lock = 0;
645*b30d1939SAndy Fiddaman }
646da2e3ebdSchin VMUNBLOCK
647*b30d1939SAndy Fiddaman return VMRECORD(addr);
648da2e3ebdSchin }
649da2e3ebdSchin
65034f9b3eeSRoland Mainz #if __STD_C
posix_memalign(reg Void_t ** memptr,reg size_t align,reg size_t size)65134f9b3eeSRoland Mainz extern int posix_memalign(reg Void_t **memptr, reg size_t align, reg size_t size)
65234f9b3eeSRoland Mainz #else
65334f9b3eeSRoland Mainz extern int posix_memalign(memptr, align, size)
65434f9b3eeSRoland Mainz reg Void_t** memptr;
65534f9b3eeSRoland Mainz reg size_t align;
65634f9b3eeSRoland Mainz reg size_t size;
65734f9b3eeSRoland Mainz #endif
65834f9b3eeSRoland Mainz {
65934f9b3eeSRoland Mainz Void_t *mem;
66034f9b3eeSRoland Mainz
66134f9b3eeSRoland Mainz if(align == 0 || (align%sizeof(Void_t*)) != 0 || ((align-1)&align) != 0 )
66234f9b3eeSRoland Mainz return EINVAL;
66334f9b3eeSRoland Mainz
66434f9b3eeSRoland Mainz if(!(mem = memalign(align, size)) )
66534f9b3eeSRoland Mainz return ENOMEM;
66634f9b3eeSRoland Mainz
66734f9b3eeSRoland Mainz *memptr = mem;
66834f9b3eeSRoland Mainz return 0;
66934f9b3eeSRoland Mainz }
67034f9b3eeSRoland Mainz
671da2e3ebdSchin #if __STD_C
valloc(reg size_t size)672da2e3ebdSchin extern Void_t* valloc(reg size_t size)
673da2e3ebdSchin #else
674da2e3ebdSchin extern Void_t* valloc(size)
675da2e3ebdSchin reg size_t size;
676da2e3ebdSchin #endif
677da2e3ebdSchin {
678da2e3ebdSchin VMFLINIT();
679*b30d1939SAndy Fiddaman
680da2e3ebdSchin GETPAGESIZE(_Vmpagesize);
681*b30d1939SAndy Fiddaman return VMRECORD(memalign(_Vmpagesize, size));
682da2e3ebdSchin }
683da2e3ebdSchin
684da2e3ebdSchin #if __STD_C
pvalloc(reg size_t size)685da2e3ebdSchin extern Void_t* pvalloc(reg size_t size)
686da2e3ebdSchin #else
687da2e3ebdSchin extern Void_t* pvalloc(size)
688da2e3ebdSchin reg size_t size;
689da2e3ebdSchin #endif
690da2e3ebdSchin {
691da2e3ebdSchin VMFLINIT();
692*b30d1939SAndy Fiddaman
693da2e3ebdSchin GETPAGESIZE(_Vmpagesize);
694*b30d1939SAndy Fiddaman return VMRECORD(memalign(_Vmpagesize, ROUND(size,_Vmpagesize)) );
695da2e3ebdSchin }
696da2e3ebdSchin
697da2e3ebdSchin #if !_PACKAGE_ast
698da2e3ebdSchin #if __STD_C
strdup(const char * s)699da2e3ebdSchin char* strdup(const char* s)
700da2e3ebdSchin #else
701da2e3ebdSchin char* strdup(s)
702da2e3ebdSchin char* s;
703da2e3ebdSchin #endif
704da2e3ebdSchin {
705da2e3ebdSchin char *ns;
706da2e3ebdSchin size_t n;
707da2e3ebdSchin
708da2e3ebdSchin if(!s)
709da2e3ebdSchin return NIL(char*);
710da2e3ebdSchin else
711da2e3ebdSchin { n = strlen(s);
712da2e3ebdSchin if((ns = malloc(n+1)) )
713da2e3ebdSchin memcpy(ns,s,n+1);
714da2e3ebdSchin return ns;
715da2e3ebdSchin }
716da2e3ebdSchin }
717da2e3ebdSchin #endif /* _PACKAGE_ast */
718da2e3ebdSchin
719da2e3ebdSchin #if !_lib_alloca || _mal_alloca
720da2e3ebdSchin #ifndef _stk_down
721da2e3ebdSchin #define _stk_down 0
722da2e3ebdSchin #endif
723da2e3ebdSchin typedef struct _alloca_s Alloca_t;
724da2e3ebdSchin union _alloca_u
725da2e3ebdSchin { struct
726da2e3ebdSchin { char* addr;
727da2e3ebdSchin Alloca_t* next;
728da2e3ebdSchin } head;
729da2e3ebdSchin char array[ALIGN];
730da2e3ebdSchin };
731da2e3ebdSchin struct _alloca_s
732da2e3ebdSchin { union _alloca_u head;
733da2e3ebdSchin Vmuchar_t data[1];
734da2e3ebdSchin };
735da2e3ebdSchin
736da2e3ebdSchin #if __STD_C
alloca(size_t size)737da2e3ebdSchin extern Void_t* alloca(size_t size)
738da2e3ebdSchin #else
739da2e3ebdSchin extern Void_t* alloca(size)
740da2e3ebdSchin size_t size;
741da2e3ebdSchin #endif
742da2e3ebdSchin { char array[ALIGN];
743da2e3ebdSchin char* file;
744da2e3ebdSchin int line;
745da2e3ebdSchin Void_t* func;
746*b30d1939SAndy Fiddaman Alloca_t* f;
747*b30d1939SAndy Fiddaman Vmalloc_t *vm;
748da2e3ebdSchin static Alloca_t* Frame;
749da2e3ebdSchin
750da2e3ebdSchin VMFLINIT();
751*b30d1939SAndy Fiddaman
752*b30d1939SAndy Fiddaman VMFLF(Vmregion,file,line,func); /* save info before freeing frames */
753*b30d1939SAndy Fiddaman
754*b30d1939SAndy Fiddaman while(Frame) /* free unused frames */
755da2e3ebdSchin { if(( _stk_down && &array[0] > Frame->head.head.addr) ||
756da2e3ebdSchin (!_stk_down && &array[0] < Frame->head.head.addr) )
757*b30d1939SAndy Fiddaman { f = Frame; Frame = f->head.head.next;
758*b30d1939SAndy Fiddaman if((vm = regionof(f)) )
759*b30d1939SAndy Fiddaman (void)(*vm->meth.freef)(vm, f, 0);
760*b30d1939SAndy Fiddaman /* else: something bad happened. just keep going */
761da2e3ebdSchin }
762da2e3ebdSchin else break;
763da2e3ebdSchin }
764da2e3ebdSchin
765*b30d1939SAndy Fiddaman Vmregion->file = file; /* restore file/line info before allocation */
766da2e3ebdSchin Vmregion->line = line;
767da2e3ebdSchin Vmregion->func = func;
768da2e3ebdSchin
769*b30d1939SAndy Fiddaman f = (Alloca_t*)(*Vmregion->meth.allocf)(Vmregion, size+sizeof(Alloca_t)-1, 0);
770*b30d1939SAndy Fiddaman
771*b30d1939SAndy Fiddaman /* if f is NULL, this mimics a stack overflow with a memory error! */
772da2e3ebdSchin f->head.head.addr = &array[0];
773da2e3ebdSchin f->head.head.next = Frame;
774da2e3ebdSchin Frame = f;
775da2e3ebdSchin
776da2e3ebdSchin return (Void_t*)f->data;
777da2e3ebdSchin }
778da2e3ebdSchin #endif /*!_lib_alloca || _mal_alloca*/
779da2e3ebdSchin
780da2e3ebdSchin #if _map_malloc
781da2e3ebdSchin
782da2e3ebdSchin /* not sure of all the implications -- 0 is conservative for now */
783da2e3ebdSchin #define USE_NATIVE 0 /* native free/realloc on non-vmalloc ptrs */
784da2e3ebdSchin
785da2e3ebdSchin #else
786da2e3ebdSchin
787*b30d1939SAndy Fiddaman #if _malloc_hook
788*b30d1939SAndy Fiddaman
vm_free_hook(void * ptr,const void * caller)789*b30d1939SAndy Fiddaman static void vm_free_hook(void* ptr, const void* caller)
790*b30d1939SAndy Fiddaman {
791*b30d1939SAndy Fiddaman free(ptr);
792*b30d1939SAndy Fiddaman }
793*b30d1939SAndy Fiddaman
vm_malloc_hook(size_t size,const void * caller)794*b30d1939SAndy Fiddaman static void* vm_malloc_hook(size_t size, const void* caller)
795*b30d1939SAndy Fiddaman {
796*b30d1939SAndy Fiddaman void* r;
797*b30d1939SAndy Fiddaman
798*b30d1939SAndy Fiddaman r = malloc(size);
799*b30d1939SAndy Fiddaman return r;
800*b30d1939SAndy Fiddaman }
801*b30d1939SAndy Fiddaman
vm_memalign_hook(size_t align,size_t size,const void * caller)802*b30d1939SAndy Fiddaman static void* vm_memalign_hook(size_t align, size_t size, const void* caller)
803*b30d1939SAndy Fiddaman {
804*b30d1939SAndy Fiddaman void* r;
805*b30d1939SAndy Fiddaman
806*b30d1939SAndy Fiddaman r = memalign(align, size);
807*b30d1939SAndy Fiddaman return r;
808*b30d1939SAndy Fiddaman }
809*b30d1939SAndy Fiddaman
vm_realloc_hook(void * ptr,size_t size,const void * caller)810*b30d1939SAndy Fiddaman static void* vm_realloc_hook(void* ptr, size_t size, const void* caller)
811*b30d1939SAndy Fiddaman {
812*b30d1939SAndy Fiddaman void* r;
813*b30d1939SAndy Fiddaman
814*b30d1939SAndy Fiddaman r = realloc(ptr, size);
815*b30d1939SAndy Fiddaman return r;
816*b30d1939SAndy Fiddaman }
817*b30d1939SAndy Fiddaman
vm_initialize_hook(void)818*b30d1939SAndy Fiddaman static void vm_initialize_hook(void)
819*b30d1939SAndy Fiddaman {
820*b30d1939SAndy Fiddaman __free_hook = vm_free_hook;
821*b30d1939SAndy Fiddaman __malloc_hook = vm_malloc_hook;
822*b30d1939SAndy Fiddaman __memalign_hook = vm_memalign_hook;
823*b30d1939SAndy Fiddaman __realloc_hook = vm_realloc_hook;
824*b30d1939SAndy Fiddaman }
825*b30d1939SAndy Fiddaman
826*b30d1939SAndy Fiddaman void (*__malloc_initialize_hook)(void) = vm_initialize_hook;
827*b30d1939SAndy Fiddaman
828*b30d1939SAndy Fiddaman #if 0 /* 2012-02-29 this may be needed to cover shared libs */
829*b30d1939SAndy Fiddaman
830*b30d1939SAndy Fiddaman void __attribute__ ((constructor)) vm_initialize_initialize_hook(void)
831*b30d1939SAndy Fiddaman {
832*b30d1939SAndy Fiddaman vm_initialize_hook();
833*b30d1939SAndy Fiddaman __malloc_initialize_hook = vm_initialize_hook;
834*b30d1939SAndy Fiddaman }
835*b30d1939SAndy Fiddaman
836*b30d1939SAndy Fiddaman #endif
837*b30d1939SAndy Fiddaman
838*b30d1939SAndy Fiddaman #else
839*b30d1939SAndy Fiddaman
840da2e3ebdSchin /* intercept _* __* __libc_* variants */
841da2e3ebdSchin
842da2e3ebdSchin #if __lib__malloc
F2(_calloc,size_t,n,size_t,m)843da2e3ebdSchin extern Void_t* F2(_calloc, size_t,n, size_t,m) { return calloc(n, m); }
F1(_cfree,Void_t *,p)844da2e3ebdSchin extern Void_t F1(_cfree, Void_t*,p) { free(p); }
F1(_free,Void_t *,p)845da2e3ebdSchin extern Void_t F1(_free, Void_t*,p) { free(p); }
F1(_malloc,size_t,n)846da2e3ebdSchin extern Void_t* F1(_malloc, size_t,n) { return malloc(n); }
847da2e3ebdSchin #if _lib_memalign
F2(_memalign,size_t,a,size_t,n)848da2e3ebdSchin extern Void_t* F2(_memalign, size_t,a, size_t,n) { return memalign(a, n); }
849da2e3ebdSchin #endif
850da2e3ebdSchin #if _lib_pvalloc
F1(_pvalloc,size_t,n)851da2e3ebdSchin extern Void_t* F1(_pvalloc, size_t,n) { return pvalloc(n); }
852da2e3ebdSchin #endif
F2(_realloc,Void_t *,p,size_t,n)853da2e3ebdSchin extern Void_t* F2(_realloc, Void_t*,p, size_t,n) { return realloc(p, n); }
854da2e3ebdSchin #if _lib_valloc
F1(_valloc,size_t,n)855da2e3ebdSchin extern Void_t* F1(_valloc, size_t,n) { return valloc(n); }
856da2e3ebdSchin #endif
857da2e3ebdSchin #endif
858da2e3ebdSchin
859da2e3ebdSchin #if _lib___malloc
F2(__calloc,size_t,n,size_t,m)860da2e3ebdSchin extern Void_t* F2(__calloc, size_t,n, size_t,m) { return calloc(n, m); }
F1(__cfree,Void_t *,p)861da2e3ebdSchin extern Void_t F1(__cfree, Void_t*,p) { free(p); }
F1(__free,Void_t *,p)862da2e3ebdSchin extern Void_t F1(__free, Void_t*,p) { free(p); }
F1(__malloc,size_t,n)863da2e3ebdSchin extern Void_t* F1(__malloc, size_t,n) { return malloc(n); }
864da2e3ebdSchin #if _lib_memalign
F2(__memalign,size_t,a,size_t,n)865da2e3ebdSchin extern Void_t* F2(__memalign, size_t,a, size_t,n) { return memalign(a, n); }
866da2e3ebdSchin #endif
867da2e3ebdSchin #if _lib_pvalloc
F1(__pvalloc,size_t,n)868da2e3ebdSchin extern Void_t* F1(__pvalloc, size_t,n) { return pvalloc(n); }
869da2e3ebdSchin #endif
F2(__realloc,Void_t *,p,size_t,n)870da2e3ebdSchin extern Void_t* F2(__realloc, Void_t*,p, size_t,n) { return realloc(p, n); }
871da2e3ebdSchin #if _lib_valloc
F1(__valloc,size_t,n)872da2e3ebdSchin extern Void_t* F1(__valloc, size_t,n) { return valloc(n); }
873da2e3ebdSchin #endif
874da2e3ebdSchin #endif
875da2e3ebdSchin
876da2e3ebdSchin #if _lib___libc_malloc
F2(__libc_calloc,size_t,n,size_t,m)877da2e3ebdSchin extern Void_t* F2(__libc_calloc, size_t,n, size_t,m) { return calloc(n, m); }
F1(__libc_cfree,Void_t *,p)878da2e3ebdSchin extern Void_t F1(__libc_cfree, Void_t*,p) { free(p); }
F1(__libc_free,Void_t *,p)879da2e3ebdSchin extern Void_t F1(__libc_free, Void_t*,p) { free(p); }
F1(__libc_malloc,size_t,n)880da2e3ebdSchin extern Void_t* F1(__libc_malloc, size_t,n) { return malloc(n); }
881da2e3ebdSchin #if _lib_memalign
F2(__libc_memalign,size_t,a,size_t,n)882da2e3ebdSchin extern Void_t* F2(__libc_memalign, size_t,a, size_t,n) { return memalign(a, n); }
883da2e3ebdSchin #endif
884da2e3ebdSchin #if _lib_pvalloc
F1(__libc_pvalloc,size_t,n)885da2e3ebdSchin extern Void_t* F1(__libc_pvalloc, size_t,n) { return pvalloc(n); }
886da2e3ebdSchin #endif
F2(__libc_realloc,Void_t *,p,size_t,n)887da2e3ebdSchin extern Void_t* F2(__libc_realloc, Void_t*,p, size_t,n) { return realloc(p, n); }
888da2e3ebdSchin #if _lib_valloc
F1(__libc_valloc,size_t,n)889da2e3ebdSchin extern Void_t* F1(__libc_valloc, size_t,n) { return valloc(n); }
890da2e3ebdSchin #endif
891da2e3ebdSchin #endif
892da2e3ebdSchin
893*b30d1939SAndy Fiddaman #endif /* _malloc_hook */
894*b30d1939SAndy Fiddaman
895da2e3ebdSchin #endif /* _map_malloc */
896da2e3ebdSchin
897da2e3ebdSchin #undef extern
898da2e3ebdSchin
899da2e3ebdSchin #if _hdr_malloc /* need the mallint interface for statistics, etc. */
900da2e3ebdSchin
901da2e3ebdSchin #undef calloc
902da2e3ebdSchin #define calloc ______calloc
903da2e3ebdSchin #undef cfree
904da2e3ebdSchin #define cfree ______cfree
905da2e3ebdSchin #undef free
906da2e3ebdSchin #define free ______free
907da2e3ebdSchin #undef malloc
908da2e3ebdSchin #define malloc ______malloc
909da2e3ebdSchin #undef pvalloc
910da2e3ebdSchin #define pvalloc ______pvalloc
911da2e3ebdSchin #undef realloc
912da2e3ebdSchin #define realloc ______realloc
913da2e3ebdSchin #undef valloc
914da2e3ebdSchin #define valloc ______valloc
915da2e3ebdSchin
916da2e3ebdSchin #if !_UWIN
917da2e3ebdSchin
918da2e3ebdSchin #include <malloc.h>
919da2e3ebdSchin
920da2e3ebdSchin typedef struct mallinfo Mallinfo_t;
921da2e3ebdSchin typedef struct mstats Mstats_t;
922da2e3ebdSchin
923da2e3ebdSchin #endif
924da2e3ebdSchin
925da2e3ebdSchin #if defined(__EXPORT__)
926da2e3ebdSchin #define extern __EXPORT__
927da2e3ebdSchin #endif
928da2e3ebdSchin
929da2e3ebdSchin #if _lib_mallopt
930da2e3ebdSchin #if __STD_C
mallopt(int cmd,int value)931da2e3ebdSchin extern int mallopt(int cmd, int value)
932da2e3ebdSchin #else
933da2e3ebdSchin extern int mallopt(cmd, value)
934da2e3ebdSchin int cmd;
935da2e3ebdSchin int value;
936da2e3ebdSchin #endif
937da2e3ebdSchin {
938da2e3ebdSchin VMFLINIT();
939da2e3ebdSchin return 0;
940da2e3ebdSchin }
941da2e3ebdSchin #endif /*_lib_mallopt*/
942da2e3ebdSchin
943da2e3ebdSchin #if _lib_mallinfo && _mem_arena_mallinfo
944da2e3ebdSchin #if __STD_C
mallinfo(void)945da2e3ebdSchin extern Mallinfo_t mallinfo(void)
946da2e3ebdSchin #else
947da2e3ebdSchin extern Mallinfo_t mallinfo()
948da2e3ebdSchin #endif
949da2e3ebdSchin {
950da2e3ebdSchin Vmstat_t sb;
951da2e3ebdSchin Mallinfo_t mi;
952da2e3ebdSchin
953da2e3ebdSchin VMFLINIT();
954da2e3ebdSchin memset(&mi,0,sizeof(mi));
955da2e3ebdSchin if(vmstat(Vmregion,&sb) >= 0)
956da2e3ebdSchin { mi.arena = sb.extent;
957da2e3ebdSchin mi.ordblks = sb.n_busy+sb.n_free;
958da2e3ebdSchin mi.uordblks = sb.s_busy;
959da2e3ebdSchin mi.fordblks = sb.s_free;
960da2e3ebdSchin }
961da2e3ebdSchin return mi;
962da2e3ebdSchin }
963da2e3ebdSchin #endif /* _lib_mallinfo */
964da2e3ebdSchin
965da2e3ebdSchin #if _lib_mstats && _mem_bytes_total_mstats
966da2e3ebdSchin #if __STD_C
mstats(void)967da2e3ebdSchin extern Mstats_t mstats(void)
968da2e3ebdSchin #else
969da2e3ebdSchin extern Mstats_t mstats()
970da2e3ebdSchin #endif
971da2e3ebdSchin {
972da2e3ebdSchin Vmstat_t sb;
973da2e3ebdSchin Mstats_t ms;
974da2e3ebdSchin
975da2e3ebdSchin VMFLINIT();
976da2e3ebdSchin memset(&ms,0,sizeof(ms));
977da2e3ebdSchin if(vmstat(Vmregion,&sb) >= 0)
978da2e3ebdSchin { ms.bytes_total = sb.extent;
979da2e3ebdSchin ms.chunks_used = sb.n_busy;
980da2e3ebdSchin ms.bytes_used = sb.s_busy;
981da2e3ebdSchin ms.chunks_free = sb.n_free;
982da2e3ebdSchin ms.bytes_free = sb.s_free;
983da2e3ebdSchin }
984da2e3ebdSchin return ms;
985da2e3ebdSchin }
986da2e3ebdSchin #endif /*_lib_mstats*/
987da2e3ebdSchin
988da2e3ebdSchin #undef extern
989da2e3ebdSchin
990da2e3ebdSchin #endif/*_hdr_malloc*/
991da2e3ebdSchin
992da2e3ebdSchin #else
993da2e3ebdSchin
994da2e3ebdSchin /*
995da2e3ebdSchin * even though there is no malloc override, still provide
996da2e3ebdSchin * _ast_* counterparts for object compatibility
997da2e3ebdSchin */
998da2e3ebdSchin
999*b30d1939SAndy Fiddaman #define setregmax(n)
1000*b30d1939SAndy Fiddaman
1001da2e3ebdSchin #undef calloc
1002da2e3ebdSchin extern Void_t* calloc _ARG_((size_t, size_t));
1003da2e3ebdSchin
1004da2e3ebdSchin #undef cfree
1005da2e3ebdSchin extern void cfree _ARG_((Void_t*));
1006da2e3ebdSchin
1007da2e3ebdSchin #undef free
1008da2e3ebdSchin extern void free _ARG_((Void_t*));
1009da2e3ebdSchin
1010da2e3ebdSchin #undef malloc
1011da2e3ebdSchin extern Void_t* malloc _ARG_((size_t));
1012da2e3ebdSchin
1013da2e3ebdSchin #if _lib_memalign
1014da2e3ebdSchin #undef memalign
1015da2e3ebdSchin extern Void_t* memalign _ARG_((size_t, size_t));
1016da2e3ebdSchin #endif
1017da2e3ebdSchin
1018da2e3ebdSchin #if _lib_pvalloc
1019da2e3ebdSchin #undef pvalloc
1020da2e3ebdSchin extern Void_t* pvalloc _ARG_((size_t));
1021da2e3ebdSchin #endif
1022da2e3ebdSchin
1023da2e3ebdSchin #undef realloc
1024da2e3ebdSchin extern Void_t* realloc _ARG_((Void_t*, size_t));
1025da2e3ebdSchin
1026da2e3ebdSchin #if _lib_valloc
1027da2e3ebdSchin #undef valloc
1028da2e3ebdSchin extern Void_t* valloc _ARG_((size_t));
1029da2e3ebdSchin #endif
1030da2e3ebdSchin
1031da2e3ebdSchin #if defined(__EXPORT__)
1032da2e3ebdSchin #define extern __EXPORT__
1033da2e3ebdSchin #endif
1034da2e3ebdSchin
1035*b30d1939SAndy Fiddaman #if !_malloc_hook
1036*b30d1939SAndy Fiddaman
F1(_ast_free,Void_t *,p)1037da2e3ebdSchin extern Void_t F1(_ast_free, Void_t*,p) { free(p); }
F1(_ast_malloc,size_t,n)1038da2e3ebdSchin extern Void_t* F1(_ast_malloc, size_t,n) { return malloc(n); }
1039da2e3ebdSchin #if _lib_memalign
F2(_ast_memalign,size_t,a,size_t,n)1040da2e3ebdSchin extern Void_t* F2(_ast_memalign, size_t,a, size_t,n) { return memalign(a, n); }
1041da2e3ebdSchin #endif
F2(_ast_realloc,Void_t *,p,size_t,n)1042*b30d1939SAndy Fiddaman extern Void_t* F2(_ast_realloc, Void_t*,p, size_t,n) { return realloc(p, n); }
1043*b30d1939SAndy Fiddaman
1044*b30d1939SAndy Fiddaman #endif
1045*b30d1939SAndy Fiddaman
F2(_ast_calloc,size_t,n,size_t,m)1046*b30d1939SAndy Fiddaman extern Void_t* F2(_ast_calloc, size_t,n, size_t,m) { return calloc(n, m); }
F1(_ast_cfree,Void_t *,p)1047*b30d1939SAndy Fiddaman extern Void_t F1(_ast_cfree, Void_t*,p) { free(p); }
1048da2e3ebdSchin #if _lib_pvalloc
F1(_ast_pvalloc,size_t,n)1049da2e3ebdSchin extern Void_t* F1(_ast_pvalloc, size_t,n) { return pvalloc(n); }
1050da2e3ebdSchin #endif
1051da2e3ebdSchin #if _lib_valloc
F1(_ast_valloc,size_t,n)1052da2e3ebdSchin extern Void_t* F1(_ast_valloc, size_t,n) { return valloc(n); }
1053da2e3ebdSchin #endif
1054da2e3ebdSchin
1055da2e3ebdSchin #undef extern
1056da2e3ebdSchin
1057da2e3ebdSchin #if _hdr_malloc
1058da2e3ebdSchin
1059da2e3ebdSchin #undef mallinfo
1060da2e3ebdSchin #undef mallopt
1061da2e3ebdSchin #undef mstats
1062da2e3ebdSchin
1063da2e3ebdSchin #define calloc ______calloc
1064da2e3ebdSchin #define cfree ______cfree
1065da2e3ebdSchin #define free ______free
1066da2e3ebdSchin #define malloc ______malloc
1067da2e3ebdSchin #define pvalloc ______pvalloc
1068da2e3ebdSchin #define realloc ______realloc
1069da2e3ebdSchin #define valloc ______valloc
1070da2e3ebdSchin
1071da2e3ebdSchin #if !_UWIN
1072da2e3ebdSchin
1073*b30d1939SAndy Fiddaman #if !_malloc_hook
1074*b30d1939SAndy Fiddaman
1075da2e3ebdSchin #include <malloc.h>
1076da2e3ebdSchin
1077*b30d1939SAndy Fiddaman #endif
1078*b30d1939SAndy Fiddaman
1079da2e3ebdSchin typedef struct mallinfo Mallinfo_t;
1080da2e3ebdSchin typedef struct mstats Mstats_t;
1081da2e3ebdSchin
1082da2e3ebdSchin #endif
1083da2e3ebdSchin
1084da2e3ebdSchin #if defined(__EXPORT__)
1085da2e3ebdSchin #define extern __EXPORT__
1086da2e3ebdSchin #endif
1087da2e3ebdSchin
1088da2e3ebdSchin #if _lib_mallopt
F2(_ast_mallopt,int,cmd,int,value)1089da2e3ebdSchin extern int F2(_ast_mallopt, int,cmd, int,value) { return mallopt(cmd, value); }
1090da2e3ebdSchin #endif
1091da2e3ebdSchin
1092da2e3ebdSchin #if _lib_mallinfo && _mem_arena_mallinfo
F0(_ast_mallinfo,void)1093da2e3ebdSchin extern Mallinfo_t F0(_ast_mallinfo, void) { return mallinfo(); }
1094da2e3ebdSchin #endif
1095da2e3ebdSchin
1096da2e3ebdSchin #if _lib_mstats && _mem_bytes_total_mstats
F0(_ast_mstats,void)1097da2e3ebdSchin extern Mstats_t F0(_ast_mstats, void) { return mstats(); }
1098da2e3ebdSchin #endif
1099da2e3ebdSchin
1100da2e3ebdSchin #undef extern
1101da2e3ebdSchin
1102da2e3ebdSchin #endif /*_hdr_malloc*/
1103da2e3ebdSchin
1104da2e3ebdSchin #endif /*!_std_malloc*/
1105da2e3ebdSchin
11063e14f97fSRoger A. Faulkner #if __STD_C
atou(char ** sp)11073e14f97fSRoger A. Faulkner static Vmulong_t atou(char** sp)
11083e14f97fSRoger A. Faulkner #else
11093e14f97fSRoger A. Faulkner static Vmulong_t atou(sp)
11103e14f97fSRoger A. Faulkner char** sp;
11113e14f97fSRoger A. Faulkner #endif
11123e14f97fSRoger A. Faulkner {
11133e14f97fSRoger A. Faulkner char* s = *sp;
11143e14f97fSRoger A. Faulkner Vmulong_t v = 0;
11153e14f97fSRoger A. Faulkner
11163e14f97fSRoger A. Faulkner if(s[0] == '0' && (s[1] == 'x' || s[1] == 'X') )
11173e14f97fSRoger A. Faulkner { for(s += 2; *s; ++s)
11183e14f97fSRoger A. Faulkner { if(*s >= '0' && *s <= '9')
11193e14f97fSRoger A. Faulkner v = (v << 4) + (*s - '0');
11203e14f97fSRoger A. Faulkner else if(*s >= 'a' && *s <= 'f')
11213e14f97fSRoger A. Faulkner v = (v << 4) + (*s - 'a') + 10;
11223e14f97fSRoger A. Faulkner else if(*s >= 'A' && *s <= 'F')
11233e14f97fSRoger A. Faulkner v = (v << 4) + (*s - 'A') + 10;
11243e14f97fSRoger A. Faulkner else break;
11253e14f97fSRoger A. Faulkner }
11263e14f97fSRoger A. Faulkner }
11273e14f97fSRoger A. Faulkner else
11283e14f97fSRoger A. Faulkner { for(; *s; ++s)
11293e14f97fSRoger A. Faulkner { if(*s >= '0' && *s <= '9')
11303e14f97fSRoger A. Faulkner v = v*10 + (*s - '0');
11313e14f97fSRoger A. Faulkner else break;
11323e14f97fSRoger A. Faulkner }
11333e14f97fSRoger A. Faulkner }
11343e14f97fSRoger A. Faulkner
11353e14f97fSRoger A. Faulkner *sp = s;
11363e14f97fSRoger A. Faulkner return v;
11373e14f97fSRoger A. Faulkner }
11383e14f97fSRoger A. Faulkner
11393e14f97fSRoger A. Faulkner #if __STD_C
insertpid(char * begs,char * ends)11403e14f97fSRoger A. Faulkner static char* insertpid(char* begs, char* ends)
11413e14f97fSRoger A. Faulkner #else
11423e14f97fSRoger A. Faulkner static char* insertpid(begs,ends)
11433e14f97fSRoger A. Faulkner char* begs;
11443e14f97fSRoger A. Faulkner char* ends;
11453e14f97fSRoger A. Faulkner #endif
11463e14f97fSRoger A. Faulkner { int pid;
11473e14f97fSRoger A. Faulkner char* s;
11483e14f97fSRoger A. Faulkner
11493e14f97fSRoger A. Faulkner if((pid = getpid()) < 0)
11503e14f97fSRoger A. Faulkner return NIL(char*);
11513e14f97fSRoger A. Faulkner
11523e14f97fSRoger A. Faulkner s = ends;
11533e14f97fSRoger A. Faulkner do
11543e14f97fSRoger A. Faulkner { if(s == begs)
11553e14f97fSRoger A. Faulkner return NIL(char*);
11563e14f97fSRoger A. Faulkner *--s = '0' + pid%10;
11573e14f97fSRoger A. Faulkner } while((pid /= 10) > 0);
11583e14f97fSRoger A. Faulkner while(s < ends)
11593e14f97fSRoger A. Faulkner *begs++ = *s++;
11603e14f97fSRoger A. Faulkner
11613e14f97fSRoger A. Faulkner return begs;
11623e14f97fSRoger A. Faulkner }
11633e14f97fSRoger A. Faulkner
1164*b30d1939SAndy Fiddaman #define FD_PRIVATE (3*OPEN_MAX/4)
1165*b30d1939SAndy Fiddaman
1166*b30d1939SAndy Fiddaman #if __STD_C
_vmfd(int fd)1167*b30d1939SAndy Fiddaman int _vmfd(int fd)
1168*b30d1939SAndy Fiddaman #else
1169*b30d1939SAndy Fiddaman int _vmfd(fd)
1170*b30d1939SAndy Fiddaman int fd;
1171*b30d1939SAndy Fiddaman #endif
1172*b30d1939SAndy Fiddaman {
1173*b30d1939SAndy Fiddaman int pd;
1174*b30d1939SAndy Fiddaman
1175*b30d1939SAndy Fiddaman if (fd >= 0)
1176*b30d1939SAndy Fiddaman {
1177*b30d1939SAndy Fiddaman if (fd < FD_PRIVATE && (pd = fcntl(fd, F_DUPFD, FD_PRIVATE)) >= 0)
1178*b30d1939SAndy Fiddaman {
1179*b30d1939SAndy Fiddaman close(fd);
1180*b30d1939SAndy Fiddaman fd = pd;
1181*b30d1939SAndy Fiddaman }
1182*b30d1939SAndy Fiddaman #ifdef FD_CLOEXEC
1183*b30d1939SAndy Fiddaman fcntl(fd, F_SETFD, FD_CLOEXEC);
1184*b30d1939SAndy Fiddaman #endif
1185*b30d1939SAndy Fiddaman }
1186*b30d1939SAndy Fiddaman return fd;
1187*b30d1939SAndy Fiddaman }
1188*b30d1939SAndy Fiddaman
11893e14f97fSRoger A. Faulkner #if __STD_C
createfile(char * file)11903e14f97fSRoger A. Faulkner static int createfile(char* file)
11913e14f97fSRoger A. Faulkner #else
11923e14f97fSRoger A. Faulkner static int createfile(file)
11933e14f97fSRoger A. Faulkner char* file;
11943e14f97fSRoger A. Faulkner #endif
11953e14f97fSRoger A. Faulkner {
11963e14f97fSRoger A. Faulkner char buf[1024];
11973e14f97fSRoger A. Faulkner char *next, *endb;
11983e14f97fSRoger A. Faulkner int fd;
11993e14f97fSRoger A. Faulkner
12003e14f97fSRoger A. Faulkner next = buf;
12013e14f97fSRoger A. Faulkner endb = buf + sizeof(buf);
12023e14f97fSRoger A. Faulkner while(*file)
12033e14f97fSRoger A. Faulkner { if(*file == '%')
12043e14f97fSRoger A. Faulkner { switch(file[1])
12053e14f97fSRoger A. Faulkner {
12063e14f97fSRoger A. Faulkner case 'p' :
12073e14f97fSRoger A. Faulkner if(!(next = insertpid(next,endb)) )
12083e14f97fSRoger A. Faulkner return -1;
12093e14f97fSRoger A. Faulkner file += 2;
12103e14f97fSRoger A. Faulkner break;
12113e14f97fSRoger A. Faulkner default :
12123e14f97fSRoger A. Faulkner goto copy;
12133e14f97fSRoger A. Faulkner }
12143e14f97fSRoger A. Faulkner }
12153e14f97fSRoger A. Faulkner else
12163e14f97fSRoger A. Faulkner { copy:
12173e14f97fSRoger A. Faulkner *next++ = *file++;
12183e14f97fSRoger A. Faulkner }
12193e14f97fSRoger A. Faulkner
12203e14f97fSRoger A. Faulkner if(next >= endb)
12213e14f97fSRoger A. Faulkner return -1;
12223e14f97fSRoger A. Faulkner }
12233e14f97fSRoger A. Faulkner
12243e14f97fSRoger A. Faulkner *next = '\0';
12253e14f97fSRoger A. Faulkner file = buf;
12263e14f97fSRoger A. Faulkner if (*file == '&' && *(file += 1) || strncmp(file, "/dev/fd/", 8) == 0 && *(file += 8))
12273e14f97fSRoger A. Faulkner fd = dup((int)atou(&file));
12283e14f97fSRoger A. Faulkner else if (*file)
1229*b30d1939SAndy Fiddaman {
12303e14f97fSRoger A. Faulkner #if _PACKAGE_ast
12313e14f97fSRoger A. Faulkner fd = open(file, O_WRONLY|O_CREAT|O_TRUNC, CREAT_MODE);
12323e14f97fSRoger A. Faulkner #else
12333e14f97fSRoger A. Faulkner fd = creat(file, CREAT_MODE);
12343e14f97fSRoger A. Faulkner #endif
1235*b30d1939SAndy Fiddaman fd = _vmfd(fd);
1236*b30d1939SAndy Fiddaman }
12373e14f97fSRoger A. Faulkner else
12383e14f97fSRoger A. Faulkner return -1;
12393e14f97fSRoger A. Faulkner #if _PACKAGE_ast
12403e14f97fSRoger A. Faulkner #ifdef FD_CLOEXEC
12413e14f97fSRoger A. Faulkner if (fd >= 0)
12423e14f97fSRoger A. Faulkner fcntl(fd, F_SETFD, FD_CLOEXEC);
12433e14f97fSRoger A. Faulkner #endif
12443e14f97fSRoger A. Faulkner #endif
12453e14f97fSRoger A. Faulkner return fd;
12463e14f97fSRoger A. Faulkner }
12473e14f97fSRoger A. Faulkner
12483e14f97fSRoger A. Faulkner #if __STD_C
pfprint(void)12493e14f97fSRoger A. Faulkner static void pfprint(void)
12503e14f97fSRoger A. Faulkner #else
12513e14f97fSRoger A. Faulkner static void pfprint()
12523e14f97fSRoger A. Faulkner #endif
12533e14f97fSRoger A. Faulkner {
12543e14f97fSRoger A. Faulkner if(Vmregion->meth.meth == VM_MTPROFILE)
12553e14f97fSRoger A. Faulkner vmprofile(Vmregion,_Vmpffd);
12563e14f97fSRoger A. Faulkner }
12573e14f97fSRoger A. Faulkner
12583e14f97fSRoger A. Faulkner /*
12593e14f97fSRoger A. Faulkner * initialize runtime options from the VMALLOC_OPTIONS env var
12603e14f97fSRoger A. Faulkner */
12613e14f97fSRoger A. Faulkner
12623e14f97fSRoger A. Faulkner #define COPY(t,e,f) while ((*t = *f++) && t < e) t++
12633e14f97fSRoger A. Faulkner
12643e14f97fSRoger A. Faulkner #if __STD_C
_vmoptions(void)12653e14f97fSRoger A. Faulkner void _vmoptions(void)
12663e14f97fSRoger A. Faulkner #else
12673e14f97fSRoger A. Faulkner void _vmoptions()
12683e14f97fSRoger A. Faulkner #endif
12693e14f97fSRoger A. Faulkner {
12703e14f97fSRoger A. Faulkner Vmalloc_t* vm = 0;
12713e14f97fSRoger A. Faulkner char* trace = 0;
12723e14f97fSRoger A. Faulkner char* s;
12733e14f97fSRoger A. Faulkner char* t;
12743e14f97fSRoger A. Faulkner char* v;
12753e14f97fSRoger A. Faulkner Vmulong_t n;
12763e14f97fSRoger A. Faulkner int fd;
12773e14f97fSRoger A. Faulkner char buf[1024];
12783e14f97fSRoger A. Faulkner
12793e14f97fSRoger A. Faulkner _Vmoptions = 1;
12803e14f97fSRoger A. Faulkner t = buf;
12813e14f97fSRoger A. Faulkner v = &buf[sizeof(buf)-1];
12823e14f97fSRoger A. Faulkner if (s = getenv("VMALLOC_OPTIONS"))
12833e14f97fSRoger A. Faulkner COPY(t, v, s);
12843e14f97fSRoger A. Faulkner if (t > buf)
12853e14f97fSRoger A. Faulkner {
12863e14f97fSRoger A. Faulkner *t = 0;
12873e14f97fSRoger A. Faulkner s = buf;
12883e14f97fSRoger A. Faulkner for (;;)
12893e14f97fSRoger A. Faulkner {
1290*b30d1939SAndy Fiddaman while (*s == ',' || *s == ' ' || *s == '\t' || *s == '\r' || *s == '\n')
12913e14f97fSRoger A. Faulkner s++;
12923e14f97fSRoger A. Faulkner if (!*(t = s))
12933e14f97fSRoger A. Faulkner break;
12943e14f97fSRoger A. Faulkner v = 0;
12953e14f97fSRoger A. Faulkner while (*s)
1296*b30d1939SAndy Fiddaman if (*s == ',' || *s == ' ' || *s == '\t' || *s == '\r' || *s == '\n')
12973e14f97fSRoger A. Faulkner {
12983e14f97fSRoger A. Faulkner *s++ = 0;
12993e14f97fSRoger A. Faulkner break;
13003e14f97fSRoger A. Faulkner }
13013e14f97fSRoger A. Faulkner else if (!v && *s == '=')
13023e14f97fSRoger A. Faulkner {
13033e14f97fSRoger A. Faulkner *s++ = 0;
13043e14f97fSRoger A. Faulkner if (!*(v = s))
13053e14f97fSRoger A. Faulkner v = 0;
13063e14f97fSRoger A. Faulkner }
13073e14f97fSRoger A. Faulkner else
13083e14f97fSRoger A. Faulkner s++;
13093e14f97fSRoger A. Faulkner if (t[0] == 'n' && t[1] == 'o')
13103e14f97fSRoger A. Faulkner continue;
13113e14f97fSRoger A. Faulkner switch (t[0])
13123e14f97fSRoger A. Faulkner {
13133e14f97fSRoger A. Faulkner case 'a': /* abort */
13143e14f97fSRoger A. Faulkner if (!vm)
1315*b30d1939SAndy Fiddaman vm = vmopen(Vmdcsystem, Vmdebug, 0);
13163e14f97fSRoger A. Faulkner if (vm && vm->meth.meth == VM_MTDEBUG)
13173e14f97fSRoger A. Faulkner vmset(vm, VM_DBABORT, 1);
13183e14f97fSRoger A. Faulkner else
13193e14f97fSRoger A. Faulkner _Vmassert |= VM_abort;
13203e14f97fSRoger A. Faulkner break;
1321*b30d1939SAndy Fiddaman case 'b': /* break */
1322*b30d1939SAndy Fiddaman _Vmassert |= VM_break;
1323*b30d1939SAndy Fiddaman break;
13243e14f97fSRoger A. Faulkner case 'c': /* check */
13253e14f97fSRoger A. Faulkner _Vmassert |= VM_check;
13263e14f97fSRoger A. Faulkner break;
1327*b30d1939SAndy Fiddaman case 'f': /* free */
1328*b30d1939SAndy Fiddaman _Vmassert |= VM_free;
1329*b30d1939SAndy Fiddaman break;
1330*b30d1939SAndy Fiddaman case 'k': /* keep */
1331*b30d1939SAndy Fiddaman _Vmassert |= VM_keep;
1332*b30d1939SAndy Fiddaman break;
13333e14f97fSRoger A. Faulkner case 'm':
1334*b30d1939SAndy Fiddaman if (v)
1335*b30d1939SAndy Fiddaman switch (t[1])
13363e14f97fSRoger A. Faulkner {
1337*b30d1939SAndy Fiddaman case 'e': /* method=METHOD */
1338*b30d1939SAndy Fiddaman if (!vm)
1339*b30d1939SAndy Fiddaman {
1340*b30d1939SAndy Fiddaman if ((v[0] == 'V' || v[0] == 'v') && (v[1] == 'M' || v[1] == 'm'))
1341*b30d1939SAndy Fiddaman v += 2;
1342*b30d1939SAndy Fiddaman if (strcmp(v, "debug") == 0)
1343*b30d1939SAndy Fiddaman vm = vmopen(Vmdcsystem, Vmdebug, 0);
1344*b30d1939SAndy Fiddaman else if (strcmp(v, "profile") == 0)
1345*b30d1939SAndy Fiddaman vm = vmopen(Vmdcsystem, Vmprofile, 0);
1346*b30d1939SAndy Fiddaman else if (strcmp(v, "last") == 0)
1347*b30d1939SAndy Fiddaman vm = vmopen(Vmdcsystem, Vmlast, 0);
1348*b30d1939SAndy Fiddaman else if (strcmp(v, "best") == 0)
1349*b30d1939SAndy Fiddaman vm = Vmheap;
1350*b30d1939SAndy Fiddaman }
1351*b30d1939SAndy Fiddaman break;
1352*b30d1939SAndy Fiddaman case 'm': /* mmap */
1353*b30d1939SAndy Fiddaman _Vmassert |= VM_mmap;
1354*b30d1939SAndy Fiddaman break;
13553e14f97fSRoger A. Faulkner }
13563e14f97fSRoger A. Faulkner break;
13573e14f97fSRoger A. Faulkner case 'p':
13583e14f97fSRoger A. Faulkner if (v)
13593e14f97fSRoger A. Faulkner switch (t[1])
13603e14f97fSRoger A. Faulkner {
13613e14f97fSRoger A. Faulkner case 'e': /* period=<count> */
13623e14f97fSRoger A. Faulkner if (!vm)
1363*b30d1939SAndy Fiddaman vm = vmopen(Vmdcsystem, Vmdebug, 0);
13643e14f97fSRoger A. Faulkner if (vm && vm->meth.meth == VM_MTDEBUG)
13653e14f97fSRoger A. Faulkner _Vmdbcheck = atou(&v);
13663e14f97fSRoger A. Faulkner break;
13673e14f97fSRoger A. Faulkner case 'r': /* profile=<path> */
13683e14f97fSRoger A. Faulkner if (!vm)
1369*b30d1939SAndy Fiddaman vm = vmopen(Vmdcsystem, Vmprofile, 0);
13703e14f97fSRoger A. Faulkner if (v && vm && vm->meth.meth == VM_MTPROFILE)
13713e14f97fSRoger A. Faulkner _Vmpffd = createfile(v);
13723e14f97fSRoger A. Faulkner break;
13733e14f97fSRoger A. Faulkner }
13743e14f97fSRoger A. Faulkner break;
13753e14f97fSRoger A. Faulkner case 's': /* start=<count> */
13763e14f97fSRoger A. Faulkner if (!vm)
1377*b30d1939SAndy Fiddaman vm = vmopen(Vmdcsystem, Vmdebug, 0);
13783e14f97fSRoger A. Faulkner if (v && vm && vm->meth.meth == VM_MTDEBUG)
13793e14f97fSRoger A. Faulkner _Vmdbstart = atou(&v);
13803e14f97fSRoger A. Faulkner break;
13813e14f97fSRoger A. Faulkner case 't': /* trace=<path> */
13823e14f97fSRoger A. Faulkner trace = v;
13833e14f97fSRoger A. Faulkner break;
13843e14f97fSRoger A. Faulkner case 'w':
13853e14f97fSRoger A. Faulkner if (t[1] == 'a')
13863e14f97fSRoger A. Faulkner switch (t[2])
13873e14f97fSRoger A. Faulkner {
13883e14f97fSRoger A. Faulkner case 'r': /* warn=<path> */
13893e14f97fSRoger A. Faulkner if (!vm)
1390*b30d1939SAndy Fiddaman vm = vmopen(Vmdcsystem, Vmdebug, 0);
13913e14f97fSRoger A. Faulkner if (v && vm && vm->meth.meth == VM_MTDEBUG && (fd = createfile(v)) >= 0)
13923e14f97fSRoger A. Faulkner vmdebug(fd);
13933e14f97fSRoger A. Faulkner break;
13943e14f97fSRoger A. Faulkner case 't': /* watch=<addr> */
13953e14f97fSRoger A. Faulkner if (!vm)
1396*b30d1939SAndy Fiddaman vm = vmopen(Vmdcsystem, Vmdebug, 0);
13973e14f97fSRoger A. Faulkner if (v && vm && vm->meth.meth == VM_MTDEBUG && (n = atou(&v)) >= 0)
13983e14f97fSRoger A. Faulkner vmdbwatch((Void_t*)n);
13993e14f97fSRoger A. Faulkner break;
14003e14f97fSRoger A. Faulkner }
14013e14f97fSRoger A. Faulkner break;
14023e14f97fSRoger A. Faulkner }
14033e14f97fSRoger A. Faulkner }
14043e14f97fSRoger A. Faulkner }
14053e14f97fSRoger A. Faulkner
14063e14f97fSRoger A. Faulkner /* slip in the new region now so that malloc() will work fine */
14073e14f97fSRoger A. Faulkner
14083e14f97fSRoger A. Faulkner if (vm)
14093e14f97fSRoger A. Faulkner {
14103e14f97fSRoger A. Faulkner if (vm->meth.meth == VM_MTDEBUG)
14113e14f97fSRoger A. Faulkner _Vmdbcheck = 1;
14123e14f97fSRoger A. Faulkner Vmregion = vm;
14133e14f97fSRoger A. Faulkner }
14143e14f97fSRoger A. Faulkner
1415*b30d1939SAndy Fiddaman /* enable tracing -- this currently disables multiple regions */
14163e14f97fSRoger A. Faulkner
1417*b30d1939SAndy Fiddaman if (trace)
14183e14f97fSRoger A. Faulkner {
1419*b30d1939SAndy Fiddaman setregmax(0);
1420*b30d1939SAndy Fiddaman if ((fd = createfile(trace)) >= 0)
1421*b30d1939SAndy Fiddaman {
1422*b30d1939SAndy Fiddaman vmset(Vmregion, VM_TRACE, 1);
1423*b30d1939SAndy Fiddaman vmtrace(fd);
1424*b30d1939SAndy Fiddaman }
14253e14f97fSRoger A. Faulkner }
1426*b30d1939SAndy Fiddaman else if (Vmregion != Vmheap || asometh(0, 0)->type == ASO_SIGNAL)
1427*b30d1939SAndy Fiddaman setregmax(0);
14283e14f97fSRoger A. Faulkner
14293e14f97fSRoger A. Faulkner /* make sure that profile data is output upon exiting */
14303e14f97fSRoger A. Faulkner
14313e14f97fSRoger A. Faulkner if (vm && vm->meth.meth == VM_MTPROFILE)
14323e14f97fSRoger A. Faulkner {
14333e14f97fSRoger A. Faulkner if (_Vmpffd < 0)
14343e14f97fSRoger A. Faulkner _Vmpffd = 2;
14353e14f97fSRoger A. Faulkner /* this may wind up calling malloc(), but region is ok now */
14363e14f97fSRoger A. Faulkner atexit(pfprint);
14373e14f97fSRoger A. Faulkner }
14383e14f97fSRoger A. Faulkner else if (_Vmpffd >= 0)
14393e14f97fSRoger A. Faulkner {
14403e14f97fSRoger A. Faulkner close(_Vmpffd);
14413e14f97fSRoger A. Faulkner _Vmpffd = -1;
14423e14f97fSRoger A. Faulkner }
14433e14f97fSRoger A. Faulkner }
14443e14f97fSRoger A. Faulkner
1445*b30d1939SAndy Fiddaman /*
1446*b30d1939SAndy Fiddaman * ast semi-private workaround for system functions
1447*b30d1939SAndy Fiddaman * that misbehave by passing bogus addresses to free()
1448*b30d1939SAndy Fiddaman *
1449*b30d1939SAndy Fiddaman * not prototyped in any header to keep it ast semi-private
1450*b30d1939SAndy Fiddaman *
1451*b30d1939SAndy Fiddaman * to keep malloc() data by disabling free()
1452*b30d1939SAndy Fiddaman * extern _vmkeep(int);
1453*b30d1939SAndy Fiddaman * int r = _vmkeep(1);
1454*b30d1939SAndy Fiddaman * and to restore to the previous state
1455*b30d1939SAndy Fiddaman * (void)_vmkeep(r);
1456*b30d1939SAndy Fiddaman */
1457*b30d1939SAndy Fiddaman
1458*b30d1939SAndy Fiddaman int
1459*b30d1939SAndy Fiddaman #if __STD_C
_vmkeep(int v)1460*b30d1939SAndy Fiddaman _vmkeep(int v)
1461*b30d1939SAndy Fiddaman #else
1462*b30d1939SAndy Fiddaman _vmkeep(v)
1463*b30d1939SAndy Fiddaman int v;
1464*b30d1939SAndy Fiddaman #endif
1465*b30d1939SAndy Fiddaman {
1466*b30d1939SAndy Fiddaman int r;
1467*b30d1939SAndy Fiddaman
1468*b30d1939SAndy Fiddaman r = !!(_Vmassert & VM_keep);
1469*b30d1939SAndy Fiddaman if (v)
1470*b30d1939SAndy Fiddaman _Vmassert |= VM_keep;
1471*b30d1939SAndy Fiddaman else
1472*b30d1939SAndy Fiddaman _Vmassert &= ~VM_keep;
1473*b30d1939SAndy Fiddaman return r;
1474*b30d1939SAndy Fiddaman }
1475*b30d1939SAndy Fiddaman
1476da2e3ebdSchin #endif /*_UWIN*/
1477