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