da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner* Copyright (c) 1985-2010 AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* by AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* http://www.opensource.org/licenses/cpl1.0.txt *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Glenn Fowler <gsf@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Phong Vo <kpv@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifndef _VMHDR_H
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define _VMHDR_H 1
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifndef _BLD_vmalloc
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define _BLD_vmalloc 1
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* Common types, and macros for vmalloc functions.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin**
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifndef __STD_C /* this is normally in vmalloc.h but it's included late here */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef __STDC__
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define __STD_C 1
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if __cplusplus || c_plusplus
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define __STD_C 1
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define __STD_C 0
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /*__cplusplus*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /*__STDC__*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /*__STD_C*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _PACKAGE_ast
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if !_UWIN
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define getpagesize ______getpagesize
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define _npt_getpagesize 1
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define brk ______brk
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define sbrk ______sbrk
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define _npt_sbrk 1
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <ast.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _npt_getpagesize
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#undef getpagesize
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _npt_sbrk
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#undef brk
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#undef sbrk
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <ast_common.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if !_UWIN
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define _npt_getpagesize 1
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define _npt_sbrk 1
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#ifndef integralof
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#define integralof(x) (((char*)(x))-((char*)0))
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#endif
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /*_PACKAGE_ast*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "FEATURE/vmalloc"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <setjmp.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* the below macros decide which combinations of sbrk() or mmap() to used */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if defined(_WIN32)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define _mem_win32 1
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#undef _mem_sbrk
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#undef _mem_mmap_anon
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#undef _mem_mmap_zero
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _mem_mmap_anon
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#undef _mem_mmap_zero
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if !_mem_win32 && !_mem_sbrk && !_mem_mmap_anon && !_mem_mmap_zero
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#undef _std_malloc
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define _std_malloc 1 /* do not define malloc/free/realloc */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chintypedef unsigned char Vmuchar_t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chintypedef unsigned long Vmulong_t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chintypedef union _head_u Head_t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chintypedef union _body_u Body_t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chintypedef struct _block_s Block_t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chintypedef struct _seg_s Seg_t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chintypedef struct _pfobj_s Pfobj_t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if !_typ_ssize_t
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chintypedef int ssize_t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define NIL(t) ((t)0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define reg register
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if __STD_C
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define NOTUSED(x) (void)(x)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define NOTUSED(x) (&x,1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* convert an address to an integral value */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define VLONG(addr) ((Vmulong_t)((char*)(addr) - (char*)0) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* Round x up to a multiple of y. ROUND2 does powers-of-2 and ROUNDX does others */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define ROUND2(x,y) (((x) + ((y)-1)) & ~((y)-1))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define ROUNDX(x,y) ((((x) + ((y)-1)) / (y)) * (y))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define ROUND(x,y) (((y)&((y)-1)) ? ROUNDX((x),(y)) : ROUND2((x),(y)) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* compute a value that is a common multiple of x and y */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define MULTIPLE(x,y) ((x)%(y) == 0 ? (x) : (y)%(x) == 0 ? (y) : (y)*(x))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define VM_check 0x0001 /* enable detailed checks */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define VM_abort 0x0002 /* abort() on assertion failure */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#define VM_region 0x0004 /* enable region segment checks */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#define VM_mmap 0x0010 /* favor mmap allocation */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _UWIN
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <ast_windows.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifndef DEBUG
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef _BLD_DEBUG
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DEBUG 1
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /*_BLD_DEBUG*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /*DEBUG*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if DEBUG
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern void _vmmessage _ARG_((const char*, long, const char*, long));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define ABORT() (_Vmassert & VM_abort)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define CHECK() (_Vmassert & VM_check)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define ASSERT(p) ((p) ? 0 : (MESSAGE("Assertion failed"), ABORT() ? (abort(),0) : 0))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define COUNT(n) ((n) += 1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define MESSAGE(s) _vmmessage(__FILE__,__LINE__,s,0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define ABORT() (0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define ASSERT(p)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define CHECK() (0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define COUNT(n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define MESSAGE(s) (0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /*DEBUG*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define VMPAGESIZE 8192
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _AST_PAGESIZE > VMPAGESIZE
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#undef VMPAGESIZE
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define VMPAGESIZE _AST_PAGESIZE
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#if _lib_getpagesize && !defined(_AST_PAGESIZE)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define GETPAGESIZE(x) ((x) ? (x) : \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (((x)=getpagesize()) < VMPAGESIZE ? ((x)=VMPAGESIZE) : (x)) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define GETPAGESIZE(x) ((x) = VMPAGESIZE)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#ifdef _AST_PAGESIZE
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#define VMHEAPINCR (_Vmpagesize*1)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#else
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#define VMHEAPINCR (_Vmpagesize*4)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#endif
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* Blocks are allocated such that their sizes are 0%(BITS+1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** This frees up enough low order bits to store state information
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define BUSY (01) /* block is busy */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define PFREE (02) /* preceding block is free */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define JUNK (04) /* marked as freed but not yet processed */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define BITS (07) /* (BUSY|PFREE|JUNK) */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define ALIGNB (8) /* size must be a multiple of BITS+1 */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define ISBITS(w) ((w) & BITS)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define CLRBITS(w) ((w) &= ~BITS)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define CPYBITS(w,f) ((w) |= ((f)&BITS) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define ISBUSY(w) ((w) & BUSY)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define SETBUSY(w) ((w) |= BUSY)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define CLRBUSY(w) ((w) &= ~BUSY)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define ISPFREE(w) ((w) & PFREE)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define SETPFREE(w) ((w) |= PFREE)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define CLRPFREE(w) ((w) &= ~PFREE)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define ISJUNK(w) ((w) & JUNK)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define SETJUNK(w) ((w) |= JUNK)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define CLRJUNK(w) ((w) &= ~JUNK)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define OFFSET(t,e) ((size_t)(&(((t*)0)->e)) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* these bits share the "mode" field with the public bits */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define VM_AGAIN 0010000 /* research the arena for space */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define VM_LOCK 0020000 /* region is locked */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define VM_LOCAL 0040000 /* local call, bypass lock */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#define VM_INUSE 0004000 /* some operation is running */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#define VM_UNUSED 0100060
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define VMETHOD(vd) ((vd)->mode&VM_METHODS)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* test/set/clear lock state */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#define SETINUSE(vd,iu) (((iu) = (vd)->mode&VM_INUSE), ((vd)->mode |= VM_INUSE) )
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#define CLRINUSE(vd,iu) ((iu) ? 0 : ((vd)->mode &= ~VM_INUSE) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define SETLOCAL(vd) ((vd)->mode |= VM_LOCAL)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define GETLOCAL(vd,l) (((l) = (vd)->mode&VM_LOCAL), ((vd)->mode &= ~VM_LOCAL) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define ISLOCK(vd,l) ((l) ? 0 : ((vd)->mode & VM_LOCK) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define SETLOCK(vd,l) ((l) ? 0 : ((vd)->mode |= VM_LOCK) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define CLRLOCK(vd,l) ((l) ? 0 : ((vd)->mode &= ~VM_LOCK) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* announcing entry/exit of allocation calls */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define ANNOUNCE(lc, vm,ev,dt,dc) \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (( ((lc)&VM_LOCAL) || !(dc) || !(dc)->exceptf ) ? 0 : \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (*(dc)->exceptf)((vm), (ev), (Void_t*)(dt), (dc)) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* local calls */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define KPVALLOC(vm,sz,func) (SETLOCAL((vm)->data), func((vm),(sz)) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define KPVALIGN(vm,sz,al,func) (SETLOCAL((vm)->data), func((vm),(sz),(al)) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define KPVFREE(vm,d,func) (SETLOCAL((vm)->data), func((vm),(d)) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define KPVRESIZE(vm,d,sz,mv,func) (SETLOCAL((vm)->data), func((vm),(d),(sz),(mv)) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define KPVADDR(vm,addr,func) (SETLOCAL((vm)->data), func((vm),(addr)) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define KPVCOMPACT(vm,func) (SETLOCAL((vm)->data), func((vm)) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* ALIGN is chosen so that a block can store all primitive types.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** It should also be a multiple of ALIGNB==(BITS+1) so the size field
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** of Block_t will always be 0%(BITS+1) as noted above.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** Of paramount importance is the ALIGNA macro below. If the local compile
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** environment is strange enough that the below method does not calculate
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** ALIGNA right, then the code below should be commented out and ALIGNA
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** redefined to the appropriate requirement.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinunion _align_u
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{ char c, *cp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int i, *ip;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin long l, *lp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin double d, *dp, ***dppp[8];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin size_t s, *sp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin void(* fn)();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin union _align_u* align;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Head_t* head;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Body_t* body;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Block_t* block;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Vmuchar_t a[ALIGNB];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _ast_fltmax_t ld, *ldp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin jmp_buf jmp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin};
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstruct _a_s
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{ char c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin union _align_u a;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin};
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define ALIGNA (sizeof(struct _a_s) - sizeof(union _align_u))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstruct _align_s
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{ char data[MULTIPLE(ALIGNA,ALIGNB)];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin};
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#undef ALIGN /* bsd sys/param.h defines this */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define ALIGN sizeof(struct _align_s)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* make sure that the head of a block is a multiple of ALIGN */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstruct _head_s
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{ union
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { Seg_t* seg; /* the containing segment */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Block_t* link; /* possible link list usage */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Pfobj_t* pf; /* profile structure pointer */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* file; /* for file name in Vmdebug */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin } seg;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin union
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { size_t size; /* size of data area in bytes */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Block_t* link; /* possible link list usage */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int line; /* for line number in Vmdebug */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin } size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin};
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define HEADSIZE ROUND(sizeof(struct _head_s),ALIGN)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinunion _head_u
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{ Vmuchar_t data[HEADSIZE]; /* to standardize size */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct _head_s head;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin};
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* now make sure that the body of a block is a multiple of ALIGN */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstruct _body_s
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{ Block_t* link; /* next in link list */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Block_t* left; /* left child in free tree */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Block_t* right; /* right child in free tree */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Block_t** self; /* self pointer when free */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin};
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define BODYSIZE ROUND(sizeof(struct _body_s),ALIGN)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinunion _body_u
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{ Vmuchar_t data[BODYSIZE]; /* to standardize size */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct _body_s body;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin};
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* After all the songs and dances, we should now have:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** sizeof(Head_t)%ALIGN == 0
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** sizeof(Body_t)%ALIGN == 0
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** and sizeof(Block_t) = sizeof(Head_t)+sizeof(Body_t)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstruct _block_s
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{ Head_t head;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Body_t body;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin};
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* requirements for smallest block type */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstruct _tiny_s
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{ Block_t* link;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Block_t* self;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin};
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define TINYSIZE ROUND(sizeof(struct _tiny_s),ALIGN)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define S_TINY 1 /* # of tiny blocks */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define MAXTINY (S_TINY*ALIGN + TINYSIZE)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define TLEFT(b) ((b)->head.head.seg.link) /* instead of LEFT */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define TINIEST(b) (SIZE(b) == TINYSIZE) /* this type uses TLEFT */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DIV(x,y) ((y) == 8 ? ((x)>>3) : (x)/(y) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define INDEX(s) DIV((s)-TINYSIZE,ALIGN)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* small block types kept in separate caches for quick allocation */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define S_CACHE 6 /* # of types of small blocks to be cached */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define N_CACHE 32 /* on allocation, create this many at a time */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define MAXCACHE (S_CACHE*ALIGN + TINYSIZE)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define C_INDEX(s) (s < MAXCACHE ? INDEX(s) : S_CACHE)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define TINY(vd) ((vd)->tiny)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define CACHE(vd) ((vd)->cache)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulknerstruct _vmdata_s
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{ int mode; /* current mode for region */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin size_t incr; /* allocate in multiple of this */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin size_t pool; /* size of an elt in a Vmpool region */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Seg_t* seg; /* list of segments */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Block_t* free; /* most recent free block */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Block_t* wild; /* wilderness block */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Block_t* root; /* root of free tree */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Block_t* tiny[S_TINY]; /* small blocks */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Block_t* cache[S_CACHE+1]; /* delayed free blocks */
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner};
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner/* Vmdata_t typedef in <vmalloc.h> */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "vmalloc.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if !_PACKAGE_ast
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* we don't use these here and they interfere with some local names */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#undef malloc
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#undef free
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#undef realloc
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* segment structure */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstruct _seg_s
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner{ Vmdata_t* vmdt; /* the data region holding this */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Seg_t* next; /* next segment */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Void_t* addr; /* starting segment address */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin size_t extent; /* extent of segment */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Vmuchar_t* baddr; /* bottom of usable memory */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin size_t size; /* allocable size */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Block_t* free; /* recent free blocks */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Block_t* last; /* Vmlast last-allocated block */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin};
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* starting block of a segment */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define SEGBLOCK(s) ((Block_t*)(((Vmuchar_t*)(s)) + ROUND(sizeof(Seg_t),ALIGN)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* short-hands for block data */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define SEG(b) ((b)->head.head.seg.seg)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define SEGLINK(b) ((b)->head.head.seg.link)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define SIZE(b) ((b)->head.head.size.size)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define SIZELINK(b) ((b)->head.head.size.link)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define LINK(b) ((b)->body.body.link)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define LEFT(b) ((b)->body.body.left)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define RIGHT(b) ((b)->body.body.right)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define VM(b) (SEG(b)->vm)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DATA(b) ((Void_t*)((b)->body.data) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define BLOCK(d) ((Block_t*)((char*)(d) - sizeof(Head_t)) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define SELF(b) ((Block_t**)((b)->body.data + SIZE(b) - sizeof(Block_t*)) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define LAST(b) (*((Block_t**)(((char*)(b)) - sizeof(Block_t*)) ) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define NEXT(b) ((Block_t*)((b)->body.data + SIZE(b)) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* functions to manipulate link lists of elts of the same size */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define SETLINK(b) (RIGHT(b) = (b) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define ISLINK(b) (RIGHT(b) == (b) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define UNLINK(vd,b,i,t) \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ((((t) = LINK(b)) ? (LEFT(t) = LEFT(b)) : NIL(Block_t*) ), \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (((t) = LEFT(b)) ? (LINK(t) = LINK(b)) : (TINY(vd)[i] = LINK(b)) ) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* delete a block from a link list or the free tree.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** The test in the below macro is worth scratching your head a bit.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** Even though tiny blocks (size < BODYSIZE) are kept in separate lists,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** only the TINIEST ones require TLEFT(b) for the back link. Since this
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** destroys the SEG(b) pointer, it must be carefully restored in bestsearch().
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** Other tiny blocks have enough space to use the usual LEFT(b).
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** In this case, I have also carefully arranged so that RIGHT(b) and
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** SELF(b) can be overlapped and the test ISLINK() will go through.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define REMOVE(vd,b,i,t,func) \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ((!TINIEST(b) && ISLINK(b)) ? UNLINK((vd),(b),(i),(t)) : \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin func((vd),SIZE(b),(b)) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* see if a block is the wilderness block */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define SEGWILD(b) (((b)->body.data+SIZE(b)+sizeof(Head_t)) >= SEG(b)->baddr)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define VMWILD(vd,b) (((b)->body.data+SIZE(b)+sizeof(Head_t)) >= vd->seg->baddr)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define VMFLF(vm,fi,ln,fn) ((fi) = (vm)->file, (vm)->file = NIL(char*), \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (ln) = (vm)->line, (vm)->line = 0 , \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (fn) = (vm)->func, (vm)->func = NIL(Void_t*) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* The lay-out of a Vmprofile block is this:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** seg_ size ----data---- _pf_ size
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** _________ ____________ _________
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** seg_, size: header required by Vmbest.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** data: actual data block.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** _pf_: pointer to the corresponding Pfobj_t struct
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** size: the true size of the block.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** So each block requires an extra Head_t.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define PF_EXTRA sizeof(Head_t)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define PFDATA(d) ((Head_t*)((Vmuchar_t*)(d)+(SIZE(BLOCK(d))&~BITS)-sizeof(Head_t)) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define PFOBJ(d) (PFDATA(d)->head.seg.pf)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define PFSIZE(d) (PFDATA(d)->head.size.size)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* The lay-out of a block allocated by Vmdebug is this:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** seg_ size file size seg_ magi ----data---- --magi-- magi line
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** --------- --------- --------- ------------ -------- ---------
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** seg_,size: header required by Vmbest management.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** file: the file where it was created.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** size: the true byte count of the block
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** seg_: should be the same as the previous seg_.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** This allows the function vmregion() to work.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** magi: magic bytes to detect overwrites.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** data: the actual data block.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** magi: more magic bytes.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** line: the line number in the file where it was created.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** So for each allocated block, we'll need 3 extra Head_t.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* convenient macros for accessing the above fields */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DB_HEAD (2*sizeof(Head_t))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DB_TAIL (2*sizeof(Head_t))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DB_EXTRA (DB_HEAD+DB_TAIL)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DBBLOCK(d) ((Block_t*)((Vmuchar_t*)(d) - 3*sizeof(Head_t)) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DBBSIZE(d) (SIZE(DBBLOCK(d)) & ~BITS)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DBSEG(d) (((Head_t*)((Vmuchar_t*)(d) - sizeof(Head_t)))->head.seg.seg )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DBSIZE(d) (((Head_t*)((Vmuchar_t*)(d) - 2*sizeof(Head_t)))->head.size.size )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DBFILE(d) (((Head_t*)((Vmuchar_t*)(d) - 2*sizeof(Head_t)))->head.seg.file )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DBLN(d) (((Head_t*)((Vmuchar_t*)DBBLOCK(d)+DBBSIZE(d)))->head.size.line )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DBLINE(d) (DBLN(d) < 0 ? -DBLN(d) : DBLN(d))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* forward/backward translation for addresses between Vmbest and Vmdebug */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DB2BEST(d) ((Vmuchar_t*)(d) - 2*sizeof(Head_t))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DB2DEBUG(b) ((Vmuchar_t*)(b) + 2*sizeof(Head_t))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* set file and line number, note that DBLN > 0 so that DBISBAD will work */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DBSETFL(d,f,l) (DBFILE(d) = (f), DBLN(d) = (f) ? (l) : 1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* set and test the state of known to be corrupted */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DBSETBAD(d) (DBLN(d) > 0 ? (DBLN(d) = -DBLN(d)) : -1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DBISBAD(d) (DBLN(d) <= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DB_MAGIC 0255 /* 10101101 */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* compute the bounds of the magic areas */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DBHEAD(d,begp,endp) \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (((begp) = (Vmuchar_t*)(&DBSEG(d)) + sizeof(Seg_t*)), ((endp) = (d)) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DBTAIL(d,begp,endp) \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (((begp) = (Vmuchar_t*)(d)+DBSIZE(d)), ((endp) = (Vmuchar_t*)(&DBLN(d))) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* external symbols for internal use by vmalloc */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chintypedef Block_t* (*Vmsearch_f)_ARG_((Vmdata_t*, size_t, Block_t*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chintypedef struct _vmextern_
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{ Block_t* (*vm_extend)_ARG_((Vmalloc_t*, size_t, Vmsearch_f ));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ssize_t (*vm_truncate)_ARG_((Vmalloc_t*, Seg_t*, size_t, int));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin size_t vm_pagesize;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* (*vm_strcpy)_ARG_((char*, const char*, int));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* (*vm_itoa)_ARG_((Vmulong_t, int));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin void (*vm_trace)_ARG_((Vmalloc_t*,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Vmuchar_t*, Vmuchar_t*, size_t, size_t));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin void (*vm_pfclose)_ARG_((Vmalloc_t*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int vm_assert;
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner int vm_options;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin} Vmextern_t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define _Vmextend (_Vmextern.vm_extend)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define _Vmtruncate (_Vmextern.vm_truncate)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define _Vmpagesize (_Vmextern.vm_pagesize)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define _Vmstrcpy (_Vmextern.vm_strcpy)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define _Vmitoa (_Vmextern.vm_itoa)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define _Vmtrace (_Vmextern.vm_trace)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define _Vmpfclose (_Vmextern.vm_pfclose)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define _Vmassert (_Vmextern.vm_assert)
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#define _Vmoptions (_Vmextern.vm_options)
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#define VMOPTIONS() do { if (!_Vmoptions) { _vmoptions(); } } while (0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulknerextern void _vmoptions _ARG_((void));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern int _vmbestcheck _ARG_((Vmdata_t*, Block_t*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin_BEGIN_EXTERNS_
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Vmextern_t _Vmextern;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _PACKAGE_ast
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _npt_getpagesize
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern int getpagesize _ARG_((void));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _npt_sbrk
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern int brk _ARG_(( void* ));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* sbrk _ARG_(( ssize_t ));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _hdr_unistd
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <unistd.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern void abort _ARG_(( void ));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern ssize_t write _ARG_(( int, const void*, size_t ));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern int getpagesize _ARG_((void));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* sbrk _ARG_((ssize_t));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if !__STDC__ && !_hdr_stdlib
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern size_t strlen _ARG_(( const char* ));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern char* strcpy _ARG_(( char*, const char* ));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern int strcmp _ARG_(( const char*, const char* ));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern int atexit _ARG_(( void(*)(void) ));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern char* getenv _ARG_(( const char* ));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* memcpy _ARG_(( Void_t*, const Void_t*, size_t ));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* memset _ARG_(( Void_t*, int, size_t ));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <stdlib.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <string.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* for vmexit.c */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern int onexit _ARG_(( void(*)(void) ));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern void _exit _ARG_(( int ));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern void _cleanup _ARG_(( void ));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /*_PACKAGE_ast*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin_END_EXTERNS_
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _UWIN
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define abort() (DebugBreak(),abort())
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* _VMHDR_H */