Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libast/vmalloc/vmdebug.c
1810 views
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 <[email protected]> *
18
* David Korn <[email protected]> *
19
* Phong Vo <[email protected]> *
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, [email protected], 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
747