rf_debugMem.c revision 1.9 1 /* $NetBSD: rf_debugMem.c,v 1.9 2001/11/13 07:11:13 lukem Exp $ */
2 /*
3 * Copyright (c) 1995 Carnegie-Mellon University.
4 * All rights reserved.
5 *
6 * Author: Daniel Stodolsky, Mark Holland, Jim Zelenka
7 *
8 * Permission to use, copy, modify and distribute this software and
9 * its documentation is hereby granted, provided that both the copyright
10 * notice and this permission notice appear in all copies of the
11 * software, derivative works or modified versions, and any portions
12 * thereof, and that both notices appear in supporting documentation.
13 *
14 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
16 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17 *
18 * Carnegie Mellon requests users of this software to return to
19 *
20 * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU
21 * School of Computer Science
22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890
24 *
25 * any improvements or extensions that they make and grant Carnegie the
26 * rights to redistribute these changes.
27 */
28
29 /* debugMem.c: memory usage debugging stuff.
30 * Malloc, Calloc, and Free are #defined everywhere
31 * to do_malloc, do_calloc, and do_free.
32 *
33 * if RF_UTILITY is nonzero, it means were compiling one of the
34 * raidframe utility programs, such as rfctrl or smd. In this
35 * case, we eliminate all references to the threads package
36 * and to the allocation list stuff.
37 */
38
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: rf_debugMem.c,v 1.9 2001/11/13 07:11:13 lukem Exp $");
41
42 #include <dev/raidframe/raidframevar.h>
43
44 #include "rf_threadstuff.h"
45 #include "rf_options.h"
46 #include "rf_debugMem.h"
47 #include "rf_general.h"
48
49 static long tot_mem_in_use = 0;
50
51 /* Hash table of information about memory allocations */
52 #define RF_MH_TABLESIZE 1000
53
54 struct mh_struct {
55 void *address;
56 int size;
57 int line;
58 char *filen;
59 char allocated;
60 struct mh_struct *next;
61 };
62 static struct mh_struct *mh_table[RF_MH_TABLESIZE];
63 RF_DECLARE_MUTEX(rf_debug_mem_mutex)
64 static int mh_table_initialized = 0;
65
66 static void memory_hash_insert(void *addr, int size, int line, char *filen);
67 static int memory_hash_remove(void *addr, int sz);
68
69 void
70 rf_record_malloc(p, size, line, filen)
71 void *p;
72 int size, line;
73 char *filen;
74 {
75 RF_ASSERT(size != 0);
76
77 /* RF_LOCK_MUTEX(rf_debug_mem_mutex); */
78 memory_hash_insert(p, size, line, filen);
79 tot_mem_in_use += size;
80 /* RF_UNLOCK_MUTEX(rf_debug_mem_mutex); */
81 if ((long) p == rf_memDebugAddress) {
82 printf("Allocate: debug address allocated from line %d file %s\n", line, filen);
83 }
84 }
85
86 void
87 rf_unrecord_malloc(p, sz)
88 void *p;
89 int sz;
90 {
91 int size;
92
93 /* RF_LOCK_MUTEX(rf_debug_mem_mutex); */
94 size = memory_hash_remove(p, sz);
95 tot_mem_in_use -= size;
96 /* RF_UNLOCK_MUTEX(rf_debug_mem_mutex); */
97 if ((long) p == rf_memDebugAddress) {
98 printf("Free: Found debug address\n"); /* this is really only a
99 * flag line for gdb */
100 }
101 }
102
103 void
104 rf_print_unfreed()
105 {
106 int i, foundone = 0;
107 struct mh_struct *p;
108
109 for (i = 0; i < RF_MH_TABLESIZE; i++) {
110 for (p = mh_table[i]; p; p = p->next)
111 if (p->allocated) {
112 if (!foundone)
113 printf("\n\nThere are unfreed memory locations at program shutdown:\n");
114 foundone = 1;
115 printf("Addr 0x%lx Size %d line %d file %s\n",
116 (long) p->address, p->size, p->line, p->filen);
117 }
118 }
119 if (tot_mem_in_use) {
120 printf("%ld total bytes in use\n", tot_mem_in_use);
121 }
122 }
123
124 int
125 rf_ConfigureDebugMem(listp)
126 RF_ShutdownList_t **listp;
127 {
128 int i, rc;
129
130 rc = rf_create_managed_mutex(listp, &rf_debug_mem_mutex);
131 if (rc) {
132 RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d\n", __FILE__,
133 __LINE__, rc);
134 return (rc);
135 }
136 if (rf_memDebug) {
137 for (i = 0; i < RF_MH_TABLESIZE; i++)
138 mh_table[i] = NULL;
139 mh_table_initialized = 1;
140 }
141 return (0);
142 }
143 #define HASHADDR(_a_) ( (((unsigned long) _a_)>>3) % RF_MH_TABLESIZE )
144
145 static void
146 memory_hash_insert(addr, size, line, filen)
147 void *addr;
148 int size, line;
149 char *filen;
150 {
151 unsigned long bucket = HASHADDR(addr);
152 struct mh_struct *p;
153
154 RF_ASSERT(mh_table_initialized);
155
156 /* search for this address in the hash table */
157 for (p = mh_table[bucket]; p && (p->address != addr); p = p->next);
158 if (!p) {
159 RF_Malloc(p, sizeof(struct mh_struct), (struct mh_struct *));
160 RF_ASSERT(p);
161 p->next = mh_table[bucket];
162 mh_table[bucket] = p;
163 p->address = addr;
164 p->allocated = 0;
165 }
166 if (p->allocated) {
167 printf("ERROR: reallocated address 0x%lx from line %d, file %s without intervening free\n", (long) addr, line, filen);
168 printf(" last allocated from line %d file %s\n", p->line, p->filen);
169 RF_ASSERT(0);
170 }
171 p->size = size;
172 p->line = line;
173 p->filen = filen;
174 p->allocated = 1;
175 }
176
177 static int
178 memory_hash_remove(addr, sz)
179 void *addr;
180 int sz;
181 {
182 unsigned long bucket = HASHADDR(addr);
183 struct mh_struct *p;
184
185 RF_ASSERT(mh_table_initialized);
186 for (p = mh_table[bucket]; p && (p->address != addr); p = p->next);
187 if (!p) {
188 printf("ERROR: freeing never-allocated address 0x%lx\n", (long) addr);
189 RF_PANIC();
190 }
191 if (!p->allocated) {
192 printf("ERROR: freeing unallocated address 0x%lx. Last allocation line %d file %s\n", (long) addr, p->line, p->filen);
193 RF_PANIC();
194 }
195 if (sz > 0 && p->size != sz) { /* you can suppress this error by
196 * using a negative value as the size
197 * to free */
198 printf("ERROR: incorrect size at free for address 0x%lx: is %d should be %d. Alloc at line %d of file %s\n", (unsigned long) addr, sz, p->size, p->line, p->filen);
199 RF_PANIC();
200 }
201 p->allocated = 0;
202 return (p->size);
203 }
204