summaryrefslogtreecommitdiffstats
path: root/sys/dev/vinum/vinummemory.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/vinum/vinummemory.c')
-rw-r--r--sys/dev/vinum/vinummemory.c290
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
OpenPOWER on IntegriCloud