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.25 2000/05/04 01:57:48 grog Exp grog $
37 * $FreeBSD: src/sys/dev/vinum/vinummemory.c,v 1.22.2.1 2000/06/02 04:26:11 grog Exp $
45 extern struct rqinfo rqinfo
[];
46 extern struct rqinfo
*rqip
;
47 int rqinfo_size
= RQINFO_SIZE
; /* for debugger */
49 #define LongJmp longjmp /* just use the kernel function */
52 /* find the base name of a path name */
56 char *f
= rindex(file
, '/'); /* chop off dirname if present */
61 return ++f
; /* skip the / */
65 expand_table(void **table
, int oldsize
, int newsize
)
67 if (newsize
> oldsize
) {
71 temp
= (int *) Malloc(newsize
); /* allocate a new table */
72 CHECKALLOC(temp
, "vinum: Can't expand table\n");
73 bzero((char *) temp
, newsize
); /* clean it all out */
74 if (*table
!= NULL
) { /* already something there, */
75 bcopy((char *) *table
, (char *) temp
, oldsize
); /* copy it to the old table */
83 #ifdef VINUMDEBUG /* XXX debug */
84 #define MALLOCENTRIES 16384
86 int highwater
= 0; /* highest index ever allocated */
87 struct mc malloced
[MALLOCENTRIES
];
90 int freecount
= FREECOUNT
; /* for debugger */
92 struct mc freeinfo
[FREECOUNT
];
95 static int mallocseq
= 0;
98 MMalloc(int size
, char *file
, int line
)
103 if (malloccount
>= MALLOCENTRIES
) { /* too many */
104 log(LOG_ERR
, "vinum: can't allocate table space to trace memory allocation");
105 return 0; /* can't continue */
107 /* Wait for malloc if we can */
108 result
= kmalloc(size
, M_DEVBUF
, mycpu
->gd_intr_nesting_level
== 0 ? M_WAITOK
: M_INTWAIT
);
110 log(LOG_ERR
, "vinum: can't allocate %d bytes from %s:%d\n", size
, file
, line
);
113 for (i
= 0; i
< malloccount
; i
++) {
114 if (((result
+ size
) > malloced
[i
].address
)
115 && (result
< malloced
[i
].address
+ malloced
[i
].size
)) /* overlap */
116 Debugger("Malloc overlap");
119 char *f
= basename(file
);
122 total_malloced
+= size
;
123 microtime(&malloced
[i
].time
);
124 malloced
[i
].seq
= mallocseq
++;
125 malloced
[i
].size
= size
;
126 malloced
[i
].line
= line
;
127 malloced
[i
].address
= result
;
128 bcopy(f
, malloced
[i
].file
, min(strlen(f
), MCFILENAMELEN
- 1));
129 malloced
[i
].file
[MCFILENAMELEN
- 1] = '\0';
131 if (malloccount
> highwater
)
132 highwater
= malloccount
;
139 FFree(void *mem
, char *file
, int line
)
144 for (i
= 0; i
< malloccount
; i
++) {
145 if ((caddr_t
) mem
== malloced
[i
].address
) { /* found it */
146 bzero(mem
, malloced
[i
].size
); /* XXX */
147 kfree(mem
, M_DEVBUF
);
149 total_malloced
-= malloced
[i
].size
;
150 if (debug
& DEBUG_MEMFREE
) { /* keep track of recent frees */
151 char *f
= rindex(file
, '/'); /* chop off dirname if present */
156 f
++; /* skip the / */
158 microtime(&freeinfo
[lastfree
].time
);
159 freeinfo
[lastfree
].seq
= malloced
[i
].seq
;
160 freeinfo
[lastfree
].size
= malloced
[i
].size
;
161 freeinfo
[lastfree
].line
= line
;
162 freeinfo
[lastfree
].address
= mem
;
163 bcopy(f
, freeinfo
[lastfree
].file
, min(strlen(f
), MCFILENAMELEN
- 1));
164 freeinfo
[lastfree
].file
[MCFILENAMELEN
- 1] = '\0';
165 if (++lastfree
== FREECOUNT
)
168 if (i
< malloccount
) /* more coming after */
169 bcopy(&malloced
[i
+ 1], &malloced
[i
], (malloccount
- i
) * sizeof(struct mc
));
175 "Freeing unallocated data at 0x%p from %s, line %d\n",
184 vinum_meminfo(caddr_t data
)
186 struct meminfo
*m
= (struct meminfo
*) data
;
188 m
->mallocs
= malloccount
;
189 m
->total_malloced
= total_malloced
;
190 m
->malloced
= malloced
;
191 m
->highwater
= highwater
;
195 vinum_mallocinfo(caddr_t data
)
197 struct mc
*m
= (struct mc
*) data
;
198 unsigned int ent
= m
->seq
; /* index of entry to return */
200 if (ent
>= malloccount
)
202 m
->address
= malloced
[ent
].address
;
203 m
->size
= malloced
[ent
].size
;
204 m
->line
= malloced
[ent
].line
;
205 m
->seq
= malloced
[ent
].seq
;
206 bcopy(malloced
[ent
].file
, m
->file
, MCFILENAMELEN
);
211 * return the nth request trace buffer entry. This
212 * is indexed back from the current entry (which
216 vinum_rqinfo(caddr_t data
)
218 struct rqinfo
*rq
= (struct rqinfo
*) data
;
219 int ent
= *(int *) data
; /* 1st word is index */
220 int lastent
= rqip
- rqinfo
; /* entry number of current entry */
222 if (ent
>= RQINFO_SIZE
) /* out of the table */
224 if ((ent
= lastent
- ent
- 1) < 0)
225 ent
+= RQINFO_SIZE
; /* roll over backwards */
226 bcopy(&rqinfo
[ent
], rq
, sizeof(struct rqinfo
));