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 #ifndef _VMHDR_H
23da2e3ebdSchin #define _VMHDR_H	1
24da2e3ebdSchin #ifndef _BLD_vmalloc
25da2e3ebdSchin #define _BLD_vmalloc	1
26da2e3ebdSchin #endif
27da2e3ebdSchin 
28da2e3ebdSchin /*	Common types, and macros for vmalloc functions.
29da2e3ebdSchin **
30da2e3ebdSchin **	Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
31da2e3ebdSchin */
32da2e3ebdSchin 
33da2e3ebdSchin #ifndef __STD_C	/* this is normally in vmalloc.h but it's included late here */
34da2e3ebdSchin #ifdef __STDC__
35da2e3ebdSchin #define	__STD_C		1
36da2e3ebdSchin #else
37da2e3ebdSchin #if __cplusplus || c_plusplus
38da2e3ebdSchin #define __STD_C		1
39da2e3ebdSchin #else
40da2e3ebdSchin #define __STD_C		0
41da2e3ebdSchin #endif /*__cplusplus*/
42da2e3ebdSchin #endif /*__STDC__*/
43da2e3ebdSchin #endif /*__STD_C*/
44da2e3ebdSchin 
45da2e3ebdSchin #if _PACKAGE_ast
46da2e3ebdSchin 
47da2e3ebdSchin #if !_UWIN
48da2e3ebdSchin #define getpagesize		______getpagesize
49da2e3ebdSchin #define _npt_getpagesize	1
50da2e3ebdSchin #define brk			______brk
51da2e3ebdSchin #define sbrk			______sbrk
52da2e3ebdSchin #define _npt_sbrk		1
53da2e3ebdSchin #endif
54da2e3ebdSchin 
55da2e3ebdSchin #include	<ast.h>
56da2e3ebdSchin 
57da2e3ebdSchin #if _npt_getpagesize
58da2e3ebdSchin #undef				getpagesize
59da2e3ebdSchin #endif
60da2e3ebdSchin #if _npt_sbrk
61da2e3ebdSchin #undef				brk
62da2e3ebdSchin #undef				sbrk
63da2e3ebdSchin #endif
64da2e3ebdSchin 
65da2e3ebdSchin #else
66da2e3ebdSchin 
67da2e3ebdSchin #include	<ast_common.h>
68da2e3ebdSchin 
69da2e3ebdSchin #if !_UWIN
70da2e3ebdSchin #define _npt_getpagesize	1
71da2e3ebdSchin #define _npt_sbrk		1
72da2e3ebdSchin #endif
73da2e3ebdSchin 
74*b30d1939SAndy Fiddaman #undef free
75*b30d1939SAndy Fiddaman #undef malloc
76*b30d1939SAndy Fiddaman #undef realloc
773e14f97fSRoger A. Faulkner 
78da2e3ebdSchin #endif /*_PACKAGE_ast*/
79da2e3ebdSchin 
80da2e3ebdSchin #include	"FEATURE/vmalloc"
81da2e3ebdSchin 
82*b30d1939SAndy Fiddaman #include	<aso.h>		/* atomic scalor operations		*/
83*b30d1939SAndy Fiddaman #include	<setjmp.h>	/* use the type jmp_buf for alignment	*/
84da2e3ebdSchin 
85*b30d1939SAndy Fiddaman /* extra information needed about methods to get memory from the system */
86da2e3ebdSchin #if defined(_WIN32)
87*b30d1939SAndy Fiddaman #define _mem_win32	1	/* use the VirtualAlloc interface	*/
88da2e3ebdSchin #endif
89da2e3ebdSchin #if !_mem_win32 && !_mem_sbrk && !_mem_mmap_anon && !_mem_mmap_zero
90da2e3ebdSchin #undef _std_malloc
91*b30d1939SAndy Fiddaman #define _std_malloc	1	/* use native malloc/free/realloc	*/
92da2e3ebdSchin #endif
93da2e3ebdSchin 
94da2e3ebdSchin typedef unsigned char	Vmuchar_t;
95da2e3ebdSchin typedef unsigned long	Vmulong_t;
96da2e3ebdSchin 
97da2e3ebdSchin typedef union _head_u	Head_t;
98da2e3ebdSchin typedef union _body_u	Body_t;
99da2e3ebdSchin typedef struct _block_s	Block_t;
100da2e3ebdSchin typedef struct _seg_s	Seg_t;
101da2e3ebdSchin typedef struct _pfobj_s	Pfobj_t;
102da2e3ebdSchin 
103da2e3ebdSchin #define NIL(t)		((t)0)
104da2e3ebdSchin #define reg		register
105da2e3ebdSchin #if __STD_C
106da2e3ebdSchin #define NOTUSED(x)	(void)(x)
107da2e3ebdSchin #else
108da2e3ebdSchin #define NOTUSED(x)	(&x,1)
109da2e3ebdSchin #endif
110da2e3ebdSchin 
111*b30d1939SAndy Fiddaman 
112da2e3ebdSchin /* convert an address to an integral value */
113*b30d1939SAndy Fiddaman #define VLONG(addr)	((Vmulong_t)((Vmuchar_t*)((Vmulong_t)addr) - (Vmuchar_t*)0) )
114da2e3ebdSchin 
115da2e3ebdSchin /* Round x up to a multiple of y. ROUND2 does powers-of-2 and ROUNDX does others */
116da2e3ebdSchin #define ROUND2(x,y)	(((x) + ((y)-1)) & ~((y)-1))
117da2e3ebdSchin #define ROUNDX(x,y)	((((x) + ((y)-1)) / (y)) * (y))
118da2e3ebdSchin #define ROUND(x,y)	(((y)&((y)-1)) ? ROUNDX((x),(y)) : ROUND2((x),(y)) )
119da2e3ebdSchin 
120da2e3ebdSchin /* compute a value that is a common multiple of x and y */
121da2e3ebdSchin #define MULTIPLE(x,y)	((x)%(y) == 0 ? (x) : (y)%(x) == 0 ? (y) : (y)*(x))
122da2e3ebdSchin 
123*b30d1939SAndy Fiddaman #define VM_abort	0x0001	/* abort() on assertion failure		*/
124*b30d1939SAndy Fiddaman #define VM_break	0x0002	/* try sbrk() block allocator first	*/
125*b30d1939SAndy Fiddaman #define VM_check	0x0004	/* enable detailed checks		*/
126*b30d1939SAndy Fiddaman #define VM_free		0x0008	/* disable addfreelist()		*/
127*b30d1939SAndy Fiddaman #define VM_keep		0x0010	/* disable free()			*/
128*b30d1939SAndy Fiddaman #define VM_mmap		0x0020	/* try mmap() block allocator first	*/
129da2e3ebdSchin 
130da2e3ebdSchin #if _UWIN
131da2e3ebdSchin #include <ast_windows.h>
132da2e3ebdSchin #endif
133da2e3ebdSchin 
134da2e3ebdSchin #ifndef DEBUG
135da2e3ebdSchin #ifdef _BLD_DEBUG
136da2e3ebdSchin #define DEBUG		1
137da2e3ebdSchin #endif /*_BLD_DEBUG*/
138da2e3ebdSchin #endif /*DEBUG*/
139da2e3ebdSchin #if DEBUG
140da2e3ebdSchin extern void		_vmmessage _ARG_((const char*, long, const char*, long));
141*b30d1939SAndy Fiddaman #define MESSAGE(s)	_vmmessage(__FILE__,__LINE__,s,0)
142da2e3ebdSchin #define ABORT()		(_Vmassert & VM_abort)
143da2e3ebdSchin #define CHECK()		(_Vmassert & VM_check)
144da2e3ebdSchin #define ASSERT(p)	((p) ? 0 : (MESSAGE("Assertion failed"), ABORT() ? (abort(),0) : 0))
145da2e3ebdSchin #define COUNT(n)	((n) += 1)
146da2e3ebdSchin #else
147da2e3ebdSchin #define ABORT()		(0)
148da2e3ebdSchin #define ASSERT(p)
149da2e3ebdSchin #define CHECK()		(0)
150da2e3ebdSchin #define COUNT(n)
151da2e3ebdSchin #define MESSAGE(s)	(0)
152da2e3ebdSchin #endif /*DEBUG*/
153da2e3ebdSchin 
154da2e3ebdSchin #define VMPAGESIZE	8192
155*b30d1939SAndy Fiddaman #if _lib_getpagesize
156*b30d1939SAndy Fiddaman #define GETPAGESIZE(x)	((x) ? (x) : ((x)=getpagesize()) )
157da2e3ebdSchin #else
158da2e3ebdSchin #define GETPAGESIZE(x)	((x) = VMPAGESIZE)
159da2e3ebdSchin #endif
160da2e3ebdSchin 
161da2e3ebdSchin /* Blocks are allocated such that their sizes are 0%(BITS+1)
162da2e3ebdSchin ** This frees up enough low order bits to store state information
163da2e3ebdSchin */
164da2e3ebdSchin #define BUSY		(01)	/* block is busy				*/
165da2e3ebdSchin #define PFREE		(02)	/* preceding block is free			*/
166da2e3ebdSchin #define JUNK		(04)	/* marked as freed but not yet processed	*/
167da2e3ebdSchin #define BITS		(07)	/* (BUSY|PFREE|JUNK)				*/
168da2e3ebdSchin #define ALIGNB		(8)	/* size must be a multiple of BITS+1		*/
169da2e3ebdSchin 
170da2e3ebdSchin #define ISBITS(w)	((w) & BITS)
171da2e3ebdSchin #define CLRBITS(w)	((w) &= ~BITS)
172da2e3ebdSchin #define CPYBITS(w,f)	((w) |= ((f)&BITS) )
173da2e3ebdSchin 
174da2e3ebdSchin #define ISBUSY(w)	((w) & BUSY)
175da2e3ebdSchin #define SETBUSY(w)	((w) |= BUSY)
176da2e3ebdSchin #define CLRBUSY(w)	((w) &= ~BUSY)
177da2e3ebdSchin 
178da2e3ebdSchin #define ISPFREE(w)	((w) & PFREE)
179da2e3ebdSchin #define SETPFREE(w)	((w) |= PFREE)
180da2e3ebdSchin #define CLRPFREE(w)	((w) &= ~PFREE)
181da2e3ebdSchin 
182da2e3ebdSchin #define ISJUNK(w)	((w) & JUNK)
183da2e3ebdSchin #define SETJUNK(w)	((w) |= JUNK)
184da2e3ebdSchin #define CLRJUNK(w)	((w) &= ~JUNK)
185da2e3ebdSchin 
186da2e3ebdSchin #define OFFSET(t,e)	((size_t)(&(((t*)0)->e)) )
187da2e3ebdSchin 
188da2e3ebdSchin #define VMETHOD(vd)	((vd)->mode&VM_METHODS)
189da2e3ebdSchin 
190*b30d1939SAndy Fiddaman /* lock and unlock regions during concurrent accesses */
191*b30d1939SAndy Fiddaman #define SETLOCK(vm,l)	((l) ? 0 : _vmlock((vm), 1) )
192*b30d1939SAndy Fiddaman #define CLRLOCK(vm,l)	((l) ? 0 : _vmlock((vm), 0) )
193da2e3ebdSchin 
194da2e3ebdSchin /* local calls */
195*b30d1939SAndy Fiddaman #define KPVALLOC(vm,sz,func)		(func((vm),(sz),1) )
196*b30d1939SAndy Fiddaman #define KPVRESIZE(vm,dt,sz,mv,func)	(func((vm),(dt),(sz),(mv),1) )
197*b30d1939SAndy Fiddaman #define KPVFREE(vm,dt,func)		(func((vm),(dt),1) )
198*b30d1939SAndy Fiddaman #define KPVADDR(vm,addr,func)		(func((vm),(addr),1) )
199*b30d1939SAndy Fiddaman #define KPVSIZE(vm,addr,func)		(func((vm),(addr),1) )
200*b30d1939SAndy Fiddaman #define KPVCOMPACT(vm,func)		(func((vm),1) )
201*b30d1939SAndy Fiddaman #define KPVALIGN(vm,sz,al,func)		(func((vm),(sz),(al),1) )
202da2e3ebdSchin 
203da2e3ebdSchin /* ALIGN is chosen so that a block can store all primitive types.
204da2e3ebdSchin ** It should also be a multiple of ALIGNB==(BITS+1) so the size field
205da2e3ebdSchin ** of Block_t will always be 0%(BITS+1) as noted above.
206da2e3ebdSchin ** Of paramount importance is the ALIGNA macro below. If the local compile
207da2e3ebdSchin ** environment is strange enough that the below method does not calculate
208da2e3ebdSchin ** ALIGNA right, then the code below should be commented out and ALIGNA
209da2e3ebdSchin ** redefined to the appropriate requirement.
210da2e3ebdSchin */
211da2e3ebdSchin union _align_u
212da2e3ebdSchin {	char		c, *cp;
213da2e3ebdSchin 	int		i, *ip;
214da2e3ebdSchin 	long		l, *lp;
215da2e3ebdSchin 	double		d, *dp, ***dppp[8];
216da2e3ebdSchin 	size_t		s, *sp;
217da2e3ebdSchin 	void(*		fn)();
218da2e3ebdSchin 	union _align_u*	align;
219da2e3ebdSchin 	Head_t*		head;
220da2e3ebdSchin 	Body_t*		body;
221da2e3ebdSchin 	Block_t*	block;
222da2e3ebdSchin 	Vmuchar_t	a[ALIGNB];
223da2e3ebdSchin 	_ast_fltmax_t	ld, *ldp;
224da2e3ebdSchin 	jmp_buf		jmp;
225da2e3ebdSchin };
226da2e3ebdSchin struct _a_s
227da2e3ebdSchin {	char		c;
228da2e3ebdSchin 	union _align_u	a;
229da2e3ebdSchin };
230da2e3ebdSchin #define ALIGNA	(sizeof(struct _a_s) - sizeof(union _align_u))
231da2e3ebdSchin struct _align_s
232da2e3ebdSchin {	char	data[MULTIPLE(ALIGNA,ALIGNB)];
233da2e3ebdSchin };
234da2e3ebdSchin #undef	ALIGN	/* bsd sys/param.h defines this */
235da2e3ebdSchin #define ALIGN	sizeof(struct _align_s)
236da2e3ebdSchin 
237da2e3ebdSchin /* make sure that the head of a block is a multiple of ALIGN */
238da2e3ebdSchin struct _head_s
239da2e3ebdSchin {	union
240da2e3ebdSchin 	{ Seg_t*	seg;	/* the containing segment	*/
241da2e3ebdSchin 	  Block_t*	link;	/* possible link list usage	*/
242da2e3ebdSchin 	  Pfobj_t*	pf;	/* profile structure pointer	*/
243da2e3ebdSchin 	  char*		file;	/* for file name in Vmdebug	*/
244da2e3ebdSchin 	} seg;
245da2e3ebdSchin 	union
246da2e3ebdSchin 	{ size_t	size;	/* size of data area in bytes	*/
247da2e3ebdSchin 	  Block_t*	link;	/* possible link list usage	*/
248da2e3ebdSchin 	  int		line;	/* for line number in Vmdebug	*/
249da2e3ebdSchin 	} size;
250da2e3ebdSchin };
251da2e3ebdSchin #define HEADSIZE	ROUND(sizeof(struct _head_s),ALIGN)
252da2e3ebdSchin union _head_u
253da2e3ebdSchin {	Vmuchar_t	data[HEADSIZE];	/* to standardize size		*/
254da2e3ebdSchin 	struct _head_s	head;
255da2e3ebdSchin };
256da2e3ebdSchin 
257da2e3ebdSchin /* now make sure that the body of a block is a multiple of ALIGN */
258da2e3ebdSchin struct _body_s
259da2e3ebdSchin {	Block_t*	link;	/* next in link list		*/
260da2e3ebdSchin 	Block_t*	left;	/* left child in free tree	*/
261da2e3ebdSchin 	Block_t*	right;	/* right child in free tree	*/
262da2e3ebdSchin 	Block_t**	self;	/* self pointer when free	*/
263da2e3ebdSchin };
264da2e3ebdSchin #define BODYSIZE	ROUND(sizeof(struct _body_s),ALIGN)
265*b30d1939SAndy Fiddaman 
266da2e3ebdSchin union _body_u
267da2e3ebdSchin {	Vmuchar_t	data[BODYSIZE];	/* to standardize size		*/
268da2e3ebdSchin 	struct _body_s	body;
269*b30d1939SAndy Fiddaman 	Block_t*	self[1];
270da2e3ebdSchin };
271da2e3ebdSchin 
272da2e3ebdSchin /* After all the songs and dances, we should now have:
273da2e3ebdSchin **	sizeof(Head_t)%ALIGN == 0
274da2e3ebdSchin **	sizeof(Body_t)%ALIGN == 0
275da2e3ebdSchin ** and	sizeof(Block_t) = sizeof(Head_t)+sizeof(Body_t)
276da2e3ebdSchin */
277da2e3ebdSchin struct _block_s
278da2e3ebdSchin {	Head_t	head;
279da2e3ebdSchin 	Body_t	body;
280da2e3ebdSchin };
281da2e3ebdSchin 
282da2e3ebdSchin /* requirements for smallest block type */
283da2e3ebdSchin struct _tiny_s
284da2e3ebdSchin {	Block_t*	link;
285da2e3ebdSchin 	Block_t*	self;
286da2e3ebdSchin };
287da2e3ebdSchin #define TINYSIZE	ROUND(sizeof(struct _tiny_s),ALIGN)
288da2e3ebdSchin #define S_TINY		1				/* # of tiny blocks	*/
289da2e3ebdSchin #define MAXTINY		(S_TINY*ALIGN + TINYSIZE)
290da2e3ebdSchin #define TLEFT(b)	((b)->head.head.seg.link)	/* instead of LEFT	*/
291da2e3ebdSchin #define TINIEST(b)	(SIZE(b) == TINYSIZE)		/* this type uses TLEFT	*/
292da2e3ebdSchin 
293da2e3ebdSchin #define DIV(x,y)	((y) == 8 ? ((x)>>3) : (x)/(y) )
294da2e3ebdSchin #define INDEX(s)	DIV((s)-TINYSIZE,ALIGN)
295da2e3ebdSchin 
296da2e3ebdSchin /* small block types kept in separate caches for quick allocation */
297da2e3ebdSchin #define S_CACHE		6	/* # of types of small blocks to be cached	*/
298da2e3ebdSchin #define N_CACHE		32	/* on allocation, create this many at a time	*/
299da2e3ebdSchin #define MAXCACHE	(S_CACHE*ALIGN + TINYSIZE)
300da2e3ebdSchin #define C_INDEX(s)	(s < MAXCACHE ? INDEX(s) : S_CACHE)
301da2e3ebdSchin 
302da2e3ebdSchin #define TINY(vd)	((vd)->tiny)
303da2e3ebdSchin #define CACHE(vd)	((vd)->cache)
304da2e3ebdSchin 
305*b30d1939SAndy Fiddaman struct _vmdata_s /* core region data - could be in shared/persistent memory	*/
306*b30d1939SAndy Fiddaman {	unsigned int	lock;		/* lock status				*/
307*b30d1939SAndy Fiddaman 	int		mode;		/* current mode for region		*/
308da2e3ebdSchin 	size_t		incr;		/* allocate in multiple of this		*/
309da2e3ebdSchin 	size_t		pool;		/* size	of an elt in a Vmpool region	*/
310da2e3ebdSchin 	Seg_t*		seg;		/* list of segments			*/
311da2e3ebdSchin 	Block_t*	free;		/* most recent free block		*/
312da2e3ebdSchin 	Block_t*	wild;		/* wilderness block			*/
313da2e3ebdSchin 	Block_t*	root;		/* root of free tree			*/
314da2e3ebdSchin 	Block_t*	tiny[S_TINY];	/* small blocks				*/
315da2e3ebdSchin 	Block_t*	cache[S_CACHE+1]; /* delayed free blocks		*/
3163e14f97fSRoger A. Faulkner };
317da2e3ebdSchin 
318da2e3ebdSchin #include	"vmalloc.h"
319da2e3ebdSchin 
320da2e3ebdSchin #if !_PACKAGE_ast
321da2e3ebdSchin /* we don't use these here and they interfere with some local names */
322da2e3ebdSchin #undef malloc
323da2e3ebdSchin #undef free
324da2e3ebdSchin #undef realloc
325da2e3ebdSchin #endif
326da2e3ebdSchin 
327da2e3ebdSchin /* segment structure */
328da2e3ebdSchin struct _seg_s
3293e14f97fSRoger A. Faulkner {	Vmdata_t*	vmdt;	/* the data region holding this	*/
330da2e3ebdSchin 	Seg_t*		next;	/* next segment			*/
331da2e3ebdSchin 	Void_t*		addr;	/* starting segment address	*/
332da2e3ebdSchin 	size_t		extent;	/* extent of segment		*/
333da2e3ebdSchin 	Vmuchar_t*	baddr;	/* bottom of usable memory	*/
334da2e3ebdSchin 	size_t		size;	/* allocable size		*/
335da2e3ebdSchin 	Block_t*	free;	/* recent free blocks		*/
336da2e3ebdSchin 	Block_t*	last;	/* Vmlast last-allocated block	*/
337da2e3ebdSchin };
338da2e3ebdSchin 
339da2e3ebdSchin /* starting block of a segment */
340da2e3ebdSchin #define SEGBLOCK(s)	((Block_t*)(((Vmuchar_t*)(s)) + ROUND(sizeof(Seg_t),ALIGN)))
341da2e3ebdSchin 
342da2e3ebdSchin /* short-hands for block data */
343da2e3ebdSchin #define SEG(b)		((b)->head.head.seg.seg)
344da2e3ebdSchin #define SEGLINK(b)	((b)->head.head.seg.link)
345da2e3ebdSchin #define	SIZE(b)		((b)->head.head.size.size)
346da2e3ebdSchin #define SIZELINK(b)	((b)->head.head.size.link)
347da2e3ebdSchin #define LINK(b)		((b)->body.body.link)
348da2e3ebdSchin #define LEFT(b)		((b)->body.body.left)
349da2e3ebdSchin #define RIGHT(b)	((b)->body.body.right)
350da2e3ebdSchin 
351da2e3ebdSchin #define DATA(b)		((Void_t*)((b)->body.data) )
352da2e3ebdSchin #define BLOCK(d)	((Block_t*)((char*)(d) - sizeof(Head_t)) )
353*b30d1939SAndy Fiddaman #define SELF(b)		(b)->body.self[SIZE(b)/sizeof(Block_t*)-1]
354da2e3ebdSchin #define LAST(b)		(*((Block_t**)(((char*)(b)) - sizeof(Block_t*)) ) )
355da2e3ebdSchin #define NEXT(b)		((Block_t*)((b)->body.data + SIZE(b)) )
356da2e3ebdSchin 
357da2e3ebdSchin /* functions to manipulate link lists of elts of the same size */
358da2e3ebdSchin #define SETLINK(b)	(RIGHT(b) =  (b) )
359da2e3ebdSchin #define ISLINK(b)	(RIGHT(b) == (b) )
360da2e3ebdSchin #define UNLINK(vd,b,i,t) \
361da2e3ebdSchin 		((((t) = LINK(b)) ? (LEFT(t) = LEFT(b)) : NIL(Block_t*) ), \
362da2e3ebdSchin 		 (((t) = LEFT(b)) ? (LINK(t) = LINK(b)) : (TINY(vd)[i] = LINK(b)) ) )
363da2e3ebdSchin 
364da2e3ebdSchin /* delete a block from a link list or the free tree.
365da2e3ebdSchin ** The test in the below macro is worth scratching your head a bit.
366da2e3ebdSchin ** Even though tiny blocks (size < BODYSIZE) are kept in separate lists,
367da2e3ebdSchin ** only the TINIEST ones require TLEFT(b) for the back link. Since this
368da2e3ebdSchin ** destroys the SEG(b) pointer, it must be carefully restored in bestsearch().
369da2e3ebdSchin ** Other tiny blocks have enough space to use the usual LEFT(b).
370da2e3ebdSchin ** In this case, I have also carefully arranged so that RIGHT(b) and
371da2e3ebdSchin ** SELF(b) can be overlapped and the test ISLINK() will go through.
372da2e3ebdSchin */
373da2e3ebdSchin #define REMOVE(vd,b,i,t,func) \
374da2e3ebdSchin 		((!TINIEST(b) && ISLINK(b)) ? UNLINK((vd),(b),(i),(t)) : \
375da2e3ebdSchin 	 		func((vd),SIZE(b),(b)) )
376da2e3ebdSchin 
377da2e3ebdSchin /* see if a block is the wilderness block */
378da2e3ebdSchin #define SEGWILD(b)	(((b)->body.data+SIZE(b)+sizeof(Head_t)) >= SEG(b)->baddr)
379da2e3ebdSchin #define VMWILD(vd,b)	(((b)->body.data+SIZE(b)+sizeof(Head_t)) >= vd->seg->baddr)
380da2e3ebdSchin 
381da2e3ebdSchin #define VMFLF(vm,fi,ln,fn)	((fi) = (vm)->file, (vm)->file = NIL(char*), \
382da2e3ebdSchin 		 		 (ln) = (vm)->line, (vm)->line = 0 , \
383da2e3ebdSchin 		 		 (fn) = (vm)->func, (vm)->func = NIL(Void_t*) )
384da2e3ebdSchin 
385da2e3ebdSchin /* The lay-out of a Vmprofile block is this:
386da2e3ebdSchin **	seg_ size ----data---- _pf_ size
387da2e3ebdSchin **	_________ ____________ _________
388da2e3ebdSchin **	seg_, size: header required by Vmbest.
389da2e3ebdSchin **	data:	actual data block.
390da2e3ebdSchin **	_pf_:	pointer to the corresponding Pfobj_t struct
391da2e3ebdSchin **	size:	the true size of the block.
392da2e3ebdSchin ** So each block requires an extra Head_t.
393da2e3ebdSchin */
394da2e3ebdSchin #define PF_EXTRA   sizeof(Head_t)
395da2e3ebdSchin #define PFDATA(d)  ((Head_t*)((Vmuchar_t*)(d)+(SIZE(BLOCK(d))&~BITS)-sizeof(Head_t)) )
396da2e3ebdSchin #define PFOBJ(d)   (PFDATA(d)->head.seg.pf)
397da2e3ebdSchin #define PFSIZE(d)  (PFDATA(d)->head.size.size)
398da2e3ebdSchin 
399da2e3ebdSchin /* The lay-out of a block allocated by Vmdebug is this:
400da2e3ebdSchin **	seg_ size file size seg_ magi ----data---- --magi-- magi line
401da2e3ebdSchin **	--------- --------- --------- ------------ -------- ---------
402da2e3ebdSchin **	seg_,size: header required by Vmbest management.
403da2e3ebdSchin **	file:	the file where it was created.
404da2e3ebdSchin **	size:	the true byte count of the block
405da2e3ebdSchin **	seg_:	should be the same as the previous seg_.
406da2e3ebdSchin **		This allows the function vmregion() to work.
407da2e3ebdSchin **	magi:	magic bytes to detect overwrites.
408da2e3ebdSchin **	data:	the actual data block.
409da2e3ebdSchin **	magi:	more magic bytes.
410da2e3ebdSchin **	line:	the line number in the file where it was created.
411da2e3ebdSchin ** So for each allocated block, we'll need 3 extra Head_t.
412da2e3ebdSchin */
413da2e3ebdSchin 
414da2e3ebdSchin /* convenient macros for accessing the above fields */
415da2e3ebdSchin #define DB_HEAD		(2*sizeof(Head_t))
416da2e3ebdSchin #define DB_TAIL		(2*sizeof(Head_t))
417da2e3ebdSchin #define DB_EXTRA	(DB_HEAD+DB_TAIL)
418da2e3ebdSchin #define DBBLOCK(d)	((Block_t*)((Vmuchar_t*)(d) - 3*sizeof(Head_t)) )
419da2e3ebdSchin #define DBBSIZE(d)	(SIZE(DBBLOCK(d)) & ~BITS)
420da2e3ebdSchin #define DBSEG(d)	(((Head_t*)((Vmuchar_t*)(d) - sizeof(Head_t)))->head.seg.seg )
421da2e3ebdSchin #define DBSIZE(d)	(((Head_t*)((Vmuchar_t*)(d) - 2*sizeof(Head_t)))->head.size.size )
422da2e3ebdSchin #define DBFILE(d)	(((Head_t*)((Vmuchar_t*)(d) - 2*sizeof(Head_t)))->head.seg.file )
423da2e3ebdSchin #define DBLN(d)		(((Head_t*)((Vmuchar_t*)DBBLOCK(d)+DBBSIZE(d)))->head.size.line )
424da2e3ebdSchin #define DBLINE(d)	(DBLN(d) < 0 ? -DBLN(d) : DBLN(d))
425da2e3ebdSchin 
426da2e3ebdSchin /* forward/backward translation for addresses between Vmbest and Vmdebug */
427da2e3ebdSchin #define DB2BEST(d)	((Vmuchar_t*)(d) - 2*sizeof(Head_t))
428da2e3ebdSchin #define DB2DEBUG(b)	((Vmuchar_t*)(b) + 2*sizeof(Head_t))
429da2e3ebdSchin 
430da2e3ebdSchin /* set file and line number, note that DBLN > 0 so that DBISBAD will work  */
431da2e3ebdSchin #define DBSETFL(d,f,l)	(DBFILE(d) = (f), DBLN(d) = (f) ? (l) : 1)
432da2e3ebdSchin 
433da2e3ebdSchin /* set and test the state of known to be corrupted */
434da2e3ebdSchin #define DBSETBAD(d)	(DBLN(d) > 0 ? (DBLN(d) = -DBLN(d)) : -1)
435da2e3ebdSchin #define DBISBAD(d)	(DBLN(d) <= 0)
436da2e3ebdSchin 
437da2e3ebdSchin #define DB_MAGIC	0255		/* 10101101	*/
438da2e3ebdSchin 
439da2e3ebdSchin /* compute the bounds of the magic areas */
440da2e3ebdSchin #define DBHEAD(d,begp,endp) \
441da2e3ebdSchin 		(((begp) = (Vmuchar_t*)(&DBSEG(d)) + sizeof(Seg_t*)), ((endp) = (d)) )
442da2e3ebdSchin #define DBTAIL(d,begp,endp) \
443da2e3ebdSchin 		(((begp) = (Vmuchar_t*)(d)+DBSIZE(d)), ((endp) = (Vmuchar_t*)(&DBLN(d))) )
444da2e3ebdSchin 
445*b30d1939SAndy Fiddaman 
446*b30d1939SAndy Fiddaman /* external symbols for use inside vmalloc only */
447da2e3ebdSchin typedef Block_t*	(*Vmsearch_f)_ARG_((Vmdata_t*, size_t, Block_t*));
448*b30d1939SAndy Fiddaman typedef struct _vmextern_s
449da2e3ebdSchin {	Block_t*	(*vm_extend)_ARG_((Vmalloc_t*, size_t, Vmsearch_f ));
450da2e3ebdSchin 	ssize_t		(*vm_truncate)_ARG_((Vmalloc_t*, Seg_t*, size_t, int));
451da2e3ebdSchin 	size_t		vm_pagesize;
452da2e3ebdSchin 	char*		(*vm_strcpy)_ARG_((char*, const char*, int));
453da2e3ebdSchin 	char*		(*vm_itoa)_ARG_((Vmulong_t, int));
454da2e3ebdSchin 	void		(*vm_trace)_ARG_((Vmalloc_t*,
455da2e3ebdSchin 					  Vmuchar_t*, Vmuchar_t*, size_t, size_t));
456da2e3ebdSchin 	void		(*vm_pfclose)_ARG_((Vmalloc_t*));
457*b30d1939SAndy Fiddaman 	unsigned int	vm_lock;
458da2e3ebdSchin 	int		vm_assert;
4593e14f97fSRoger A. Faulkner 	int		vm_options;
460da2e3ebdSchin } Vmextern_t;
461da2e3ebdSchin 
462da2e3ebdSchin #define _Vmextend	(_Vmextern.vm_extend)
463da2e3ebdSchin #define _Vmtruncate	(_Vmextern.vm_truncate)
464da2e3ebdSchin #define _Vmpagesize	(_Vmextern.vm_pagesize)
465da2e3ebdSchin #define _Vmstrcpy	(_Vmextern.vm_strcpy)
466da2e3ebdSchin #define _Vmitoa		(_Vmextern.vm_itoa)
467da2e3ebdSchin #define _Vmtrace	(_Vmextern.vm_trace)
468da2e3ebdSchin #define _Vmpfclose	(_Vmextern.vm_pfclose)
469*b30d1939SAndy Fiddaman #define _Vmlock		(_Vmextern.vm_lock)
470da2e3ebdSchin #define _Vmassert	(_Vmextern.vm_assert)
4713e14f97fSRoger A. Faulkner #define _Vmoptions	(_Vmextern.vm_options)
4723e14f97fSRoger A. Faulkner 
473*b30d1939SAndy Fiddaman #define VMOPTIONS()     do { if (!_Vmoptions) { _vmoptions(); } } while (0)
474da2e3ebdSchin 
475da2e3ebdSchin extern int		_vmbestcheck _ARG_((Vmdata_t*, Block_t*));
476*b30d1939SAndy Fiddaman extern int		_vmfd _ARG_((int));
477*b30d1939SAndy Fiddaman extern int		_vmlock _ARG_((Vmalloc_t*, int));
478*b30d1939SAndy Fiddaman extern void		_vmoptions _ARG_((void));
479da2e3ebdSchin 
480da2e3ebdSchin _BEGIN_EXTERNS_
481da2e3ebdSchin 
482da2e3ebdSchin extern Vmextern_t	_Vmextern;
483da2e3ebdSchin 
484da2e3ebdSchin #if _PACKAGE_ast
485da2e3ebdSchin 
486da2e3ebdSchin #if _npt_getpagesize
487da2e3ebdSchin extern int		getpagesize _ARG_((void));
488da2e3ebdSchin #endif
489da2e3ebdSchin #if _npt_sbrk
490da2e3ebdSchin extern int		brk _ARG_(( void* ));
491da2e3ebdSchin extern Void_t*		sbrk _ARG_(( ssize_t ));
492da2e3ebdSchin #endif
493da2e3ebdSchin 
494da2e3ebdSchin #else
495da2e3ebdSchin 
496da2e3ebdSchin #if _hdr_unistd
497da2e3ebdSchin #include	<unistd.h>
498da2e3ebdSchin #else
499da2e3ebdSchin extern void		abort _ARG_(( void ));
500da2e3ebdSchin extern ssize_t		write _ARG_(( int, const void*, size_t ));
501da2e3ebdSchin extern int		getpagesize _ARG_((void));
502da2e3ebdSchin extern Void_t*		sbrk _ARG_((ssize_t));
503da2e3ebdSchin #endif
504da2e3ebdSchin 
505da2e3ebdSchin #if !__STDC__ && !_hdr_stdlib
506da2e3ebdSchin extern size_t		strlen _ARG_(( const char* ));
507da2e3ebdSchin extern char*		strcpy _ARG_(( char*, const char* ));
508da2e3ebdSchin extern int		strcmp _ARG_(( const char*, const char* ));
509da2e3ebdSchin extern int		atexit _ARG_(( void(*)(void) ));
510da2e3ebdSchin extern char*		getenv _ARG_(( const char* ));
511da2e3ebdSchin extern Void_t*		memcpy _ARG_(( Void_t*, const Void_t*, size_t ));
512da2e3ebdSchin extern Void_t*		memset _ARG_(( Void_t*, int, size_t ));
513da2e3ebdSchin #else
514da2e3ebdSchin #include	<stdlib.h>
515da2e3ebdSchin #include	<string.h>
516da2e3ebdSchin #endif
517da2e3ebdSchin 
518da2e3ebdSchin /* for vmexit.c */
519da2e3ebdSchin extern int		onexit _ARG_(( void(*)(void) ));
520da2e3ebdSchin extern void		_exit _ARG_(( int ));
521da2e3ebdSchin extern void		_cleanup _ARG_(( void ));
522da2e3ebdSchin 
523da2e3ebdSchin #endif /*_PACKAGE_ast*/
524da2e3ebdSchin 
525*b30d1939SAndy Fiddaman /* for vmdcsbrk.c */
526*b30d1939SAndy Fiddaman #if !_typ_ssize_t
527*b30d1939SAndy Fiddaman typedef int		ssize_t;
528da2e3ebdSchin #endif
529da2e3ebdSchin 
530*b30d1939SAndy Fiddaman _END_EXTERNS_
531*b30d1939SAndy Fiddaman 
532da2e3ebdSchin #endif /* _VMHDR_H */
533