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