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