]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/vinum/vinummemory.c
This commit was generated by cvs2svn to compensate for changes in r50276,
[FreeBSD/FreeBSD.git] / sys / dev / vinum / vinummemory.c
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.20 1999/03/19 03:21:08 grog Exp grog $
37  */
38
39 #include <dev/vinum/vinumhdr.h>
40
41 #ifdef VINUMDEBUG
42 #undef longjmp                                              /* this was defined as LongJmp */
43 void longjmp(jmp_buf, int);                                 /* the kernel doesn't define this */
44
45 #include <dev/vinum/request.h>
46 extern struct rqinfo rqinfo[];
47 extern struct rqinfo *rqip;
48
49 #ifdef __i386__                                             /* check for validity */
50 void 
51 LongJmp(jmp_buf buf, int retval)
52 {
53 /*
54    * longjmp is not documented, not even jmp_buf.
55    * This is what's in i386/i386/support.s:
56    * ENTRY(longjmp)
57    *    movl    4(%esp),%eax
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); 
66    *    incl    %eax
67    *    ret
68    *
69    * from which we deduce the structure of jmp_buf:
70  */
71     struct JmpBuf {
72         int jb_ebx;
73         int jb_esp;
74         int jb_ebp;
75         int jb_esi;
76         int jb_edi;
77         int jb_eip;
78     };
79
80     struct JmpBuf *jb = (struct JmpBuf *) buf;
81
82     if ((jb->jb_esp < 0xc0000000)
83         || (jb->jb_ebp < 0xc0000000)
84         || (jb->jb_eip < 0xc0000000))
85         panic("Invalid longjmp");
86     longjmp(buf, retval);
87 }
88
89 /* find the base name of a path name */
90 char *
91 basename(char *file)
92 {
93     char *f = rindex(file, '/');                            /* chop off dirname if present */
94
95     if (f == NULL)
96         return file;
97     else
98         return ++f;                                         /* skip the / */
99 }
100
101 #else
102 #define LongJmp longjmp                                     /* just use the kernel function */
103 #endif
104 #endif
105
106 void 
107 expand_table(void **table, int oldsize, int newsize)
108 {
109     if (newsize > oldsize) {
110         int *temp;
111
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 */
117             Free(*table);
118         }
119         *table = temp;
120     }
121 }
122
123 #if VINUMDEBUG                                              /* XXX debug */
124 #define MALLOCENTRIES 16384
125 int malloccount = 0;
126 int highwater = 0;                                          /* highest index ever allocated */
127 struct mc malloced[MALLOCENTRIES];
128
129 #define FREECOUNT 64
130 int lastfree = 0;
131 struct mc freeinfo[FREECOUNT];
132
133 int total_malloced;
134 static int mallocseq = 0;
135
136 caddr_t 
137 MMalloc(int size, char *file, int line)
138 {
139     caddr_t result;
140     int i;
141     int s;
142
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 */
146     }
147     result = malloc(size, M_DEVBUF, M_WAITOK);
148     if (result == NULL)
149         log(LOG_ERR, "vinum: can't allocate %d bytes from %s:%d\n", size, file, line);
150     else {
151         s = splhigh();
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");
156         }
157         if (result) {
158             char *f = basename(file);
159
160             i = malloccount++;
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));
168         }
169         if (malloccount > highwater)
170             highwater = malloccount;
171         splx(s);
172     }
173     return result;
174 }
175
176 void 
177 FFree(void *mem, char *file, int line)
178 {
179     int i;
180     int s;
181
182     s = splhigh();
183     for (i = 0; i < malloccount; i++) {
184         if ((caddr_t) mem == malloced[i].address) {         /* found it */
185             bzero(mem, malloced[i].size);                   /* XXX */
186             free(mem, M_DEVBUF);
187             malloccount--;
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 */
191
192                 if (f == NULL)
193                     f = file;
194                 else
195                     f++;                                    /* skip the / */
196
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)
204                     lastfree = 0;
205             }
206             if (i < malloccount)                            /* more coming after */
207                 bcopy(&malloced[i + 1], &malloced[i], (malloccount - i) * sizeof(struct mc));
208             splx(s);
209             return;
210         }
211     }
212     splx(s);
213     log(LOG_ERR, "Freeing unallocated data at 0x%08x from %s, line %d\n", (int) mem, file, line);
214     Debugger("Free");
215 }
216
217 void 
218 vinum_meminfo(caddr_t data)
219 {
220     struct meminfo *m = (struct meminfo *) data;
221
222     m->mallocs = malloccount;
223     m->total_malloced = total_malloced;
224     m->malloced = malloced;
225     m->highwater = highwater;
226 }
227
228 int 
229 vinum_mallocinfo(caddr_t data)
230 {
231     struct mc *m = (struct mc *) data;
232     unsigned int ent = m->seq;                              /* index of entry to return */
233
234     if (ent >= malloccount)
235         return ENOENT;
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);
241     return 0;
242 }
243
244 /*
245  * return the nth request trace buffer entry.  This
246  * is indexed back from the current entry (which
247  * has index 0) 
248  */
249 int 
250 vinum_rqinfo(caddr_t data)
251 {
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 */
255
256     if (ent >= RQINFO_SIZE)                                 /* out of the table */
257         return ENOENT;
258     if ((ent = lastent - ent - 1) < 0)
259         ent += RQINFO_SIZE;                                 /* roll over backwards */
260     bcopy(&rqinfo[ent], rq, sizeof(struct rqinfo));
261     return 0;
262 }
263 #endif