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 39static MemPool MallocPool; 40 41#ifdef DMALLOCDEBUG 42static int MallocMax; 43static int MallocCount; 44 45void mallocstats(void); 46#endif 47 48#ifdef malloc 49#undef malloc 50#undef free 51#endif 52 53static void *Malloc_align(size_t, size_t); 54 55void * 56Malloc(size_t bytes, const char *file __unused, int line __unused) 57{ 58 return (Malloc_align(bytes, 1)); 59} 60 61void * 62Memalign(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 71static void * 72Malloc_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 106void 107Free(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 148void * 149Calloc(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 170void * 171Realloc(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 202void * 203Reallocf(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 214void 215mallocstats(void) 216{ 217 printf("Active Allocations: %d/%d\n", MallocCount, MallocMax); 218#ifdef ZALLOCDEBUG 219 zallocstats(&MallocPool); 220#endif 221} 222 223#endif 224