xref: /onnv-gate/usr/src/lib/libast/common/vmalloc/vmhdr.h (revision 12068:08a39a083754)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1985-2010 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
78462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
84887Schin *                                                                      *
94887Schin *                A copy of the License is available at                 *
104887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
114887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
124887Schin *                                                                      *
134887Schin *              Information and Software Systems Research               *
144887Schin *                            AT&T Research                             *
154887Schin *                           Florham Park NJ                            *
164887Schin *                                                                      *
174887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
184887Schin *                  David Korn <dgk@research.att.com>                   *
194887Schin *                   Phong Vo <kpv@research.att.com>                    *
204887Schin *                                                                      *
214887Schin ***********************************************************************/
224887Schin #ifndef _VMHDR_H
234887Schin #define _VMHDR_H	1
244887Schin #ifndef _BLD_vmalloc
254887Schin #define _BLD_vmalloc	1
264887Schin #endif
274887Schin 
284887Schin /*	Common types, and macros for vmalloc functions.
294887Schin **
304887Schin **	Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
314887Schin */
324887Schin 
334887Schin #ifndef __STD_C	/* this is normally in vmalloc.h but it's included late here */
344887Schin #ifdef __STDC__
354887Schin #define	__STD_C		1
364887Schin #else
374887Schin #if __cplusplus || c_plusplus
384887Schin #define __STD_C		1
394887Schin #else
404887Schin #define __STD_C		0
414887Schin #endif /*__cplusplus*/
424887Schin #endif /*__STDC__*/
434887Schin #endif /*__STD_C*/
444887Schin 
454887Schin #if _PACKAGE_ast
464887Schin 
474887Schin #if !_UWIN
484887Schin #define getpagesize		______getpagesize
494887Schin #define _npt_getpagesize	1
504887Schin #define brk			______brk
514887Schin #define sbrk			______sbrk
524887Schin #define _npt_sbrk		1
534887Schin #endif
544887Schin 
554887Schin #include	<ast.h>
564887Schin 
574887Schin #if _npt_getpagesize
584887Schin #undef				getpagesize
594887Schin #endif
604887Schin #if _npt_sbrk
614887Schin #undef				brk
624887Schin #undef				sbrk
634887Schin #endif
644887Schin 
654887Schin #else
664887Schin 
674887Schin #include	<ast_common.h>
684887Schin 
694887Schin #if !_UWIN
704887Schin #define _npt_getpagesize	1
714887Schin #define _npt_sbrk		1
724887Schin #endif
734887Schin 
74*12068SRoger.Faulkner@Oracle.COM #ifndef integralof
75*12068SRoger.Faulkner@Oracle.COM #define integralof(x)		(((char*)(x))-((char*)0))
76*12068SRoger.Faulkner@Oracle.COM #endif
77*12068SRoger.Faulkner@Oracle.COM 
784887Schin #endif /*_PACKAGE_ast*/
794887Schin 
804887Schin #include	"FEATURE/vmalloc"
814887Schin 
824887Schin #include	<setjmp.h>
834887Schin 
844887Schin /* the below macros decide which combinations of sbrk() or mmap() to used */
854887Schin #if defined(_WIN32)
864887Schin #define _mem_win32	1
874887Schin #undef _mem_sbrk
884887Schin #undef _mem_mmap_anon
894887Schin #undef _mem_mmap_zero
904887Schin #endif
914887Schin 
924887Schin #if _mem_mmap_anon
934887Schin #undef _mem_mmap_zero
944887Schin #endif
954887Schin 
964887Schin #if !_mem_win32 && !_mem_sbrk && !_mem_mmap_anon && !_mem_mmap_zero
974887Schin #undef _std_malloc
984887Schin #define _std_malloc	1	/* do not define malloc/free/realloc */
994887Schin #endif
1004887Schin 
1014887Schin typedef unsigned char	Vmuchar_t;
1024887Schin typedef unsigned long	Vmulong_t;
1034887Schin 
1044887Schin typedef union _head_u	Head_t;
1054887Schin typedef union _body_u	Body_t;
1064887Schin typedef struct _block_s	Block_t;
1074887Schin typedef struct _seg_s	Seg_t;
1084887Schin typedef struct _pfobj_s	Pfobj_t;
1094887Schin 
1104887Schin #if !_typ_ssize_t
1114887Schin typedef int		ssize_t;
1124887Schin #endif
1134887Schin 
1144887Schin #define NIL(t)		((t)0)
1154887Schin #define reg		register
1164887Schin #if __STD_C
1174887Schin #define NOTUSED(x)	(void)(x)
1184887Schin #else
1194887Schin #define NOTUSED(x)	(&x,1)
1204887Schin #endif
1214887Schin 
1224887Schin /* convert an address to an integral value */
1234887Schin #define VLONG(addr)	((Vmulong_t)((char*)(addr) - (char*)0) )
1244887Schin 
1254887Schin /* Round x up to a multiple of y. ROUND2 does powers-of-2 and ROUNDX does others */
1264887Schin #define ROUND2(x,y)	(((x) + ((y)-1)) & ~((y)-1))
1274887Schin #define ROUNDX(x,y)	((((x) + ((y)-1)) / (y)) * (y))
1284887Schin #define ROUND(x,y)	(((y)&((y)-1)) ? ROUNDX((x),(y)) : ROUND2((x),(y)) )
1294887Schin 
1304887Schin /* compute a value that is a common multiple of x and y */
1314887Schin #define MULTIPLE(x,y)	((x)%(y) == 0 ? (x) : (y)%(x) == 0 ? (y) : (y)*(x))
1324887Schin 
1334887Schin #define VM_check	0x0001	/* enable detailed checks		*/
1344887Schin #define VM_abort	0x0002	/* abort() on assertion failure		*/
1358462SApril.Chin@Sun.COM #define VM_region	0x0004	/* enable region segment checks		*/
1368462SApril.Chin@Sun.COM #define VM_mmap		0x0010	/* favor mmap allocation		*/
1374887Schin 
1384887Schin #if _UWIN
1394887Schin #include <ast_windows.h>
1404887Schin #endif
1414887Schin 
1424887Schin #ifndef DEBUG
1434887Schin #ifdef _BLD_DEBUG
1444887Schin #define DEBUG		1
1454887Schin #endif /*_BLD_DEBUG*/
1464887Schin #endif /*DEBUG*/
1474887Schin #if DEBUG
1484887Schin extern void		_vmmessage _ARG_((const char*, long, const char*, long));
1494887Schin #define ABORT()		(_Vmassert & VM_abort)
1504887Schin #define CHECK()		(_Vmassert & VM_check)
1514887Schin #define ASSERT(p)	((p) ? 0 : (MESSAGE("Assertion failed"), ABORT() ? (abort(),0) : 0))
1524887Schin #define COUNT(n)	((n) += 1)
1534887Schin #define MESSAGE(s)	_vmmessage(__FILE__,__LINE__,s,0)
1544887Schin #else
1554887Schin #define ABORT()		(0)
1564887Schin #define ASSERT(p)
1574887Schin #define CHECK()		(0)
1584887Schin #define COUNT(n)
1594887Schin #define MESSAGE(s)	(0)
1604887Schin #endif /*DEBUG*/
1614887Schin 
1624887Schin #define VMPAGESIZE	8192
16310898Sroland.mainz@nrubsig.org 
1644887Schin #if _AST_PAGESIZE > VMPAGESIZE
1654887Schin #undef	VMPAGESIZE
1664887Schin #define VMPAGESIZE	_AST_PAGESIZE
1674887Schin #endif
16810898Sroland.mainz@nrubsig.org 
16910898Sroland.mainz@nrubsig.org #if _lib_getpagesize && !defined(_AST_PAGESIZE)
1704887Schin #define GETPAGESIZE(x)	((x) ? (x) : \
1714887Schin 			 (((x)=getpagesize()) < VMPAGESIZE ? ((x)=VMPAGESIZE) : (x)) )
1724887Schin #else
1734887Schin #define GETPAGESIZE(x)	((x) = VMPAGESIZE)
1744887Schin #endif
1754887Schin 
17610898Sroland.mainz@nrubsig.org #ifdef	_AST_PAGESIZE
17710898Sroland.mainz@nrubsig.org #define VMHEAPINCR	(_Vmpagesize*1)
17810898Sroland.mainz@nrubsig.org #else
17910898Sroland.mainz@nrubsig.org #define VMHEAPINCR	(_Vmpagesize*4)
18010898Sroland.mainz@nrubsig.org #endif
18110898Sroland.mainz@nrubsig.org 
1824887Schin /* Blocks are allocated such that their sizes are 0%(BITS+1)
1834887Schin ** This frees up enough low order bits to store state information
1844887Schin */
1854887Schin #define BUSY		(01)	/* block is busy				*/
1864887Schin #define PFREE		(02)	/* preceding block is free			*/
1874887Schin #define JUNK		(04)	/* marked as freed but not yet processed	*/
1884887Schin #define BITS		(07)	/* (BUSY|PFREE|JUNK)				*/
1894887Schin #define ALIGNB		(8)	/* size must be a multiple of BITS+1		*/
1904887Schin 
1914887Schin #define ISBITS(w)	((w) & BITS)
1924887Schin #define CLRBITS(w)	((w) &= ~BITS)
1934887Schin #define CPYBITS(w,f)	((w) |= ((f)&BITS) )
1944887Schin 
1954887Schin #define ISBUSY(w)	((w) & BUSY)
1964887Schin #define SETBUSY(w)	((w) |= BUSY)
1974887Schin #define CLRBUSY(w)	((w) &= ~BUSY)
1984887Schin 
1994887Schin #define ISPFREE(w)	((w) & PFREE)
2004887Schin #define SETPFREE(w)	((w) |= PFREE)
2014887Schin #define CLRPFREE(w)	((w) &= ~PFREE)
2024887Schin 
2034887Schin #define ISJUNK(w)	((w) & JUNK)
2044887Schin #define SETJUNK(w)	((w) |= JUNK)
2054887Schin #define CLRJUNK(w)	((w) &= ~JUNK)
2064887Schin 
2074887Schin #define OFFSET(t,e)	((size_t)(&(((t*)0)->e)) )
2084887Schin 
2094887Schin /* these bits share the "mode" field with the public bits */
2104887Schin #define VM_AGAIN	0010000		/* research the arena for space */
2114887Schin #define VM_LOCK		0020000		/* region is locked		*/
2124887Schin #define VM_LOCAL	0040000		/* local call, bypass lock	*/
2138462SApril.Chin@Sun.COM #define VM_INUSE	0004000		/* some operation is running	*/
2148462SApril.Chin@Sun.COM #define VM_UNUSED	0100060
2154887Schin #define VMETHOD(vd)	((vd)->mode&VM_METHODS)
2164887Schin 
2174887Schin /* test/set/clear lock state */
2188462SApril.Chin@Sun.COM #define SETINUSE(vd,iu)	(((iu) = (vd)->mode&VM_INUSE), ((vd)->mode |= VM_INUSE) )
2198462SApril.Chin@Sun.COM #define CLRINUSE(vd,iu)	((iu) ? 0 : ((vd)->mode &= ~VM_INUSE) )
2204887Schin #define SETLOCAL(vd)	((vd)->mode |= VM_LOCAL)
2214887Schin #define GETLOCAL(vd,l)	(((l) = (vd)->mode&VM_LOCAL), ((vd)->mode &= ~VM_LOCAL) )
2224887Schin #define ISLOCK(vd,l)	((l) ? 0 : ((vd)->mode &  VM_LOCK) )
2234887Schin #define SETLOCK(vd,l)	((l) ? 0 : ((vd)->mode |= VM_LOCK) )
2244887Schin #define CLRLOCK(vd,l)	((l) ? 0 : ((vd)->mode &= ~VM_LOCK) )
2254887Schin 
2264887Schin /* announcing entry/exit of allocation calls */
2274887Schin #define ANNOUNCE(lc, vm,ev,dt,dc) \
2284887Schin 		(( ((lc)&VM_LOCAL) || !(dc) || !(dc)->exceptf ) ? 0 : \
2294887Schin 			(*(dc)->exceptf)((vm), (ev), (Void_t*)(dt), (dc)) )
2304887Schin 
2314887Schin 
2324887Schin /* local calls */
2334887Schin #define KPVALLOC(vm,sz,func)		(SETLOCAL((vm)->data), func((vm),(sz)) )
2344887Schin #define KPVALIGN(vm,sz,al,func)		(SETLOCAL((vm)->data), func((vm),(sz),(al)) )
2354887Schin #define KPVFREE(vm,d,func)		(SETLOCAL((vm)->data), func((vm),(d)) )
2364887Schin #define KPVRESIZE(vm,d,sz,mv,func)	(SETLOCAL((vm)->data), func((vm),(d),(sz),(mv)) )
2374887Schin #define KPVADDR(vm,addr,func)		(SETLOCAL((vm)->data), func((vm),(addr)) )
2384887Schin #define KPVCOMPACT(vm,func)		(SETLOCAL((vm)->data), func((vm)) )
2394887Schin 
2404887Schin /* ALIGN is chosen so that a block can store all primitive types.
2414887Schin ** It should also be a multiple of ALIGNB==(BITS+1) so the size field
2424887Schin ** of Block_t will always be 0%(BITS+1) as noted above.
2434887Schin ** Of paramount importance is the ALIGNA macro below. If the local compile
2444887Schin ** environment is strange enough that the below method does not calculate
2454887Schin ** ALIGNA right, then the code below should be commented out and ALIGNA
2464887Schin ** redefined to the appropriate requirement.
2474887Schin */
2484887Schin union _align_u
2494887Schin {	char		c, *cp;
2504887Schin 	int		i, *ip;
2514887Schin 	long		l, *lp;
2524887Schin 	double		d, *dp, ***dppp[8];
2534887Schin 	size_t		s, *sp;
2544887Schin 	void(*		fn)();
2554887Schin 	union _align_u*	align;
2564887Schin 	Head_t*		head;
2574887Schin 	Body_t*		body;
2584887Schin 	Block_t*	block;
2594887Schin 	Vmuchar_t	a[ALIGNB];
2604887Schin 	_ast_fltmax_t	ld, *ldp;
2614887Schin 	jmp_buf		jmp;
2624887Schin };
2634887Schin struct _a_s
2644887Schin {	char		c;
2654887Schin 	union _align_u	a;
2664887Schin };
2674887Schin #define ALIGNA	(sizeof(struct _a_s) - sizeof(union _align_u))
2684887Schin struct _align_s
2694887Schin {	char	data[MULTIPLE(ALIGNA,ALIGNB)];
2704887Schin };
2714887Schin #undef	ALIGN	/* bsd sys/param.h defines this */
2724887Schin #define ALIGN	sizeof(struct _align_s)
2734887Schin 
2744887Schin /* make sure that the head of a block is a multiple of ALIGN */
2754887Schin struct _head_s
2764887Schin {	union
2774887Schin 	{ Seg_t*	seg;	/* the containing segment	*/
2784887Schin 	  Block_t*	link;	/* possible link list usage	*/
2794887Schin 	  Pfobj_t*	pf;	/* profile structure pointer	*/
2804887Schin 	  char*		file;	/* for file name in Vmdebug	*/
2814887Schin 	} seg;
2824887Schin 	union
2834887Schin 	{ size_t	size;	/* size of data area in bytes	*/
2844887Schin 	  Block_t*	link;	/* possible link list usage	*/
2854887Schin 	  int		line;	/* for line number in Vmdebug	*/
2864887Schin 	} size;
2874887Schin };
2884887Schin #define HEADSIZE	ROUND(sizeof(struct _head_s),ALIGN)
2894887Schin union _head_u
2904887Schin {	Vmuchar_t	data[HEADSIZE];	/* to standardize size		*/
2914887Schin 	struct _head_s	head;
2924887Schin };
2934887Schin 
2944887Schin /* now make sure that the body of a block is a multiple of ALIGN */
2954887Schin struct _body_s
2964887Schin {	Block_t*	link;	/* next in link list		*/
2974887Schin 	Block_t*	left;	/* left child in free tree	*/
2984887Schin 	Block_t*	right;	/* right child in free tree	*/
2994887Schin 	Block_t**	self;	/* self pointer when free	*/
3004887Schin };
3014887Schin #define BODYSIZE	ROUND(sizeof(struct _body_s),ALIGN)
3024887Schin union _body_u
3034887Schin {	Vmuchar_t	data[BODYSIZE];	/* to standardize size		*/
3044887Schin 	struct _body_s	body;
3054887Schin };
3064887Schin 
3074887Schin /* After all the songs and dances, we should now have:
3084887Schin **	sizeof(Head_t)%ALIGN == 0
3094887Schin **	sizeof(Body_t)%ALIGN == 0
3104887Schin ** and	sizeof(Block_t) = sizeof(Head_t)+sizeof(Body_t)
3114887Schin */
3124887Schin struct _block_s
3134887Schin {	Head_t	head;
3144887Schin 	Body_t	body;
3154887Schin };
3164887Schin 
3174887Schin /* requirements for smallest block type */
3184887Schin struct _tiny_s
3194887Schin {	Block_t*	link;
3204887Schin 	Block_t*	self;
3214887Schin };
3224887Schin #define TINYSIZE	ROUND(sizeof(struct _tiny_s),ALIGN)
3234887Schin #define S_TINY		1				/* # of tiny blocks	*/
3244887Schin #define MAXTINY		(S_TINY*ALIGN + TINYSIZE)
3254887Schin #define TLEFT(b)	((b)->head.head.seg.link)	/* instead of LEFT	*/
3264887Schin #define TINIEST(b)	(SIZE(b) == TINYSIZE)		/* this type uses TLEFT	*/
3274887Schin 
3284887Schin #define DIV(x,y)	((y) == 8 ? ((x)>>3) : (x)/(y) )
3294887Schin #define INDEX(s)	DIV((s)-TINYSIZE,ALIGN)
3304887Schin 
3314887Schin /* small block types kept in separate caches for quick allocation */
3324887Schin #define S_CACHE		6	/* # of types of small blocks to be cached	*/
3334887Schin #define N_CACHE		32	/* on allocation, create this many at a time	*/
3344887Schin #define MAXCACHE	(S_CACHE*ALIGN + TINYSIZE)
3354887Schin #define C_INDEX(s)	(s < MAXCACHE ? INDEX(s) : S_CACHE)
3364887Schin 
3374887Schin #define TINY(vd)	((vd)->tiny)
3384887Schin #define CACHE(vd)	((vd)->cache)
3394887Schin 
340*12068SRoger.Faulkner@Oracle.COM struct _vmdata_s
3414887Schin {	int		mode;		/* current mode for region		*/
3424887Schin 	size_t		incr;		/* allocate in multiple of this		*/
3434887Schin 	size_t		pool;		/* size	of an elt in a Vmpool region	*/
3444887Schin 	Seg_t*		seg;		/* list of segments			*/
3454887Schin 	Block_t*	free;		/* most recent free block		*/
3464887Schin 	Block_t*	wild;		/* wilderness block			*/
3474887Schin 	Block_t*	root;		/* root of free tree			*/
3484887Schin 	Block_t*	tiny[S_TINY];	/* small blocks				*/
3494887Schin 	Block_t*	cache[S_CACHE+1]; /* delayed free blocks		*/
350*12068SRoger.Faulkner@Oracle.COM };
351*12068SRoger.Faulkner@Oracle.COM /* Vmdata_t typedef in <vmalloc.h> */
3524887Schin 
3534887Schin #include	"vmalloc.h"
3544887Schin 
3554887Schin #if !_PACKAGE_ast
3564887Schin /* we don't use these here and they interfere with some local names */
3574887Schin #undef malloc
3584887Schin #undef free
3594887Schin #undef realloc
3604887Schin #endif
3614887Schin 
3624887Schin /* segment structure */
3634887Schin struct _seg_s
364*12068SRoger.Faulkner@Oracle.COM {	Vmdata_t*	vmdt;	/* the data region holding this	*/
3654887Schin 	Seg_t*		next;	/* next segment			*/
3664887Schin 	Void_t*		addr;	/* starting segment address	*/
3674887Schin 	size_t		extent;	/* extent of segment		*/
3684887Schin 	Vmuchar_t*	baddr;	/* bottom of usable memory	*/
3694887Schin 	size_t		size;	/* allocable size		*/
3704887Schin 	Block_t*	free;	/* recent free blocks		*/
3714887Schin 	Block_t*	last;	/* Vmlast last-allocated block	*/
3724887Schin };
3734887Schin 
3744887Schin /* starting block of a segment */
3754887Schin #define SEGBLOCK(s)	((Block_t*)(((Vmuchar_t*)(s)) + ROUND(sizeof(Seg_t),ALIGN)))
3764887Schin 
3774887Schin /* short-hands for block data */
3784887Schin #define SEG(b)		((b)->head.head.seg.seg)
3794887Schin #define SEGLINK(b)	((b)->head.head.seg.link)
3804887Schin #define	SIZE(b)		((b)->head.head.size.size)
3814887Schin #define SIZELINK(b)	((b)->head.head.size.link)
3824887Schin #define LINK(b)		((b)->body.body.link)
3834887Schin #define LEFT(b)		((b)->body.body.left)
3844887Schin #define RIGHT(b)	((b)->body.body.right)
3854887Schin #define VM(b)		(SEG(b)->vm)
3864887Schin 
3874887Schin #define DATA(b)		((Void_t*)((b)->body.data) )
3884887Schin #define BLOCK(d)	((Block_t*)((char*)(d) - sizeof(Head_t)) )
3894887Schin #define SELF(b)		((Block_t**)((b)->body.data + SIZE(b) - sizeof(Block_t*)) )
3904887Schin #define LAST(b)		(*((Block_t**)(((char*)(b)) - sizeof(Block_t*)) ) )
3914887Schin #define NEXT(b)		((Block_t*)((b)->body.data + SIZE(b)) )
3924887Schin 
3934887Schin /* functions to manipulate link lists of elts of the same size */
3944887Schin #define SETLINK(b)	(RIGHT(b) =  (b) )
3954887Schin #define ISLINK(b)	(RIGHT(b) == (b) )
3964887Schin #define UNLINK(vd,b,i,t) \
3974887Schin 		((((t) = LINK(b)) ? (LEFT(t) = LEFT(b)) : NIL(Block_t*) ), \
3984887Schin 		 (((t) = LEFT(b)) ? (LINK(t) = LINK(b)) : (TINY(vd)[i] = LINK(b)) ) )
3994887Schin 
4004887Schin /* delete a block from a link list or the free tree.
4014887Schin ** The test in the below macro is worth scratching your head a bit.
4024887Schin ** Even though tiny blocks (size < BODYSIZE) are kept in separate lists,
4034887Schin ** only the TINIEST ones require TLEFT(b) for the back link. Since this
4044887Schin ** destroys the SEG(b) pointer, it must be carefully restored in bestsearch().
4054887Schin ** Other tiny blocks have enough space to use the usual LEFT(b).
4064887Schin ** In this case, I have also carefully arranged so that RIGHT(b) and
4074887Schin ** SELF(b) can be overlapped and the test ISLINK() will go through.
4084887Schin */
4094887Schin #define REMOVE(vd,b,i,t,func) \
4104887Schin 		((!TINIEST(b) && ISLINK(b)) ? UNLINK((vd),(b),(i),(t)) : \
4114887Schin 	 		func((vd),SIZE(b),(b)) )
4124887Schin 
4134887Schin /* see if a block is the wilderness block */
4144887Schin #define SEGWILD(b)	(((b)->body.data+SIZE(b)+sizeof(Head_t)) >= SEG(b)->baddr)
4154887Schin #define VMWILD(vd,b)	(((b)->body.data+SIZE(b)+sizeof(Head_t)) >= vd->seg->baddr)
4164887Schin 
4174887Schin #define VMFLF(vm,fi,ln,fn)	((fi) = (vm)->file, (vm)->file = NIL(char*), \
4184887Schin 		 		 (ln) = (vm)->line, (vm)->line = 0 , \
4194887Schin 		 		 (fn) = (vm)->func, (vm)->func = NIL(Void_t*) )
4204887Schin 
4214887Schin /* The lay-out of a Vmprofile block is this:
4224887Schin **	seg_ size ----data---- _pf_ size
4234887Schin **	_________ ____________ _________
4244887Schin **	seg_, size: header required by Vmbest.
4254887Schin **	data:	actual data block.
4264887Schin **	_pf_:	pointer to the corresponding Pfobj_t struct
4274887Schin **	size:	the true size of the block.
4284887Schin ** So each block requires an extra Head_t.
4294887Schin */
4304887Schin #define PF_EXTRA   sizeof(Head_t)
4314887Schin #define PFDATA(d)  ((Head_t*)((Vmuchar_t*)(d)+(SIZE(BLOCK(d))&~BITS)-sizeof(Head_t)) )
4324887Schin #define PFOBJ(d)   (PFDATA(d)->head.seg.pf)
4334887Schin #define PFSIZE(d)  (PFDATA(d)->head.size.size)
4344887Schin 
4354887Schin /* The lay-out of a block allocated by Vmdebug is this:
4364887Schin **	seg_ size file size seg_ magi ----data---- --magi-- magi line
4374887Schin **	--------- --------- --------- ------------ -------- ---------
4384887Schin **	seg_,size: header required by Vmbest management.
4394887Schin **	file:	the file where it was created.
4404887Schin **	size:	the true byte count of the block
4414887Schin **	seg_:	should be the same as the previous seg_.
4424887Schin **		This allows the function vmregion() to work.
4434887Schin **	magi:	magic bytes to detect overwrites.
4444887Schin **	data:	the actual data block.
4454887Schin **	magi:	more magic bytes.
4464887Schin **	line:	the line number in the file where it was created.
4474887Schin ** So for each allocated block, we'll need 3 extra Head_t.
4484887Schin */
4494887Schin 
4504887Schin /* convenient macros for accessing the above fields */
4514887Schin #define DB_HEAD		(2*sizeof(Head_t))
4524887Schin #define DB_TAIL		(2*sizeof(Head_t))
4534887Schin #define DB_EXTRA	(DB_HEAD+DB_TAIL)
4544887Schin #define DBBLOCK(d)	((Block_t*)((Vmuchar_t*)(d) - 3*sizeof(Head_t)) )
4554887Schin #define DBBSIZE(d)	(SIZE(DBBLOCK(d)) & ~BITS)
4564887Schin #define DBSEG(d)	(((Head_t*)((Vmuchar_t*)(d) - sizeof(Head_t)))->head.seg.seg )
4574887Schin #define DBSIZE(d)	(((Head_t*)((Vmuchar_t*)(d) - 2*sizeof(Head_t)))->head.size.size )
4584887Schin #define DBFILE(d)	(((Head_t*)((Vmuchar_t*)(d) - 2*sizeof(Head_t)))->head.seg.file )
4594887Schin #define DBLN(d)		(((Head_t*)((Vmuchar_t*)DBBLOCK(d)+DBBSIZE(d)))->head.size.line )
4604887Schin #define DBLINE(d)	(DBLN(d) < 0 ? -DBLN(d) : DBLN(d))
4614887Schin 
4624887Schin /* forward/backward translation for addresses between Vmbest and Vmdebug */
4634887Schin #define DB2BEST(d)	((Vmuchar_t*)(d) - 2*sizeof(Head_t))
4644887Schin #define DB2DEBUG(b)	((Vmuchar_t*)(b) + 2*sizeof(Head_t))
4654887Schin 
4664887Schin /* set file and line number, note that DBLN > 0 so that DBISBAD will work  */
4674887Schin #define DBSETFL(d,f,l)	(DBFILE(d) = (f), DBLN(d) = (f) ? (l) : 1)
4684887Schin 
4694887Schin /* set and test the state of known to be corrupted */
4704887Schin #define DBSETBAD(d)	(DBLN(d) > 0 ? (DBLN(d) = -DBLN(d)) : -1)
4714887Schin #define DBISBAD(d)	(DBLN(d) <= 0)
4724887Schin 
4734887Schin #define DB_MAGIC	0255		/* 10101101	*/
4744887Schin 
4754887Schin /* compute the bounds of the magic areas */
4764887Schin #define DBHEAD(d,begp,endp) \
4774887Schin 		(((begp) = (Vmuchar_t*)(&DBSEG(d)) + sizeof(Seg_t*)), ((endp) = (d)) )
4784887Schin #define DBTAIL(d,begp,endp) \
4794887Schin 		(((begp) = (Vmuchar_t*)(d)+DBSIZE(d)), ((endp) = (Vmuchar_t*)(&DBLN(d))) )
4804887Schin 
4814887Schin /* external symbols for internal use by vmalloc */
4824887Schin typedef Block_t*	(*Vmsearch_f)_ARG_((Vmdata_t*, size_t, Block_t*));
4834887Schin typedef struct _vmextern_
4844887Schin {	Block_t*	(*vm_extend)_ARG_((Vmalloc_t*, size_t, Vmsearch_f ));
4854887Schin 	ssize_t		(*vm_truncate)_ARG_((Vmalloc_t*, Seg_t*, size_t, int));
4864887Schin 	size_t		vm_pagesize;
4874887Schin 	char*		(*vm_strcpy)_ARG_((char*, const char*, int));
4884887Schin 	char*		(*vm_itoa)_ARG_((Vmulong_t, int));
4894887Schin 	void		(*vm_trace)_ARG_((Vmalloc_t*,
4904887Schin 					  Vmuchar_t*, Vmuchar_t*, size_t, size_t));
4914887Schin 	void		(*vm_pfclose)_ARG_((Vmalloc_t*));
4924887Schin 	int		vm_assert;
493*12068SRoger.Faulkner@Oracle.COM 	int		vm_options;
4944887Schin } Vmextern_t;
4954887Schin 
4964887Schin #define _Vmextend	(_Vmextern.vm_extend)
4974887Schin #define _Vmtruncate	(_Vmextern.vm_truncate)
4984887Schin #define _Vmpagesize	(_Vmextern.vm_pagesize)
4994887Schin #define _Vmstrcpy	(_Vmextern.vm_strcpy)
5004887Schin #define _Vmitoa		(_Vmextern.vm_itoa)
5014887Schin #define _Vmtrace	(_Vmextern.vm_trace)
5024887Schin #define _Vmpfclose	(_Vmextern.vm_pfclose)
5034887Schin #define _Vmassert	(_Vmextern.vm_assert)
504*12068SRoger.Faulkner@Oracle.COM #define _Vmoptions	(_Vmextern.vm_options)
5054887Schin 
506*12068SRoger.Faulkner@Oracle.COM #define VMOPTIONS()	do { if (!_Vmoptions) { _vmoptions(); } } while (0)
507*12068SRoger.Faulkner@Oracle.COM 
508*12068SRoger.Faulkner@Oracle.COM extern void		_vmoptions _ARG_((void));
5094887Schin extern int		_vmbestcheck _ARG_((Vmdata_t*, Block_t*));
5104887Schin 
5114887Schin _BEGIN_EXTERNS_
5124887Schin 
5134887Schin extern Vmextern_t	_Vmextern;
5144887Schin 
5154887Schin #if _PACKAGE_ast
5164887Schin 
5174887Schin #if _npt_getpagesize
5184887Schin extern int		getpagesize _ARG_((void));
5194887Schin #endif
5204887Schin #if _npt_sbrk
5214887Schin extern int		brk _ARG_(( void* ));
5224887Schin extern Void_t*		sbrk _ARG_(( ssize_t ));
5234887Schin #endif
5244887Schin 
5254887Schin #else
5264887Schin 
5274887Schin #if _hdr_unistd
5284887Schin #include	<unistd.h>
5294887Schin #else
5304887Schin extern void		abort _ARG_(( void ));
5314887Schin extern ssize_t		write _ARG_(( int, const void*, size_t ));
5324887Schin extern int		getpagesize _ARG_((void));
5334887Schin extern Void_t*		sbrk _ARG_((ssize_t));
5344887Schin #endif
5354887Schin 
5364887Schin #if !__STDC__ && !_hdr_stdlib
5374887Schin extern size_t		strlen _ARG_(( const char* ));
5384887Schin extern char*		strcpy _ARG_(( char*, const char* ));
5394887Schin extern int		strcmp _ARG_(( const char*, const char* ));
5404887Schin extern int		atexit _ARG_(( void(*)(void) ));
5414887Schin extern char*		getenv _ARG_(( const char* ));
5424887Schin extern Void_t*		memcpy _ARG_(( Void_t*, const Void_t*, size_t ));
5434887Schin extern Void_t*		memset _ARG_(( Void_t*, int, size_t ));
5444887Schin #else
5454887Schin #include	<stdlib.h>
5464887Schin #include	<string.h>
5474887Schin #endif
5484887Schin 
5494887Schin /* for vmexit.c */
5504887Schin extern int		onexit _ARG_(( void(*)(void) ));
5514887Schin extern void		_exit _ARG_(( int ));
5524887Schin extern void		_cleanup _ARG_(( void ));
5534887Schin 
5544887Schin #endif /*_PACKAGE_ast*/
5554887Schin 
5564887Schin _END_EXTERNS_
5574887Schin 
5584887Schin #if _UWIN
5594887Schin #define abort()		(DebugBreak(),abort())
5604887Schin #endif
5614887Schin 
5624887Schin #endif /* _VMHDR_H */
563