2 * Copyright (c) 1997, 1998
3 * Nan Yang Computer Services Limited. All rights reserved.
5 * This software is distributed under the so-called ``Berkeley
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Nan Yang Computer
20 * 4. Neither the name of the Company nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * This software is provided ``as is'', and any express or implied
25 * warranties, including, but not limited to, the implied warranties of
26 * merchantability and fitness for a particular purpose are disclaimed.
27 * In no event shall the company or contributors be liable for any
28 * direct, indirect, incidental, special, exemplary, or consequential
29 * damages (including, but not limited to, procurement of substitute
30 * goods or services; loss of use, data, or profits; or business
31 * interruption) however caused and on any theory of liability, whether
32 * in contract, strict liability, or tort (including negligence or
33 * otherwise) arising in any way out of the use of this software, even if
34 * advised of the possibility of such damage.
36 * $Id: vinummemory.c,v 1.20 1999/03/19 03:21:08 grog Exp grog $
39 #include <dev/vinum/vinumhdr.h>
42 #undef longjmp /* this was defined as LongJmp */
43 void longjmp(jmp_buf, int); /* the kernel doesn't define this */
45 #include <dev/vinum/request.h>
46 extern struct rqinfo rqinfo[];
47 extern struct rqinfo *rqip;
49 #ifdef __i386__ /* check for validity */
51 LongJmp(jmp_buf buf, int retval)
54 * longjmp is not documented, not even jmp_buf.
55 * This is what's in i386/i386/support.s:
58 * movl (%eax),%ebx restore ebx
59 * movl 4(%eax),%esp restore esp
60 * movl 8(%eax),%ebp restore ebp
61 * movl 12(%eax),%esi restore esi
62 * movl 16(%eax),%edi restore edi
63 * movl 20(%eax),%edx get rta
64 * movl %edx,(%esp) put in return frame
65 * xorl %eax,%eax return(1);
69 * from which we deduce the structure of jmp_buf:
80 struct JmpBuf *jb = (struct JmpBuf *) buf;
82 if ((jb->jb_esp < 0xc0000000)
83 || (jb->jb_ebp < 0xc0000000)
84 || (jb->jb_eip < 0xc0000000))
85 panic("Invalid longjmp");
89 /* find the base name of a path name */
93 char *f = rindex(file, '/'); /* chop off dirname if present */
98 return ++f; /* skip the / */
102 #define LongJmp longjmp /* just use the kernel function */
107 expand_table(void **table, int oldsize, int newsize)
109 if (newsize > oldsize) {
112 temp = (int *) Malloc(newsize); /* allocate a new table */
113 CHECKALLOC(temp, "vinum: Can't expand table\n");
114 bzero((char *) temp, newsize); /* clean it all out */
115 if (*table != NULL) { /* already something there, */
116 bcopy((char *) *table, (char *) temp, oldsize); /* copy it to the old table */
123 #if VINUMDEBUG /* XXX debug */
124 #define MALLOCENTRIES 16384
126 int highwater = 0; /* highest index ever allocated */
127 struct mc malloced[MALLOCENTRIES];
131 struct mc freeinfo[FREECOUNT];
134 static int mallocseq = 0;
137 MMalloc(int size, char *file, int line)
143 if (malloccount >= MALLOCENTRIES) { /* too many */
144 log(LOG_ERR, "vinum: can't allocate table space to trace memory allocation");
145 return 0; /* can't continue */
147 result = malloc(size, M_DEVBUF, M_WAITOK);
149 log(LOG_ERR, "vinum: can't allocate %d bytes from %s:%d\n", size, file, line);
152 for (i = 0; i < malloccount; i++) {
153 if (((result + size) > malloced[i].address)
154 && (result < malloced[i].address + malloced[i].size)) /* overlap */
155 Debugger("Malloc overlap");
158 char *f = basename(file);
161 total_malloced += size;
162 microtime(&malloced[i].time);
163 malloced[i].seq = mallocseq++;
164 malloced[i].size = size;
165 malloced[i].line = line;
166 malloced[i].address = result;
167 bcopy(f, malloced[i].file, min(strlen(f) + 1, 16));
169 if (malloccount > highwater)
170 highwater = malloccount;
177 FFree(void *mem, char *file, int line)
183 for (i = 0; i < malloccount; i++) {
184 if ((caddr_t) mem == malloced[i].address) { /* found it */
185 bzero(mem, malloced[i].size); /* XXX */
188 total_malloced -= malloced[i].size;
189 if (debug & DEBUG_MEMFREE) { /* keep track of recent frees */
190 char *f = rindex(file, '/'); /* chop off dirname if present */
195 f++; /* skip the / */
197 microtime(&freeinfo[lastfree].time);
198 freeinfo[lastfree].seq = malloced[i].seq;
199 freeinfo[lastfree].size = malloced[i].size;
200 freeinfo[lastfree].line = line;
201 freeinfo[lastfree].address = mem;
202 bcopy(f, freeinfo[lastfree].file, min(strlen(f) + 1, 16));
203 if (++lastfree == FREECOUNT)
206 if (i < malloccount) /* more coming after */
207 bcopy(&malloced[i + 1], &malloced[i], (malloccount - i) * sizeof(struct mc));
213 log(LOG_ERR, "Freeing unallocated data at 0x%08x from %s, line %d\n", (int) mem, file, line);
218 vinum_meminfo(caddr_t data)
220 struct meminfo *m = (struct meminfo *) data;
222 m->mallocs = malloccount;
223 m->total_malloced = total_malloced;
224 m->malloced = malloced;
225 m->highwater = highwater;
229 vinum_mallocinfo(caddr_t data)
231 struct mc *m = (struct mc *) data;
232 unsigned int ent = m->seq; /* index of entry to return */
234 if (ent >= malloccount)
236 m->address = malloced[ent].address;
237 m->size = malloced[ent].size;
238 m->line = malloced[ent].line;
239 m->seq = malloced[ent].seq;
240 bcopy(malloced[ent].file, m->file, 16);
245 * return the nth request trace buffer entry. This
246 * is indexed back from the current entry (which
250 vinum_rqinfo(caddr_t data)
252 struct rqinfo *rq = (struct rqinfo *) data;
253 int ent = *(int *) data; /* 1st word is index */
254 int lastent = rqip - rqinfo; /* entry number of current entry */
256 if (ent >= RQINFO_SIZE) /* out of the table */
258 if ((ent = lastent - ent - 1) < 0)
259 ent += RQINFO_SIZE; /* roll over backwards */
260 bcopy(&rqinfo[ent], rq, sizeof(struct rqinfo));