diff options
Diffstat (limited to 'sys/dev/vinum/vinummemory.c')
-rw-r--r-- | sys/dev/vinum/vinummemory.c | 290 |
1 files changed, 290 insertions, 0 deletions
diff --git a/sys/dev/vinum/vinummemory.c b/sys/dev/vinum/vinummemory.c new file mode 100644 index 0000000..62c573d --- /dev/null +++ b/sys/dev/vinum/vinummemory.c @@ -0,0 +1,290 @@ +/*- + * Copyright (c) 1997, 1998 + * Nan Yang Computer Services Limited. All rights reserved. + * + * This software is distributed under the so-called ``Berkeley + * License'': + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Nan Yang Computer + * Services Limited. + * 4. Neither the name of the Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided ``as is'', and any express or implied + * warranties, including, but not limited to, the implied warranties of + * merchantability and fitness for a particular purpose are disclaimed. + * In no event shall the company or contributors be liable for any + * direct, indirect, incidental, special, exemplary, or consequential + * damages (including, but not limited to, procurement of substitute + * goods or services; loss of use, data, or profits; or business + * interruption) however caused and on any theory of liability, whether + * in contract, strict liability, or tort (including negligence or + * otherwise) arising in any way out of the use of this software, even if + * advised of the possibility of such damage. + * + * $Id: vinummemory.c,v 1.31 2003/05/23 01:08:36 grog Exp $ + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <dev/vinum/vinumhdr.h> + +#ifdef VINUMDEBUG +#include <dev/vinum/request.h> +extern struct rqinfo rqinfo[]; +extern struct rqinfo *rqip; +int rqinfo_size = RQINFO_SIZE; /* for debugger */ + +#undef longjmp /* this was defined as LongJmp */ +#define strrchr rindex +#ifdef __i386__ /* check for validity */ +void +LongJmp(jmp_buf buf, int retval) +{ +/* + * longjmp is not documented, not even jmp_buf. + * This is what's in i386/i386/support.s: + * ENTRY(longjmp) + * movl 4(%esp),%eax + * movl (%eax),%ebx restore ebx + * movl 4(%eax),%esp restore esp + * movl 8(%eax),%ebp restore ebp + * movl 12(%eax),%esi restore esi + * movl 16(%eax),%edi restore edi + * movl 20(%eax),%edx get rta + * movl %edx,(%esp) put in return frame + * xorl %eax,%eax return(1); + * incl %eax + * ret + * + * from which we deduce the structure of jmp_buf: + */ + struct JmpBuf { + int jb_ebx; + int jb_esp; + int jb_ebp; + int jb_esi; + int jb_edi; + int jb_eip; + }; + + struct JmpBuf *jb = (struct JmpBuf *) buf; + + if ((jb->jb_esp < 0xc0000000) + || (jb->jb_ebp < 0xc0000000) + || (jb->jb_eip < 0xc0000000)) + panic("Invalid longjmp"); + longjmp(buf, retval); +} + +#else /* not i386 */ +#define LongJmp longjmp /* just use the kernel function */ +#endif /* i386 */ +#endif /* VINUMDEBUG */ + +/* find the base name of a path name */ +char * +basename(char *file) +{ + char *f = strrchr(file, '/'); /* chop off dirname if present */ + + if (f == NULL) + return file; + else + return ++f; /* skip the / */ +} + +#ifdef VINUMDEBUG +void +expand_table(void **table, int oldsize, int newsize, char *file, int line) +#else +void +expand_table(void **table, int oldsize, int newsize) +#endif +{ + if (newsize > oldsize) { + int *temp; + int s; + + s = splhigh(); +#ifdef VINUMDEBUG + temp = (int *) MMalloc(newsize, file, line); /* allocate a new table */ +#else + temp = (int *) Malloc(newsize); /* allocate a new table */ +#endif + CHECKALLOC(temp, "vinum: Can't expand table\n"); + bzero((char *) temp, newsize); /* clean it all out */ + if (*table != NULL) { /* already something there, */ + bcopy((char *) *table, (char *) temp, oldsize); /* copy it to the old table */ +#ifdef VINUMDEBUG + FFree(*table, file, line); +#else + Free(*table); +#endif + } + *table = temp; + splx(s); + } +} + +#ifdef VINUMDEBUG +#define MALLOCENTRIES 16384 +int malloccount = 0; +int highwater = 0; /* highest index ever allocated */ +struct mc malloced[MALLOCENTRIES]; + +#define FREECOUNT 64 +int freecount = FREECOUNT; /* for debugger */ +int lastfree = 0; +struct mc freeinfo[FREECOUNT]; + +int total_malloced; +static int mallocseq = 0; + +caddr_t +MMalloc(int size, char *file, int line) +{ + int s; + caddr_t result; + int i; + + if (malloccount >= MALLOCENTRIES) { /* too many */ + log(LOG_ERR, "vinum: can't allocate table space to trace memory allocation"); + return 0; /* can't continue */ + } + /* Wait for malloc if we can */ + result = malloc(size, + M_DEVBUF, + curthread->td_intr_nesting_level == 0 ? M_WAITOK : M_NOWAIT); + if (result == NULL) + log(LOG_ERR, "vinum: can't allocate %d bytes from %s:%d\n", size, file, line); + else { + s = splhigh(); + for (i = 0; i < malloccount; i++) { + if (((result + size) > malloced[i].address) + && (result < malloced[i].address + malloced[i].size)) /* overlap */ + Debugger("Malloc overlap"); + } + if (result) { + char *f = basename(file); + + i = malloccount++; + total_malloced += size; + microtime(&malloced[i].time); + malloced[i].seq = mallocseq++; + malloced[i].size = size; + malloced[i].line = line; + malloced[i].address = result; + strlcpy(malloced[i].file, f, MCFILENAMELEN); + } + if (malloccount > highwater) + highwater = malloccount; + splx(s); + } + return result; +} + +void +FFree(void *mem, char *file, int line) +{ + int s; + int i; + + s = splhigh(); + for (i = 0; i < malloccount; i++) { + if ((caddr_t) mem == malloced[i].address) { /* found it */ + bzero(mem, malloced[i].size); /* XXX */ + free(mem, M_DEVBUF); + malloccount--; + total_malloced -= malloced[i].size; + if (debug & DEBUG_MEMFREE) { /* keep track of recent frees */ + char *f = strrchr(file, '/'); /* chop off dirname if present */ + + if (f == NULL) + f = file; + else + f++; /* skip the / */ + + microtime(&freeinfo[lastfree].time); + freeinfo[lastfree].seq = malloced[i].seq; + freeinfo[lastfree].size = malloced[i].size; + freeinfo[lastfree].line = line; + freeinfo[lastfree].address = mem; + bcopy(f, freeinfo[lastfree].file, MCFILENAMELEN); + if (++lastfree == FREECOUNT) + lastfree = 0; + } + if (i < malloccount) /* more coming after */ + bcopy(&malloced[i + 1], &malloced[i], (malloccount - i) * sizeof(struct mc)); + splx(s); + return; + } + } + splx(s); + log(LOG_ERR, + "Freeing unallocated data at 0x%p from %s, line %d\n", + mem, + file, + line); + Debugger("Free"); +} + +void +vinum_meminfo(caddr_t data) +{ + struct meminfo *m = (struct meminfo *) data; + + m->mallocs = malloccount; + m->total_malloced = total_malloced; + m->malloced = malloced; + m->highwater = highwater; +} + +int +vinum_mallocinfo(caddr_t data) +{ + struct mc *m = (struct mc *) data; + unsigned int ent = m->seq; /* index of entry to return */ + + if (ent >= malloccount) + return ENOENT; + m->address = malloced[ent].address; + m->size = malloced[ent].size; + m->line = malloced[ent].line; + m->seq = malloced[ent].seq; + strlcpy(m->file, malloced[ent].file, MCFILENAMELEN); + return 0; +} + +/* + * return the nth request trace buffer entry. This + * is indexed back from the current entry (which + * has index 0) + */ +int +vinum_rqinfo(caddr_t data) +{ + struct rqinfo *rq = (struct rqinfo *) data; + int ent = *(int *) data; /* 1st word is index */ + int lastent = rqip - rqinfo; /* entry number of current entry */ + + if (ent >= RQINFO_SIZE) /* out of the table */ + return ENOENT; + if ((ent = lastent - ent - 1) < 0) + ent += RQINFO_SIZE; /* roll over backwards */ + bcopy(&rqinfo[ent], rq, sizeof(struct rqinfo)); + return 0; +} +#endif |