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