1*4887Schin /*********************************************************************** 2*4887Schin * * 3*4887Schin * This software is part of the ast package * 4*4887Schin * Copyright (c) 1985-2007 AT&T Knowledge Ventures * 5*4887Schin * and is licensed under the * 6*4887Schin * Common Public License, Version 1.0 * 7*4887Schin * by AT&T Knowledge Ventures * 8*4887Schin * * 9*4887Schin * A copy of the License is available at * 10*4887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 11*4887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12*4887Schin * * 13*4887Schin * Information and Software Systems Research * 14*4887Schin * AT&T Research * 15*4887Schin * Florham Park NJ * 16*4887Schin * * 17*4887Schin * Glenn Fowler <gsf@research.att.com> * 18*4887Schin * David Korn <dgk@research.att.com> * 19*4887Schin * Phong Vo <kpv@research.att.com> * 20*4887Schin * * 21*4887Schin ***********************************************************************/ 22*4887Schin #if defined(_UWIN) && defined(_BLD_ast) 23*4887Schin 24*4887Schin void _STUB_vmdebug(){} 25*4887Schin 26*4887Schin #else 27*4887Schin 28*4887Schin #include "vmhdr.h" 29*4887Schin 30*4887Schin /* Method to help with debugging. This does rigorous checks on 31*4887Schin ** addresses and arena integrity. 32*4887Schin ** 33*4887Schin ** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94. 34*4887Schin */ 35*4887Schin 36*4887Schin /* structure to keep track of file names */ 37*4887Schin typedef struct _dbfile_s Dbfile_t; 38*4887Schin struct _dbfile_s 39*4887Schin { Dbfile_t* next; 40*4887Schin char file[1]; 41*4887Schin }; 42*4887Schin static Dbfile_t* Dbfile; 43*4887Schin 44*4887Schin /* global watch list */ 45*4887Schin #define S_WATCH 32 46*4887Schin static int Dbnwatch; 47*4887Schin static Void_t* Dbwatch[S_WATCH]; 48*4887Schin 49*4887Schin /* types of warnings reported by dbwarn() */ 50*4887Schin #define DB_CHECK 0 51*4887Schin #define DB_ALLOC 1 52*4887Schin #define DB_FREE 2 53*4887Schin #define DB_RESIZE 3 54*4887Schin #define DB_WATCH 4 55*4887Schin #define DB_RESIZED 5 56*4887Schin 57*4887Schin #define LONGV(x) ((Vmulong_t)(x)) 58*4887Schin 59*4887Schin static int Dbinit = 0; 60*4887Schin #define DBINIT() (Dbinit ? 0 : (dbinit(), Dbinit=1) ) 61*4887Schin static void dbinit() 62*4887Schin { int fd; 63*4887Schin if((fd = vmtrace(-1)) >= 0) 64*4887Schin vmtrace(fd); 65*4887Schin } 66*4887Schin 67*4887Schin static int Dbfd = 2; /* default warning file descriptor */ 68*4887Schin #if __STD_C 69*4887Schin int vmdebug(int fd) 70*4887Schin #else 71*4887Schin int vmdebug(fd) 72*4887Schin int fd; 73*4887Schin #endif 74*4887Schin { 75*4887Schin int old = Dbfd; 76*4887Schin Dbfd = fd; 77*4887Schin return old; 78*4887Schin } 79*4887Schin 80*4887Schin /* just an entry point to make it easy to set break point */ 81*4887Schin #if __STD_C 82*4887Schin static void vmdbwarn(Vmalloc_t* vm, char* mesg, int n) 83*4887Schin #else 84*4887Schin static void vmdbwarn(vm, mesg, n) 85*4887Schin Vmalloc_t* vm; 86*4887Schin char* mesg; 87*4887Schin int n; 88*4887Schin #endif 89*4887Schin { 90*4887Schin reg Vmdata_t* vd = vm->data; 91*4887Schin 92*4887Schin write(Dbfd,mesg,n); 93*4887Schin if(vd->mode&VM_DBABORT) 94*4887Schin abort(); 95*4887Schin } 96*4887Schin 97*4887Schin /* issue a warning of some type */ 98*4887Schin #if __STD_C 99*4887Schin static void dbwarn(Vmalloc_t* vm, Void_t* data, int where, 100*4887Schin const char* file, int line, const Void_t* func, int type) 101*4887Schin #else 102*4887Schin static void dbwarn(vm, data, where, file, line, func, type) 103*4887Schin Vmalloc_t* vm; /* region holding the block */ 104*4887Schin Void_t* data; /* data block */ 105*4887Schin int where; /* byte that was corrupted */ 106*4887Schin const char* file; /* file where call originates */ 107*4887Schin int line; /* line number of call */ 108*4887Schin const Void_t* func; /* function called from */ 109*4887Schin int type; /* operation being done */ 110*4887Schin #endif 111*4887Schin { 112*4887Schin char buf[1024], *bufp, *endbuf, *s; 113*4887Schin #define SLOP 64 /* enough for a message and an int */ 114*4887Schin 115*4887Schin DBINIT(); 116*4887Schin 117*4887Schin bufp = buf; 118*4887Schin endbuf = buf + sizeof(buf); 119*4887Schin 120*4887Schin if(type == DB_ALLOC) 121*4887Schin bufp = (*_Vmstrcpy)(bufp, "alloc error", ':'); 122*4887Schin else if(type == DB_FREE) 123*4887Schin bufp = (*_Vmstrcpy)(bufp, "free error", ':'); 124*4887Schin else if(type == DB_RESIZE) 125*4887Schin bufp = (*_Vmstrcpy)(bufp, "resize error", ':'); 126*4887Schin else if(type == DB_CHECK) 127*4887Schin bufp = (*_Vmstrcpy)(bufp, "corrupted data", ':'); 128*4887Schin else if(type == DB_WATCH) 129*4887Schin bufp = (*_Vmstrcpy)(bufp, "alert", ':'); 130*4887Schin 131*4887Schin /* region info */ 132*4887Schin bufp = (*_Vmstrcpy)(bufp, "region", '='); 133*4887Schin bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(vm), 0), ':'); 134*4887Schin 135*4887Schin if(data) 136*4887Schin { bufp = (*_Vmstrcpy)(bufp,"block",'='); 137*4887Schin bufp = (*_Vmstrcpy)(bufp,(*_Vmitoa)(VLONG(data),0),':'); 138*4887Schin } 139*4887Schin 140*4887Schin if(!data) 141*4887Schin { if(where == DB_ALLOC) 142*4887Schin bufp = (*_Vmstrcpy)(bufp, "can't get memory", ':'); 143*4887Schin else bufp = (*_Vmstrcpy)(bufp, "region is locked", ':'); 144*4887Schin } 145*4887Schin else if(type == DB_FREE || type == DB_RESIZE) 146*4887Schin { if(where == 0) 147*4887Schin bufp = (*_Vmstrcpy)(bufp, "unallocated block", ':'); 148*4887Schin else bufp = (*_Vmstrcpy)(bufp, "already freed", ':'); 149*4887Schin } 150*4887Schin else if(type == DB_WATCH) 151*4887Schin { bufp = (*_Vmstrcpy)(bufp, "size", '='); 152*4887Schin bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(DBSIZE(data),-1), ':'); 153*4887Schin if(where == DB_ALLOC) 154*4887Schin bufp = (*_Vmstrcpy)(bufp,"just allocated", ':'); 155*4887Schin else if(where == DB_FREE) 156*4887Schin bufp = (*_Vmstrcpy)(bufp,"being freed", ':'); 157*4887Schin else if(where == DB_RESIZE) 158*4887Schin bufp = (*_Vmstrcpy)(bufp,"being resized", ':'); 159*4887Schin else if(where == DB_RESIZED) 160*4887Schin bufp = (*_Vmstrcpy)(bufp,"just resized", ':'); 161*4887Schin } 162*4887Schin else if(type == DB_CHECK) 163*4887Schin { bufp = (*_Vmstrcpy)(bufp, "bad byte at", '='); 164*4887Schin bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(LONGV(where),-1), ':'); 165*4887Schin if((s = DBFILE(data)) && (bufp + strlen(s) + SLOP) < endbuf) 166*4887Schin { bufp = (*_Vmstrcpy)(bufp,"allocated at", '='); 167*4887Schin bufp = (*_Vmstrcpy)(bufp, s, ','); 168*4887Schin bufp = (*_Vmstrcpy)(bufp,(*_Vmitoa)(LONGV(DBLINE(data)),-1),':'); 169*4887Schin } 170*4887Schin } 171*4887Schin 172*4887Schin /* location where offending call originates from */ 173*4887Schin if(file && file[0] && line > 0 && (bufp + strlen(file) + SLOP) < endbuf) 174*4887Schin { bufp = (*_Vmstrcpy)(bufp, "detected at", '='); 175*4887Schin bufp = (*_Vmstrcpy)(bufp, file, ','); 176*4887Schin bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(LONGV(line),-1), ','); 177*4887Schin bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(func),-1), ':'); 178*4887Schin } 179*4887Schin 180*4887Schin *bufp++ = '\n'; 181*4887Schin *bufp = '\0'; 182*4887Schin 183*4887Schin vmdbwarn(vm,buf,(bufp-buf)); 184*4887Schin } 185*4887Schin 186*4887Schin /* check for watched address and issue warnings */ 187*4887Schin #if __STD_C 188*4887Schin static void dbwatch(Vmalloc_t* vm, Void_t* data, 189*4887Schin const char* file, int line, const Void_t* func, int type) 190*4887Schin #else 191*4887Schin static void dbwatch(vm, data, file, line, func, type) 192*4887Schin Vmalloc_t* vm; 193*4887Schin Void_t* data; 194*4887Schin const char* file; 195*4887Schin int line; 196*4887Schin const Void_t* func; 197*4887Schin int type; 198*4887Schin #endif 199*4887Schin { 200*4887Schin reg int n; 201*4887Schin 202*4887Schin for(n = Dbnwatch; n >= 0; --n) 203*4887Schin { if(Dbwatch[n] == data) 204*4887Schin { dbwarn(vm,data,type,file,line,func,DB_WATCH); 205*4887Schin return; 206*4887Schin } 207*4887Schin } 208*4887Schin } 209*4887Schin 210*4887Schin /* record information about the block */ 211*4887Schin #if __STD_C 212*4887Schin static void dbsetinfo(Vmuchar_t* data, size_t size, const char* file, int line) 213*4887Schin #else 214*4887Schin static void dbsetinfo(data, size, file, line) 215*4887Schin Vmuchar_t* data; /* real address not the one from Vmbest */ 216*4887Schin size_t size; /* the actual requested size */ 217*4887Schin const char* file; /* file where the request came from */ 218*4887Schin int line; /* and line number */ 219*4887Schin #endif 220*4887Schin { 221*4887Schin reg Vmuchar_t *begp, *endp; 222*4887Schin reg Dbfile_t *last, *db; 223*4887Schin 224*4887Schin DBINIT(); 225*4887Schin 226*4887Schin /* find the file structure */ 227*4887Schin if(!file || !file[0]) 228*4887Schin db = NIL(Dbfile_t*); 229*4887Schin else 230*4887Schin { for(last = NIL(Dbfile_t*), db = Dbfile; db; last = db, db = db->next) 231*4887Schin if(strcmp(db->file,file) == 0) 232*4887Schin break; 233*4887Schin if(!db) 234*4887Schin { db = (Dbfile_t*)vmalloc(Vmheap,sizeof(Dbfile_t)+strlen(file)); 235*4887Schin if(db) 236*4887Schin { (*_Vmstrcpy)(db->file,file,0); 237*4887Schin db->next = Dbfile; 238*4887Schin Dbfile = db->next; 239*4887Schin } 240*4887Schin } 241*4887Schin else if(last) /* move-to-front heuristic */ 242*4887Schin { last->next = db->next; 243*4887Schin db->next = Dbfile; 244*4887Schin Dbfile = db->next; 245*4887Schin } 246*4887Schin } 247*4887Schin 248*4887Schin DBSETFL(data,(db ? db->file : NIL(char*)),line); 249*4887Schin DBSIZE(data) = size; 250*4887Schin DBSEG(data) = SEG(DBBLOCK(data)); 251*4887Schin 252*4887Schin DBHEAD(data,begp,endp); 253*4887Schin while(begp < endp) 254*4887Schin *begp++ = DB_MAGIC; 255*4887Schin DBTAIL(data,begp,endp); 256*4887Schin while(begp < endp) 257*4887Schin *begp++ = DB_MAGIC; 258*4887Schin } 259*4887Schin 260*4887Schin /* Check to see if an address is in some data block of a region. 261*4887Schin ** This returns -(offset+1) if block is already freed, +(offset+1) 262*4887Schin ** if block is live, 0 if no match. 263*4887Schin */ 264*4887Schin #if __STD_C 265*4887Schin static long dbaddr(Vmalloc_t* vm, Void_t* addr) 266*4887Schin #else 267*4887Schin static long dbaddr(vm, addr) 268*4887Schin Vmalloc_t* vm; 269*4887Schin Void_t* addr; 270*4887Schin #endif 271*4887Schin { 272*4887Schin reg Block_t *b, *endb; 273*4887Schin reg Seg_t* seg; 274*4887Schin reg Vmuchar_t* data; 275*4887Schin reg long offset = -1L; 276*4887Schin reg Vmdata_t* vd = vm->data; 277*4887Schin reg int local; 278*4887Schin 279*4887Schin GETLOCAL(vd,local); 280*4887Schin if(ISLOCK(vd,local) || !addr) 281*4887Schin return -1L; 282*4887Schin SETLOCK(vd,local); 283*4887Schin 284*4887Schin b = endb = NIL(Block_t*); 285*4887Schin for(seg = vd->seg; seg; seg = seg->next) 286*4887Schin { b = SEGBLOCK(seg); 287*4887Schin endb = (Block_t*)(seg->baddr - sizeof(Head_t)); 288*4887Schin if((Vmuchar_t*)addr > (Vmuchar_t*)b && 289*4887Schin (Vmuchar_t*)addr < (Vmuchar_t*)endb) 290*4887Schin break; 291*4887Schin } 292*4887Schin if(!seg) 293*4887Schin goto done; 294*4887Schin 295*4887Schin if(local) /* must be vmfree or vmresize checking address */ 296*4887Schin { if(DBSEG(addr) == seg) 297*4887Schin { b = DBBLOCK(addr); 298*4887Schin if(ISBUSY(SIZE(b)) && !ISJUNK(SIZE(b)) ) 299*4887Schin offset = 0; 300*4887Schin else offset = -2L; 301*4887Schin } 302*4887Schin goto done; 303*4887Schin } 304*4887Schin 305*4887Schin while(b < endb) 306*4887Schin { data = (Vmuchar_t*)DATA(b); 307*4887Schin if((Vmuchar_t*)addr >= data && (Vmuchar_t*)addr < data+SIZE(b)) 308*4887Schin { if(ISBUSY(SIZE(b)) && !ISJUNK(SIZE(b)) ) 309*4887Schin { data = DB2DEBUG(data); 310*4887Schin if((Vmuchar_t*)addr >= data && 311*4887Schin (Vmuchar_t*)addr < data+DBSIZE(data)) 312*4887Schin offset = (Vmuchar_t*)addr - data; 313*4887Schin } 314*4887Schin goto done; 315*4887Schin } 316*4887Schin 317*4887Schin b = (Block_t*)((Vmuchar_t*)DATA(b) + (SIZE(b)&~BITS) ); 318*4887Schin } 319*4887Schin 320*4887Schin done: 321*4887Schin CLRLOCK(vd,local); 322*4887Schin return offset; 323*4887Schin } 324*4887Schin 325*4887Schin 326*4887Schin #if __STD_C 327*4887Schin static long dbsize(Vmalloc_t* vm, Void_t* addr) 328*4887Schin #else 329*4887Schin static long dbsize(vm, addr) 330*4887Schin Vmalloc_t* vm; 331*4887Schin Void_t* addr; 332*4887Schin #endif 333*4887Schin { 334*4887Schin reg Block_t *b, *endb; 335*4887Schin reg Seg_t* seg; 336*4887Schin reg long size; 337*4887Schin reg Vmdata_t* vd = vm->data; 338*4887Schin 339*4887Schin if(ISLOCK(vd,0)) 340*4887Schin return -1L; 341*4887Schin SETLOCK(vd,0); 342*4887Schin 343*4887Schin size = -1L; 344*4887Schin for(seg = vd->seg; seg; seg = seg->next) 345*4887Schin { b = SEGBLOCK(seg); 346*4887Schin endb = (Block_t*)(seg->baddr - sizeof(Head_t)); 347*4887Schin if((Vmuchar_t*)addr <= (Vmuchar_t*)b || 348*4887Schin (Vmuchar_t*)addr >= (Vmuchar_t*)endb) 349*4887Schin continue; 350*4887Schin while(b < endb) 351*4887Schin { if(addr == (Void_t*)DB2DEBUG(DATA(b))) 352*4887Schin { if(ISBUSY(SIZE(b)) && !ISJUNK(SIZE(b)) ) 353*4887Schin size = (long)DBSIZE(addr); 354*4887Schin goto done; 355*4887Schin } 356*4887Schin 357*4887Schin b = (Block_t*)((Vmuchar_t*)DATA(b) + (SIZE(b)&~BITS) ); 358*4887Schin } 359*4887Schin } 360*4887Schin done: 361*4887Schin CLRLOCK(vd,0); 362*4887Schin return size; 363*4887Schin } 364*4887Schin 365*4887Schin #if __STD_C 366*4887Schin static Void_t* dballoc(Vmalloc_t* vm, size_t size) 367*4887Schin #else 368*4887Schin static Void_t* dballoc(vm, size) 369*4887Schin Vmalloc_t* vm; 370*4887Schin size_t size; 371*4887Schin #endif 372*4887Schin { 373*4887Schin reg size_t s; 374*4887Schin reg Vmuchar_t* data; 375*4887Schin reg char* file; 376*4887Schin reg int line; 377*4887Schin reg Void_t* func; 378*4887Schin reg Vmdata_t* vd = vm->data; 379*4887Schin 380*4887Schin VMFLF(vm,file,line,func); 381*4887Schin 382*4887Schin if(ISLOCK(vd,0) ) 383*4887Schin { dbwarn(vm,NIL(Vmuchar_t*),0,file,line,func,DB_ALLOC); 384*4887Schin return NIL(Void_t*); 385*4887Schin } 386*4887Schin SETLOCK(vd,0); 387*4887Schin 388*4887Schin if(vd->mode&VM_DBCHECK) 389*4887Schin vmdbcheck(vm); 390*4887Schin 391*4887Schin s = ROUND(size,ALIGN) + DB_EXTRA; 392*4887Schin if(s < sizeof(Body_t)) /* no tiny blocks during Vmdebug */ 393*4887Schin s = sizeof(Body_t); 394*4887Schin 395*4887Schin if(!(data = (Vmuchar_t*)KPVALLOC(vm,s,(*(Vmbest->allocf))) ) ) 396*4887Schin { dbwarn(vm,NIL(Vmuchar_t*),DB_ALLOC,file,line,func,DB_ALLOC); 397*4887Schin goto done; 398*4887Schin } 399*4887Schin 400*4887Schin data = DB2DEBUG(data); 401*4887Schin dbsetinfo(data,size,file,line); 402*4887Schin 403*4887Schin if((vd->mode&VM_TRACE) && _Vmtrace) 404*4887Schin { vm->file = file; vm->line = line; vm->func = func; 405*4887Schin (*_Vmtrace)(vm,NIL(Vmuchar_t*),data,size,0); 406*4887Schin } 407*4887Schin 408*4887Schin if(Dbnwatch > 0 ) 409*4887Schin dbwatch(vm,data,file,line,func,DB_ALLOC); 410*4887Schin 411*4887Schin done: 412*4887Schin CLRLOCK(vd,0); 413*4887Schin ANNOUNCE(0, vm, VM_ALLOC, (Void_t*)data, vm->disc); 414*4887Schin return (Void_t*)data; 415*4887Schin } 416*4887Schin 417*4887Schin 418*4887Schin #if __STD_C 419*4887Schin static int dbfree(Vmalloc_t* vm, Void_t* data ) 420*4887Schin #else 421*4887Schin static int dbfree(vm, data ) 422*4887Schin Vmalloc_t* vm; 423*4887Schin Void_t* data; 424*4887Schin #endif 425*4887Schin { 426*4887Schin char* file; 427*4887Schin int line; 428*4887Schin Void_t* func; 429*4887Schin reg long offset; 430*4887Schin reg int rv, *ip, *endip; 431*4887Schin reg Vmdata_t* vd = vm->data; 432*4887Schin 433*4887Schin VMFLF(vm,file,line,func); 434*4887Schin 435*4887Schin if(!data) 436*4887Schin return 0; 437*4887Schin 438*4887Schin if(ISLOCK(vd,0) ) 439*4887Schin { dbwarn(vm,NIL(Vmuchar_t*),0,file,line,func,DB_FREE); 440*4887Schin return -1; 441*4887Schin } 442*4887Schin SETLOCK(vd,0); 443*4887Schin 444*4887Schin if(vd->mode&VM_DBCHECK) 445*4887Schin vmdbcheck(vm); 446*4887Schin 447*4887Schin if((offset = KPVADDR(vm,data,dbaddr)) != 0) 448*4887Schin { if(vm->disc->exceptf) 449*4887Schin (void)(*vm->disc->exceptf)(vm,VM_BADADDR,data,vm->disc); 450*4887Schin dbwarn(vm,(Vmuchar_t*)data,offset == -1L ? 0 : 1,file,line,func,DB_FREE); 451*4887Schin CLRLOCK(vd,0); 452*4887Schin return -1; 453*4887Schin } 454*4887Schin 455*4887Schin if(Dbnwatch > 0) 456*4887Schin dbwatch(vm,data,file,line,func,DB_FREE); 457*4887Schin 458*4887Schin if((vd->mode&VM_TRACE) && _Vmtrace) 459*4887Schin { vm->file = file; vm->line = line; vm->func = func; 460*4887Schin (*_Vmtrace)(vm,(Vmuchar_t*)data,NIL(Vmuchar_t*),DBSIZE(data),0); 461*4887Schin } 462*4887Schin 463*4887Schin /* clear free space */ 464*4887Schin ip = (int*)data; 465*4887Schin endip = ip + (DBSIZE(data)+sizeof(int)-1)/sizeof(int); 466*4887Schin while(ip < endip) 467*4887Schin *ip++ = 0; 468*4887Schin 469*4887Schin rv = KPVFREE((vm), (Void_t*)DB2BEST(data), (*Vmbest->freef)); 470*4887Schin CLRLOCK(vd,0); 471*4887Schin ANNOUNCE(0, vm, VM_FREE, data, vm->disc); 472*4887Schin return rv; 473*4887Schin } 474*4887Schin 475*4887Schin /* Resizing an existing block */ 476*4887Schin #if __STD_C 477*4887Schin static Void_t* dbresize(Vmalloc_t* vm, Void_t* addr, reg size_t size, int type) 478*4887Schin #else 479*4887Schin static Void_t* dbresize(vm,addr,size,type) 480*4887Schin Vmalloc_t* vm; /* region allocating from */ 481*4887Schin Void_t* addr; /* old block of data */ 482*4887Schin reg size_t size; /* new size */ 483*4887Schin int type; /* !=0 for movable, >0 for copy */ 484*4887Schin #endif 485*4887Schin { 486*4887Schin reg Vmuchar_t* data; 487*4887Schin reg size_t s, oldsize; 488*4887Schin reg long offset; 489*4887Schin char *file, *oldfile; 490*4887Schin int line, oldline; 491*4887Schin Void_t* func; 492*4887Schin reg Vmdata_t* vd = vm->data; 493*4887Schin 494*4887Schin if(!addr) 495*4887Schin { oldsize = 0; 496*4887Schin data = (Vmuchar_t*)dballoc(vm,size); 497*4887Schin goto done; 498*4887Schin } 499*4887Schin if(size == 0) 500*4887Schin { (void)dbfree(vm,addr); 501*4887Schin return NIL(Void_t*); 502*4887Schin } 503*4887Schin 504*4887Schin VMFLF(vm,file,line,func); 505*4887Schin 506*4887Schin if(ISLOCK(vd,0) ) 507*4887Schin { dbwarn(vm,NIL(Vmuchar_t*),0,file,line,func,DB_RESIZE); 508*4887Schin return NIL(Void_t*); 509*4887Schin } 510*4887Schin SETLOCK(vd,0); 511*4887Schin 512*4887Schin if(vd->mode&VM_DBCHECK) 513*4887Schin vmdbcheck(vm); 514*4887Schin 515*4887Schin if((offset = KPVADDR(vm,addr,dbaddr)) != 0) 516*4887Schin { if(vm->disc->exceptf) 517*4887Schin (void)(*vm->disc->exceptf)(vm,VM_BADADDR,addr,vm->disc); 518*4887Schin dbwarn(vm,(Vmuchar_t*)addr,offset == -1L ? 0 : 1,file,line,func,DB_RESIZE); 519*4887Schin CLRLOCK(vd,0); 520*4887Schin return NIL(Void_t*); 521*4887Schin } 522*4887Schin 523*4887Schin if(Dbnwatch > 0) 524*4887Schin dbwatch(vm,addr,file,line,func,DB_RESIZE); 525*4887Schin 526*4887Schin /* Vmbest data block */ 527*4887Schin data = DB2BEST(addr); 528*4887Schin oldsize = DBSIZE(addr); 529*4887Schin oldfile = DBFILE(addr); 530*4887Schin oldline = DBLINE(addr); 531*4887Schin 532*4887Schin /* do the resize */ 533*4887Schin s = ROUND(size,ALIGN) + DB_EXTRA; 534*4887Schin if(s < sizeof(Body_t)) 535*4887Schin s = sizeof(Body_t); 536*4887Schin data = (Vmuchar_t*)KPVRESIZE(vm,(Void_t*)data,s, 537*4887Schin (type&~VM_RSZERO),(*(Vmbest->resizef)) ); 538*4887Schin if(!data) /* failed, reset data for old block */ 539*4887Schin { dbwarn(vm,NIL(Vmuchar_t*),DB_ALLOC,file,line,func,DB_RESIZE); 540*4887Schin dbsetinfo((Vmuchar_t*)addr,oldsize,oldfile,oldline); 541*4887Schin } 542*4887Schin else 543*4887Schin { data = DB2DEBUG(data); 544*4887Schin dbsetinfo(data,size,file,line); 545*4887Schin 546*4887Schin if((vd->mode&VM_TRACE) && _Vmtrace) 547*4887Schin { vm->file = file; vm->line = line; 548*4887Schin (*_Vmtrace)(vm,(Vmuchar_t*)addr,data,size,0); 549*4887Schin } 550*4887Schin if(Dbnwatch > 0) 551*4887Schin dbwatch(vm,data,file,line,func,DB_RESIZED); 552*4887Schin } 553*4887Schin 554*4887Schin CLRLOCK(vd,0); 555*4887Schin ANNOUNCE(0, vm, VM_RESIZE, (Void_t*)data, vm->disc); 556*4887Schin 557*4887Schin done: if(data && (type&VM_RSZERO) && size > oldsize) 558*4887Schin { reg Vmuchar_t *d = data+oldsize, *ed = data+size; 559*4887Schin do { *d++ = 0; } while(d < ed); 560*4887Schin } 561*4887Schin return (Void_t*)data; 562*4887Schin } 563*4887Schin 564*4887Schin /* compact any residual free space */ 565*4887Schin #if __STD_C 566*4887Schin static int dbcompact(Vmalloc_t* vm) 567*4887Schin #else 568*4887Schin static int dbcompact(vm) 569*4887Schin Vmalloc_t* vm; 570*4887Schin #endif 571*4887Schin { 572*4887Schin return (*(Vmbest->compactf))(vm); 573*4887Schin } 574*4887Schin 575*4887Schin /* check for memory overwrites over all live blocks */ 576*4887Schin #if __STD_C 577*4887Schin int vmdbcheck(Vmalloc_t* vm) 578*4887Schin #else 579*4887Schin int vmdbcheck(vm) 580*4887Schin Vmalloc_t* vm; 581*4887Schin #endif 582*4887Schin { 583*4887Schin reg Block_t *b, *endb; 584*4887Schin reg Seg_t* seg; 585*4887Schin int rv; 586*4887Schin reg Vmdata_t* vd = vm->data; 587*4887Schin 588*4887Schin /* check the meta-data of this region */ 589*4887Schin if(vd->mode & (VM_MTDEBUG|VM_MTBEST|VM_MTPROFILE)) 590*4887Schin { if(_vmbestcheck(vd, NIL(Block_t*)) < 0) 591*4887Schin return -1; 592*4887Schin if(!(vd->mode&VM_MTDEBUG)) 593*4887Schin return 0; 594*4887Schin } 595*4887Schin else return -1; 596*4887Schin 597*4887Schin rv = 0; 598*4887Schin for(seg = vd->seg; seg; seg = seg->next) 599*4887Schin { b = SEGBLOCK(seg); 600*4887Schin endb = (Block_t*)(seg->baddr - sizeof(Head_t)); 601*4887Schin while(b < endb) 602*4887Schin { reg Vmuchar_t *data, *begp, *endp; 603*4887Schin 604*4887Schin if(ISJUNK(SIZE(b)) || !ISBUSY(SIZE(b))) 605*4887Schin goto next; 606*4887Schin 607*4887Schin data = DB2DEBUG(DATA(b)); 608*4887Schin if(DBISBAD(data)) /* seen this before */ 609*4887Schin { rv += 1; 610*4887Schin goto next; 611*4887Schin } 612*4887Schin 613*4887Schin DBHEAD(data,begp,endp); 614*4887Schin for(; begp < endp; ++begp) 615*4887Schin if(*begp != DB_MAGIC) 616*4887Schin goto set_bad; 617*4887Schin 618*4887Schin DBTAIL(data,begp,endp); 619*4887Schin for(; begp < endp; ++begp) 620*4887Schin { if(*begp == DB_MAGIC) 621*4887Schin continue; 622*4887Schin set_bad: 623*4887Schin dbwarn(vm,data,begp-data,NIL(char*),0,0,DB_CHECK); 624*4887Schin DBSETBAD(data); 625*4887Schin rv += 1; 626*4887Schin goto next; 627*4887Schin } 628*4887Schin 629*4887Schin next: b = (Block_t*)((Vmuchar_t*)DATA(b) + (SIZE(b)&~BITS)); 630*4887Schin } 631*4887Schin } 632*4887Schin 633*4887Schin return rv; 634*4887Schin } 635*4887Schin 636*4887Schin /* set/delete an address to watch */ 637*4887Schin #if __STD_C 638*4887Schin Void_t* vmdbwatch(Void_t* addr) 639*4887Schin #else 640*4887Schin Void_t* vmdbwatch(addr) 641*4887Schin Void_t* addr; /* address to insert */ 642*4887Schin #endif 643*4887Schin { 644*4887Schin reg int n; 645*4887Schin reg Void_t* out; 646*4887Schin 647*4887Schin out = NIL(Void_t*); 648*4887Schin if(!addr) 649*4887Schin Dbnwatch = 0; 650*4887Schin else 651*4887Schin { for(n = Dbnwatch - 1; n >= 0; --n) 652*4887Schin if(Dbwatch[n] == addr) 653*4887Schin break; 654*4887Schin if(n < 0) /* insert */ 655*4887Schin { if(Dbnwatch == S_WATCH) 656*4887Schin { /* delete left-most */ 657*4887Schin out = Dbwatch[0]; 658*4887Schin Dbnwatch -= 1; 659*4887Schin for(n = 0; n < Dbnwatch; ++n) 660*4887Schin Dbwatch[n] = Dbwatch[n+1]; 661*4887Schin } 662*4887Schin Dbwatch[Dbnwatch] = addr; 663*4887Schin Dbnwatch += 1; 664*4887Schin } 665*4887Schin } 666*4887Schin return out; 667*4887Schin } 668*4887Schin 669*4887Schin #if __STD_C 670*4887Schin static Void_t* dbalign(Vmalloc_t* vm, size_t size, size_t align) 671*4887Schin #else 672*4887Schin static Void_t* dbalign(vm, size, align) 673*4887Schin Vmalloc_t* vm; 674*4887Schin size_t size; 675*4887Schin size_t align; 676*4887Schin #endif 677*4887Schin { 678*4887Schin reg Vmuchar_t* data; 679*4887Schin reg size_t s; 680*4887Schin reg char* file; 681*4887Schin reg int line; 682*4887Schin reg Void_t* func; 683*4887Schin reg Vmdata_t* vd = vm->data; 684*4887Schin 685*4887Schin VMFLF(vm,file,line,func); 686*4887Schin 687*4887Schin if(size <= 0 || align <= 0) 688*4887Schin return NIL(Void_t*); 689*4887Schin 690*4887Schin if(ISLOCK(vd,0) ) 691*4887Schin return NIL(Void_t*); 692*4887Schin SETLOCK(vd,0); 693*4887Schin 694*4887Schin if((s = ROUND(size,ALIGN) + DB_EXTRA) < sizeof(Body_t)) 695*4887Schin s = sizeof(Body_t); 696*4887Schin 697*4887Schin if(!(data = (Vmuchar_t*)KPVALIGN(vm,s,align,(*(Vmbest->alignf)))) ) 698*4887Schin goto done; 699*4887Schin 700*4887Schin data += DB_HEAD; 701*4887Schin dbsetinfo(data,size,file,line); 702*4887Schin 703*4887Schin if((vd->mode&VM_TRACE) && _Vmtrace) 704*4887Schin { vm->file = file; vm->line = line; vm->func = func; 705*4887Schin (*_Vmtrace)(vm,NIL(Vmuchar_t*),data,size,align); 706*4887Schin } 707*4887Schin 708*4887Schin done: 709*4887Schin CLRLOCK(vd,0); 710*4887Schin ANNOUNCE(0, vm, VM_ALLOC, (Void_t*)data, vm->disc); 711*4887Schin return (Void_t*)data; 712*4887Schin } 713*4887Schin 714*4887Schin static Vmethod_t _Vmdebug = 715*4887Schin { 716*4887Schin dballoc, 717*4887Schin dbresize, 718*4887Schin dbfree, 719*4887Schin dbaddr, 720*4887Schin dbsize, 721*4887Schin dbcompact, 722*4887Schin dbalign, 723*4887Schin VM_MTDEBUG 724*4887Schin }; 725*4887Schin 726*4887Schin __DEFINE__(Vmethod_t*,Vmdebug,&_Vmdebug); 727*4887Schin 728*4887Schin #ifdef NoF 729*4887Schin NoF(vmdebug) 730*4887Schin #endif 731*4887Schin 732*4887Schin #endif 733