14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*8462SApril.Chin@Sun.COM * Copyright (c) 1985-2008 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 7*8462SApril.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 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) ) 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 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 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 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 1804887Schin *bufp++ = '\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 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 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 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; 277*8462SApril.Chin@Sun.COM reg int local, inuse; 2784887Schin 279*8462SApril.Chin@Sun.COM SETINUSE(vd, inuse); 2804887Schin GETLOCAL(vd,local); 2814887Schin if(ISLOCK(vd,local) || !addr) 282*8462SApril.Chin@Sun.COM { CLRINUSE(vd, inuse); 2834887Schin return -1L; 284*8462SApril.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); 325*8462SApril.Chin@Sun.COM CLRINUSE(vd, inuse); 3264887Schin return offset; 3274887Schin } 3284887Schin 3294887Schin 3304887Schin #if __STD_C 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; 342*8462SApril.Chin@Sun.COM reg int inuse; 3434887Schin 344*8462SApril.Chin@Sun.COM SETINUSE(vd, inuse); 3454887Schin if(ISLOCK(vd,0)) 346*8462SApril.Chin@Sun.COM { CLRINUSE(vd, inuse); 3474887Schin return -1L; 348*8462SApril.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); 370*8462SApril.Chin@Sun.COM CLRINUSE(vd, inuse); 3714887Schin return size; 3724887Schin } 3734887Schin 3744887Schin #if __STD_C 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; 388*8462SApril.Chin@Sun.COM reg int inuse; 3894887Schin 390*8462SApril.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); 395*8462SApril.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); 426*8462SApril.Chin@Sun.COM CLRINUSE(vd, inuse); 4274887Schin return (Void_t*)data; 4284887Schin } 4294887Schin 4304887Schin 4314887Schin #if __STD_C 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; 445*8462SApril.Chin@Sun.COM reg int inuse; 4464887Schin 447*8462SApril.Chin@Sun.COM SETINUSE(vd, inuse); 4484887Schin VMFLF(vm,file,line,func); 4494887Schin 4504887Schin if(!data) 451*8462SApril.Chin@Sun.COM { CLRINUSE(vd, inuse); 4524887Schin return 0; 453*8462SApril.Chin@Sun.COM } 4544887Schin 4554887Schin if(ISLOCK(vd,0) ) 4564887Schin { dbwarn(vm,NIL(Vmuchar_t*),0,file,line,func,DB_FREE); 457*8462SApril.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) 4664887Schin { if(vm->disc->exceptf) 4674887Schin (void)(*vm->disc->exceptf)(vm,VM_BADADDR,data,vm->disc); 4684887Schin dbwarn(vm,(Vmuchar_t*)data,offset == -1L ? 0 : 1,file,line,func,DB_FREE); 4694887Schin CLRLOCK(vd,0); 470*8462SApril.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); 491*8462SApril.Chin@Sun.COM CLRINUSE(vd, inuse); 4924887Schin return rv; 4934887Schin } 4944887Schin 4954887Schin /* Resizing an existing block */ 4964887Schin #if __STD_C 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; 513*8462SApril.Chin@Sun.COM reg int inuse; 5144887Schin 515*8462SApril.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); 523*8462SApril.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); 531*8462SApril.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) 5404887Schin { if(vm->disc->exceptf) 5414887Schin (void)(*vm->disc->exceptf)(vm,VM_BADADDR,addr,vm->disc); 5424887Schin dbwarn(vm,(Vmuchar_t*)addr,offset == -1L ? 0 : 1,file,line,func,DB_RESIZE); 5434887Schin CLRLOCK(vd,0); 544*8462SApril.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 } 586*8462SApril.Chin@Sun.COM CLRINUSE(vd, inuse); 5874887Schin return (Void_t*)data; 5884887Schin } 5894887Schin 5904887Schin /* compact any residual free space */ 5914887Schin #if __STD_C 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 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 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 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; 710*8462SApril.Chin@Sun.COM reg int inuse; 7114887Schin 712*8462SApril.Chin@Sun.COM SETINUSE(vd, inuse); 7134887Schin VMFLF(vm,file,line,func); 7144887Schin 7154887Schin if(size <= 0 || align <= 0) 716*8462SApril.Chin@Sun.COM { CLRINUSE(vd, inuse); 7174887Schin return NIL(Void_t*); 718*8462SApril.Chin@Sun.COM } 7194887Schin 7204887Schin if(ISLOCK(vd,0) ) 721*8462SApril.Chin@Sun.COM { CLRINUSE(vd, inuse); 7224887Schin return NIL(Void_t*); 723*8462SApril.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); 743*8462SApril.Chin@Sun.COM CLRINUSE(vd, inuse); 7444887Schin return (Void_t*)data; 7454887Schin } 7464887Schin 7474887Schin static Vmethod_t _Vmdebug = 7484887Schin { 7494887Schin dballoc, 7504887Schin dbresize, 7514887Schin dbfree, 7524887Schin dbaddr, 7534887Schin dbsize, 7544887Schin dbcompact, 7554887Schin dbalign, 7564887Schin VM_MTDEBUG 7574887Schin }; 7584887Schin 7594887Schin __DEFINE__(Vmethod_t*,Vmdebug,&_Vmdebug); 7604887Schin 7614887Schin #ifdef NoF 7624887Schin NoF(vmdebug) 7634887Schin #endif 7644887Schin 7654887Schin #endif 766