** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
*/
-#define VMALLOC_VERSION 19990805L
-
-#include "config.h"
-
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif // HAVE_SYS_TYPES_H
-
typedef struct _vmalloc_s Vmalloc_t;
- typedef struct _vmstat_s Vmstat_t;
- typedef struct _vmdisc_s Vmdisc_t;
typedef struct _vmethod_s Vmethod_t;
- typedef void *(*Vmemory_f)
- (Vmalloc_t *, void *, size_t, size_t, Vmdisc_t *);
- typedef int (*Vmexcept_f)
- (Vmalloc_t *, int, void *, Vmdisc_t *);
-
- struct _vmstat_s {
- int n_busy; /* number of busy blocks */
- int n_free; /* number of free blocks */
- size_t s_busy; /* total amount of busy space */
- size_t s_free; /* total amount of free space */
- size_t m_busy; /* largest busy piece */
- size_t m_free; /* largest free piece */
- int n_seg; /* number of segments */
- size_t extent; /* total size of region */
- };
-
- struct _vmdisc_s {
- Vmemory_f memoryf; /* memory manipulator */
- Vmexcept_f exceptf; /* exception handler */
- size_t round; /* rounding requirement */
- };
struct _vmethod_s {
void *(*allocf) (Vmalloc_t *, size_t);
void *(*resizef) (Vmalloc_t *, void *, size_t);
int (*freef) (Vmalloc_t *, void *);
- long (*addrf) (Vmalloc_t *, void *);
- unsigned short meth;
};
struct _vmalloc_s {
Vmethod_t meth; /* method for allocation */
- char *file; /* file name */
- int line; /* line number */
-#ifdef _VM_PRIVATE_
- _VM_PRIVATE_
-#endif
void **allocated; /* pointers we have given out */
size_t size; /* used entries in `allocated` */
size_t capacity; /* available entries in `allocated` */
};
-#define VM_TRUST 0000001 /* forgo some security checks */
-#define VM_TRACE 0000002 /* generate trace */
-#define VM_DBCHECK 0000004 /* check for boundary overwrite */
-#define VM_DBABORT 0000010 /* abort on any warning */
-#define VM_FLAGS 0000017 /* user-settable flags */
-
-#define VM_MTBEST 0000100 /* Vmbest method */
-#define VM_MTPOOL 0000200 /* Vmpool method */
-#define VM_MTLAST 0000400 /* Vmlast method */
-#define VM_MTDEBUG 0001000 /* Vmdebug method */
-#define VM_MTPROFILE 0002000 /* Vmdebug method */
-#define VM_METHODS 0003700 /* available allocation methods */
-
-#define VM_RSCOPY 0000001 /* copy old contents */
-#define VM_RSMOVE 0000002 /* old contents is moveable */
-#define VM_RSZERO 0000004 /* clear new space */
-
-/* exception types */
-#define VM_OPEN 0 /* region being opened */
-#define VM_CLOSE 1 /* region being closed */
-#define VM_NOMEM 2 /* can't obtain memory */
-#define VM_BADADDR 3 /* bad addr in vmfree/vmresize */
-#define VM_DISC 4 /* discipline being changed */
-
-
extern Vmalloc_t *vmopen(void);
extern int vmclose(Vmalloc_t *);
extern int vmclear(Vmalloc_t *);
#ifndef vmfree
#define vmfree(vm,d) (*(_VM_(vm)->meth.freef))((vm),(void*)(d))
#endif
-#define vmaddr(vm,addr) (*(_VM_(vm)->meth.addrf))((vm),(void*)(addr))
-#define vmoldof(v,p,t,n,x) (t*)vmresize((v), (p), sizeof(t)*(n)+(x))
#define vmnewof(v,p,t,n,x) (t*)vmresize((v), (p), sizeof(t)*(n)+(x))
#endif /* _VMALLOC_H */
#ifdef __cplusplus
#ifndef _VMHDR_H
#define _VMHDR_H 1
-#ifndef _BLD_vmalloc
-#define _BLD_vmalloc 1
-#endif
-#ifdef _WIN32
-#include <io.h>
-#endif
/* Common types, and macros for vmalloc functions.
**
** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
*/
-#include "config.h"
-
-#include <inttypes.h>
#include <stdlib.h>
-
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif // HAVE_SYS_TYPES_H
-
-#undef BITS
-
- typedef unsigned char Vmuchar_t;
- typedef uint64_t Vmulong_t;
-
- typedef union _head_u Head_t;
- typedef union _body_u Body_t;
- typedef struct _block_s Block_t;
- typedef struct _seg_s Seg_t;
- typedef struct _pfobj_s Pfobj_t;
-
-#define NIL(t) ((t)0)
-#define reg register
-#define NOTUSED(x) (void)(x)
-
-/* convert an address to an integral value */
-#define VLONG(addr) ((Vmulong_t)((char*)(addr) - (char*)0) )
-
-/* Round x up to a multiple of y. ROUND2 does powers-of-2 and ROUNDX does others */
-#define ROUND2(x,y) (((x) + ((y)-1)) & ~((y)-1))
-#define ROUNDX(x,y) ((((x) + ((y)-1)) / (y)) * (y))
-#define ROUND(x,y) (((y)&((y)-1)) ? ROUNDX((x),(y)) : ROUND2((x),(y)) )
-
-/* compute a value that is a common multiple of x and y */
-#define MULTIPLE(x,y) ((x)%(y) == 0 ? (x) : (y)%(x) == 0 ? (y) : (y)*(x))
-
-#ifndef DEBUG
-#define ASSERT(p)
-#define COUNT(n)
-#else
- extern int printf(const char *, ...);
-#if defined(__LINE__) && defined(__FILE__)
-#define PRFILELINE printf("Assertion failed at %s:%d\n",__FILE__,__LINE__)
-#else
-#define PRFILELINE 0
-#endif
-#define ASSERT(p) ((p) ? 0 : (PRFILELINE, abort(), 0) )
-#define COUNT(n) ((n) += 1)
-#endif /*DEBUG*/
-#define VMPAGESIZE 8192
-#ifdef HAVE_GETPAGESIZE
-#define GETPAGESIZE(x) ((x) ? (x) : \
- (((x)=getpagesize()) < VMPAGESIZE ? ((x)=VMPAGESIZE) : (x)) )
-#else
-#define GETPAGESIZE(x) ((x) = VMPAGESIZE)
-#endif
-/* Blocks are allocated such that their sizes are 0%(BITS+1)
-** This frees up enough low order bits to store state information
-*/
-#define BUSY (01) /* block is busy */
-#define PFREE (02) /* preceding block is free */
-#define JUNK (04) /* marked as freed but not yet processed */
-#define BITS (07) /* (BUSY|PFREE|JUNK) */
-#define ALIGNB (8) /* size must be a multiple of BITS+1 */
-#define ISBITS(w) ((w) & BITS)
-#define CLRBITS(w) ((w) &= ~BITS)
-#define CPYBITS(w,f) ((w) |= ((f)&BITS) )
-#define ISBUSY(w) ((w) & BUSY)
-#define SETBUSY(w) ((w) |= BUSY)
-#define CLRBUSY(w) ((w) &= ~BUSY)
-#define ISPFREE(w) ((w) & PFREE)
-#define SETPFREE(w) ((w) |= PFREE)
-#define CLRPFREE(w) ((w) &= ~PFREE)
-#define ISJUNK(w) ((w) & JUNK)
-#define SETJUNK(w) ((w) |= JUNK)
-#define CLRJUNK(w) ((w) &= ~JUNK)
-#define OFFSET(t,e) ((size_t)(&(((t*)0)->e)) )
-/* these bits share the "mode" field with the public bits */
-#define VM_AGAIN 0010000 /* research the arena for space */
-#define VM_LOCK 0020000 /* region is locked */
-#define VM_LOCAL 0040000 /* local call, bypass lock */
-#define VM_UNUSED 0104060
-#define VMETHOD(vd) ((vd)->mode&VM_METHODS)
-/* test/set/clear lock state */
-#define SETLOCAL(vd) ((vd)->mode |= VM_LOCAL)
-#define GETLOCAL(vd,l) (((l) = (vd)->mode&VM_LOCAL), ((vd)->mode &= ~VM_LOCAL) )
-#define ISLOCK(vd,l) ((l) ? 0 : ((vd)->mode & VM_LOCK) )
-#define SETLOCK(vd,l) ((l) ? 0 : ((vd)->mode |= VM_LOCK) )
-#define CLRLOCK(vd,l) ((l) ? 0 : ((vd)->mode &= ~VM_LOCK) )
-/* local calls */
-#define KPVALLOC(vm,sz,func) (SETLOCAL((vm)->data), func((vm),(sz)) )
-#define KPVALIGN(vm,sz,al,func) (SETLOCAL((vm)->data), func((vm),(sz),(al)) )
-#define KPVFREE(vm,d,func) (SETLOCAL((vm)->data), func((vm),(d)) )
-#define KPVRESIZE(vm,d,sz,mv,func) (SETLOCAL((vm)->data), func((vm),(d),(sz),(mv)) )
-#define KPVADDR(vm,addr,func) (SETLOCAL((vm)->data), func((vm),(addr)) )
-/* ALIGN is chosen so that a block can store all primitive types.
-** It should also be a multiple of ALIGNB==(BITS+1) so the size field
-** of Block_t will always be 0%(BITS+1) as noted above.
-** Of paramount importance is the ALIGNA macro below. If the local compile
-** environment is strange enough that the below method does not calculate
-** ALIGNA right, then the code below should be commented out and ALIGNA
-** redefined to the appropriate requirement.
-*/
- union _align_u {
- char c, *cp;
- int i, *ip;
- long l, *lp;
- double d, *dp, ***dppp[8];
- size_t s, *sp;
- void (*fn) (void);
- union _align_u *align;
- Head_t *head;
- Body_t *body;
- Block_t *block;
- Vmuchar_t a[ALIGNB];
-#if _long_double
- long double ld, *ldp;
-#endif
- };
- struct _a_s {
- char c;
- union _align_u a;
- };
-#define ALIGNA (sizeof(struct _a_s) - sizeof(union _align_u))
- struct _align_s {
- char data[MULTIPLE(ALIGNA, ALIGNB)];
- };
-#define ALIGN sizeof(struct _align_s)
-
-/* make sure that the head of a block is a multiple of ALIGN */
- struct _head_s {
- union {
- Seg_t *seg; /* the containing segment */
- Block_t *link; /* possible link list usage */
- Pfobj_t *pf; /* profile structure pointer */
- char *file; /* for file name in Vmdebug */
- } seg;
- union {
- size_t size; /* size of data area in bytes */
- Block_t *link; /* possible link list usage */
- int line; /* for line number in Vmdebug */
- } size;
- };
-#define HEADSIZE ROUND(sizeof(struct _head_s),ALIGN)
- union _head_u {
- Vmuchar_t data[HEADSIZE]; /* to standardize size */
- struct _head_s head;
- };
-
-/* now make sure that the body of a block is a multiple of ALIGN */
- struct _body_s {
- Block_t *link; /* next in link list */
- Block_t *left; /* left child in free tree */
- Block_t *right; /* right child in free tree */
- Block_t **self; /* self pointer when free */
- };
-#define BODYSIZE ROUND(sizeof(struct _body_s),ALIGN)
- union _body_u {
- Vmuchar_t data[BODYSIZE]; /* to standardize size */
- struct _body_s body;
- };
-
-/* After all the songs and dances, we should now have:
-** sizeof(Head_t)%ALIGN == 0
-** sizeof(Body_t)%ALIGN == 0
-** and sizeof(Block_t) = sizeof(Head_t)+sizeof(Body_t)
-*/
- struct _block_s {
- Head_t head;
- Body_t body;
- };
-
-/* requirements for smallest block type */
- struct _tiny_s {
- Block_t *link;
- Block_t *self;
- };
-#define TINYSIZE ROUND(sizeof(struct _tiny_s),ALIGN)
-#define S_TINY 7 /* # of tiny blocks */
-#define MAXTINY (S_TINY*ALIGN + TINYSIZE)
-#define TLEFT(b) ((b)->head.head.seg.link) /* instead of LEFT */
-#define TINIEST(b) (SIZE(b) == TINYSIZE) /* this type uses TLEFT */
-
-#define DIV(x,y) ((y) == 8 ? ((x)>>3) : (x)/(y) )
-#define INDEX(s) DIV((s)-TINYSIZE,ALIGN)
-
-/* number of small block types that can be cached after free */
-#define S_CACHE 7
-#define MAXCACHE (S_CACHE*ALIGN + TINYSIZE)
-#define C_INDEX(s) (s < MAXCACHE ? INDEX(s) : S_CACHE)
-
-#define TINY(vd) ((vd)->tiny)
-#define CACHE(vd) ((vd)->cache)
-
- typedef struct _vmdata_s {
- int mode; /* current mode for region */
- size_t incr; /* allocate in multiple of this */
- size_t pool; /* size of an elt in a Vmpool region */
- Seg_t *seg; /* list of segments */
- Block_t *free; /* most recent free block */
- Block_t *wild; /* wilderness block */
- Block_t *root; /* root of free tree */
- Block_t *tiny[S_TINY]; /* small blocks */
- Block_t *cache[S_CACHE + 1]; /* delayed free blocks */
- } Vmdata_t;
-
-/* private parts of Vmalloc_t */
-#define _VM_PRIVATE_ \
- Vmdisc_t* disc; /* discipline to get space */ \
- Vmdata_t* data; /* the real region data */ \
- Vmalloc_t* next; /* linked list of regions */
-
#include "vmalloc.h"
-/* segment structure */
- struct _seg_s {
- Vmalloc_t *vm; /* the region that holds this */
- Seg_t *next; /* next segment */
- void *addr; /* starting segment address */
- size_t extent; /* extent of segment */
- Vmuchar_t *baddr; /* bottom of usable memory */
- size_t size; /* allocable size */
- Block_t *free; /* recent free blocks */
- Block_t *last; /* Vmlast last-allocated block */
- };
-
-/* starting block of a segment */
-#define SEGBLOCK(s) ((Block_t*)(((Vmuchar_t*)(s)) + ROUND(sizeof(Seg_t),ALIGN)))
-
-/* short-hands for block data */
-#define SEG(b) ((b)->head.head.seg.seg)
-#define SEGLINK(b) ((b)->head.head.seg.link)
-#define SIZE(b) ((b)->head.head.size.size)
-#define SIZELINK(b) ((b)->head.head.size.link)
-#define LINK(b) ((b)->body.body.link)
-#define LEFT(b) ((b)->body.body.left)
-#define RIGHT(b) ((b)->body.body.right)
-#define VM(b) (SEG(b)->vm)
-
-#define DATA(b) ((void*)((b)->body.data) )
-#define BLOCK(d) ((Block_t*)((char*)(d) - sizeof(Head_t)) )
-#define SELF(b) ((Block_t**)((b)->body.data + SIZE(b) - sizeof(Block_t*)) )
-#define LAST(b) (*((Block_t**)(((char*)(b)) - sizeof(Block_t*)) ) )
-#define NEXT(b) ((Block_t*)((b)->body.data + SIZE(b)) )
-
-/* functions to manipulate link lists of elts of the same size */
-#define SETLINK(b) (RIGHT(b) = (b) )
-#define ISLINK(b) (RIGHT(b) == (b) )
-#define UNLINK(vd,b,i,t) \
- ((((t) = LINK(b)) ? (LEFT(t) = LEFT(b)) : NIL(Block_t*) ), \
- (((t) = LEFT(b)) ? (LINK(t) = LINK(b)) : (TINY(vd)[i] = LINK(b)) ) )
-
-/* delete a block from a link list or the free tree.
-** The test in the below macro is worth scratching your head a bit.
-** Even though tiny blocks (size < BODYSIZE) are kept in separate lists,
-** only the TINIEST ones require TLEFT(b) for the back link. Since this
-** destroys the SEG(b) pointer, it must be carefully restored in bestsearch().
-** Other tiny blocks have enough space to use the usual LEFT(b).
-** In this case, I have also carefully arranged so that RIGHT(b) and
-** SELF(b) can be overlapped and the test ISLINK() will go through.
-*/
-#define REMOVE(vd,b,i,t,func) \
- ((!TINIEST(b) && ISLINK(b)) ? UNLINK((vd),(b),(i),(t)) : \
- func((vd),SIZE(b),(b)) )
-
-/* see if a block is the wilderness block */
-#define SEGWILD(b) (((b)->body.data+SIZE(b)+sizeof(Head_t)) >= SEG(b)->baddr)
-#define VMWILD(vd,b) (((b)->body.data+SIZE(b)+sizeof(Head_t)) >= vd->seg->baddr)
-
-#define VMFILELINE(vm,f,l) ((f) = (vm)->file, (vm)->file = NIL(char*), \
- (l) = (vm)->line, (vm)->line = 0 )
-
-/* The lay-out of a Vmprofile block is this:
-** seg_ size ----data---- _pf_ size
-** _________ ____________ _________
-** seg_, size: header required by Vmbest.
-** data: actual data block.
-** _pf_: pointer to the corresponding Pfobj_t struct
-** size: the true size of the block.
-** So each block requires an extra Head_t.
-*/
-#define PF_EXTRA sizeof(Head_t)
-#define PFDATA(d) ((Head_t*)((Vmuchar_t*)(d)+(SIZE(BLOCK(d))&~BITS)-sizeof(Head_t)) )
-#define PFOBJ(d) (PFDATA(d)->head.seg.pf)
-#define PFSIZE(d) (PFDATA(d)->head.size.size)
-
-/* The lay-out of a block allocated by Vmdebug is this:
-** seg_ size file size seg_ magi ----data---- --magi-- magi line
-** --------- --------- --------- ------------ -------- ---------
-** seg_,size: header required by Vmbest management.
-** file: the file where it was created.
-** size: the true byte count of the block
-** seg_: should be the same as the previous seg_.
-** magi: magic bytes to detect overwrites.
-** data: the actual data block.
-** magi: more magic bytes.
-** line: the line number in the file where it was created.
-** So for each allocated block, we'll need 3 extra Head_t.
-*/
-
-/* convenient macros for accessing the above fields */
-#define DB_HEAD (2*sizeof(Head_t))
-#define DB_TAIL (2*sizeof(Head_t))
-#define DB_EXTRA (DB_HEAD+DB_TAIL)
-#define DBBLOCK(d) ((Block_t*)((Vmuchar_t*)(d) - 3*sizeof(Head_t)) )
-#define DBBSIZE(d) (SIZE(DBBLOCK(d)) & ~BITS)
-#define DBSEG(d) (((Head_t*)((Vmuchar_t*)(d) - sizeof(Head_t)))->head.seg.seg )
-#define DBSIZE(d) (((Head_t*)((Vmuchar_t*)(d) - 2*sizeof(Head_t)))->head.size.size )
-#define DBFILE(d) (((Head_t*)((Vmuchar_t*)(d) - 2*sizeof(Head_t)))->head.seg.file )
-#define DBLN(d) (((Head_t*)((Vmuchar_t*)DBBLOCK(d)+DBBSIZE(d)))->head.size.line )
-#define DBLINE(d) (DBLN(d) < 0 ? -DBLN(d) : DBLN(d))
-
-/* forward/backward translation for addresses between Vmbest and Vmdebug */
-#define DB2BEST(d) ((Vmuchar_t*)(d) - 2*sizeof(Head_t))
-#define DB2DEBUG(b) ((Vmuchar_t*)(b) + 2*sizeof(Head_t))
-
-/* set file and line number, note that DBLN > 0 so that DBISBAD will work */
-#define DBSETFL(d,f,l) (DBFILE(d) = (f), DBLN(d) = (f) ? (l) : 1)
-
-/* set and test the state of known to be corrupted */
-#define DBSETBAD(d) (DBLN(d) > 0 ? (DBLN(d) = -DBLN(d)) : -1)
-#define DBISBAD(d) (DBLN(d) <= 0)
-
-#define DB_MAGIC 0255 /* 10101101 */
-
-/* compute the bounds of the magic areas */
-#define DBHEAD(d,begp,endp) \
- (((begp) = (Vmuchar_t*)(&DBSEG(d)) + sizeof(Seg_t*)), ((endp) = (d)) )
-#define DBTAIL(d,begp,endp) \
- (((begp) = (Vmuchar_t*)(d)+DBSIZE(d)), ((endp) = (Vmuchar_t*)(&DBLN(d))) )
-
-/* clear and copy functions */
-#define INTCOPY(to,fr,n) \
- switch(n/sizeof(int)) \
- { default: memcpy((void*)to,(void*)fr,n); break; \
- case 7: *to++ = *fr++; \
- case 6: *to++ = *fr++; \
- case 5: *to++ = *fr++; \
- case 4: *to++ = *fr++; \
- case 3: *to++ = *fr++; \
- case 2: *to++ = *fr++; \
- case 1: *to++ = *fr++; \
- }
-#define INTZERO(d,n) \
- switch(n/sizeof(int)) \
- { default: memset((void*)d,0,n); break; \
- case 7: *d++ = 0; \
- case 6: *d++ = 0; \
- case 5: *d++ = 0; \
- case 4: *d++ = 0; \
- case 3: *d++ = 0; \
- case 2: *d++ = 0; \
- case 1: *d++ = 0; \
- }
-
-/* external symbols for internal use by vmalloc */
- typedef Block_t *(*Vmsearch_f) (Vmdata_t *, size_t, Block_t *);
-
- extern size_t getpagesize(void);
-
-#ifndef _WIN32
- extern void abort(void);
- extern ssize_t write(int, const void *, size_t);
-#endif
-
-#ifndef cfree
-#define cfree ______cfree
-#endif
-#include <stdlib.h>
-#undef cfree
-#include <string.h>
-
-/* for vmexit.c */
-#ifndef _WIN32
- extern int onexit(void(*)(void));
- extern void _exit(int);
-#endif
- extern void _cleanup(void);
-
-/* for vmdcsbrk.c */
-#if !defined(_WIN32)
- extern Vmuchar_t *sbrk(ssize_t);
-#endif
-
void *bestalloc(Vmalloc_t * vm, size_t size);
int bestfree(Vmalloc_t * vm, void * data);
void *bestresize(Vmalloc_t * vm, void * data, size_t size);