Blame src/lib/libast/vmalloc/vmdebug.c

Packit Service a8c26c
/***********************************************************************
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*               This software is part of the ast package               *
Packit Service a8c26c
*          Copyright (c) 1985-2012 AT&T Intellectual Property          *
Packit Service a8c26c
*                      and is licensed under the                       *
Packit Service a8c26c
*                 Eclipse Public License, Version 1.0                  *
Packit Service a8c26c
*                    by AT&T Intellectual Property                     *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*                A copy of the License is available at                 *
Packit Service a8c26c
*          http://www.eclipse.org/org/documents/epl-v10.html           *
Packit Service a8c26c
*         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*              Information and Software Systems Research               *
Packit Service a8c26c
*                            AT&T Research                             *
Packit Service a8c26c
*                           Florham Park NJ                            *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*                 Glenn Fowler <gsf@research.att.com>                  *
Packit Service a8c26c
*                  David Korn <dgk@research.att.com>                   *
Packit Service a8c26c
*                   Phong Vo <kpv@research.att.com>                    *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
***********************************************************************/
Packit Service a8c26c
#if defined(_UWIN) && defined(_BLD_ast)
Packit Service a8c26c
Packit Service a8c26c
void _STUB_vmdebug(){}
Packit Service a8c26c
Packit Service a8c26c
#else
Packit Service a8c26c
Packit Service a8c26c
#include	"vmhdr.h"
Packit Service a8c26c
Packit Service a8c26c
/*	Method to help with debugging. This does rigorous checks on
Packit Service a8c26c
**	addresses and arena integrity.
Packit Service a8c26c
**
Packit Service a8c26c
**	Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
Packit Service a8c26c
*/
Packit Service a8c26c
Packit Service a8c26c
/* structure to keep track of file names */
Packit Service a8c26c
typedef struct _dbfile_s	Dbfile_t;
Packit Service a8c26c
struct _dbfile_s
Packit Service a8c26c
{	Dbfile_t*	next;
Packit Service a8c26c
	char		file[1];
Packit Service a8c26c
};
Packit Service a8c26c
static Dbfile_t*	Dbfile;
Packit Service a8c26c
	
Packit Service a8c26c
/* global watch list */
Packit Service a8c26c
#define S_WATCH	32
Packit Service a8c26c
static int	Dbnwatch;
Packit Service a8c26c
static Void_t*	Dbwatch[S_WATCH];
Packit Service a8c26c
Packit Service a8c26c
/* types of warnings reported by dbwarn() */
Packit Service a8c26c
#define	DB_CHECK	0
Packit Service a8c26c
#define DB_ALLOC	1
Packit Service a8c26c
#define DB_FREE		2
Packit Service a8c26c
#define DB_RESIZE	3
Packit Service a8c26c
#define DB_WATCH	4
Packit Service a8c26c
#define DB_RESIZED	5
Packit Service a8c26c
Packit Service a8c26c
static int Dbinit = 0;
Packit Service a8c26c
#define DBINIT()	(Dbinit ? 0 : (dbinit(), Dbinit=1) )
Packit Service a8c26c
static void dbinit()
Packit Service a8c26c
{	int	fd;	
Packit Service a8c26c
	if((fd = vmtrace(-1)) >= 0)
Packit Service a8c26c
		vmtrace(fd);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
static int	Dbfd = 2;	/* default warning file descriptor */
Packit Service a8c26c
#if __STD_C
Packit Service a8c26c
int vmdebug(int fd)
Packit Service a8c26c
#else
Packit Service a8c26c
int vmdebug(fd)
Packit Service a8c26c
int	fd;
Packit Service a8c26c
#endif
Packit Service a8c26c
{
Packit Service a8c26c
	int	old = Dbfd;
Packit Service a8c26c
	Dbfd = fd;
Packit Service a8c26c
	return old;
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
Packit Service a8c26c
/* just an entry point to make it easy to set break point */
Packit Service a8c26c
#if __STD_C
Packit Service a8c26c
static void vmdbwarn(Vmalloc_t* vm, char* mesg, int n)
Packit Service a8c26c
#else
Packit Service a8c26c
static void vmdbwarn(vm, mesg, n)
Packit Service a8c26c
Vmalloc_t*	vm;
Packit Service a8c26c
char*		mesg;
Packit Service a8c26c
int		n;
Packit Service a8c26c
#endif
Packit Service a8c26c
{
Packit Service a8c26c
	reg Vmdata_t*	vd = vm->data;
Packit Service a8c26c
Packit Service a8c26c
	write(Dbfd,mesg,n);
Packit Service a8c26c
	if(vd->mode&VM_DBABORT)
Packit Service a8c26c
		abort();
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
/* issue a warning of some type */
Packit Service a8c26c
#if __STD_C
Packit Service a8c26c
static void dbwarn(Vmalloc_t* vm, Void_t* data, int where,
Packit Service a8c26c
		   char* file, int line, Void_t* func, int type)
Packit Service a8c26c
#else
Packit Service a8c26c
static void dbwarn(vm, data, where, file, line, func, type)
Packit Service a8c26c
Vmalloc_t*	vm;	/* region holding the block	*/
Packit Service a8c26c
Void_t*		data;	/* data block			*/
Packit Service a8c26c
int		where;	/* byte that was corrupted	*/
Packit Service a8c26c
char*		file;	/* file where call originates	*/
Packit Service a8c26c
int		line;	/* line number of call		*/
Packit Service a8c26c
Void_t*		func;	/* function called from		*/
Packit Service a8c26c
int		type;	/* operation being done		*/
Packit Service a8c26c
#endif
Packit Service a8c26c
{
Packit Service a8c26c
	char	buf[1024], *bufp, *endbuf, *s;
Packit Service a8c26c
#define SLOP	64	/* enough for a message and an int */
Packit Service a8c26c
Packit Service a8c26c
	DBINIT();
Packit Service a8c26c
Packit Service a8c26c
	bufp = buf;
Packit Service a8c26c
	endbuf = buf + sizeof(buf);
Packit Service a8c26c
Packit Service a8c26c
	if(type == DB_ALLOC)
Packit Service a8c26c
		bufp = (*_Vmstrcpy)(bufp, "alloc error", ':');
Packit Service a8c26c
	else if(type == DB_FREE)
Packit Service a8c26c
		bufp = (*_Vmstrcpy)(bufp, "free error", ':');
Packit Service a8c26c
	else if(type == DB_RESIZE)
Packit Service a8c26c
		bufp = (*_Vmstrcpy)(bufp, "resize error", ':');
Packit Service a8c26c
	else if(type == DB_CHECK)
Packit Service a8c26c
		bufp = (*_Vmstrcpy)(bufp, "corrupted data", ':');
Packit Service a8c26c
	else if(type == DB_WATCH)
Packit Service a8c26c
		bufp = (*_Vmstrcpy)(bufp, "alert", ':');
Packit Service a8c26c
Packit Service a8c26c
	/* region info */
Packit Service a8c26c
	bufp = (*_Vmstrcpy)(bufp, "region", '=');
Packit Service a8c26c
	bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(vm), 0), ':');
Packit Service a8c26c
Packit Service a8c26c
	if(data)
Packit Service a8c26c
	{	bufp = (*_Vmstrcpy)(bufp,"block",'=');
Packit Service a8c26c
		bufp = (*_Vmstrcpy)(bufp,(*_Vmitoa)(VLONG(data),0),':');
Packit Service a8c26c
	}
Packit Service a8c26c
Packit Service a8c26c
	if(!data)
Packit Service a8c26c
	{	if(where == DB_ALLOC)
Packit Service a8c26c
			bufp = (*_Vmstrcpy)(bufp, "can't get memory", ':');
Packit Service a8c26c
		else	bufp = (*_Vmstrcpy)(bufp, "region is locked", ':');
Packit Service a8c26c
	}
Packit Service a8c26c
	else if(type == DB_FREE || type == DB_RESIZE)
Packit Service a8c26c
	{	if(where == 0)
Packit Service a8c26c
			bufp = (*_Vmstrcpy)(bufp, "unallocated block", ':');
Packit Service a8c26c
		else	bufp = (*_Vmstrcpy)(bufp, "already freed", ':');
Packit Service a8c26c
	}
Packit Service a8c26c
	else if(type == DB_WATCH)
Packit Service a8c26c
	{	bufp = (*_Vmstrcpy)(bufp, "size", '=');
Packit Service a8c26c
		bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)((Vmulong_t)DBSIZE(data),-1), ':');
Packit Service a8c26c
		if(where == DB_ALLOC)
Packit Service a8c26c
			bufp = (*_Vmstrcpy)(bufp,"just allocated", ':');
Packit Service a8c26c
		else if(where == DB_FREE)
Packit Service a8c26c
			bufp = (*_Vmstrcpy)(bufp,"being freed", ':');
Packit Service a8c26c
		else if(where == DB_RESIZE)
Packit Service a8c26c
			bufp = (*_Vmstrcpy)(bufp,"being resized", ':');
Packit Service a8c26c
		else if(where == DB_RESIZED)
Packit Service a8c26c
			bufp = (*_Vmstrcpy)(bufp,"just resized", ':');
Packit Service a8c26c
	}
Packit Service a8c26c
	else if(type == DB_CHECK)
Packit Service a8c26c
	{	bufp = (*_Vmstrcpy)(bufp, "bad byte at", '=');
Packit Service a8c26c
		bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(where),-1), ':');
Packit Service a8c26c
		if((s = DBFILE(data)) && (bufp + strlen(s) + SLOP) < endbuf)
Packit Service a8c26c
		{	bufp = (*_Vmstrcpy)(bufp,"allocated at", '=');
Packit Service a8c26c
			bufp = (*_Vmstrcpy)(bufp, s, ',');
Packit Service a8c26c
			bufp = (*_Vmstrcpy)(bufp,(*_Vmitoa)(VLONG(DBLINE(data)),-1),':');
Packit Service a8c26c
		}
Packit Service a8c26c
	}
Packit Service a8c26c
Packit Service a8c26c
	/* location where offending call originates from */
Packit Service a8c26c
	if(file && file[0] && line > 0 && (bufp + strlen(file) + SLOP) < endbuf)
Packit Service a8c26c
	{	bufp = (*_Vmstrcpy)(bufp, "detected at", '=');
Packit Service a8c26c
		bufp = (*_Vmstrcpy)(bufp, file, ',');
Packit Service a8c26c
		bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(line),-1), ',');
Packit Service a8c26c
		bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(func),-1), ':');
Packit Service a8c26c
	}
Packit Service a8c26c
Packit Service a8c26c
	*bufp++ = '\n';
Packit Service a8c26c
	*bufp = '\0';
Packit Service a8c26c
Packit Service a8c26c
	vmdbwarn(vm,buf,(int)(bufp-buf));
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
/* check for watched address and issue warnings */
Packit Service a8c26c
#if __STD_C
Packit Service a8c26c
static void dbwatch(Vmalloc_t* vm, Void_t* data,
Packit Service a8c26c
		    char* file, int line, Void_t* func, int type)
Packit Service a8c26c
#else
Packit Service a8c26c
static void dbwatch(vm, data, file, line, func, type)
Packit Service a8c26c
Vmalloc_t*	vm;
Packit Service a8c26c
Void_t*		data;
Packit Service a8c26c
char*		file;
Packit Service a8c26c
int		line;
Packit Service a8c26c
Void_t*		func;
Packit Service a8c26c
int		type;
Packit Service a8c26c
#endif
Packit Service a8c26c
{
Packit Service a8c26c
	reg int		n;
Packit Service a8c26c
Packit Service a8c26c
	for(n = Dbnwatch; n >= 0; --n)
Packit Service a8c26c
	{	if(Dbwatch[n] == data)
Packit Service a8c26c
		{	dbwarn(vm,data,type,file,line,func,DB_WATCH);
Packit Service a8c26c
			return;
Packit Service a8c26c
		}
Packit Service a8c26c
	}
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
/* record information about the block */
Packit Service a8c26c
#if __STD_C
Packit Service a8c26c
static void dbsetinfo(Vmuchar_t* data, size_t size, char* file, int line)
Packit Service a8c26c
#else
Packit Service a8c26c
static void dbsetinfo(data, size, file, line)
Packit Service a8c26c
Vmuchar_t*	data;	/* real address not the one from Vmbest	*/
Packit Service a8c26c
size_t		size;	/* the actual requested size		*/
Packit Service a8c26c
char*		file;	/* file where the request came from	*/
Packit Service a8c26c
int		line;	/* and line number			*/
Packit Service a8c26c
#endif
Packit Service a8c26c
{
Packit Service a8c26c
	reg Vmuchar_t	*begp, *endp;
Packit Service a8c26c
	reg Dbfile_t	*last, *db;
Packit Service a8c26c
Packit Service a8c26c
	DBINIT();
Packit Service a8c26c
Packit Service a8c26c
	/* find the file structure */
Packit Service a8c26c
	if(!file || !file[0])
Packit Service a8c26c
		db = NIL(Dbfile_t*);
Packit Service a8c26c
	else
Packit Service a8c26c
	{	for(last = NIL(Dbfile_t*), db = Dbfile; db; last = db, db = db->next)
Packit Service a8c26c
			if(strcmp(db->file,file) == 0)
Packit Service a8c26c
				break;
Packit Service a8c26c
		if(!db)
Packit Service a8c26c
		{	db = (Dbfile_t*)vmalloc(Vmheap,sizeof(Dbfile_t)+strlen(file));
Packit Service a8c26c
			if(db)
Packit Service a8c26c
			{	(*_Vmstrcpy)(db->file,file,0);
Packit Service a8c26c
				db->next = Dbfile;
Packit Service a8c26c
				Dbfile = db;
Packit Service a8c26c
			}
Packit Service a8c26c
		}
Packit Service a8c26c
		else if(last) /* move-to-front heuristic */
Packit Service a8c26c
		{	last->next = db->next;
Packit Service a8c26c
			db->next = Dbfile;
Packit Service a8c26c
			Dbfile = db;
Packit Service a8c26c
		}
Packit Service a8c26c
	}
Packit Service a8c26c
Packit Service a8c26c
	DBSETFL(data,(db ? db->file : NIL(char*)),line);
Packit Service a8c26c
	DBSIZE(data) = size;
Packit Service a8c26c
	DBSEG(data)  = SEG(DBBLOCK(data));
Packit Service a8c26c
Packit Service a8c26c
	DBHEAD(data,begp,endp);
Packit Service a8c26c
	while(begp < endp)
Packit Service a8c26c
		*begp++ = DB_MAGIC;
Packit Service a8c26c
	DBTAIL(data,begp,endp);
Packit Service a8c26c
	while(begp < endp)
Packit Service a8c26c
		*begp++ = DB_MAGIC;
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
/* Check to see if an address is in some data block of a region.
Packit Service a8c26c
** This returns -(offset+1) if block is already freed, +(offset+1)
Packit Service a8c26c
** if block is live, 0 if no match.
Packit Service a8c26c
*/
Packit Service a8c26c
#if __STD_C
Packit Service a8c26c
static long dbaddr(Vmalloc_t* vm, Void_t* addr, int local)
Packit Service a8c26c
#else
Packit Service a8c26c
static long dbaddr(vm, addr, local)
Packit Service a8c26c
Vmalloc_t*	vm;
Packit Service a8c26c
Void_t*		addr;
Packit Service a8c26c
int		local;
Packit Service a8c26c
#endif
Packit Service a8c26c
{
Packit Service a8c26c
	reg Block_t	*b, *endb;
Packit Service a8c26c
	reg Seg_t	*seg;
Packit Service a8c26c
	reg Vmuchar_t	*data;
Packit Service a8c26c
	reg long	offset = -1L;
Packit Service a8c26c
	reg Vmdata_t	*vd = vm->data;
Packit Service a8c26c
Packit Service a8c26c
	SETLOCK(vm, local);
Packit Service a8c26c
Packit Service a8c26c
	b = endb = NIL(Block_t*);
Packit Service a8c26c
	for(seg = vd->seg; seg; seg = seg->next)
Packit Service a8c26c
	{	b = SEGBLOCK(seg);
Packit Service a8c26c
		endb = (Block_t*)(seg->baddr - sizeof(Head_t));
Packit Service a8c26c
		if((Vmuchar_t*)addr > (Vmuchar_t*)b &&
Packit Service a8c26c
		   (Vmuchar_t*)addr < (Vmuchar_t*)endb)
Packit Service a8c26c
			break;
Packit Service a8c26c
	}
Packit Service a8c26c
	if(!seg)
Packit Service a8c26c
		goto done;
Packit Service a8c26c
Packit Service a8c26c
	if(local) /* must be vmfree or vmresize checking address */
Packit Service a8c26c
	{	if(DBSEG(addr) == seg)
Packit Service a8c26c
		{	b = DBBLOCK(addr);
Packit Service a8c26c
			if(ISBUSY(SIZE(b)) && !ISJUNK(SIZE(b)) )
Packit Service a8c26c
				offset = 0;
Packit Service a8c26c
			else	offset = -2L;
Packit Service a8c26c
		}
Packit Service a8c26c
		goto done;
Packit Service a8c26c
	}
Packit Service a8c26c
Packit Service a8c26c
	while(b < endb)
Packit Service a8c26c
	{	data = (Vmuchar_t*)DATA(b);
Packit Service a8c26c
		if((Vmuchar_t*)addr >= data && (Vmuchar_t*)addr < data+SIZE(b))
Packit Service a8c26c
		{	if(ISBUSY(SIZE(b)) && !ISJUNK(SIZE(b)) )
Packit Service a8c26c
			{	data = DB2DEBUG(data);
Packit Service a8c26c
				if((Vmuchar_t*)addr >= data &&
Packit Service a8c26c
				   (Vmuchar_t*)addr < data+DBSIZE(data))
Packit Service a8c26c
					offset = (long)((Vmuchar_t*)addr - data);
Packit Service a8c26c
			}
Packit Service a8c26c
			goto done;
Packit Service a8c26c
		}
Packit Service a8c26c
Packit Service a8c26c
		b = (Block_t*)((Vmuchar_t*)DATA(b) + (SIZE(b)&~BITS) );
Packit Service a8c26c
	}
Packit Service a8c26c
Packit Service a8c26c
done:
Packit Service a8c26c
	CLRLOCK(vm, local);
Packit Service a8c26c
	return offset;
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
Packit Service a8c26c
#if __STD_C
Packit Service a8c26c
static long dbsize(Vmalloc_t* vm, Void_t* addr, int local)
Packit Service a8c26c
#else
Packit Service a8c26c
static long dbsize(vm, addr, local)
Packit Service a8c26c
Vmalloc_t*	vm;
Packit Service a8c26c
Void_t*		addr;
Packit Service a8c26c
int		local;
Packit Service a8c26c
#endif
Packit Service a8c26c
{
Packit Service a8c26c
	Block_t		*b, *endb;
Packit Service a8c26c
	Seg_t		*seg;
Packit Service a8c26c
	long		size;
Packit Service a8c26c
	Vmdata_t	*vd = vm->data;
Packit Service a8c26c
Packit Service a8c26c
	SETLOCK(vm, local);
Packit Service a8c26c
Packit Service a8c26c
	size = -1L;
Packit Service a8c26c
	for(seg = vd->seg; seg; seg = seg->next)
Packit Service a8c26c
	{	b = SEGBLOCK(seg);
Packit Service a8c26c
		endb = (Block_t*)(seg->baddr - sizeof(Head_t));
Packit Service a8c26c
		if((Vmuchar_t*)addr <= (Vmuchar_t*)b ||
Packit Service a8c26c
		   (Vmuchar_t*)addr >= (Vmuchar_t*)endb)
Packit Service a8c26c
			continue;
Packit Service a8c26c
		while(b < endb)
Packit Service a8c26c
		{	if(addr == (Void_t*)DB2DEBUG(DATA(b)))
Packit Service a8c26c
			{	if(ISBUSY(SIZE(b)) && !ISJUNK(SIZE(b)) )
Packit Service a8c26c
					size = (long)DBSIZE(addr);
Packit Service a8c26c
				goto done;
Packit Service a8c26c
			}
Packit Service a8c26c
Packit Service a8c26c
			b = (Block_t*)((Vmuchar_t*)DATA(b) + (SIZE(b)&~BITS) );
Packit Service a8c26c
		}
Packit Service a8c26c
	}
Packit Service a8c26c
Packit Service a8c26c
done:
Packit Service a8c26c
	CLRLOCK(vm, local);
Packit Service a8c26c
	return size;
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
#if __STD_C
Packit Service a8c26c
static Void_t* dballoc(Vmalloc_t* vm, size_t size, int local)
Packit Service a8c26c
#else
Packit Service a8c26c
static Void_t* dballoc(vm, size, local)
Packit Service a8c26c
Vmalloc_t*	vm;
Packit Service a8c26c
size_t		size;
Packit Service a8c26c
int		local;
Packit Service a8c26c
#endif
Packit Service a8c26c
{
Packit Service a8c26c
	size_t		s;
Packit Service a8c26c
	Vmuchar_t	*data;
Packit Service a8c26c
	char		*file;
Packit Service a8c26c
	int		line;
Packit Service a8c26c
	Void_t		*func;
Packit Service a8c26c
	Vmdata_t	*vd = vm->data;
Packit Service a8c26c
	VMFLF(vm,file,line,func);
Packit Service a8c26c
Packit Service a8c26c
	SETLOCK(vm, local);
Packit Service a8c26c
Packit Service a8c26c
	if(vd->mode&VM_DBCHECK)
Packit Service a8c26c
		vmdbcheck(vm);
Packit Service a8c26c
Packit Service a8c26c
	s = ROUND(size,ALIGN) + DB_EXTRA;
Packit Service a8c26c
	if(s < sizeof(Body_t))	/* no tiny blocks during Vmdebug */
Packit Service a8c26c
		s = sizeof(Body_t);
Packit Service a8c26c
Packit Service a8c26c
	if(!(data = (Vmuchar_t*)KPVALLOC(vm,s,(*(Vmbest->allocf))) ) )
Packit Service a8c26c
	{	dbwarn(vm,NIL(Vmuchar_t*),DB_ALLOC,file,line,func,DB_ALLOC);
Packit Service a8c26c
		goto done;
Packit Service a8c26c
	}
Packit Service a8c26c
Packit Service a8c26c
	data = DB2DEBUG(data);
Packit Service a8c26c
	dbsetinfo(data,size,file,line);
Packit Service a8c26c
Packit Service a8c26c
	if((vd->mode&VM_TRACE) && _Vmtrace)
Packit Service a8c26c
	{	vm->file = file; vm->line = line; vm->func = func;
Packit Service a8c26c
		(*_Vmtrace)(vm,NIL(Vmuchar_t*),data,size,0);
Packit Service a8c26c
	}
Packit Service a8c26c
Packit Service a8c26c
	if(Dbnwatch > 0 )
Packit Service a8c26c
		dbwatch(vm,data,file,line,func,DB_ALLOC);
Packit Service a8c26c
Packit Service a8c26c
done:
Packit Service a8c26c
	CLRLOCK(vm, local);
Packit Service a8c26c
Packit Service a8c26c
	return (Void_t*)data;
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
Packit Service a8c26c
#if __STD_C
Packit Service a8c26c
static int dbfree(Vmalloc_t* vm, Void_t* data, int local )
Packit Service a8c26c
#else
Packit Service a8c26c
static int dbfree(vm, data, local )
Packit Service a8c26c
Vmalloc_t*	vm;
Packit Service a8c26c
Void_t*		data;
Packit Service a8c26c
int		local;
Packit Service a8c26c
#endif
Packit Service a8c26c
{
Packit Service a8c26c
	char		*file;
Packit Service a8c26c
	int		line;
Packit Service a8c26c
	Void_t		*func;
Packit Service a8c26c
	long		offset;
Packit Service a8c26c
	int		rv, *ip, *endip;
Packit Service a8c26c
	Vmdata_t	*vd = vm->data;
Packit Service a8c26c
	VMFLF(vm,file,line,func);
Packit Service a8c26c
Packit Service a8c26c
	if(!data)
Packit Service a8c26c
		return 0;
Packit Service a8c26c
Packit Service a8c26c
	SETLOCK(vm, local);
Packit Service a8c26c
Packit Service a8c26c
	if(vd->mode&VM_DBCHECK)
Packit Service a8c26c
		vmdbcheck(vm);
Packit Service a8c26c
Packit Service a8c26c
	if((offset = KPVADDR(vm,data,dbaddr)) != 0)
Packit Service a8c26c
	{	dbwarn(vm,(Vmuchar_t*)data,offset == -1L ? 0 : 1,file,line,func,DB_FREE);
Packit Service a8c26c
		rv = -1;
Packit Service a8c26c
	}
Packit Service a8c26c
	else
Packit Service a8c26c
	{	if(Dbnwatch > 0)
Packit Service a8c26c
			dbwatch(vm,data,file,line,func,DB_FREE);
Packit Service a8c26c
Packit Service a8c26c
		if((vd->mode&VM_TRACE) && _Vmtrace)
Packit Service a8c26c
		{	vm->file = file; vm->line = line; vm->func = func;
Packit Service a8c26c
			(*_Vmtrace)(vm,(Vmuchar_t*)data,NIL(Vmuchar_t*),DBSIZE(data),0);
Packit Service a8c26c
		}
Packit Service a8c26c
Packit Service a8c26c
		/* clear free space */
Packit Service a8c26c
		ip = (int*)data;
Packit Service a8c26c
		endip = ip + (DBSIZE(data)+sizeof(int)-1)/sizeof(int);
Packit Service a8c26c
		while(ip < endip)
Packit Service a8c26c
			*ip++ = 0;
Packit Service a8c26c
Packit Service a8c26c
		rv = KPVFREE((vm), (Void_t*)DB2BEST(data), (*Vmbest->freef));
Packit Service a8c26c
	}
Packit Service a8c26c
Packit Service a8c26c
	CLRLOCK(vm, local);
Packit Service a8c26c
	return rv;
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
/*	Resizing an existing block */
Packit Service a8c26c
#if __STD_C
Packit Service a8c26c
static Void_t* dbresize(Vmalloc_t* vm, Void_t* addr, reg size_t size, int type, int local)
Packit Service a8c26c
#else
Packit Service a8c26c
static Void_t* dbresize(vm, addr, size, type, local)
Packit Service a8c26c
Vmalloc_t*	vm;	/* region allocating from	*/
Packit Service a8c26c
Void_t*		addr;	/* old block of data		*/
Packit Service a8c26c
reg size_t	size;	/* new size			*/
Packit Service a8c26c
int		type;	/* !=0 for movable, >0 for copy	*/
Packit Service a8c26c
int		local;
Packit Service a8c26c
#endif
Packit Service a8c26c
{
Packit Service a8c26c
	Vmuchar_t	*data;
Packit Service a8c26c
	long		offset;
Packit Service a8c26c
	size_t		s, oldsize;
Packit Service a8c26c
	char		*file, *oldfile;
Packit Service a8c26c
	int		line, oldline;
Packit Service a8c26c
	Void_t		*func;
Packit Service a8c26c
	Vmdata_t	*vd = vm->data;
Packit Service a8c26c
	VMFLF(vm,file,line,func);
Packit Service a8c26c
Packit Service a8c26c
	if(!addr)
Packit Service a8c26c
	{	vm->file = file; vm->line = line;
Packit Service a8c26c
		data = (Vmuchar_t*)dballoc(vm, size, local);
Packit Service a8c26c
		if(data && (type&VM_RSZERO) )
Packit Service a8c26c
			memset((Void_t*)data, 0, size);
Packit Service a8c26c
		return data;
Packit Service a8c26c
	}
Packit Service a8c26c
	if(size == 0)
Packit Service a8c26c
	{	vm->file = file; vm->line = line;
Packit Service a8c26c
		(void)dbfree(vm, addr, local);
Packit Service a8c26c
		return NIL(Void_t*);
Packit Service a8c26c
	}
Packit Service a8c26c
Packit Service a8c26c
	SETLOCK(vm, local);
Packit Service a8c26c
Packit Service a8c26c
	if(vd->mode&VM_DBCHECK)
Packit Service a8c26c
		vmdbcheck(vm);
Packit Service a8c26c
Packit Service a8c26c
	if((offset = KPVADDR(vm,addr,dbaddr)) != 0)
Packit Service a8c26c
	{	dbwarn(vm,(Vmuchar_t*)addr,offset == -1L ? 0 : 1,file,line,func,DB_RESIZE);
Packit Service a8c26c
		data = NIL(Vmuchar_t*);
Packit Service a8c26c
	}
Packit Service a8c26c
	else
Packit Service a8c26c
	{	if(Dbnwatch > 0)
Packit Service a8c26c
			dbwatch(vm,addr,file,line,func,DB_RESIZE);
Packit Service a8c26c
Packit Service a8c26c
		/* Vmbest data block */
Packit Service a8c26c
		data = DB2BEST(addr);
Packit Service a8c26c
		oldsize = DBSIZE(addr);
Packit Service a8c26c
		oldfile = DBFILE(addr);
Packit Service a8c26c
		oldline = DBLINE(addr);
Packit Service a8c26c
Packit Service a8c26c
		/* do the resize */
Packit Service a8c26c
		s = ROUND(size,ALIGN) + DB_EXTRA;
Packit Service a8c26c
		if(s < sizeof(Body_t))
Packit Service a8c26c
			s = sizeof(Body_t);
Packit Service a8c26c
		data = (Vmuchar_t*)KPVRESIZE(vm,(Void_t*)data,s,
Packit Service a8c26c
					 (type&~VM_RSZERO),(*(Vmbest->resizef)) );
Packit Service a8c26c
		if(!data) /* failed, reset data for old block */
Packit Service a8c26c
		{	dbwarn(vm,NIL(Vmuchar_t*),DB_ALLOC,file,line,func,DB_RESIZE);
Packit Service a8c26c
			dbsetinfo((Vmuchar_t*)addr,oldsize,oldfile,oldline);
Packit Service a8c26c
		}
Packit Service a8c26c
		else
Packit Service a8c26c
		{	data = DB2DEBUG(data);
Packit Service a8c26c
			dbsetinfo(data,size,file,line);
Packit Service a8c26c
	
Packit Service a8c26c
			if((vd->mode&VM_TRACE) && _Vmtrace)
Packit Service a8c26c
			{	vm->file = file; vm->line = line;
Packit Service a8c26c
				(*_Vmtrace)(vm,(Vmuchar_t*)addr,data,size,0);
Packit Service a8c26c
			}
Packit Service a8c26c
			if(Dbnwatch > 0)
Packit Service a8c26c
				dbwatch(vm,data,file,line,func,DB_RESIZED);
Packit Service a8c26c
		}
Packit Service a8c26c
Packit Service a8c26c
		if(data && (type&VM_RSZERO) && size > oldsize)
Packit Service a8c26c
		{	Vmuchar_t *d = data+oldsize, *ed = data+size;
Packit Service a8c26c
			do { *d++ = 0; } while(d < ed);
Packit Service a8c26c
		}
Packit Service a8c26c
	}
Packit Service a8c26c
Packit Service a8c26c
	CLRLOCK(vm, local);
Packit Service a8c26c
Packit Service a8c26c
	return (Void_t*)data;
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
/* compact any residual free space */
Packit Service a8c26c
#if __STD_C
Packit Service a8c26c
static int dbcompact(Vmalloc_t* vm, int local)
Packit Service a8c26c
#else
Packit Service a8c26c
static int dbcompact(vm, local)
Packit Service a8c26c
Vmalloc_t*	vm;
Packit Service a8c26c
int		local;
Packit Service a8c26c
#endif
Packit Service a8c26c
{
Packit Service a8c26c
	return (*(Vmbest->compactf))(vm, local);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
/* check for memory overwrites over all live blocks */
Packit Service a8c26c
#if __STD_C
Packit Service a8c26c
int vmdbcheck(Vmalloc_t* vm)
Packit Service a8c26c
#else
Packit Service a8c26c
int vmdbcheck(vm)
Packit Service a8c26c
Vmalloc_t*	vm;
Packit Service a8c26c
#endif
Packit Service a8c26c
{
Packit Service a8c26c
	reg Block_t	*b, *endb;
Packit Service a8c26c
	reg Seg_t*	seg;
Packit Service a8c26c
	int		rv;
Packit Service a8c26c
	reg Vmdata_t*	vd = vm->data;
Packit Service a8c26c
Packit Service a8c26c
	/* check the meta-data of this region */
Packit Service a8c26c
	if(vd->mode & (VM_MTDEBUG|VM_MTBEST|VM_MTPROFILE))
Packit Service a8c26c
	{	if(_vmbestcheck(vd, NIL(Block_t*)) < 0)
Packit Service a8c26c
			return -1;
Packit Service a8c26c
		if(!(vd->mode&VM_MTDEBUG) )
Packit Service a8c26c
			return 0;
Packit Service a8c26c
	}
Packit Service a8c26c
	else	return -1;
Packit Service a8c26c
Packit Service a8c26c
	rv = 0;
Packit Service a8c26c
	for(seg = vd->seg; seg; seg = seg->next)
Packit Service a8c26c
	{	b = SEGBLOCK(seg);
Packit Service a8c26c
		endb = (Block_t*)(seg->baddr - sizeof(Head_t));
Packit Service a8c26c
		while(b < endb)
Packit Service a8c26c
		{	reg Vmuchar_t	*data, *begp, *endp;
Packit Service a8c26c
Packit Service a8c26c
			if(ISJUNK(SIZE(b)) || !ISBUSY(SIZE(b)))
Packit Service a8c26c
				goto next;
Packit Service a8c26c
Packit Service a8c26c
			data = DB2DEBUG(DATA(b));
Packit Service a8c26c
			if(DBISBAD(data))	/* seen this before */
Packit Service a8c26c
			{	rv += 1;
Packit Service a8c26c
				goto next;
Packit Service a8c26c
			}
Packit Service a8c26c
Packit Service a8c26c
			DBHEAD(data,begp,endp);
Packit Service a8c26c
			for(; begp < endp; ++begp)
Packit Service a8c26c
				if(*begp != DB_MAGIC)
Packit Service a8c26c
					goto set_bad;
Packit Service a8c26c
Packit Service a8c26c
			DBTAIL(data,begp,endp);
Packit Service a8c26c
			for(; begp < endp; ++begp)
Packit Service a8c26c
			{	if(*begp == DB_MAGIC)
Packit Service a8c26c
					continue;
Packit Service a8c26c
			set_bad:
Packit Service a8c26c
				dbwarn(vm,data,(long)(begp-data),vm->file,vm->line,0,DB_CHECK);
Packit Service a8c26c
				DBSETBAD(data);
Packit Service a8c26c
				rv += 1;
Packit Service a8c26c
				goto next;
Packit Service a8c26c
			}
Packit Service a8c26c
Packit Service a8c26c
		next:	b = (Block_t*)((Vmuchar_t*)DATA(b) + (SIZE(b)&~BITS));
Packit Service a8c26c
		}
Packit Service a8c26c
	}
Packit Service a8c26c
Packit Service a8c26c
	return rv;
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
/* set/delete an address to watch */
Packit Service a8c26c
#if __STD_C
Packit Service a8c26c
Void_t* vmdbwatch(Void_t* addr)
Packit Service a8c26c
#else
Packit Service a8c26c
Void_t* vmdbwatch(addr)
Packit Service a8c26c
Void_t*		addr;	/* address to insert	*/
Packit Service a8c26c
#endif
Packit Service a8c26c
{
Packit Service a8c26c
	reg int		n;
Packit Service a8c26c
	reg Void_t*	out;
Packit Service a8c26c
Packit Service a8c26c
	out = NIL(Void_t*);
Packit Service a8c26c
	if(!addr)
Packit Service a8c26c
		Dbnwatch = 0;
Packit Service a8c26c
	else
Packit Service a8c26c
	{	for(n = Dbnwatch - 1; n >= 0; --n)
Packit Service a8c26c
			if(Dbwatch[n] == addr)
Packit Service a8c26c
				break;
Packit Service a8c26c
		if(n < 0)	/* insert */
Packit Service a8c26c
		{	if(Dbnwatch == S_WATCH)	
Packit Service a8c26c
			{	/* delete left-most */
Packit Service a8c26c
				out = Dbwatch[0];
Packit Service a8c26c
				Dbnwatch -= 1;
Packit Service a8c26c
				for(n = 0; n < Dbnwatch; ++n)
Packit Service a8c26c
					Dbwatch[n] = Dbwatch[n+1];
Packit Service a8c26c
			}
Packit Service a8c26c
			Dbwatch[Dbnwatch] = addr;
Packit Service a8c26c
			Dbnwatch += 1;
Packit Service a8c26c
		}
Packit Service a8c26c
	}
Packit Service a8c26c
	return out;
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
#if __STD_C
Packit Service a8c26c
static Void_t* dbalign(Vmalloc_t* vm, size_t size, size_t align, int local)
Packit Service a8c26c
#else
Packit Service a8c26c
static Void_t* dbalign(vm, size, align, local)
Packit Service a8c26c
Vmalloc_t*	vm;
Packit Service a8c26c
size_t		size;
Packit Service a8c26c
size_t		align;
Packit Service a8c26c
int		local;
Packit Service a8c26c
#endif
Packit Service a8c26c
{
Packit Service a8c26c
	Vmuchar_t	*data;
Packit Service a8c26c
	size_t		s;
Packit Service a8c26c
	char		*file;
Packit Service a8c26c
	int		line;
Packit Service a8c26c
	Void_t		*func;
Packit Service a8c26c
	Vmdata_t	*vd = vm->data;
Packit Service a8c26c
	VMFLF(vm,file,line,func);
Packit Service a8c26c
Packit Service a8c26c
	if(size <= 0 || align <= 0)
Packit Service a8c26c
		return NIL(Void_t*);
Packit Service a8c26c
Packit Service a8c26c
	SETLOCK(vm, local);
Packit Service a8c26c
Packit Service a8c26c
	if((s = ROUND(size,ALIGN) + DB_EXTRA) < sizeof(Body_t))
Packit Service a8c26c
		s = sizeof(Body_t);
Packit Service a8c26c
Packit Service a8c26c
	if((data = (Vmuchar_t*)KPVALIGN(vm,s,align,(*(Vmbest->alignf)))) )
Packit Service a8c26c
	{	data += DB_HEAD;
Packit Service a8c26c
		dbsetinfo(data,size,file,line);
Packit Service a8c26c
Packit Service a8c26c
		if((vd->mode&VM_TRACE) && _Vmtrace)
Packit Service a8c26c
		{	vm->file = file; vm->line = line; vm->func = func;
Packit Service a8c26c
			(*_Vmtrace)(vm,NIL(Vmuchar_t*),data,size,align);
Packit Service a8c26c
		}
Packit Service a8c26c
	}
Packit Service a8c26c
Packit Service a8c26c
	CLRLOCK(vm, local);
Packit Service a8c26c
Packit Service a8c26c
	return (Void_t*)data;
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
/* print statistics of region vm. If vm is NULL, use Vmregion */
Packit Service a8c26c
#if __STD_C
Packit Service a8c26c
ssize_t vmdbstat(Vmalloc_t* vm)
Packit Service a8c26c
#else
Packit Service a8c26c
ssize_t vmdbstat(vm)
Packit Service a8c26c
Vmalloc_t*	vm;
Packit Service a8c26c
#endif
Packit Service a8c26c
{	Vmstat_t	st;
Packit Service a8c26c
	char		buf[1024], *bufp;
Packit Service a8c26c
Packit Service a8c26c
	vmstat(vm ? vm : Vmregion, &st);
Packit Service a8c26c
	bufp = buf;
Packit Service a8c26c
	bufp = (*_Vmstrcpy)(bufp, "n_busy", '=');
Packit Service a8c26c
	bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(st.n_busy),-1), ',');
Packit Service a8c26c
	bufp = (*_Vmstrcpy)(bufp, " s_busy", '=');
Packit Service a8c26c
	bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(st.s_busy),-1), '\n');
Packit Service a8c26c
	bufp = (*_Vmstrcpy)(bufp, "n_free", '=');
Packit Service a8c26c
	bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(st.n_free),-1), ',');
Packit Service a8c26c
	bufp = (*_Vmstrcpy)(bufp, " s_free", '=');
Packit Service a8c26c
	bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(st.s_free),-1), '\n');
Packit Service a8c26c
	bufp = (*_Vmstrcpy)(bufp, "m_busy", '=');
Packit Service a8c26c
	bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(st.m_busy),-1), ',');
Packit Service a8c26c
	bufp = (*_Vmstrcpy)(bufp, " m_free", '=');
Packit Service a8c26c
	bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(st.m_free),-1), '\n');
Packit Service a8c26c
	bufp = (*_Vmstrcpy)(bufp, "n_segment", '=');
Packit Service a8c26c
	bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(st.n_seg),-1), ',');
Packit Service a8c26c
	bufp = (*_Vmstrcpy)(bufp, " extent", '=');
Packit Service a8c26c
	bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(st.extent),-1), '\n');
Packit Service a8c26c
	*bufp = 0;
Packit Service a8c26c
	write(Dbfd, buf, strlen(buf));
Packit Service a8c26c
	return strlen(buf);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
static Vmethod_t _Vmdebug =
Packit Service a8c26c
{
Packit Service a8c26c
	dballoc,
Packit Service a8c26c
	dbresize,
Packit Service a8c26c
	dbfree,
Packit Service a8c26c
	dbaddr,
Packit Service a8c26c
	dbsize,
Packit Service a8c26c
	dbcompact,
Packit Service a8c26c
	dbalign,
Packit Service a8c26c
	VM_MTDEBUG
Packit Service a8c26c
};
Packit Service a8c26c
Packit Service a8c26c
__DEFINE__(Vmethod_t*,Vmdebug,&_Vmdebug);
Packit Service a8c26c
Packit Service a8c26c
#ifdef NoF
Packit Service a8c26c
NoF(vmdebug)
Packit Service a8c26c
#endif
Packit Service a8c26c
Packit Service a8c26c
#endif