14887Schin /***********************************************************************
24887Schin * *
34887Schin * This software is part of the ast package *
4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1985-2010 AT&T Intellectual Property *
54887Schin * and is licensed under the *
64887Schin * Common Public License, Version 1.0 *
78462SApril.Chin@Sun.COM * by AT&T Intellectual Property *
84887Schin * *
94887Schin * A copy of the License is available at *
104887Schin * http://www.opensource.org/licenses/cpl1.0.txt *
114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
124887Schin * *
134887Schin * Information and Software Systems Research *
144887Schin * AT&T Research *
154887Schin * Florham Park NJ *
164887Schin * *
174887Schin * Glenn Fowler <gsf@research.att.com> *
184887Schin * David Korn <dgk@research.att.com> *
194887Schin * Phong Vo <kpv@research.att.com> *
204887Schin * *
214887Schin ***********************************************************************/
224887Schin #if defined(_UWIN) && defined(_BLD_ast)
234887Schin
_STUB_vmdebug()244887Schin void _STUB_vmdebug(){}
254887Schin
264887Schin #else
274887Schin
284887Schin #include "vmhdr.h"
294887Schin
304887Schin /* Method to help with debugging. This does rigorous checks on
314887Schin ** addresses and arena integrity.
324887Schin **
334887Schin ** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
344887Schin */
354887Schin
364887Schin /* structure to keep track of file names */
374887Schin typedef struct _dbfile_s Dbfile_t;
384887Schin struct _dbfile_s
394887Schin { Dbfile_t* next;
404887Schin char file[1];
414887Schin };
424887Schin static Dbfile_t* Dbfile;
434887Schin
444887Schin /* global watch list */
454887Schin #define S_WATCH 32
464887Schin static int Dbnwatch;
474887Schin static Void_t* Dbwatch[S_WATCH];
484887Schin
494887Schin /* types of warnings reported by dbwarn() */
504887Schin #define DB_CHECK 0
514887Schin #define DB_ALLOC 1
524887Schin #define DB_FREE 2
534887Schin #define DB_RESIZE 3
544887Schin #define DB_WATCH 4
554887Schin #define DB_RESIZED 5
564887Schin
574887Schin #define LONGV(x) ((Vmulong_t)(x))
584887Schin
594887Schin static int Dbinit = 0;
604887Schin #define DBINIT() (Dbinit ? 0 : (dbinit(), Dbinit=1) )
dbinit()614887Schin static void dbinit()
624887Schin { int fd;
634887Schin if((fd = vmtrace(-1)) >= 0)
644887Schin vmtrace(fd);
654887Schin }
664887Schin
674887Schin static int Dbfd = 2; /* default warning file descriptor */
684887Schin #if __STD_C
vmdebug(int fd)694887Schin int vmdebug(int fd)
704887Schin #else
714887Schin int vmdebug(fd)
724887Schin int fd;
734887Schin #endif
744887Schin {
754887Schin int old = Dbfd;
764887Schin Dbfd = fd;
774887Schin return old;
784887Schin }
794887Schin
804887Schin /* just an entry point to make it easy to set break point */
814887Schin #if __STD_C
vmdbwarn(Vmalloc_t * vm,char * mesg,int n)824887Schin static void vmdbwarn(Vmalloc_t* vm, char* mesg, int n)
834887Schin #else
844887Schin static void vmdbwarn(vm, mesg, n)
854887Schin Vmalloc_t* vm;
864887Schin char* mesg;
874887Schin int n;
884887Schin #endif
894887Schin {
904887Schin reg Vmdata_t* vd = vm->data;
914887Schin
924887Schin write(Dbfd,mesg,n);
934887Schin if(vd->mode&VM_DBABORT)
944887Schin abort();
954887Schin }
964887Schin
974887Schin /* issue a warning of some type */
984887Schin #if __STD_C
dbwarn(Vmalloc_t * vm,Void_t * data,int where,const char * file,int line,const Void_t * func,int type)994887Schin static void dbwarn(Vmalloc_t* vm, Void_t* data, int where,
1004887Schin const char* file, int line, const Void_t* func, int type)
1014887Schin #else
1024887Schin static void dbwarn(vm, data, where, file, line, func, type)
1034887Schin Vmalloc_t* vm; /* region holding the block */
1044887Schin Void_t* data; /* data block */
1054887Schin int where; /* byte that was corrupted */
1064887Schin const char* file; /* file where call originates */
1074887Schin int line; /* line number of call */
1084887Schin const Void_t* func; /* function called from */
1094887Schin int type; /* operation being done */
1104887Schin #endif
1114887Schin {
1124887Schin char buf[1024], *bufp, *endbuf, *s;
1134887Schin #define SLOP 64 /* enough for a message and an int */
1144887Schin
1154887Schin DBINIT();
1164887Schin
1174887Schin bufp = buf;
1184887Schin endbuf = buf + sizeof(buf);
1194887Schin
1204887Schin if(type == DB_ALLOC)
1214887Schin bufp = (*_Vmstrcpy)(bufp, "alloc error", ':');
1224887Schin else if(type == DB_FREE)
1234887Schin bufp = (*_Vmstrcpy)(bufp, "free error", ':');
1244887Schin else if(type == DB_RESIZE)
1254887Schin bufp = (*_Vmstrcpy)(bufp, "resize error", ':');
1264887Schin else if(type == DB_CHECK)
1274887Schin bufp = (*_Vmstrcpy)(bufp, "corrupted data", ':');
1284887Schin else if(type == DB_WATCH)
1294887Schin bufp = (*_Vmstrcpy)(bufp, "alert", ':');
1304887Schin
1314887Schin /* region info */
1324887Schin bufp = (*_Vmstrcpy)(bufp, "region", '=');
1334887Schin bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(vm), 0), ':');
1344887Schin
1354887Schin if(data)
1364887Schin { bufp = (*_Vmstrcpy)(bufp,"block",'=');
1374887Schin bufp = (*_Vmstrcpy)(bufp,(*_Vmitoa)(VLONG(data),0),':');
1384887Schin }
1394887Schin
1404887Schin if(!data)
1414887Schin { if(where == DB_ALLOC)
1424887Schin bufp = (*_Vmstrcpy)(bufp, "can't get memory", ':');
1434887Schin else bufp = (*_Vmstrcpy)(bufp, "region is locked", ':');
1444887Schin }
1454887Schin else if(type == DB_FREE || type == DB_RESIZE)
1464887Schin { if(where == 0)
1474887Schin bufp = (*_Vmstrcpy)(bufp, "unallocated block", ':');
1484887Schin else bufp = (*_Vmstrcpy)(bufp, "already freed", ':');
1494887Schin }
1504887Schin else if(type == DB_WATCH)
1514887Schin { bufp = (*_Vmstrcpy)(bufp, "size", '=');
1524887Schin bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(DBSIZE(data),-1), ':');
1534887Schin if(where == DB_ALLOC)
1544887Schin bufp = (*_Vmstrcpy)(bufp,"just allocated", ':');
1554887Schin else if(where == DB_FREE)
1564887Schin bufp = (*_Vmstrcpy)(bufp,"being freed", ':');
1574887Schin else if(where == DB_RESIZE)
1584887Schin bufp = (*_Vmstrcpy)(bufp,"being resized", ':');
1594887Schin else if(where == DB_RESIZED)
1604887Schin bufp = (*_Vmstrcpy)(bufp,"just resized", ':');
1614887Schin }
1624887Schin else if(type == DB_CHECK)
1634887Schin { bufp = (*_Vmstrcpy)(bufp, "bad byte at", '=');
1644887Schin bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(LONGV(where),-1), ':');
1654887Schin if((s = DBFILE(data)) && (bufp + strlen(s) + SLOP) < endbuf)
1664887Schin { bufp = (*_Vmstrcpy)(bufp,"allocated at", '=');
1674887Schin bufp = (*_Vmstrcpy)(bufp, s, ',');
1684887Schin bufp = (*_Vmstrcpy)(bufp,(*_Vmitoa)(LONGV(DBLINE(data)),-1),':');
1694887Schin }
1704887Schin }
1714887Schin
1724887Schin /* location where offending call originates from */
1734887Schin if(file && file[0] && line > 0 && (bufp + strlen(file) + SLOP) < endbuf)
1744887Schin { bufp = (*_Vmstrcpy)(bufp, "detected at", '=');
1754887Schin bufp = (*_Vmstrcpy)(bufp, file, ',');
1764887Schin bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(LONGV(line),-1), ',');
1774887Schin bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(func),-1), ':');
1784887Schin }
1794887Schin
180*12068SRoger.Faulkner@Oracle.COM *(bufp - 1) = '\n';
1814887Schin *bufp = '\0';
1824887Schin
1834887Schin vmdbwarn(vm,buf,(bufp-buf));
1844887Schin }
1854887Schin
1864887Schin /* check for watched address and issue warnings */
1874887Schin #if __STD_C
dbwatch(Vmalloc_t * vm,Void_t * data,const char * file,int line,const Void_t * func,int type)1884887Schin static void dbwatch(Vmalloc_t* vm, Void_t* data,
1894887Schin const char* file, int line, const Void_t* func, int type)
1904887Schin #else
1914887Schin static void dbwatch(vm, data, file, line, func, type)
1924887Schin Vmalloc_t* vm;
1934887Schin Void_t* data;
1944887Schin const char* file;
1954887Schin int line;
1964887Schin const Void_t* func;
1974887Schin int type;
1984887Schin #endif
1994887Schin {
2004887Schin reg int n;
2014887Schin
2024887Schin for(n = Dbnwatch; n >= 0; --n)
2034887Schin { if(Dbwatch[n] == data)
2044887Schin { dbwarn(vm,data,type,file,line,func,DB_WATCH);
2054887Schin return;
2064887Schin }
2074887Schin }
2084887Schin }
2094887Schin
2104887Schin /* record information about the block */
2114887Schin #if __STD_C
dbsetinfo(Vmuchar_t * data,size_t size,const char * file,int line)2124887Schin static void dbsetinfo(Vmuchar_t* data, size_t size, const char* file, int line)
2134887Schin #else
2144887Schin static void dbsetinfo(data, size, file, line)
2154887Schin Vmuchar_t* data; /* real address not the one from Vmbest */
2164887Schin size_t size; /* the actual requested size */
2174887Schin const char* file; /* file where the request came from */
2184887Schin int line; /* and line number */
2194887Schin #endif
2204887Schin {
2214887Schin reg Vmuchar_t *begp, *endp;
2224887Schin reg Dbfile_t *last, *db;
2234887Schin
2244887Schin DBINIT();
2254887Schin
2264887Schin /* find the file structure */
2274887Schin if(!file || !file[0])
2284887Schin db = NIL(Dbfile_t*);
2294887Schin else
2304887Schin { for(last = NIL(Dbfile_t*), db = Dbfile; db; last = db, db = db->next)
2314887Schin if(strcmp(db->file,file) == 0)
2324887Schin break;
2334887Schin if(!db)
2344887Schin { db = (Dbfile_t*)vmalloc(Vmheap,sizeof(Dbfile_t)+strlen(file));
2354887Schin if(db)
2364887Schin { (*_Vmstrcpy)(db->file,file,0);
2374887Schin db->next = Dbfile;
2384887Schin Dbfile = db->next;
2394887Schin }
2404887Schin }
2414887Schin else if(last) /* move-to-front heuristic */
2424887Schin { last->next = db->next;
2434887Schin db->next = Dbfile;
2444887Schin Dbfile = db->next;
2454887Schin }
2464887Schin }
2474887Schin
2484887Schin DBSETFL(data,(db ? db->file : NIL(char*)),line);
2494887Schin DBSIZE(data) = size;
2504887Schin DBSEG(data) = SEG(DBBLOCK(data));
2514887Schin
2524887Schin DBHEAD(data,begp,endp);
2534887Schin while(begp < endp)
2544887Schin *begp++ = DB_MAGIC;
2554887Schin DBTAIL(data,begp,endp);
2564887Schin while(begp < endp)
2574887Schin *begp++ = DB_MAGIC;
2584887Schin }
2594887Schin
2604887Schin /* Check to see if an address is in some data block of a region.
2614887Schin ** This returns -(offset+1) if block is already freed, +(offset+1)
2624887Schin ** if block is live, 0 if no match.
2634887Schin */
2644887Schin #if __STD_C
dbaddr(Vmalloc_t * vm,Void_t * addr)2654887Schin static long dbaddr(Vmalloc_t* vm, Void_t* addr)
2664887Schin #else
2674887Schin static long dbaddr(vm, addr)
2684887Schin Vmalloc_t* vm;
2694887Schin Void_t* addr;
2704887Schin #endif
2714887Schin {
2724887Schin reg Block_t *b, *endb;
2734887Schin reg Seg_t* seg;
2744887Schin reg Vmuchar_t* data;
2754887Schin reg long offset = -1L;
2764887Schin reg Vmdata_t* vd = vm->data;
2778462SApril.Chin@Sun.COM reg int local, inuse;
2784887Schin
2798462SApril.Chin@Sun.COM SETINUSE(vd, inuse);
2804887Schin GETLOCAL(vd,local);
2814887Schin if(ISLOCK(vd,local) || !addr)
2828462SApril.Chin@Sun.COM { CLRINUSE(vd, inuse);
2834887Schin return -1L;
2848462SApril.Chin@Sun.COM }
2854887Schin SETLOCK(vd,local);
2864887Schin
2874887Schin b = endb = NIL(Block_t*);
2884887Schin for(seg = vd->seg; seg; seg = seg->next)
2894887Schin { b = SEGBLOCK(seg);
2904887Schin endb = (Block_t*)(seg->baddr - sizeof(Head_t));
2914887Schin if((Vmuchar_t*)addr > (Vmuchar_t*)b &&
2924887Schin (Vmuchar_t*)addr < (Vmuchar_t*)endb)
2934887Schin break;
2944887Schin }
2954887Schin if(!seg)
2964887Schin goto done;
2974887Schin
2984887Schin if(local) /* must be vmfree or vmresize checking address */
2994887Schin { if(DBSEG(addr) == seg)
3004887Schin { b = DBBLOCK(addr);
3014887Schin if(ISBUSY(SIZE(b)) && !ISJUNK(SIZE(b)) )
3024887Schin offset = 0;
3034887Schin else offset = -2L;
3044887Schin }
3054887Schin goto done;
3064887Schin }
3074887Schin
3084887Schin while(b < endb)
3094887Schin { data = (Vmuchar_t*)DATA(b);
3104887Schin if((Vmuchar_t*)addr >= data && (Vmuchar_t*)addr < data+SIZE(b))
3114887Schin { if(ISBUSY(SIZE(b)) && !ISJUNK(SIZE(b)) )
3124887Schin { data = DB2DEBUG(data);
3134887Schin if((Vmuchar_t*)addr >= data &&
3144887Schin (Vmuchar_t*)addr < data+DBSIZE(data))
3154887Schin offset = (Vmuchar_t*)addr - data;
3164887Schin }
3174887Schin goto done;
3184887Schin }
3194887Schin
3204887Schin b = (Block_t*)((Vmuchar_t*)DATA(b) + (SIZE(b)&~BITS) );
3214887Schin }
3224887Schin
3234887Schin done:
3244887Schin CLRLOCK(vd,local);
3258462SApril.Chin@Sun.COM CLRINUSE(vd, inuse);
3264887Schin return offset;
3274887Schin }
3284887Schin
3294887Schin
3304887Schin #if __STD_C
dbsize(Vmalloc_t * vm,Void_t * addr)3314887Schin static long dbsize(Vmalloc_t* vm, Void_t* addr)
3324887Schin #else
3334887Schin static long dbsize(vm, addr)
3344887Schin Vmalloc_t* vm;
3354887Schin Void_t* addr;
3364887Schin #endif
3374887Schin {
3384887Schin reg Block_t *b, *endb;
3394887Schin reg Seg_t* seg;
3404887Schin reg long size;
3414887Schin reg Vmdata_t* vd = vm->data;
3428462SApril.Chin@Sun.COM reg int inuse;
3434887Schin
3448462SApril.Chin@Sun.COM SETINUSE(vd, inuse);
3454887Schin if(ISLOCK(vd,0))
3468462SApril.Chin@Sun.COM { CLRINUSE(vd, inuse);
3474887Schin return -1L;
3488462SApril.Chin@Sun.COM }
3494887Schin SETLOCK(vd,0);
3504887Schin
3514887Schin size = -1L;
3524887Schin for(seg = vd->seg; seg; seg = seg->next)
3534887Schin { b = SEGBLOCK(seg);
3544887Schin endb = (Block_t*)(seg->baddr - sizeof(Head_t));
3554887Schin if((Vmuchar_t*)addr <= (Vmuchar_t*)b ||
3564887Schin (Vmuchar_t*)addr >= (Vmuchar_t*)endb)
3574887Schin continue;
3584887Schin while(b < endb)
3594887Schin { if(addr == (Void_t*)DB2DEBUG(DATA(b)))
3604887Schin { if(ISBUSY(SIZE(b)) && !ISJUNK(SIZE(b)) )
3614887Schin size = (long)DBSIZE(addr);
3624887Schin goto done;
3634887Schin }
3644887Schin
3654887Schin b = (Block_t*)((Vmuchar_t*)DATA(b) + (SIZE(b)&~BITS) );
3664887Schin }
3674887Schin }
3684887Schin done:
3694887Schin CLRLOCK(vd,0);
3708462SApril.Chin@Sun.COM CLRINUSE(vd, inuse);
3714887Schin return size;
3724887Schin }
3734887Schin
3744887Schin #if __STD_C
dballoc(Vmalloc_t * vm,size_t size)3754887Schin static Void_t* dballoc(Vmalloc_t* vm, size_t size)
3764887Schin #else
3774887Schin static Void_t* dballoc(vm, size)
3784887Schin Vmalloc_t* vm;
3794887Schin size_t size;
3804887Schin #endif
3814887Schin {
3824887Schin reg size_t s;
3834887Schin reg Vmuchar_t* data;
3844887Schin reg char* file;
3854887Schin reg int line;
3864887Schin reg Void_t* func;
3874887Schin reg Vmdata_t* vd = vm->data;
3888462SApril.Chin@Sun.COM reg int inuse;
3894887Schin
3908462SApril.Chin@Sun.COM SETINUSE(vd, inuse);
3914887Schin VMFLF(vm,file,line,func);
3924887Schin
3934887Schin if(ISLOCK(vd,0) )
3944887Schin { dbwarn(vm,NIL(Vmuchar_t*),0,file,line,func,DB_ALLOC);
3958462SApril.Chin@Sun.COM CLRINUSE(vd, inuse);
3964887Schin return NIL(Void_t*);
3974887Schin }
3984887Schin SETLOCK(vd,0);
3994887Schin
4004887Schin if(vd->mode&VM_DBCHECK)
4014887Schin vmdbcheck(vm);
4024887Schin
4034887Schin s = ROUND(size,ALIGN) + DB_EXTRA;
4044887Schin if(s < sizeof(Body_t)) /* no tiny blocks during Vmdebug */
4054887Schin s = sizeof(Body_t);
4064887Schin
4074887Schin if(!(data = (Vmuchar_t*)KPVALLOC(vm,s,(*(Vmbest->allocf))) ) )
4084887Schin { dbwarn(vm,NIL(Vmuchar_t*),DB_ALLOC,file,line,func,DB_ALLOC);
4094887Schin goto done;
4104887Schin }
4114887Schin
4124887Schin data = DB2DEBUG(data);
4134887Schin dbsetinfo(data,size,file,line);
4144887Schin
4154887Schin if((vd->mode&VM_TRACE) && _Vmtrace)
4164887Schin { vm->file = file; vm->line = line; vm->func = func;
4174887Schin (*_Vmtrace)(vm,NIL(Vmuchar_t*),data,size,0);
4184887Schin }
4194887Schin
4204887Schin if(Dbnwatch > 0 )
4214887Schin dbwatch(vm,data,file,line,func,DB_ALLOC);
4224887Schin
4234887Schin done:
4244887Schin CLRLOCK(vd,0);
4254887Schin ANNOUNCE(0, vm, VM_ALLOC, (Void_t*)data, vm->disc);
4268462SApril.Chin@Sun.COM CLRINUSE(vd, inuse);
4274887Schin return (Void_t*)data;
4284887Schin }
4294887Schin
4304887Schin
4314887Schin #if __STD_C
dbfree(Vmalloc_t * vm,Void_t * data)4324887Schin static int dbfree(Vmalloc_t* vm, Void_t* data )
4334887Schin #else
4344887Schin static int dbfree(vm, data )
4354887Schin Vmalloc_t* vm;
4364887Schin Void_t* data;
4374887Schin #endif
4384887Schin {
4394887Schin char* file;
4404887Schin int line;
4414887Schin Void_t* func;
4424887Schin reg long offset;
4434887Schin reg int rv, *ip, *endip;
4444887Schin reg Vmdata_t* vd = vm->data;
4458462SApril.Chin@Sun.COM reg int inuse;
4464887Schin
4478462SApril.Chin@Sun.COM SETINUSE(vd, inuse);
4484887Schin VMFLF(vm,file,line,func);
4494887Schin
4504887Schin if(!data)
4518462SApril.Chin@Sun.COM { CLRINUSE(vd, inuse);
4524887Schin return 0;
4538462SApril.Chin@Sun.COM }
4544887Schin
4554887Schin if(ISLOCK(vd,0) )
4564887Schin { dbwarn(vm,NIL(Vmuchar_t*),0,file,line,func,DB_FREE);
4578462SApril.Chin@Sun.COM CLRINUSE(vd, inuse);
4584887Schin return -1;
4594887Schin }
4604887Schin SETLOCK(vd,0);
4614887Schin
4624887Schin if(vd->mode&VM_DBCHECK)
4634887Schin vmdbcheck(vm);
4644887Schin
4654887Schin if((offset = KPVADDR(vm,data,dbaddr)) != 0)
466*12068SRoger.Faulkner@Oracle.COM { dbwarn(vm,(Vmuchar_t*)data,offset == -1L ? 0 : 1,file,line,func,DB_FREE);
467*12068SRoger.Faulkner@Oracle.COM if(vm->disc->exceptf)
4684887Schin (void)(*vm->disc->exceptf)(vm,VM_BADADDR,data,vm->disc);
4694887Schin CLRLOCK(vd,0);
4708462SApril.Chin@Sun.COM CLRINUSE(vd, inuse);
4714887Schin return -1;
4724887Schin }
4734887Schin
4744887Schin if(Dbnwatch > 0)
4754887Schin dbwatch(vm,data,file,line,func,DB_FREE);
4764887Schin
4774887Schin if((vd->mode&VM_TRACE) && _Vmtrace)
4784887Schin { vm->file = file; vm->line = line; vm->func = func;
4794887Schin (*_Vmtrace)(vm,(Vmuchar_t*)data,NIL(Vmuchar_t*),DBSIZE(data),0);
4804887Schin }
4814887Schin
4824887Schin /* clear free space */
4834887Schin ip = (int*)data;
4844887Schin endip = ip + (DBSIZE(data)+sizeof(int)-1)/sizeof(int);
4854887Schin while(ip < endip)
4864887Schin *ip++ = 0;
4874887Schin
4884887Schin rv = KPVFREE((vm), (Void_t*)DB2BEST(data), (*Vmbest->freef));
4894887Schin CLRLOCK(vd,0);
4904887Schin ANNOUNCE(0, vm, VM_FREE, data, vm->disc);
4918462SApril.Chin@Sun.COM CLRINUSE(vd, inuse);
4924887Schin return rv;
4934887Schin }
4944887Schin
4954887Schin /* Resizing an existing block */
4964887Schin #if __STD_C
dbresize(Vmalloc_t * vm,Void_t * addr,reg size_t size,int type)4974887Schin static Void_t* dbresize(Vmalloc_t* vm, Void_t* addr, reg size_t size, int type)
4984887Schin #else
4994887Schin static Void_t* dbresize(vm,addr,size,type)
5004887Schin Vmalloc_t* vm; /* region allocating from */
5014887Schin Void_t* addr; /* old block of data */
5024887Schin reg size_t size; /* new size */
5034887Schin int type; /* !=0 for movable, >0 for copy */
5044887Schin #endif
5054887Schin {
5064887Schin reg Vmuchar_t* data;
5074887Schin reg size_t s, oldsize;
5084887Schin reg long offset;
5094887Schin char *file, *oldfile;
5104887Schin int line, oldline;
5114887Schin Void_t* func;
5124887Schin reg Vmdata_t* vd = vm->data;
5138462SApril.Chin@Sun.COM reg int inuse;
5144887Schin
5158462SApril.Chin@Sun.COM SETINUSE(vd, inuse);
5164887Schin if(!addr)
5174887Schin { oldsize = 0;
5184887Schin data = (Vmuchar_t*)dballoc(vm,size);
5194887Schin goto done;
5204887Schin }
5214887Schin if(size == 0)
5224887Schin { (void)dbfree(vm,addr);
5238462SApril.Chin@Sun.COM CLRINUSE(vd, inuse);
5244887Schin return NIL(Void_t*);
5254887Schin }
5264887Schin
5274887Schin VMFLF(vm,file,line,func);
5284887Schin
5294887Schin if(ISLOCK(vd,0) )
5304887Schin { dbwarn(vm,NIL(Vmuchar_t*),0,file,line,func,DB_RESIZE);
5318462SApril.Chin@Sun.COM CLRINUSE(vd, inuse);
5324887Schin return NIL(Void_t*);
5334887Schin }
5344887Schin SETLOCK(vd,0);
5354887Schin
5364887Schin if(vd->mode&VM_DBCHECK)
5374887Schin vmdbcheck(vm);
5384887Schin
5394887Schin if((offset = KPVADDR(vm,addr,dbaddr)) != 0)
540*12068SRoger.Faulkner@Oracle.COM { dbwarn(vm,(Vmuchar_t*)addr,offset == -1L ? 0 : 1,file,line,func,DB_RESIZE);
541*12068SRoger.Faulkner@Oracle.COM if(vm->disc->exceptf)
5424887Schin (void)(*vm->disc->exceptf)(vm,VM_BADADDR,addr,vm->disc);
5434887Schin CLRLOCK(vd,0);
5448462SApril.Chin@Sun.COM CLRINUSE(vd, inuse);
5454887Schin return NIL(Void_t*);
5464887Schin }
5474887Schin
5484887Schin if(Dbnwatch > 0)
5494887Schin dbwatch(vm,addr,file,line,func,DB_RESIZE);
5504887Schin
5514887Schin /* Vmbest data block */
5524887Schin data = DB2BEST(addr);
5534887Schin oldsize = DBSIZE(addr);
5544887Schin oldfile = DBFILE(addr);
5554887Schin oldline = DBLINE(addr);
5564887Schin
5574887Schin /* do the resize */
5584887Schin s = ROUND(size,ALIGN) + DB_EXTRA;
5594887Schin if(s < sizeof(Body_t))
5604887Schin s = sizeof(Body_t);
5614887Schin data = (Vmuchar_t*)KPVRESIZE(vm,(Void_t*)data,s,
5624887Schin (type&~VM_RSZERO),(*(Vmbest->resizef)) );
5634887Schin if(!data) /* failed, reset data for old block */
5644887Schin { dbwarn(vm,NIL(Vmuchar_t*),DB_ALLOC,file,line,func,DB_RESIZE);
5654887Schin dbsetinfo((Vmuchar_t*)addr,oldsize,oldfile,oldline);
5664887Schin }
5674887Schin else
5684887Schin { data = DB2DEBUG(data);
5694887Schin dbsetinfo(data,size,file,line);
5704887Schin
5714887Schin if((vd->mode&VM_TRACE) && _Vmtrace)
5724887Schin { vm->file = file; vm->line = line;
5734887Schin (*_Vmtrace)(vm,(Vmuchar_t*)addr,data,size,0);
5744887Schin }
5754887Schin if(Dbnwatch > 0)
5764887Schin dbwatch(vm,data,file,line,func,DB_RESIZED);
5774887Schin }
5784887Schin
5794887Schin CLRLOCK(vd,0);
5804887Schin ANNOUNCE(0, vm, VM_RESIZE, (Void_t*)data, vm->disc);
5814887Schin
5824887Schin done: if(data && (type&VM_RSZERO) && size > oldsize)
5834887Schin { reg Vmuchar_t *d = data+oldsize, *ed = data+size;
5844887Schin do { *d++ = 0; } while(d < ed);
5854887Schin }
5868462SApril.Chin@Sun.COM CLRINUSE(vd, inuse);
5874887Schin return (Void_t*)data;
5884887Schin }
5894887Schin
5904887Schin /* compact any residual free space */
5914887Schin #if __STD_C
dbcompact(Vmalloc_t * vm)5924887Schin static int dbcompact(Vmalloc_t* vm)
5934887Schin #else
5944887Schin static int dbcompact(vm)
5954887Schin Vmalloc_t* vm;
5964887Schin #endif
5974887Schin {
5984887Schin return (*(Vmbest->compactf))(vm);
5994887Schin }
6004887Schin
6014887Schin /* check for memory overwrites over all live blocks */
6024887Schin #if __STD_C
vmdbcheck(Vmalloc_t * vm)6034887Schin int vmdbcheck(Vmalloc_t* vm)
6044887Schin #else
6054887Schin int vmdbcheck(vm)
6064887Schin Vmalloc_t* vm;
6074887Schin #endif
6084887Schin {
6094887Schin reg Block_t *b, *endb;
6104887Schin reg Seg_t* seg;
6114887Schin int rv;
6124887Schin reg Vmdata_t* vd = vm->data;
6134887Schin
6144887Schin /* check the meta-data of this region */
6154887Schin if(vd->mode & (VM_MTDEBUG|VM_MTBEST|VM_MTPROFILE))
6164887Schin { if(_vmbestcheck(vd, NIL(Block_t*)) < 0)
6174887Schin return -1;
6184887Schin if(!(vd->mode&VM_MTDEBUG))
6194887Schin return 0;
6204887Schin }
6214887Schin else return -1;
6224887Schin
6234887Schin rv = 0;
6244887Schin for(seg = vd->seg; seg; seg = seg->next)
6254887Schin { b = SEGBLOCK(seg);
6264887Schin endb = (Block_t*)(seg->baddr - sizeof(Head_t));
6274887Schin while(b < endb)
6284887Schin { reg Vmuchar_t *data, *begp, *endp;
6294887Schin
6304887Schin if(ISJUNK(SIZE(b)) || !ISBUSY(SIZE(b)))
6314887Schin goto next;
6324887Schin
6334887Schin data = DB2DEBUG(DATA(b));
6344887Schin if(DBISBAD(data)) /* seen this before */
6354887Schin { rv += 1;
6364887Schin goto next;
6374887Schin }
6384887Schin
6394887Schin DBHEAD(data,begp,endp);
6404887Schin for(; begp < endp; ++begp)
6414887Schin if(*begp != DB_MAGIC)
6424887Schin goto set_bad;
6434887Schin
6444887Schin DBTAIL(data,begp,endp);
6454887Schin for(; begp < endp; ++begp)
6464887Schin { if(*begp == DB_MAGIC)
6474887Schin continue;
6484887Schin set_bad:
6494887Schin dbwarn(vm,data,begp-data,NIL(char*),0,0,DB_CHECK);
6504887Schin DBSETBAD(data);
6514887Schin rv += 1;
6524887Schin goto next;
6534887Schin }
6544887Schin
6554887Schin next: b = (Block_t*)((Vmuchar_t*)DATA(b) + (SIZE(b)&~BITS));
6564887Schin }
6574887Schin }
6584887Schin
6594887Schin return rv;
6604887Schin }
6614887Schin
6624887Schin /* set/delete an address to watch */
6634887Schin #if __STD_C
vmdbwatch(Void_t * addr)6644887Schin Void_t* vmdbwatch(Void_t* addr)
6654887Schin #else
6664887Schin Void_t* vmdbwatch(addr)
6674887Schin Void_t* addr; /* address to insert */
6684887Schin #endif
6694887Schin {
6704887Schin reg int n;
6714887Schin reg Void_t* out;
6724887Schin
6734887Schin out = NIL(Void_t*);
6744887Schin if(!addr)
6754887Schin Dbnwatch = 0;
6764887Schin else
6774887Schin { for(n = Dbnwatch - 1; n >= 0; --n)
6784887Schin if(Dbwatch[n] == addr)
6794887Schin break;
6804887Schin if(n < 0) /* insert */
6814887Schin { if(Dbnwatch == S_WATCH)
6824887Schin { /* delete left-most */
6834887Schin out = Dbwatch[0];
6844887Schin Dbnwatch -= 1;
6854887Schin for(n = 0; n < Dbnwatch; ++n)
6864887Schin Dbwatch[n] = Dbwatch[n+1];
6874887Schin }
6884887Schin Dbwatch[Dbnwatch] = addr;
6894887Schin Dbnwatch += 1;
6904887Schin }
6914887Schin }
6924887Schin return out;
6934887Schin }
6944887Schin
6954887Schin #if __STD_C
dbalign(Vmalloc_t * vm,size_t size,size_t align)6964887Schin static Void_t* dbalign(Vmalloc_t* vm, size_t size, size_t align)
6974887Schin #else
6984887Schin static Void_t* dbalign(vm, size, align)
6994887Schin Vmalloc_t* vm;
7004887Schin size_t size;
7014887Schin size_t align;
7024887Schin #endif
7034887Schin {
7044887Schin reg Vmuchar_t* data;
7054887Schin reg size_t s;
7064887Schin reg char* file;
7074887Schin reg int line;
7084887Schin reg Void_t* func;
7094887Schin reg Vmdata_t* vd = vm->data;
7108462SApril.Chin@Sun.COM reg int inuse;
7114887Schin
7128462SApril.Chin@Sun.COM SETINUSE(vd, inuse);
7134887Schin VMFLF(vm,file,line,func);
7144887Schin
7154887Schin if(size <= 0 || align <= 0)
7168462SApril.Chin@Sun.COM { CLRINUSE(vd, inuse);
7174887Schin return NIL(Void_t*);
7188462SApril.Chin@Sun.COM }
7194887Schin
7204887Schin if(ISLOCK(vd,0) )
7218462SApril.Chin@Sun.COM { CLRINUSE(vd, inuse);
7224887Schin return NIL(Void_t*);
7238462SApril.Chin@Sun.COM }
7244887Schin SETLOCK(vd,0);
7254887Schin
7264887Schin if((s = ROUND(size,ALIGN) + DB_EXTRA) < sizeof(Body_t))
7274887Schin s = sizeof(Body_t);
7284887Schin
7294887Schin if(!(data = (Vmuchar_t*)KPVALIGN(vm,s,align,(*(Vmbest->alignf)))) )
7304887Schin goto done;
7314887Schin
7324887Schin data += DB_HEAD;
7334887Schin dbsetinfo(data,size,file,line);
7344887Schin
7354887Schin if((vd->mode&VM_TRACE) && _Vmtrace)
7364887Schin { vm->file = file; vm->line = line; vm->func = func;
7374887Schin (*_Vmtrace)(vm,NIL(Vmuchar_t*),data,size,align);
7384887Schin }
7394887Schin
7404887Schin done:
7414887Schin CLRLOCK(vd,0);
7424887Schin ANNOUNCE(0, vm, VM_ALLOC, (Void_t*)data, vm->disc);
7438462SApril.Chin@Sun.COM CLRINUSE(vd, inuse);
7444887Schin return (Void_t*)data;
7454887Schin }
7464887Schin
747*12068SRoger.Faulkner@Oracle.COM /* print statistics of region vm. If vm is NULL, use Vmregion */
748*12068SRoger.Faulkner@Oracle.COM #if __STD_C
vmdbstat(Vmalloc_t * vm)749*12068SRoger.Faulkner@Oracle.COM ssize_t vmdbstat(Vmalloc_t* vm)
750*12068SRoger.Faulkner@Oracle.COM #else
751*12068SRoger.Faulkner@Oracle.COM ssize_t vmdbstat(vm)
752*12068SRoger.Faulkner@Oracle.COM Vmalloc_t* vm;
753*12068SRoger.Faulkner@Oracle.COM #endif
754*12068SRoger.Faulkner@Oracle.COM { Vmstat_t st;
755*12068SRoger.Faulkner@Oracle.COM char buf[1024], *bufp;
756*12068SRoger.Faulkner@Oracle.COM
757*12068SRoger.Faulkner@Oracle.COM vmstat(vm ? vm : Vmregion, &st);
758*12068SRoger.Faulkner@Oracle.COM bufp = buf;
759*12068SRoger.Faulkner@Oracle.COM bufp = (*_Vmstrcpy)(bufp, "n_busy", '=');
760*12068SRoger.Faulkner@Oracle.COM bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)((Vmulong_t)st.n_busy,-1), ',');
761*12068SRoger.Faulkner@Oracle.COM bufp = (*_Vmstrcpy)(bufp, " s_busy", '=');
762*12068SRoger.Faulkner@Oracle.COM bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(st.s_busy),-1), '\n');
763*12068SRoger.Faulkner@Oracle.COM bufp = (*_Vmstrcpy)(bufp, "n_free", '=');
764*12068SRoger.Faulkner@Oracle.COM bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)((Vmulong_t)st.n_free,-1), ',');
765*12068SRoger.Faulkner@Oracle.COM bufp = (*_Vmstrcpy)(bufp, " s_free", '=');
766*12068SRoger.Faulkner@Oracle.COM bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(st.s_free),-1), '\n');
767*12068SRoger.Faulkner@Oracle.COM bufp = (*_Vmstrcpy)(bufp, "m_busy", '=');
768*12068SRoger.Faulkner@Oracle.COM bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(st.m_busy),-1), ',');
769*12068SRoger.Faulkner@Oracle.COM bufp = (*_Vmstrcpy)(bufp, " m_free", '=');
770*12068SRoger.Faulkner@Oracle.COM bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(st.m_free),-1), '\n');
771*12068SRoger.Faulkner@Oracle.COM bufp = (*_Vmstrcpy)(bufp, "n_segment", '=');
772*12068SRoger.Faulkner@Oracle.COM bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)((Vmulong_t)st.n_seg,-1), ',');
773*12068SRoger.Faulkner@Oracle.COM bufp = (*_Vmstrcpy)(bufp, " extent", '=');
774*12068SRoger.Faulkner@Oracle.COM bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(st.extent),-1), '\n');
775*12068SRoger.Faulkner@Oracle.COM *bufp = 0;
776*12068SRoger.Faulkner@Oracle.COM write(Dbfd, buf, strlen(buf));
777*12068SRoger.Faulkner@Oracle.COM return strlen(buf);
778*12068SRoger.Faulkner@Oracle.COM }
779*12068SRoger.Faulkner@Oracle.COM
7804887Schin static Vmethod_t _Vmdebug =
7814887Schin {
7824887Schin dballoc,
7834887Schin dbresize,
7844887Schin dbfree,
7854887Schin dbaddr,
7864887Schin dbsize,
7874887Schin dbcompact,
7884887Schin dbalign,
7894887Schin VM_MTDEBUG
7904887Schin };
7914887Schin
7924887Schin __DEFINE__(Vmethod_t*,Vmdebug,&_Vmdebug);
7934887Schin
7944887Schin #ifdef NoF
7954887Schin NoF(vmdebug)
7964887Schin #endif
7974887Schin
7984887Schin #endif
799