1da2e3ebdSchin /*********************************************************************** 2da2e3ebdSchin * * 3da2e3ebdSchin * This software is part of the ast package * 4*3e14f97fSRoger A. Faulkner * Copyright (c) 1985-2010 AT&T Intellectual Property * 5da2e3ebdSchin * and is licensed under the * 6da2e3ebdSchin * Common Public License, Version 1.0 * 77c2fbfb3SApril Chin * by AT&T Intellectual Property * 8da2e3ebdSchin * * 9da2e3ebdSchin * A copy of the License is available at * 10da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt * 11da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 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*3e14f97fSRoger A. Faulkner #ifndef integralof 75*3e14f97fSRoger A. Faulkner #define integralof(x) (((char*)(x))-((char*)0)) 76*3e14f97fSRoger A. Faulkner #endif 77*3e14f97fSRoger A. Faulkner 78da2e3ebdSchin #endif /*_PACKAGE_ast*/ 79da2e3ebdSchin 80da2e3ebdSchin #include "FEATURE/vmalloc" 81da2e3ebdSchin 82da2e3ebdSchin #include <setjmp.h> 83da2e3ebdSchin 84da2e3ebdSchin /* the below macros decide which combinations of sbrk() or mmap() to used */ 85da2e3ebdSchin #if defined(_WIN32) 86da2e3ebdSchin #define _mem_win32 1 87da2e3ebdSchin #undef _mem_sbrk 88da2e3ebdSchin #undef _mem_mmap_anon 89da2e3ebdSchin #undef _mem_mmap_zero 90da2e3ebdSchin #endif 91da2e3ebdSchin 92da2e3ebdSchin #if _mem_mmap_anon 93da2e3ebdSchin #undef _mem_mmap_zero 94da2e3ebdSchin #endif 95da2e3ebdSchin 96da2e3ebdSchin #if !_mem_win32 && !_mem_sbrk && !_mem_mmap_anon && !_mem_mmap_zero 97da2e3ebdSchin #undef _std_malloc 98da2e3ebdSchin #define _std_malloc 1 /* do not define malloc/free/realloc */ 99da2e3ebdSchin #endif 100da2e3ebdSchin 101da2e3ebdSchin typedef unsigned char Vmuchar_t; 102da2e3ebdSchin typedef unsigned long Vmulong_t; 103da2e3ebdSchin 104da2e3ebdSchin typedef union _head_u Head_t; 105da2e3ebdSchin typedef union _body_u Body_t; 106da2e3ebdSchin typedef struct _block_s Block_t; 107da2e3ebdSchin typedef struct _seg_s Seg_t; 108da2e3ebdSchin typedef struct _pfobj_s Pfobj_t; 109da2e3ebdSchin 110da2e3ebdSchin #if !_typ_ssize_t 111da2e3ebdSchin typedef int ssize_t; 112da2e3ebdSchin #endif 113da2e3ebdSchin 114da2e3ebdSchin #define NIL(t) ((t)0) 115da2e3ebdSchin #define reg register 116da2e3ebdSchin #if __STD_C 117da2e3ebdSchin #define NOTUSED(x) (void)(x) 118da2e3ebdSchin #else 119da2e3ebdSchin #define NOTUSED(x) (&x,1) 120da2e3ebdSchin #endif 121da2e3ebdSchin 122da2e3ebdSchin /* convert an address to an integral value */ 123da2e3ebdSchin #define VLONG(addr) ((Vmulong_t)((char*)(addr) - (char*)0) ) 124da2e3ebdSchin 125da2e3ebdSchin /* Round x up to a multiple of y. ROUND2 does powers-of-2 and ROUNDX does others */ 126da2e3ebdSchin #define ROUND2(x,y) (((x) + ((y)-1)) & ~((y)-1)) 127da2e3ebdSchin #define ROUNDX(x,y) ((((x) + ((y)-1)) / (y)) * (y)) 128da2e3ebdSchin #define ROUND(x,y) (((y)&((y)-1)) ? ROUNDX((x),(y)) : ROUND2((x),(y)) ) 129da2e3ebdSchin 130da2e3ebdSchin /* compute a value that is a common multiple of x and y */ 131da2e3ebdSchin #define MULTIPLE(x,y) ((x)%(y) == 0 ? (x) : (y)%(x) == 0 ? (y) : (y)*(x)) 132da2e3ebdSchin 133da2e3ebdSchin #define VM_check 0x0001 /* enable detailed checks */ 134da2e3ebdSchin #define VM_abort 0x0002 /* abort() on assertion failure */ 1357c2fbfb3SApril Chin #define VM_region 0x0004 /* enable region segment checks */ 1367c2fbfb3SApril Chin #define VM_mmap 0x0010 /* favor mmap allocation */ 137da2e3ebdSchin 138da2e3ebdSchin #if _UWIN 139da2e3ebdSchin #include <ast_windows.h> 140da2e3ebdSchin #endif 141da2e3ebdSchin 142da2e3ebdSchin #ifndef DEBUG 143da2e3ebdSchin #ifdef _BLD_DEBUG 144da2e3ebdSchin #define DEBUG 1 145da2e3ebdSchin #endif /*_BLD_DEBUG*/ 146da2e3ebdSchin #endif /*DEBUG*/ 147da2e3ebdSchin #if DEBUG 148da2e3ebdSchin extern void _vmmessage _ARG_((const char*, long, const char*, long)); 149da2e3ebdSchin #define ABORT() (_Vmassert & VM_abort) 150da2e3ebdSchin #define CHECK() (_Vmassert & VM_check) 151da2e3ebdSchin #define ASSERT(p) ((p) ? 0 : (MESSAGE("Assertion failed"), ABORT() ? (abort(),0) : 0)) 152da2e3ebdSchin #define COUNT(n) ((n) += 1) 153da2e3ebdSchin #define MESSAGE(s) _vmmessage(__FILE__,__LINE__,s,0) 154da2e3ebdSchin #else 155da2e3ebdSchin #define ABORT() (0) 156da2e3ebdSchin #define ASSERT(p) 157da2e3ebdSchin #define CHECK() (0) 158da2e3ebdSchin #define COUNT(n) 159da2e3ebdSchin #define MESSAGE(s) (0) 160da2e3ebdSchin #endif /*DEBUG*/ 161da2e3ebdSchin 162da2e3ebdSchin #define VMPAGESIZE 8192 16334f9b3eeSRoland Mainz 164da2e3ebdSchin #if _AST_PAGESIZE > VMPAGESIZE 165da2e3ebdSchin #undef VMPAGESIZE 166da2e3ebdSchin #define VMPAGESIZE _AST_PAGESIZE 167da2e3ebdSchin #endif 16834f9b3eeSRoland Mainz 16934f9b3eeSRoland Mainz #if _lib_getpagesize && !defined(_AST_PAGESIZE) 170da2e3ebdSchin #define GETPAGESIZE(x) ((x) ? (x) : \ 171da2e3ebdSchin (((x)=getpagesize()) < VMPAGESIZE ? ((x)=VMPAGESIZE) : (x)) ) 172da2e3ebdSchin #else 173da2e3ebdSchin #define GETPAGESIZE(x) ((x) = VMPAGESIZE) 174da2e3ebdSchin #endif 175da2e3ebdSchin 17634f9b3eeSRoland Mainz #ifdef _AST_PAGESIZE 17734f9b3eeSRoland Mainz #define VMHEAPINCR (_Vmpagesize*1) 17834f9b3eeSRoland Mainz #else 17934f9b3eeSRoland Mainz #define VMHEAPINCR (_Vmpagesize*4) 18034f9b3eeSRoland Mainz #endif 18134f9b3eeSRoland Mainz 182da2e3ebdSchin /* Blocks are allocated such that their sizes are 0%(BITS+1) 183da2e3ebdSchin ** This frees up enough low order bits to store state information 184da2e3ebdSchin */ 185da2e3ebdSchin #define BUSY (01) /* block is busy */ 186da2e3ebdSchin #define PFREE (02) /* preceding block is free */ 187da2e3ebdSchin #define JUNK (04) /* marked as freed but not yet processed */ 188da2e3ebdSchin #define BITS (07) /* (BUSY|PFREE|JUNK) */ 189da2e3ebdSchin #define ALIGNB (8) /* size must be a multiple of BITS+1 */ 190da2e3ebdSchin 191da2e3ebdSchin #define ISBITS(w) ((w) & BITS) 192da2e3ebdSchin #define CLRBITS(w) ((w) &= ~BITS) 193da2e3ebdSchin #define CPYBITS(w,f) ((w) |= ((f)&BITS) ) 194da2e3ebdSchin 195da2e3ebdSchin #define ISBUSY(w) ((w) & BUSY) 196da2e3ebdSchin #define SETBUSY(w) ((w) |= BUSY) 197da2e3ebdSchin #define CLRBUSY(w) ((w) &= ~BUSY) 198da2e3ebdSchin 199da2e3ebdSchin #define ISPFREE(w) ((w) & PFREE) 200da2e3ebdSchin #define SETPFREE(w) ((w) |= PFREE) 201da2e3ebdSchin #define CLRPFREE(w) ((w) &= ~PFREE) 202da2e3ebdSchin 203da2e3ebdSchin #define ISJUNK(w) ((w) & JUNK) 204da2e3ebdSchin #define SETJUNK(w) ((w) |= JUNK) 205da2e3ebdSchin #define CLRJUNK(w) ((w) &= ~JUNK) 206da2e3ebdSchin 207da2e3ebdSchin #define OFFSET(t,e) ((size_t)(&(((t*)0)->e)) ) 208da2e3ebdSchin 209da2e3ebdSchin /* these bits share the "mode" field with the public bits */ 210da2e3ebdSchin #define VM_AGAIN 0010000 /* research the arena for space */ 211da2e3ebdSchin #define VM_LOCK 0020000 /* region is locked */ 212da2e3ebdSchin #define VM_LOCAL 0040000 /* local call, bypass lock */ 2137c2fbfb3SApril Chin #define VM_INUSE 0004000 /* some operation is running */ 2147c2fbfb3SApril Chin #define VM_UNUSED 0100060 215da2e3ebdSchin #define VMETHOD(vd) ((vd)->mode&VM_METHODS) 216da2e3ebdSchin 217da2e3ebdSchin /* test/set/clear lock state */ 2187c2fbfb3SApril Chin #define SETINUSE(vd,iu) (((iu) = (vd)->mode&VM_INUSE), ((vd)->mode |= VM_INUSE) ) 2197c2fbfb3SApril Chin #define CLRINUSE(vd,iu) ((iu) ? 0 : ((vd)->mode &= ~VM_INUSE) ) 220da2e3ebdSchin #define SETLOCAL(vd) ((vd)->mode |= VM_LOCAL) 221da2e3ebdSchin #define GETLOCAL(vd,l) (((l) = (vd)->mode&VM_LOCAL), ((vd)->mode &= ~VM_LOCAL) ) 222da2e3ebdSchin #define ISLOCK(vd,l) ((l) ? 0 : ((vd)->mode & VM_LOCK) ) 223da2e3ebdSchin #define SETLOCK(vd,l) ((l) ? 0 : ((vd)->mode |= VM_LOCK) ) 224da2e3ebdSchin #define CLRLOCK(vd,l) ((l) ? 0 : ((vd)->mode &= ~VM_LOCK) ) 225da2e3ebdSchin 226da2e3ebdSchin /* announcing entry/exit of allocation calls */ 227da2e3ebdSchin #define ANNOUNCE(lc, vm,ev,dt,dc) \ 228da2e3ebdSchin (( ((lc)&VM_LOCAL) || !(dc) || !(dc)->exceptf ) ? 0 : \ 229da2e3ebdSchin (*(dc)->exceptf)((vm), (ev), (Void_t*)(dt), (dc)) ) 230da2e3ebdSchin 231da2e3ebdSchin 232da2e3ebdSchin /* local calls */ 233da2e3ebdSchin #define KPVALLOC(vm,sz,func) (SETLOCAL((vm)->data), func((vm),(sz)) ) 234da2e3ebdSchin #define KPVALIGN(vm,sz,al,func) (SETLOCAL((vm)->data), func((vm),(sz),(al)) ) 235da2e3ebdSchin #define KPVFREE(vm,d,func) (SETLOCAL((vm)->data), func((vm),(d)) ) 236da2e3ebdSchin #define KPVRESIZE(vm,d,sz,mv,func) (SETLOCAL((vm)->data), func((vm),(d),(sz),(mv)) ) 237da2e3ebdSchin #define KPVADDR(vm,addr,func) (SETLOCAL((vm)->data), func((vm),(addr)) ) 238da2e3ebdSchin #define KPVCOMPACT(vm,func) (SETLOCAL((vm)->data), func((vm)) ) 239da2e3ebdSchin 240da2e3ebdSchin /* ALIGN is chosen so that a block can store all primitive types. 241da2e3ebdSchin ** It should also be a multiple of ALIGNB==(BITS+1) so the size field 242da2e3ebdSchin ** of Block_t will always be 0%(BITS+1) as noted above. 243da2e3ebdSchin ** Of paramount importance is the ALIGNA macro below. If the local compile 244da2e3ebdSchin ** environment is strange enough that the below method does not calculate 245da2e3ebdSchin ** ALIGNA right, then the code below should be commented out and ALIGNA 246da2e3ebdSchin ** redefined to the appropriate requirement. 247da2e3ebdSchin */ 248da2e3ebdSchin union _align_u 249da2e3ebdSchin { char c, *cp; 250da2e3ebdSchin int i, *ip; 251da2e3ebdSchin long l, *lp; 252da2e3ebdSchin double d, *dp, ***dppp[8]; 253da2e3ebdSchin size_t s, *sp; 254da2e3ebdSchin void(* fn)(); 255da2e3ebdSchin union _align_u* align; 256da2e3ebdSchin Head_t* head; 257da2e3ebdSchin Body_t* body; 258da2e3ebdSchin Block_t* block; 259da2e3ebdSchin Vmuchar_t a[ALIGNB]; 260da2e3ebdSchin _ast_fltmax_t ld, *ldp; 261da2e3ebdSchin jmp_buf jmp; 262da2e3ebdSchin }; 263da2e3ebdSchin struct _a_s 264da2e3ebdSchin { char c; 265da2e3ebdSchin union _align_u a; 266da2e3ebdSchin }; 267da2e3ebdSchin #define ALIGNA (sizeof(struct _a_s) - sizeof(union _align_u)) 268da2e3ebdSchin struct _align_s 269da2e3ebdSchin { char data[MULTIPLE(ALIGNA,ALIGNB)]; 270da2e3ebdSchin }; 271da2e3ebdSchin #undef ALIGN /* bsd sys/param.h defines this */ 272da2e3ebdSchin #define ALIGN sizeof(struct _align_s) 273da2e3ebdSchin 274da2e3ebdSchin /* make sure that the head of a block is a multiple of ALIGN */ 275da2e3ebdSchin struct _head_s 276da2e3ebdSchin { union 277da2e3ebdSchin { Seg_t* seg; /* the containing segment */ 278da2e3ebdSchin Block_t* link; /* possible link list usage */ 279da2e3ebdSchin Pfobj_t* pf; /* profile structure pointer */ 280da2e3ebdSchin char* file; /* for file name in Vmdebug */ 281da2e3ebdSchin } seg; 282da2e3ebdSchin union 283da2e3ebdSchin { size_t size; /* size of data area in bytes */ 284da2e3ebdSchin Block_t* link; /* possible link list usage */ 285da2e3ebdSchin int line; /* for line number in Vmdebug */ 286da2e3ebdSchin } size; 287da2e3ebdSchin }; 288da2e3ebdSchin #define HEADSIZE ROUND(sizeof(struct _head_s),ALIGN) 289da2e3ebdSchin union _head_u 290da2e3ebdSchin { Vmuchar_t data[HEADSIZE]; /* to standardize size */ 291da2e3ebdSchin struct _head_s head; 292da2e3ebdSchin }; 293da2e3ebdSchin 294da2e3ebdSchin /* now make sure that the body of a block is a multiple of ALIGN */ 295da2e3ebdSchin struct _body_s 296da2e3ebdSchin { Block_t* link; /* next in link list */ 297da2e3ebdSchin Block_t* left; /* left child in free tree */ 298da2e3ebdSchin Block_t* right; /* right child in free tree */ 299da2e3ebdSchin Block_t** self; /* self pointer when free */ 300da2e3ebdSchin }; 301da2e3ebdSchin #define BODYSIZE ROUND(sizeof(struct _body_s),ALIGN) 302da2e3ebdSchin union _body_u 303da2e3ebdSchin { Vmuchar_t data[BODYSIZE]; /* to standardize size */ 304da2e3ebdSchin struct _body_s body; 305da2e3ebdSchin }; 306da2e3ebdSchin 307da2e3ebdSchin /* After all the songs and dances, we should now have: 308da2e3ebdSchin ** sizeof(Head_t)%ALIGN == 0 309da2e3ebdSchin ** sizeof(Body_t)%ALIGN == 0 310da2e3ebdSchin ** and sizeof(Block_t) = sizeof(Head_t)+sizeof(Body_t) 311da2e3ebdSchin */ 312da2e3ebdSchin struct _block_s 313da2e3ebdSchin { Head_t head; 314da2e3ebdSchin Body_t body; 315da2e3ebdSchin }; 316da2e3ebdSchin 317da2e3ebdSchin /* requirements for smallest block type */ 318da2e3ebdSchin struct _tiny_s 319da2e3ebdSchin { Block_t* link; 320da2e3ebdSchin Block_t* self; 321da2e3ebdSchin }; 322da2e3ebdSchin #define TINYSIZE ROUND(sizeof(struct _tiny_s),ALIGN) 323da2e3ebdSchin #define S_TINY 1 /* # of tiny blocks */ 324da2e3ebdSchin #define MAXTINY (S_TINY*ALIGN + TINYSIZE) 325da2e3ebdSchin #define TLEFT(b) ((b)->head.head.seg.link) /* instead of LEFT */ 326da2e3ebdSchin #define TINIEST(b) (SIZE(b) == TINYSIZE) /* this type uses TLEFT */ 327da2e3ebdSchin 328da2e3ebdSchin #define DIV(x,y) ((y) == 8 ? ((x)>>3) : (x)/(y) ) 329da2e3ebdSchin #define INDEX(s) DIV((s)-TINYSIZE,ALIGN) 330da2e3ebdSchin 331da2e3ebdSchin /* small block types kept in separate caches for quick allocation */ 332da2e3ebdSchin #define S_CACHE 6 /* # of types of small blocks to be cached */ 333da2e3ebdSchin #define N_CACHE 32 /* on allocation, create this many at a time */ 334da2e3ebdSchin #define MAXCACHE (S_CACHE*ALIGN + TINYSIZE) 335da2e3ebdSchin #define C_INDEX(s) (s < MAXCACHE ? INDEX(s) : S_CACHE) 336da2e3ebdSchin 337da2e3ebdSchin #define TINY(vd) ((vd)->tiny) 338da2e3ebdSchin #define CACHE(vd) ((vd)->cache) 339da2e3ebdSchin 340*3e14f97fSRoger A. Faulkner struct _vmdata_s 341da2e3ebdSchin { int mode; /* current mode for region */ 342da2e3ebdSchin size_t incr; /* allocate in multiple of this */ 343da2e3ebdSchin size_t pool; /* size of an elt in a Vmpool region */ 344da2e3ebdSchin Seg_t* seg; /* list of segments */ 345da2e3ebdSchin Block_t* free; /* most recent free block */ 346da2e3ebdSchin Block_t* wild; /* wilderness block */ 347da2e3ebdSchin Block_t* root; /* root of free tree */ 348da2e3ebdSchin Block_t* tiny[S_TINY]; /* small blocks */ 349da2e3ebdSchin Block_t* cache[S_CACHE+1]; /* delayed free blocks */ 350*3e14f97fSRoger A. Faulkner }; 351*3e14f97fSRoger A. Faulkner /* Vmdata_t typedef in <vmalloc.h> */ 352da2e3ebdSchin 353da2e3ebdSchin #include "vmalloc.h" 354da2e3ebdSchin 355da2e3ebdSchin #if !_PACKAGE_ast 356da2e3ebdSchin /* we don't use these here and they interfere with some local names */ 357da2e3ebdSchin #undef malloc 358da2e3ebdSchin #undef free 359da2e3ebdSchin #undef realloc 360da2e3ebdSchin #endif 361da2e3ebdSchin 362da2e3ebdSchin /* segment structure */ 363da2e3ebdSchin struct _seg_s 364*3e14f97fSRoger A. Faulkner { Vmdata_t* vmdt; /* the data region holding this */ 365da2e3ebdSchin Seg_t* next; /* next segment */ 366da2e3ebdSchin Void_t* addr; /* starting segment address */ 367da2e3ebdSchin size_t extent; /* extent of segment */ 368da2e3ebdSchin Vmuchar_t* baddr; /* bottom of usable memory */ 369da2e3ebdSchin size_t size; /* allocable size */ 370da2e3ebdSchin Block_t* free; /* recent free blocks */ 371da2e3ebdSchin Block_t* last; /* Vmlast last-allocated block */ 372da2e3ebdSchin }; 373da2e3ebdSchin 374da2e3ebdSchin /* starting block of a segment */ 375da2e3ebdSchin #define SEGBLOCK(s) ((Block_t*)(((Vmuchar_t*)(s)) + ROUND(sizeof(Seg_t),ALIGN))) 376da2e3ebdSchin 377da2e3ebdSchin /* short-hands for block data */ 378da2e3ebdSchin #define SEG(b) ((b)->head.head.seg.seg) 379da2e3ebdSchin #define SEGLINK(b) ((b)->head.head.seg.link) 380da2e3ebdSchin #define SIZE(b) ((b)->head.head.size.size) 381da2e3ebdSchin #define SIZELINK(b) ((b)->head.head.size.link) 382da2e3ebdSchin #define LINK(b) ((b)->body.body.link) 383da2e3ebdSchin #define LEFT(b) ((b)->body.body.left) 384da2e3ebdSchin #define RIGHT(b) ((b)->body.body.right) 385da2e3ebdSchin #define VM(b) (SEG(b)->vm) 386da2e3ebdSchin 387da2e3ebdSchin #define DATA(b) ((Void_t*)((b)->body.data) ) 388da2e3ebdSchin #define BLOCK(d) ((Block_t*)((char*)(d) - sizeof(Head_t)) ) 389da2e3ebdSchin #define SELF(b) ((Block_t**)((b)->body.data + SIZE(b) - sizeof(Block_t*)) ) 390da2e3ebdSchin #define LAST(b) (*((Block_t**)(((char*)(b)) - sizeof(Block_t*)) ) ) 391da2e3ebdSchin #define NEXT(b) ((Block_t*)((b)->body.data + SIZE(b)) ) 392da2e3ebdSchin 393da2e3ebdSchin /* functions to manipulate link lists of elts of the same size */ 394da2e3ebdSchin #define SETLINK(b) (RIGHT(b) = (b) ) 395da2e3ebdSchin #define ISLINK(b) (RIGHT(b) == (b) ) 396da2e3ebdSchin #define UNLINK(vd,b,i,t) \ 397da2e3ebdSchin ((((t) = LINK(b)) ? (LEFT(t) = LEFT(b)) : NIL(Block_t*) ), \ 398da2e3ebdSchin (((t) = LEFT(b)) ? (LINK(t) = LINK(b)) : (TINY(vd)[i] = LINK(b)) ) ) 399da2e3ebdSchin 400da2e3ebdSchin /* delete a block from a link list or the free tree. 401da2e3ebdSchin ** The test in the below macro is worth scratching your head a bit. 402da2e3ebdSchin ** Even though tiny blocks (size < BODYSIZE) are kept in separate lists, 403da2e3ebdSchin ** only the TINIEST ones require TLEFT(b) for the back link. Since this 404da2e3ebdSchin ** destroys the SEG(b) pointer, it must be carefully restored in bestsearch(). 405da2e3ebdSchin ** Other tiny blocks have enough space to use the usual LEFT(b). 406da2e3ebdSchin ** In this case, I have also carefully arranged so that RIGHT(b) and 407da2e3ebdSchin ** SELF(b) can be overlapped and the test ISLINK() will go through. 408da2e3ebdSchin */ 409da2e3ebdSchin #define REMOVE(vd,b,i,t,func) \ 410da2e3ebdSchin ((!TINIEST(b) && ISLINK(b)) ? UNLINK((vd),(b),(i),(t)) : \ 411da2e3ebdSchin func((vd),SIZE(b),(b)) ) 412da2e3ebdSchin 413da2e3ebdSchin /* see if a block is the wilderness block */ 414da2e3ebdSchin #define SEGWILD(b) (((b)->body.data+SIZE(b)+sizeof(Head_t)) >= SEG(b)->baddr) 415da2e3ebdSchin #define VMWILD(vd,b) (((b)->body.data+SIZE(b)+sizeof(Head_t)) >= vd->seg->baddr) 416da2e3ebdSchin 417da2e3ebdSchin #define VMFLF(vm,fi,ln,fn) ((fi) = (vm)->file, (vm)->file = NIL(char*), \ 418da2e3ebdSchin (ln) = (vm)->line, (vm)->line = 0 , \ 419da2e3ebdSchin (fn) = (vm)->func, (vm)->func = NIL(Void_t*) ) 420da2e3ebdSchin 421da2e3ebdSchin /* The lay-out of a Vmprofile block is this: 422da2e3ebdSchin ** seg_ size ----data---- _pf_ size 423da2e3ebdSchin ** _________ ____________ _________ 424da2e3ebdSchin ** seg_, size: header required by Vmbest. 425da2e3ebdSchin ** data: actual data block. 426da2e3ebdSchin ** _pf_: pointer to the corresponding Pfobj_t struct 427da2e3ebdSchin ** size: the true size of the block. 428da2e3ebdSchin ** So each block requires an extra Head_t. 429da2e3ebdSchin */ 430da2e3ebdSchin #define PF_EXTRA sizeof(Head_t) 431da2e3ebdSchin #define PFDATA(d) ((Head_t*)((Vmuchar_t*)(d)+(SIZE(BLOCK(d))&~BITS)-sizeof(Head_t)) ) 432da2e3ebdSchin #define PFOBJ(d) (PFDATA(d)->head.seg.pf) 433da2e3ebdSchin #define PFSIZE(d) (PFDATA(d)->head.size.size) 434da2e3ebdSchin 435da2e3ebdSchin /* The lay-out of a block allocated by Vmdebug is this: 436da2e3ebdSchin ** seg_ size file size seg_ magi ----data---- --magi-- magi line 437da2e3ebdSchin ** --------- --------- --------- ------------ -------- --------- 438da2e3ebdSchin ** seg_,size: header required by Vmbest management. 439da2e3ebdSchin ** file: the file where it was created. 440da2e3ebdSchin ** size: the true byte count of the block 441da2e3ebdSchin ** seg_: should be the same as the previous seg_. 442da2e3ebdSchin ** This allows the function vmregion() to work. 443da2e3ebdSchin ** magi: magic bytes to detect overwrites. 444da2e3ebdSchin ** data: the actual data block. 445da2e3ebdSchin ** magi: more magic bytes. 446da2e3ebdSchin ** line: the line number in the file where it was created. 447da2e3ebdSchin ** So for each allocated block, we'll need 3 extra Head_t. 448da2e3ebdSchin */ 449da2e3ebdSchin 450da2e3ebdSchin /* convenient macros for accessing the above fields */ 451da2e3ebdSchin #define DB_HEAD (2*sizeof(Head_t)) 452da2e3ebdSchin #define DB_TAIL (2*sizeof(Head_t)) 453da2e3ebdSchin #define DB_EXTRA (DB_HEAD+DB_TAIL) 454da2e3ebdSchin #define DBBLOCK(d) ((Block_t*)((Vmuchar_t*)(d) - 3*sizeof(Head_t)) ) 455da2e3ebdSchin #define DBBSIZE(d) (SIZE(DBBLOCK(d)) & ~BITS) 456da2e3ebdSchin #define DBSEG(d) (((Head_t*)((Vmuchar_t*)(d) - sizeof(Head_t)))->head.seg.seg ) 457da2e3ebdSchin #define DBSIZE(d) (((Head_t*)((Vmuchar_t*)(d) - 2*sizeof(Head_t)))->head.size.size ) 458da2e3ebdSchin #define DBFILE(d) (((Head_t*)((Vmuchar_t*)(d) - 2*sizeof(Head_t)))->head.seg.file ) 459da2e3ebdSchin #define DBLN(d) (((Head_t*)((Vmuchar_t*)DBBLOCK(d)+DBBSIZE(d)))->head.size.line ) 460da2e3ebdSchin #define DBLINE(d) (DBLN(d) < 0 ? -DBLN(d) : DBLN(d)) 461da2e3ebdSchin 462da2e3ebdSchin /* forward/backward translation for addresses between Vmbest and Vmdebug */ 463da2e3ebdSchin #define DB2BEST(d) ((Vmuchar_t*)(d) - 2*sizeof(Head_t)) 464da2e3ebdSchin #define DB2DEBUG(b) ((Vmuchar_t*)(b) + 2*sizeof(Head_t)) 465da2e3ebdSchin 466da2e3ebdSchin /* set file and line number, note that DBLN > 0 so that DBISBAD will work */ 467da2e3ebdSchin #define DBSETFL(d,f,l) (DBFILE(d) = (f), DBLN(d) = (f) ? (l) : 1) 468da2e3ebdSchin 469da2e3ebdSchin /* set and test the state of known to be corrupted */ 470da2e3ebdSchin #define DBSETBAD(d) (DBLN(d) > 0 ? (DBLN(d) = -DBLN(d)) : -1) 471da2e3ebdSchin #define DBISBAD(d) (DBLN(d) <= 0) 472da2e3ebdSchin 473da2e3ebdSchin #define DB_MAGIC 0255 /* 10101101 */ 474da2e3ebdSchin 475da2e3ebdSchin /* compute the bounds of the magic areas */ 476da2e3ebdSchin #define DBHEAD(d,begp,endp) \ 477da2e3ebdSchin (((begp) = (Vmuchar_t*)(&DBSEG(d)) + sizeof(Seg_t*)), ((endp) = (d)) ) 478da2e3ebdSchin #define DBTAIL(d,begp,endp) \ 479da2e3ebdSchin (((begp) = (Vmuchar_t*)(d)+DBSIZE(d)), ((endp) = (Vmuchar_t*)(&DBLN(d))) ) 480da2e3ebdSchin 481da2e3ebdSchin /* external symbols for internal use by vmalloc */ 482da2e3ebdSchin typedef Block_t* (*Vmsearch_f)_ARG_((Vmdata_t*, size_t, Block_t*)); 483da2e3ebdSchin typedef struct _vmextern_ 484da2e3ebdSchin { Block_t* (*vm_extend)_ARG_((Vmalloc_t*, size_t, Vmsearch_f )); 485da2e3ebdSchin ssize_t (*vm_truncate)_ARG_((Vmalloc_t*, Seg_t*, size_t, int)); 486da2e3ebdSchin size_t vm_pagesize; 487da2e3ebdSchin char* (*vm_strcpy)_ARG_((char*, const char*, int)); 488da2e3ebdSchin char* (*vm_itoa)_ARG_((Vmulong_t, int)); 489da2e3ebdSchin void (*vm_trace)_ARG_((Vmalloc_t*, 490da2e3ebdSchin Vmuchar_t*, Vmuchar_t*, size_t, size_t)); 491da2e3ebdSchin void (*vm_pfclose)_ARG_((Vmalloc_t*)); 492da2e3ebdSchin int vm_assert; 493*3e14f97fSRoger A. Faulkner int vm_options; 494da2e3ebdSchin } Vmextern_t; 495da2e3ebdSchin 496da2e3ebdSchin #define _Vmextend (_Vmextern.vm_extend) 497da2e3ebdSchin #define _Vmtruncate (_Vmextern.vm_truncate) 498da2e3ebdSchin #define _Vmpagesize (_Vmextern.vm_pagesize) 499da2e3ebdSchin #define _Vmstrcpy (_Vmextern.vm_strcpy) 500da2e3ebdSchin #define _Vmitoa (_Vmextern.vm_itoa) 501da2e3ebdSchin #define _Vmtrace (_Vmextern.vm_trace) 502da2e3ebdSchin #define _Vmpfclose (_Vmextern.vm_pfclose) 503da2e3ebdSchin #define _Vmassert (_Vmextern.vm_assert) 504*3e14f97fSRoger A. Faulkner #define _Vmoptions (_Vmextern.vm_options) 505da2e3ebdSchin 506*3e14f97fSRoger A. Faulkner #define VMOPTIONS() do { if (!_Vmoptions) { _vmoptions(); } } while (0) 507*3e14f97fSRoger A. Faulkner 508*3e14f97fSRoger A. Faulkner extern void _vmoptions _ARG_((void)); 509da2e3ebdSchin extern int _vmbestcheck _ARG_((Vmdata_t*, Block_t*)); 510da2e3ebdSchin 511da2e3ebdSchin _BEGIN_EXTERNS_ 512da2e3ebdSchin 513da2e3ebdSchin extern Vmextern_t _Vmextern; 514da2e3ebdSchin 515da2e3ebdSchin #if _PACKAGE_ast 516da2e3ebdSchin 517da2e3ebdSchin #if _npt_getpagesize 518da2e3ebdSchin extern int getpagesize _ARG_((void)); 519da2e3ebdSchin #endif 520da2e3ebdSchin #if _npt_sbrk 521da2e3ebdSchin extern int brk _ARG_(( void* )); 522da2e3ebdSchin extern Void_t* sbrk _ARG_(( ssize_t )); 523da2e3ebdSchin #endif 524da2e3ebdSchin 525da2e3ebdSchin #else 526da2e3ebdSchin 527da2e3ebdSchin #if _hdr_unistd 528da2e3ebdSchin #include <unistd.h> 529da2e3ebdSchin #else 530da2e3ebdSchin extern void abort _ARG_(( void )); 531da2e3ebdSchin extern ssize_t write _ARG_(( int, const void*, size_t )); 532da2e3ebdSchin extern int getpagesize _ARG_((void)); 533da2e3ebdSchin extern Void_t* sbrk _ARG_((ssize_t)); 534da2e3ebdSchin #endif 535da2e3ebdSchin 536da2e3ebdSchin #if !__STDC__ && !_hdr_stdlib 537da2e3ebdSchin extern size_t strlen _ARG_(( const char* )); 538da2e3ebdSchin extern char* strcpy _ARG_(( char*, const char* )); 539da2e3ebdSchin extern int strcmp _ARG_(( const char*, const char* )); 540da2e3ebdSchin extern int atexit _ARG_(( void(*)(void) )); 541da2e3ebdSchin extern char* getenv _ARG_(( const char* )); 542da2e3ebdSchin extern Void_t* memcpy _ARG_(( Void_t*, const Void_t*, size_t )); 543da2e3ebdSchin extern Void_t* memset _ARG_(( Void_t*, int, size_t )); 544da2e3ebdSchin #else 545da2e3ebdSchin #include <stdlib.h> 546da2e3ebdSchin #include <string.h> 547da2e3ebdSchin #endif 548da2e3ebdSchin 549da2e3ebdSchin /* for vmexit.c */ 550da2e3ebdSchin extern int onexit _ARG_(( void(*)(void) )); 551da2e3ebdSchin extern void _exit _ARG_(( int )); 552da2e3ebdSchin extern void _cleanup _ARG_(( void )); 553da2e3ebdSchin 554da2e3ebdSchin #endif /*_PACKAGE_ast*/ 555da2e3ebdSchin 556da2e3ebdSchin _END_EXTERNS_ 557da2e3ebdSchin 558da2e3ebdSchin #if _UWIN 559da2e3ebdSchin #define abort() (DebugBreak(),abort()) 560da2e3ebdSchin #endif 561da2e3ebdSchin 562da2e3ebdSchin #endif /* _VMHDR_H */ 563