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