1 /*-
2 * Copyright (c) 1997, 1998
3 * Nan Yang Computer Services Limited. All rights reserved.
4 *
5 * This software is distributed under the so-called ``Berkeley
6 * License'':
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
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
19 * Services Limited.
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.
23 *
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.
35 *
36 * $Id: vinummemory.c,v 1.28 2001/05/23 23:04:06 grog Exp grog $
37 * $FreeBSD: releng/5.0/sys/dev/vinum/vinummemory.c 83366 2001-09-12 08:38:13Z julian $
38 */
39
40 #include <dev/vinum/vinumhdr.h>
41
42 #ifdef VINUMDEBUG
43 #undef longjmp /* this was defined as LongJmp */
44
45 #include <dev/vinum/request.h>
46 extern struct rqinfo rqinfo[];
47 extern struct rqinfo *rqip;
48 int rqinfo_size = RQINFO_SIZE; /* for debugger */
49
50 #ifdef __i386__ /* check for validity */
51 void
52 LongJmp(jmp_buf buf, int retval)
53 {
54 /*
55 * longjmp is not documented, not even jmp_buf.
56 * This is what's in i386/i386/support.s:
57 * ENTRY(longjmp)
58 * movl 4(%esp),%eax
59 * movl (%eax),%ebx restore ebx
60 * movl 4(%eax),%esp restore esp
61 * movl 8(%eax),%ebp restore ebp
62 * movl 12(%eax),%esi restore esi
63 * movl 16(%eax),%edi restore edi
64 * movl 20(%eax),%edx get rta
65 * movl %edx,(%esp) put in return frame
66 * xorl %eax,%eax return(1);
67 * incl %eax
68 * ret
69 *
70 * from which we deduce the structure of jmp_buf:
71 */
72 struct JmpBuf {
73 int jb_ebx;
74 int jb_esp;
75 int jb_ebp;
76 int jb_esi;
77 int jb_edi;
78 int jb_eip;
79 };
80
81 struct JmpBuf *jb = (struct JmpBuf *) buf;
82
83 if ((jb->jb_esp < 0xc0000000)
84 || (jb->jb_ebp < 0xc0000000)
85 || (jb->jb_eip < 0xc0000000))
86 panic("Invalid longjmp");
87 longjmp(buf, retval);
88 }
89
90 #else
91 #define LongJmp longjmp /* just use the kernel function */
92 #endif
93 #endif
94
95 /* find the base name of a path name */
96 char *
97 basename(char *file)
98 {
99 char *f = rindex(file, '/'); /* chop off dirname if present */
100
101 if (f == NULL)
102 return file;
103 else
104 return ++f; /* skip the / */
105 }
106
107 void
108 expand_table(void **table, int oldsize, int newsize)
109 {
110 if (newsize > oldsize) {
111 int *temp;
112 int s;
113
114 s = splhigh();
115 temp = (int *) Malloc(newsize); /* allocate a new table */
116 CHECKALLOC(temp, "vinum: Can't expand table\n");
117 bzero((char *) temp, newsize); /* clean it all out */
118 if (*table != NULL) { /* already something there, */
119 bcopy((char *) *table, (char *) temp, oldsize); /* copy it to the old table */
120 Free(*table);
121 }
122 *table = temp;
123 splx(s);
124 }
125 }
126
127 #ifdef VINUMDEBUG /* XXX debug */
128 #define MALLOCENTRIES 16384
129 int malloccount = 0;
130 int highwater = 0; /* highest index ever allocated */
131 struct mc malloced[MALLOCENTRIES];
132
133 #define FREECOUNT 64
134 int freecount = FREECOUNT; /* for debugger */
135 int lastfree = 0;
136 struct mc freeinfo[FREECOUNT];
137
138 int total_malloced;
139 static int mallocseq = 0;
140
141 caddr_t
142 MMalloc(int size, char *file, int line)
143 {
144 int s;
145 caddr_t result;
146 int i;
147
148 if (malloccount >= MALLOCENTRIES) { /* too many */
149 log(LOG_ERR, "vinum: can't allocate table space to trace memory allocation");
150 return 0; /* can't continue */
151 }
152 /* Wait for malloc if we can */
153 result = malloc(size,
154 M_DEVBUF,
155 curthread->td_intr_nesting_level == 0 ? M_WAITOK : M_NOWAIT);
156 if (result == NULL)
157 log(LOG_ERR, "vinum: can't allocate %d bytes from %s:%d\n", size, file, line);
158 else {
159 s = splhigh();
160 for (i = 0; i < malloccount; i++) {
161 if (((result + size) > malloced[i].address)
162 && (result < malloced[i].address + malloced[i].size)) /* overlap */
163 Debugger("Malloc overlap");
164 }
165 if (result) {
166 char *f = basename(file);
167
168 i = malloccount++;
169 total_malloced += size;
170 microtime(&malloced[i].time);
171 malloced[i].seq = mallocseq++;
172 malloced[i].size = size;
173 malloced[i].line = line;
174 malloced[i].address = result;
175 bcopy(f, malloced[i].file, min(strlen(f), MCFILENAMELEN - 1));
176 malloced[i].file[MCFILENAMELEN - 1] = '\0';
177 }
178 if (malloccount > highwater)
179 highwater = malloccount;
180 splx(s);
181 }
182 return result;
183 }
184
185 void
186 FFree(void *mem, char *file, int line)
187 {
188 int s;
189 int i;
190
191 s = splhigh();
192 for (i = 0; i < malloccount; i++) {
193 if ((caddr_t) mem == malloced[i].address) { /* found it */
194 bzero(mem, malloced[i].size); /* XXX */
195 free(mem, M_DEVBUF);
196 malloccount--;
197 total_malloced -= malloced[i].size;
198 if (debug & DEBUG_MEMFREE) { /* keep track of recent frees */
199 char *f = rindex(file, '/'); /* chop off dirname if present */
200
201 if (f == NULL)
202 f = file;
203 else
204 f++; /* skip the / */
205
206 microtime(&freeinfo[lastfree].time);
207 freeinfo[lastfree].seq = malloced[i].seq;
208 freeinfo[lastfree].size = malloced[i].size;
209 freeinfo[lastfree].line = line;
210 freeinfo[lastfree].address = mem;
211 bcopy(f, freeinfo[lastfree].file, min(strlen(f), MCFILENAMELEN - 1));
212 freeinfo[lastfree].file[MCFILENAMELEN - 1] = '\0';
213 if (++lastfree == FREECOUNT)
214 lastfree = 0;
215 }
216 if (i < malloccount) /* more coming after */
217 bcopy(&malloced[i + 1], &malloced[i], (malloccount - i) * sizeof(struct mc));
218 splx(s);
219 return;
220 }
221 }
222 splx(s);
223 log(LOG_ERR,
224 "Freeing unallocated data at 0x%p from %s, line %d\n",
225 mem,
226 file,
227 line);
228 Debugger("Free");
229 }
230
231 void
232 vinum_meminfo(caddr_t data)
233 {
234 struct meminfo *m = (struct meminfo *) data;
235
236 m->mallocs = malloccount;
237 m->total_malloced = total_malloced;
238 m->malloced = malloced;
239 m->highwater = highwater;
240 }
241
242 int
243 vinum_mallocinfo(caddr_t data)
244 {
245 struct mc *m = (struct mc *) data;
246 unsigned int ent = m->seq; /* index of entry to return */
247
248 if (ent >= malloccount)
249 return ENOENT;
250 m->address = malloced[ent].address;
251 m->size = malloced[ent].size;
252 m->line = malloced[ent].line;
253 m->seq = malloced[ent].seq;
254 bcopy(malloced[ent].file, m->file, MCFILENAMELEN);
255 return 0;
256 }
257
258 /*
259 * return the nth request trace buffer entry. This
260 * is indexed back from the current entry (which
261 * has index 0)
262 */
263 int
264 vinum_rqinfo(caddr_t data)
265 {
266 struct rqinfo *rq = (struct rqinfo *) data;
267 int ent = *(int *) data; /* 1st word is index */
268 int lastent = rqip - rqinfo; /* entry number of current entry */
269
270 if (ent >= RQINFO_SIZE) /* out of the table */
271 return ENOENT;
272 if ((ent = lastent - ent - 1) < 0)
273 ent += RQINFO_SIZE; /* roll over backwards */
274 bcopy(&rqinfo[ent], rq, sizeof(struct rqinfo));
275 return 0;
276 }
277 #endif
Cache object: 7b129cada58eb634afcd10818340cdb5
|