1 /* 2 * This module derived from code donated to the FreeBSD Project by 3 * Matthew Dillon <dillon@backplane.com> 4 * 5 * Copyright (c) 1998 The FreeBSD Project 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #include <sys/cdefs.h> 31 /* 32 * MALLOC.C - malloc equivalent, runs on top of zalloc and uses sbrk 33 */ 34 35 #include "zalloc_defs.h" 36 37 static MemPool MallocPool; 38 39 #ifdef DMALLOCDEBUG 40 static int MallocMax; 41 static int MallocCount; 42 43 void mallocstats(void); 44 #endif 45 46 #ifdef malloc 47 #undef malloc 48 #undef free 49 #endif 50 51 static void *Malloc_align(size_t, size_t); 52 53 #ifndef MIN 54 # define MIN(a,b) ((a) <= (b)) ? (a) : (b) 55 #endif 56 57 void * 58 Malloc(size_t bytes, const char *file __unused, int line __unused) 59 { 60 return (Malloc_align(bytes, 1)); 61 } 62 63 void * 64 Memalign(size_t alignment, size_t bytes, const char *file __unused, 65 int line __unused) 66 { 67 if (alignment == 0) 68 alignment = 1; 69 70 return (Malloc_align(bytes, alignment)); 71 } 72 73 static void * 74 Malloc_align(size_t bytes, size_t alignment) 75 { 76 Guard *res; 77 78 #ifdef USEENDGUARD 79 bytes += MALLOCALIGN + 1; 80 #else 81 bytes += MALLOCALIGN; 82 #endif 83 84 while ((res = znalloc(&MallocPool, bytes, alignment)) == NULL) { 85 int incr = (bytes + BLKEXTENDMASK) & ~BLKEXTENDMASK; 86 char *base; 87 88 if ((base = sbrk(incr)) == (char *)-1) 89 return (NULL); 90 zextendPool(&MallocPool, base, incr); 91 zfree(&MallocPool, base, incr); 92 } 93 #ifdef DMALLOCDEBUG 94 if (++MallocCount > MallocMax) 95 MallocMax = MallocCount; 96 #endif 97 #ifdef USEGUARD 98 res->ga_Magic = GAMAGIC; 99 #endif 100 res->ga_Bytes = bytes; 101 #ifdef USEENDGUARD 102 *((signed char *)res + bytes - 1) = -2; 103 #endif 104 105 return ((char *)res + MALLOCALIGN); 106 } 107 108 void 109 Free(void *ptr, const char *file, int line) 110 { 111 size_t bytes; 112 113 if (ptr != NULL) { 114 Guard *res = (void *)((char *)ptr - MALLOCALIGN); 115 116 if (file == NULL) 117 file = "unknown"; 118 #ifdef USEGUARD 119 if (res->ga_Magic == GAFREE) { 120 printf("free: duplicate free @ %p from %s:%d\n", 121 ptr, file, line); 122 return; 123 } 124 if (res->ga_Magic != GAMAGIC) { 125 size_t dump_bytes; 126 127 dump_bytes = MIN((ptr - MallocPool.mp_Base), 512); 128 hexdump(ptr - dump_bytes, dump_bytes); 129 panic("free: guard1 fail @ %p from %s:%d", 130 ptr, file, line); 131 } 132 res->ga_Magic = GAFREE; 133 #endif 134 #ifdef USEENDGUARD 135 if (*((signed char *)res + res->ga_Bytes - 1) == -1) { 136 printf("free: duplicate2 free @ %p from %s:%d\n", 137 ptr, file, line); 138 return; 139 } 140 if (*((signed char *)res + res->ga_Bytes - 1) != -2) 141 panic("free: guard2 fail @ %p + %zu from %s:%d", 142 ptr, res->ga_Bytes - MALLOCALIGN, file, line); 143 *((signed char *)res + res->ga_Bytes - 1) = -1; 144 #endif 145 146 bytes = res->ga_Bytes; 147 zfree(&MallocPool, res, bytes); 148 #ifdef DMALLOCDEBUG 149 --MallocCount; 150 #endif 151 } 152 } 153 154 155 void * 156 Calloc(size_t n1, size_t n2, const char *file, int line) 157 { 158 uintptr_t bytes = (uintptr_t)n1 * (uintptr_t)n2; 159 void *res; 160 161 if ((res = Malloc(bytes, file, line)) != NULL) { 162 bzero(res, bytes); 163 #ifdef DMALLOCDEBUG 164 if (++MallocCount > MallocMax) 165 MallocMax = MallocCount; 166 #endif 167 } 168 return (res); 169 } 170 171 /* 172 * realloc() - I could be fancier here and free the old buffer before 173 * allocating the new one (saving potential fragmentation 174 * and potential buffer copies). But I don't bother. 175 */ 176 177 void * 178 Realloc(void *ptr, size_t size, const char *file, int line) 179 { 180 void *res; 181 size_t old; 182 183 if ((res = Malloc(size, file, line)) != NULL) { 184 if (ptr != NULL) { 185 Guard *g = (Guard *)((char *)ptr - MALLOCALIGN); 186 187 old = g->ga_Bytes - MALLOCALIGN; 188 if (old < size) 189 bcopy(ptr, res, old); 190 else 191 bcopy(ptr, res, size); 192 Free(ptr, file, line); 193 } else { 194 #ifdef DMALLOCDEBUG 195 if (++MallocCount > MallocMax) 196 MallocMax = MallocCount; 197 #ifdef EXITSTATS 198 if (DidAtExit == 0) { 199 DidAtExit = 1; 200 atexit(mallocstats); 201 } 202 #endif 203 #endif 204 } 205 } 206 return (res); 207 } 208 209 void * 210 Reallocf(void *ptr, size_t size, const char *file, int line) 211 { 212 void *res; 213 214 if ((res = Realloc(ptr, size, file, line)) == NULL) 215 Free(ptr, file, line); 216 return (res); 217 } 218 219 #ifdef DMALLOCDEBUG 220 221 void 222 mallocstats(void) 223 { 224 printf("Active Allocations: %d/%d\n", MallocCount, MallocMax); 225 #ifdef ZALLOCDEBUG 226 zallocstats(&MallocPool); 227 #endif 228 } 229 230 #endif 231