rf_debugMem.c revision 1.6 1 /* $NetBSD: rf_debugMem.c,v 1.6 1999/09/04 21:11:21 oster 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 "rf_types.h"
40
41 #include "rf_threadstuff.h"
42 #include "rf_threadid.h"
43 #include "rf_options.h"
44 #include "rf_debugMem.h"
45 #include "rf_general.h"
46
47 static long tot_mem_in_use = 0;
48
49 /* Hash table of information about memory allocations */
50 #define RF_MH_TABLESIZE 1000
51
52 struct mh_struct {
53 void *address;
54 int size;
55 int line;
56 char *filen;
57 char allocated;
58 struct mh_struct *next;
59 };
60 static struct mh_struct *mh_table[RF_MH_TABLESIZE];
61 RF_DECLARE_MUTEX(rf_debug_mem_mutex)
62 static int mh_table_initialized = 0;
63
64 static void memory_hash_insert(void *addr, int size, int line, char *filen);
65 static int memory_hash_remove(void *addr, int sz);
66
67 void
68 rf_record_malloc(p, size, line, filen)
69 void *p;
70 int size, line;
71 char *filen;
72 {
73 RF_ASSERT(size != 0);
74
75 /* RF_LOCK_MUTEX(rf_debug_mem_mutex); */
76 memory_hash_insert(p, size, line, filen);
77 tot_mem_in_use += size;
78 /* RF_UNLOCK_MUTEX(rf_debug_mem_mutex); */
79 if ((long) p == rf_memDebugAddress) {
80 printf("Allocate: debug address allocated from line %d file %s\n", line, filen);
81 }
82 }
83
84 void
85 rf_unrecord_malloc(p, sz)
86 void *p;
87 int sz;
88 {
89 int size;
90
91 /* RF_LOCK_MUTEX(rf_debug_mem_mutex); */
92 size = memory_hash_remove(p, sz);
93 tot_mem_in_use -= size;
94 /* RF_UNLOCK_MUTEX(rf_debug_mem_mutex); */
95 if ((long) p == rf_memDebugAddress) {
96 printf("Free: Found debug address\n"); /* this is really only a
97 * flag line for gdb */
98 }
99 }
100
101 void
102 rf_print_unfreed()
103 {
104 int i, foundone = 0;
105 struct mh_struct *p;
106
107 for (i = 0; i < RF_MH_TABLESIZE; i++) {
108 for (p = mh_table[i]; p; p = p->next)
109 if (p->allocated) {
110 if (!foundone)
111 printf("\n\nThere are unfreed memory locations at program shutdown:\n");
112 foundone = 1;
113 printf("Addr 0x%lx Size %d line %d file %s\n",
114 (long) p->address, p->size, p->line, p->filen);
115 }
116 }
117 if (tot_mem_in_use) {
118 printf("%ld total bytes in use\n", tot_mem_in_use);
119 }
120 }
121
122 int
123 rf_ConfigureDebugMem(listp)
124 RF_ShutdownList_t **listp;
125 {
126 int i, rc;
127
128 rc = rf_create_managed_mutex(listp, &rf_debug_mem_mutex);
129 if (rc) {
130 RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d\n", __FILE__,
131 __LINE__, rc);
132 return (rc);
133 }
134 if (rf_memDebug) {
135 for (i = 0; i < RF_MH_TABLESIZE; i++)
136 mh_table[i] = NULL;
137 mh_table_initialized = 1;
138 }
139 return (0);
140 }
141 #define HASHADDR(_a_) ( (((unsigned long) _a_)>>3) % RF_MH_TABLESIZE )
142
143 static void
144 memory_hash_insert(addr, size, line, filen)
145 void *addr;
146 int size, line;
147 char *filen;
148 {
149 unsigned long bucket = HASHADDR(addr);
150 struct mh_struct *p;
151
152 RF_ASSERT(mh_table_initialized);
153
154 /* search for this address in the hash table */
155 for (p = mh_table[bucket]; p && (p->address != addr); p = p->next);
156 if (!p) {
157 RF_Malloc(p, sizeof(struct mh_struct), (struct mh_struct *));
158 RF_ASSERT(p);
159 p->next = mh_table[bucket];
160 mh_table[bucket] = p;
161 p->address = addr;
162 p->allocated = 0;
163 }
164 if (p->allocated) {
165 printf("ERROR: reallocated address 0x%lx from line %d, file %s without intervening free\n", (long) addr, line, filen);
166 printf(" last allocated from line %d file %s\n", p->line, p->filen);
167 RF_ASSERT(0);
168 }
169 p->size = size;
170 p->line = line;
171 p->filen = filen;
172 p->allocated = 1;
173 }
174
175 static int
176 memory_hash_remove(addr, sz)
177 void *addr;
178 int sz;
179 {
180 unsigned long bucket = HASHADDR(addr);
181 struct mh_struct *p;
182
183 RF_ASSERT(mh_table_initialized);
184 for (p = mh_table[bucket]; p && (p->address != addr); p = p->next);
185 if (!p) {
186 printf("ERROR: freeing never-allocated address 0x%lx\n", (long) addr);
187 RF_PANIC();
188 }
189 if (!p->allocated) {
190 printf("ERROR: freeing unallocated address 0x%lx. Last allocation line %d file %s\n", (long) addr, p->line, p->filen);
191 RF_PANIC();
192 }
193 if (sz > 0 && p->size != sz) { /* you can suppress this error by
194 * using a negative value as the size
195 * to free */
196 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);
197 RF_PANIC();
198 }
199 p->allocated = 0;
200 return (p->size);
201 }
202