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 __FBSDID("$FreeBSD$"); 32 33 /* 34 * MALLOC.C - malloc equivalent, runs on top of zalloc and uses sbrk 35 */ 36 37 #include "zalloc_defs.h" 38 39 static MemPool MallocPool; 40 41 #ifdef DMALLOCDEBUG 42 static int MallocMax; 43 static int MallocCount; 44 45 void mallocstats(void); 46 #endif 47 48 #ifdef malloc 49 #undef malloc 50 #undef free 51 #endif 52 53 static void *Malloc_align(size_t, size_t); 54 55 void * 56 Malloc(size_t bytes, const char *file __unused, int line __unused) 57 { 58 return (Malloc_align(bytes, 1)); 59 } 60 61 void * 62 Memalign(size_t alignment, size_t bytes, const char *file __unused, 63 int line __unused) 64 { 65 if (alignment == 0) 66 alignment = 1; 67 68 return (Malloc_align(bytes, alignment)); 69 } 70 71 static void * 72 Malloc_align(size_t bytes, size_t alignment) 73 { 74 Guard *res; 75 76 #ifdef USEENDGUARD 77 bytes += MALLOCALIGN + 1; 78 #else 79 bytes += MALLOCALIGN; 80 #endif 81 82 while ((res = znalloc(&MallocPool, bytes, alignment)) == NULL) { 83 int incr = (bytes + BLKEXTENDMASK) & ~BLKEXTENDMASK; 84 char *base; 85 86 if ((base = sbrk(incr)) == (char *)-1) 87 return (NULL); 88 zextendPool(&MallocPool, base, incr); 89 zfree(&MallocPool, base, incr); 90 } 91 #ifdef DMALLOCDEBUG 92 if (++MallocCount > MallocMax) 93 MallocMax = MallocCount; 94 #endif 95 #ifdef USEGUARD 96 res->ga_Magic = GAMAGIC; 97 #endif 98 res->ga_Bytes = bytes; 99 #ifdef USEENDGUARD 100 *((signed char *)res + bytes - 1) = -2; 101 #endif 102 103 return ((char *)res + MALLOCALIGN); 104 } 105 106 void 107 Free(void *ptr, const char *file, int line) 108 { 109 size_t bytes; 110 111 if (ptr != NULL) { 112 Guard *res = (void *)((char *)ptr - MALLOCALIGN); 113 114 if (file == NULL) 115 file = "unknown"; 116 #ifdef USEGUARD 117 if (res->ga_Magic == GAFREE) { 118 printf("free: duplicate free @ %p from %s:%d\n", 119 ptr, file, line); 120 return; 121 } 122 if (res->ga_Magic != GAMAGIC) 123 panic("free: guard1 fail @ %p from %s:%d", 124 ptr, file, line); 125 res->ga_Magic = GAFREE; 126 #endif 127 #ifdef USEENDGUARD 128 if (*((signed char *)res + res->ga_Bytes - 1) == -1) { 129 printf("free: duplicate2 free @ %p from %s:%d\n", 130 ptr, file, line); 131 return; 132 } 133 if (*((signed char *)res + res->ga_Bytes - 1) != -2) 134 panic("free: guard2 fail @ %p + %zu from %s:%d", 135 ptr, res->ga_Bytes - MALLOCALIGN, file, line); 136 *((signed char *)res + res->ga_Bytes - 1) = -1; 137 #endif 138 139 bytes = res->ga_Bytes; 140 zfree(&MallocPool, res, bytes); 141 #ifdef DMALLOCDEBUG 142 --MallocCount; 143 #endif 144 } 145 } 146 147 148 void * 149 Calloc(size_t n1, size_t n2, const char *file, int line) 150 { 151 uintptr_t bytes = (uintptr_t)n1 * (uintptr_t)n2; 152 void *res; 153 154 if ((res = Malloc(bytes, file, line)) != NULL) { 155 bzero(res, bytes); 156 #ifdef DMALLOCDEBUG 157 if (++MallocCount > MallocMax) 158 MallocMax = MallocCount; 159 #endif 160 } 161 return (res); 162 } 163 164 /* 165 * realloc() - I could be fancier here and free the old buffer before 166 * allocating the new one (saving potential fragmentation 167 * and potential buffer copies). But I don't bother. 168 */ 169 170 void * 171 Realloc(void *ptr, size_t size, const char *file, int line) 172 { 173 void *res; 174 size_t old; 175 176 if ((res = Malloc(size, file, line)) != NULL) { 177 if (ptr != NULL) { 178 Guard *g = (Guard *)((char *)ptr - MALLOCALIGN); 179 180 old = g->ga_Bytes - MALLOCALIGN; 181 if (old < size) 182 bcopy(ptr, res, old); 183 else 184 bcopy(ptr, res, size); 185 Free(ptr, file, line); 186 } else { 187 #ifdef DMALLOCDEBUG 188 if (++MallocCount > MallocMax) 189 MallocMax = MallocCount; 190 #ifdef EXITSTATS 191 if (DidAtExit == 0) { 192 DidAtExit = 1; 193 atexit(mallocstats); 194 } 195 #endif 196 #endif 197 } 198 } 199 return (res); 200 } 201 202 void * 203 Reallocf(void *ptr, size_t size, const char *file, int line) 204 { 205 void *res; 206 207 if ((res = Realloc(ptr, size, file, line)) == NULL) 208 Free(ptr, file, line); 209 return (res); 210 } 211 212 #ifdef DMALLOCDEBUG 213 214 void 215 mallocstats(void) 216 { 217 printf("Active Allocations: %d/%d\n", MallocCount, MallocMax); 218 #ifdef ZALLOCDEBUG 219 zallocstats(&MallocPool); 220 #endif 221 } 222 223 #endif 224