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.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 $ 38 */ 39 40 #include "vinumhdr.h" 41 42 #ifdef VINUMDEBUG 43 44 #include "request.h" 45 extern struct rqinfo rqinfo[]; 46 extern struct rqinfo *rqip; 47 int rqinfo_size = RQINFO_SIZE; /* for debugger */ 48 49 #define LongJmp longjmp /* just use the kernel function */ 50 #endif 51 52 /* find the base name of a path name */ 53 char * 54 basename(char *file) 55 { 56 char *f = rindex(file, '/'); /* chop off dirname if present */ 57 58 if (f == NULL) 59 return file; 60 else 61 return ++f; /* skip the / */ 62 } 63 64 void 65 expand_table(void **table, int oldsize, int newsize) 66 { 67 if (newsize > oldsize) { 68 int *temp; 69 70 crit_enter(); 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 */ 76 Free(*table); 77 } 78 *table = temp; 79 crit_exit(); 80 } 81 } 82 83 #ifdef VINUMDEBUG /* XXX debug */ 84 #define MALLOCENTRIES 16384 85 int malloccount = 0; 86 int highwater = 0; /* highest index ever allocated */ 87 struct mc malloced[MALLOCENTRIES]; 88 89 #define FREECOUNT 64 90 int freecount = FREECOUNT; /* for debugger */ 91 int lastfree = 0; 92 struct mc freeinfo[FREECOUNT]; 93 94 int total_malloced; 95 static int mallocseq = 0; 96 97 caddr_t 98 MMalloc(int size, char *file, int line) 99 { 100 caddr_t result; 101 int i; 102 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 */ 106 } 107 /* Wait for malloc if we can */ 108 result = kmalloc(size, M_DEVBUF, mycpu->gd_intr_nesting_level == 0 ? M_WAITOK : M_INTWAIT); 109 if (result == NULL) 110 log(LOG_ERR, "vinum: can't allocate %d bytes from %s:%d\n", size, file, line); 111 else { 112 crit_enter(); 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"); 117 } 118 if (result) { 119 char *f = basename(file); 120 121 i = malloccount++; 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'; 130 } 131 if (malloccount > highwater) 132 highwater = malloccount; 133 crit_exit(); 134 } 135 return result; 136 } 137 138 void 139 FFree(void *mem, char *file, int line) 140 { 141 int i; 142 143 crit_enter(); 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); 148 malloccount--; 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 */ 152 153 if (f == NULL) 154 f = file; 155 else 156 f++; /* skip the / */ 157 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) 166 lastfree = 0; 167 } 168 if (i < malloccount) /* more coming after */ 169 bcopy(&malloced[i + 1], &malloced[i], (malloccount - i) * sizeof(struct mc)); 170 crit_exit(); 171 return; 172 } 173 } 174 log(LOG_ERR, 175 "Freeing unallocated data at 0x%p from %s, line %d\n", 176 mem, 177 file, 178 line); 179 Debugger("Free"); 180 crit_exit(); 181 } 182 183 void 184 vinum_meminfo(caddr_t data) 185 { 186 struct meminfo *m = (struct meminfo *) data; 187 188 m->mallocs = malloccount; 189 m->total_malloced = total_malloced; 190 m->malloced = malloced; 191 m->highwater = highwater; 192 } 193 194 int 195 vinum_mallocinfo(caddr_t data) 196 { 197 struct mc *m = (struct mc *) data; 198 unsigned int ent = m->seq; /* index of entry to return */ 199 200 if (ent >= malloccount) 201 return ENOENT; 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); 207 return 0; 208 } 209 210 /* 211 * return the nth request trace buffer entry. This 212 * is indexed back from the current entry (which 213 * has index 0) 214 */ 215 int 216 vinum_rqinfo(caddr_t data) 217 { 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 */ 221 222 if (ent >= RQINFO_SIZE) /* out of the table */ 223 return ENOENT; 224 if ((ent = lastent - ent - 1) < 0) 225 ent += RQINFO_SIZE; /* roll over backwards */ 226 bcopy(&rqinfo[ent], rq, sizeof(struct rqinfo)); 227 return 0; 228 } 229 #endif 230