1 1.22 christos /* $NetBSD: rf_debugMem.c,v 1.22 2019/02/09 03:34:00 christos Exp $ */ 2 1.1 oster /* 3 1.1 oster * Copyright (c) 1995 Carnegie-Mellon University. 4 1.1 oster * All rights reserved. 5 1.1 oster * 6 1.1 oster * Author: Daniel Stodolsky, Mark Holland, Jim Zelenka 7 1.1 oster * 8 1.1 oster * Permission to use, copy, modify and distribute this software and 9 1.1 oster * its documentation is hereby granted, provided that both the copyright 10 1.1 oster * notice and this permission notice appear in all copies of the 11 1.1 oster * software, derivative works or modified versions, and any portions 12 1.1 oster * thereof, and that both notices appear in supporting documentation. 13 1.1 oster * 14 1.1 oster * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 15 1.1 oster * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 16 1.1 oster * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 17 1.1 oster * 18 1.1 oster * Carnegie Mellon requests users of this software to return to 19 1.1 oster * 20 1.1 oster * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU 21 1.1 oster * School of Computer Science 22 1.1 oster * Carnegie Mellon University 23 1.1 oster * Pittsburgh PA 15213-3890 24 1.1 oster * 25 1.1 oster * any improvements or extensions that they make and grant Carnegie the 26 1.1 oster * rights to redistribute these changes. 27 1.1 oster */ 28 1.1 oster 29 1.1 oster /* debugMem.c: memory usage debugging stuff. 30 1.3 oster * Malloc, Calloc, and Free are #defined everywhere 31 1.1 oster * to do_malloc, do_calloc, and do_free. 32 1.1 oster */ 33 1.9 lukem 34 1.9 lukem #include <sys/cdefs.h> 35 1.22 christos __KERNEL_RCSID(0, "$NetBSD: rf_debugMem.c,v 1.22 2019/02/09 03:34:00 christos Exp $"); 36 1.1 oster 37 1.8 oster #include <dev/raidframe/raidframevar.h> 38 1.1 oster 39 1.1 oster #include "rf_threadstuff.h" 40 1.1 oster #include "rf_options.h" 41 1.1 oster #include "rf_debugMem.h" 42 1.1 oster #include "rf_general.h" 43 1.21 mrg #include "rf_shutdown.h" 44 1.1 oster 45 1.11 oster #if RF_DEBUG_MEM 46 1.11 oster 47 1.22 christos static size_t tot_mem_in_use = 0; 48 1.1 oster 49 1.1 oster /* Hash table of information about memory allocations */ 50 1.1 oster #define RF_MH_TABLESIZE 1000 51 1.1 oster 52 1.1 oster struct mh_struct { 53 1.3 oster void *address; 54 1.22 christos size_t size; 55 1.22 christos const char *file; 56 1.22 christos uint32_t line; 57 1.3 oster char allocated; 58 1.3 oster struct mh_struct *next; 59 1.1 oster }; 60 1.1 oster static struct mh_struct *mh_table[RF_MH_TABLESIZE]; 61 1.21 mrg static rf_declare_mutex2(rf_debug_mem_mutex); 62 1.11 oster static int mh_table_initialized = 0; 63 1.1 oster 64 1.22 christos static void memory_hash_insert(void *, size_t, const char *, uint32_t); 65 1.22 christos static int memory_hash_remove(void *, size_t); 66 1.1 oster 67 1.15 perry void 68 1.22 christos rf_record_malloc(void *p, size_t size, const char *file, uint32_t line) 69 1.3 oster { 70 1.3 oster RF_ASSERT(size != 0); 71 1.3 oster 72 1.21 mrg /* rf_lock_mutex2(rf_debug_mem_mutex); */ 73 1.22 christos memory_hash_insert(p, size, file, line); 74 1.3 oster tot_mem_in_use += size; 75 1.21 mrg /* rf_unlock_mutex2(rf_debug_mem_mutex); */ 76 1.22 christos if ((intptr_t)p == rf_memDebugAddress) { 77 1.22 christos printf("%s,%d: %s: Debug address allocated\n", file, line, 78 1.22 christos __func__); 79 1.3 oster } 80 1.1 oster } 81 1.1 oster 82 1.15 perry void 83 1.22 christos rf_unrecord_malloc(void *p, size_t sz) 84 1.3 oster { 85 1.22 christos size_t size; 86 1.3 oster 87 1.21 mrg /* rf_lock_mutex2(rf_debug_mem_mutex); */ 88 1.3 oster size = memory_hash_remove(p, sz); 89 1.3 oster tot_mem_in_use -= size; 90 1.21 mrg /* rf_unlock_mutex2(rf_debug_mem_mutex); */ 91 1.22 christos if ((intptr_t) p == rf_memDebugAddress) { 92 1.22 christos /* this is really only a flag line for gdb */ 93 1.22 christos printf("%s: Found debug address\n", __func__); 94 1.3 oster } 95 1.3 oster } 96 1.3 oster 97 1.15 perry void 98 1.20 cegger rf_print_unfreed(void) 99 1.3 oster { 100 1.22 christos size_t i; 101 1.22 christos int foundone = 0; 102 1.3 oster struct mh_struct *p; 103 1.3 oster 104 1.3 oster for (i = 0; i < RF_MH_TABLESIZE; i++) { 105 1.22 christos for (p = mh_table[i]; p; p = p->next) { 106 1.22 christos if (!p->allocated) 107 1.22 christos continue; 108 1.22 christos if (foundone) { 109 1.22 christos printf("\n\n:%s: There are unfreed memory" 110 1.22 christos " locations at program shutdown:\n", 111 1.22 christos __func__); 112 1.3 oster } 113 1.22 christos foundone = 1; 114 1.22 christos printf("%s: @%s,%d: addr %p size %zu\n", __func__, 115 1.22 christos p->file, p->line, p->address, p->size); 116 1.22 christos } 117 1.3 oster } 118 1.3 oster if (tot_mem_in_use) { 119 1.22 christos printf("%s: %zu total bytes in use\n", 120 1.22 christos __func__, tot_mem_in_use); 121 1.3 oster } 122 1.3 oster } 123 1.11 oster #endif /* RF_DEBUG_MEM */ 124 1.3 oster 125 1.21 mrg #if RF_DEBUG_MEM 126 1.21 mrg static void 127 1.21 mrg rf_ShutdownDebugMem(void *unused) 128 1.21 mrg { 129 1.21 mrg rf_destroy_mutex2(rf_debug_mem_mutex); 130 1.21 mrg } 131 1.21 mrg #endif 132 1.21 mrg 133 1.15 perry int 134 1.18 christos rf_ConfigureDebugMem(RF_ShutdownList_t **listp) 135 1.3 oster { 136 1.11 oster #if RF_DEBUG_MEM 137 1.22 christos size_t i; 138 1.3 oster 139 1.21 mrg rf_init_mutex2(rf_debug_mem_mutex, IPL_VM); 140 1.3 oster if (rf_memDebug) { 141 1.3 oster for (i = 0; i < RF_MH_TABLESIZE; i++) 142 1.3 oster mh_table[i] = NULL; 143 1.3 oster mh_table_initialized = 1; 144 1.3 oster } 145 1.21 mrg rf_ShutdownCreate(listp, rf_ShutdownDebugMem, NULL); 146 1.11 oster #endif 147 1.3 oster return (0); 148 1.3 oster } 149 1.11 oster 150 1.11 oster #if RF_DEBUG_MEM 151 1.11 oster 152 1.22 christos #define HASHADDR(a) ((size_t)((((uintptr_t)a) >> 3) % RF_MH_TABLESIZE)) 153 1.1 oster 154 1.15 perry static void 155 1.22 christos memory_hash_insert(void *addr, size_t size, const char *file, uint32_t line) 156 1.3 oster { 157 1.22 christos size_t bucket = (size_t)HASHADDR(addr); 158 1.3 oster struct mh_struct *p; 159 1.3 oster 160 1.3 oster RF_ASSERT(mh_table_initialized); 161 1.3 oster 162 1.3 oster /* search for this address in the hash table */ 163 1.22 christos for (p = mh_table[bucket]; p && (p->address != addr); p = p->next) 164 1.22 christos continue; 165 1.3 oster if (!p) { 166 1.22 christos p = RF_Malloc(sizeof(*p)); 167 1.3 oster RF_ASSERT(p); 168 1.3 oster p->next = mh_table[bucket]; 169 1.3 oster mh_table[bucket] = p; 170 1.3 oster p->address = addr; 171 1.3 oster p->allocated = 0; 172 1.3 oster } 173 1.3 oster if (p->allocated) { 174 1.22 christos printf("%s: @%s,%u: ERROR: Reallocated addr %p without free\n", 175 1.22 christos __func__, file, line, addr); 176 1.22 christos printf("%s: last allocated @%s,%u\n", 177 1.22 christos __func__, p->file, p->line); 178 1.3 oster RF_ASSERT(0); 179 1.3 oster } 180 1.3 oster p->size = size; 181 1.3 oster p->line = line; 182 1.22 christos p->file = file; 183 1.3 oster p->allocated = 1; 184 1.3 oster } 185 1.3 oster 186 1.15 perry static int 187 1.22 christos memory_hash_remove(void *addr, size_t sz) 188 1.3 oster { 189 1.22 christos size_t bucket = HASHADDR(addr); 190 1.3 oster struct mh_struct *p; 191 1.3 oster 192 1.3 oster RF_ASSERT(mh_table_initialized); 193 1.22 christos for (p = mh_table[bucket]; p && (p->address != addr); p = p->next) 194 1.22 christos continue; 195 1.3 oster if (!p) { 196 1.22 christos printf("%s: ERROR: Freeing never-allocated address %p\n", 197 1.22 christos __func__, addr); 198 1.3 oster RF_PANIC(); 199 1.3 oster } 200 1.3 oster if (!p->allocated) { 201 1.22 christos printf("%s: ERROR: Freeing unallocated address %p." 202 1.22 christos " Last allocation @%s,%u\n", 203 1.22 christos __func__, addr, p->file, p->line); 204 1.3 oster RF_PANIC(); 205 1.3 oster } 206 1.3 oster if (sz > 0 && p->size != sz) { /* you can suppress this error by 207 1.3 oster * using a negative value as the size 208 1.3 oster * to free */ 209 1.22 christos printf("%s: ERROR: Incorrect size (%zu should be %zu) at" 210 1.22 christos " free for address %p. Allocated @%s,%u\n", __func__, 211 1.22 christos sz, p->size, addr, p->file, p->line); 212 1.3 oster RF_PANIC(); 213 1.3 oster } 214 1.3 oster p->allocated = 0; 215 1.22 christos return p->size; 216 1.1 oster } 217 1.11 oster #endif /* RF_DEBUG_MEM */ 218 1.11 oster 219 1.11 oster 220