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.1.1.1 2003/10/10 03:08:44 grog Exp $
37 * $FreeBSD$
38 */
39
40 #include <dev/vinum/vinumhdr.h>
41
42 #ifdef VINUMDEBUG
43 #include <dev/vinum/request.h>
44 extern struct rqinfo rqinfo[];
45 extern struct rqinfo *rqip;
46 int rqinfo_size = RQINFO_SIZE; /* for debugger */
47
48 #undef longjmp /* this was defined as LongJmp */
49 /* XXX add tests for buf validity */
50 void
51 LongJmp(label_t * buf)
52 {
53 longjmp(buf);
54 }
55
56 #endif /* VINUMDEBUG */
57
58 /* find the base name of a path name */
59 char *
60 basename(char *file)
61 {
62 char *f = strrchr(file, '/'); /* chop off dirname if present */
63
64 if (f == NULL)
65 return file;
66 else
67 return ++f; /* skip the / */
68 }
69
70 void
71 expand_table(void **table, int oldsize, int newsize)
72 {
73 if (newsize > oldsize) {
74 int *temp;
75 int s;
76
77 s = splhigh();
78 temp = (int *) Malloc(newsize); /* allocate a new table */
79 CHECKALLOC(temp, "vinum: Can't expand table\n");
80 bzero((char *) temp, newsize); /* clean it all out */
81 if (*table != NULL) { /* already something there, */
82 bcopy((char *) *table, (char *) temp, oldsize); /* copy it to the old table */
83 Free(*table);
84 }
85 *table = temp;
86 splx(s);
87 }
88 }
89
90 #ifdef VINUMDEBUG /* XXX debug */
91 #define MALLOCENTRIES 16384
92 int malloccount = 0;
93 int highwater = 0; /* highest index ever allocated */
94 struct mc malloced[MALLOCENTRIES];
95
96 #define FREECOUNT 64
97 int freecount = FREECOUNT; /* for debugger */
98 int lastfree = 0;
99 struct mc freeinfo[FREECOUNT];
100
101 int total_malloced;
102 static int mallocseq = 0;
103
104 caddr_t
105 MMalloc(int size, char *file, int line)
106 {
107 int s;
108 caddr_t result;
109 int i;
110
111 if (malloccount >= MALLOCENTRIES) { /* too many */
112 log(LOG_ERR, "vinum: can't allocate table space to trace memory allocation");
113 return 0; /* can't continue */
114 }
115 /* Wait for malloc if we can */
116 /*
117 * XXX We can wait if we're in process context. How do we tell?
118 */
119 result = malloc(size, M_DEVBUF, M_NOWAIT);
120 if (result == NULL)
121 log(LOG_ERR, "vinum: can't allocate %d bytes from %s:%d\n", size, file, line);
122 else {
123 s = splhigh();
124 for (i = 0; i < malloccount; i++) {
125 if (((result + size) > malloced[i].address)
126 && (result < malloced[i].address + malloced[i].size)) /* overlap */
127 panic("Malloc overlap");
128 }
129 if (result) {
130 char *f = basename(file);
131
132 i = malloccount++;
133 total_malloced += size;
134 microtime(&malloced[i].time);
135 malloced[i].seq = mallocseq++;
136 malloced[i].size = size;
137 malloced[i].line = line;
138 malloced[i].address = result;
139 bcopy(f, malloced[i].file, min(strlen(f), MCFILENAMELEN - 1));
140 malloced[i].file[MCFILENAMELEN - 1] = '\0';
141 }
142 if (malloccount > highwater)
143 highwater = malloccount;
144 splx(s);
145 }
146 return result;
147 }
148
149 void
150 FFree(void *mem, char *file, int line)
151 {
152 int s;
153 int i;
154
155 s = splhigh();
156 for (i = 0; i < malloccount; i++) {
157 if ((caddr_t) mem == malloced[i].address) { /* found it */
158 bzero(mem, malloced[i].size); /* XXX */
159 free(mem, M_DEVBUF);
160 malloccount--;
161 total_malloced -= malloced[i].size;
162 if (debug & DEBUG_MEMFREE) { /* keep track of recent frees */
163 char *f = strrchr(file, '/'); /* chop off dirname if present */
164
165 if (f == NULL)
166 f = file;
167 else
168 f++; /* skip the / */
169
170 microtime(&freeinfo[lastfree].time);
171 freeinfo[lastfree].seq = malloced[i].seq;
172 freeinfo[lastfree].size = malloced[i].size;
173 freeinfo[lastfree].line = line;
174 freeinfo[lastfree].address = mem;
175 bcopy(f, freeinfo[lastfree].file, min(strlen(f), MCFILENAMELEN - 1));
176 freeinfo[lastfree].file[MCFILENAMELEN - 1] = '\0';
177 if (++lastfree == FREECOUNT)
178 lastfree = 0;
179 }
180 if (i < malloccount) /* more coming after */
181 bcopy(&malloced[i + 1], &malloced[i], (malloccount - i) * sizeof(struct mc));
182 splx(s);
183 return;
184 }
185 }
186 splx(s);
187 log(LOG_ERR,
188 "Freeing unallocated data at 0x%p from %s, line %d\n",
189 mem,
190 file,
191 line);
192 panic("Free");
193 }
194
195 void
196 vinum_meminfo(caddr_t data)
197 {
198 struct meminfo *m = (struct meminfo *) data;
199
200 m->mallocs = malloccount;
201 m->total_malloced = total_malloced;
202 m->malloced = malloced;
203 m->highwater = highwater;
204 }
205
206 int
207 vinum_mallocinfo(caddr_t data)
208 {
209 struct mc *m = (struct mc *) data;
210 unsigned int ent = m->seq; /* index of entry to return */
211
212 if (ent >= malloccount)
213 return ENOENT;
214 m->address = malloced[ent].address;
215 m->size = malloced[ent].size;
216 m->line = malloced[ent].line;
217 m->seq = malloced[ent].seq;
218 bcopy(malloced[ent].file, m->file, MCFILENAMELEN);
219 return 0;
220 }
221
222 /*
223 * return the nth request trace buffer entry. This
224 * is indexed back from the current entry (which
225 * has index 0)
226 */
227 int
228 vinum_rqinfo(caddr_t data)
229 {
230 struct rqinfo *rq = (struct rqinfo *) data;
231 int ent = *(int *) data; /* 1st word is index */
232 int lastent = rqip - rqinfo; /* entry number of current entry */
233
234 if (ent >= RQINFO_SIZE) /* out of the table */
235 return ENOENT;
236 if ((ent = lastent - ent - 1) < 0)
237 ent += RQINFO_SIZE; /* roll over backwards */
238 bcopy(&rqinfo[ent], rq, sizeof(struct rqinfo));
239 return 0;
240 }
241 #endif
Cache object: 1fad9bdfa70303d1941afc9d691c1994
|