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