139665Smsmith/* 239665Smsmith * This module derived from code donated to the FreeBSD Project by 339665Smsmith * Matthew Dillon <dillon@backplane.com> 439665Smsmith * 539665Smsmith * Copyright (c) 1998 The FreeBSD Project 639665Smsmith * All rights reserved. 739665Smsmith * 839665Smsmith * Redistribution and use in source and binary forms, with or without 939665Smsmith * modification, are permitted provided that the following conditions 1039665Smsmith * are met: 1139665Smsmith * 1. Redistributions of source code must retain the above copyright 1239665Smsmith * notice, this list of conditions and the following disclaimer. 1339665Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1439665Smsmith * notice, this list of conditions and the following disclaimer in the 1539665Smsmith * documentation and/or other materials provided with the distribution. 1639665Smsmith * 1739665Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1839665Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1939665Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2039665Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2139665Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2239665Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2339665Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2439665Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2539665Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2639665Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2739665Smsmith * SUCH DAMAGE. 2839665Smsmith */ 2939665Smsmith 3084221Sdillon#include <sys/cdefs.h> 3184221Sdillon__FBSDID("$FreeBSD$"); 3284221Sdillon 3339665Smsmith/* 3439665Smsmith * MALLOC.C - malloc equivalent, runs on top of zalloc and uses sbrk 3539665Smsmith */ 3639665Smsmith 3739665Smsmith#include "zalloc_defs.h" 3839665Smsmith 3939863Smsmithstatic MemPool MallocPool; 4039665Smsmith 4139665Smsmith#ifdef DMALLOCDEBUG 4239665Smsmithstatic int MallocMax; 4339665Smsmithstatic int MallocCount; 4439665Smsmith 4539665Smsmithvoid mallocstats(void); 4639665Smsmith#endif 4739665Smsmith 4839672Sdfr#ifdef malloc 4939672Sdfr#undef malloc 5039672Sdfr#undef free 5139672Sdfr#endif 5239672Sdfr 5339665Smsmithvoid * 54100394SpeterMalloc(size_t bytes, const char *file, int line) 5539665Smsmith{ 5639665Smsmith Guard *res; 5739665Smsmith 5839665Smsmith#ifdef USEENDGUARD 5939665Smsmith bytes += MALLOCALIGN + 1; 6039665Smsmith#else 6139665Smsmith bytes += MALLOCALIGN; 6239665Smsmith#endif 6339665Smsmith 6439665Smsmith while ((res = znalloc(&MallocPool, bytes)) == NULL) { 6539665Smsmith int incr = (bytes + BLKEXTENDMASK) & ~BLKEXTENDMASK; 6639665Smsmith char *base; 6739665Smsmith 6839665Smsmith if ((base = sbrk(incr)) == (char *)-1) 6939665Smsmith return(NULL); 7039665Smsmith zextendPool(&MallocPool, base, incr); 7139665Smsmith zfree(&MallocPool, base, incr); 7239665Smsmith } 7339665Smsmith#ifdef DMALLOCDEBUG 7439665Smsmith if (++MallocCount > MallocMax) 7539665Smsmith MallocMax = MallocCount; 7639665Smsmith#endif 7739665Smsmith#ifdef USEGUARD 7839665Smsmith res->ga_Magic = GAMAGIC; 7939665Smsmith#endif 8039665Smsmith res->ga_Bytes = bytes; 8139665Smsmith#ifdef USEENDGUARD 82126206Sgrehan *((signed char *)res + bytes - 1) = -2; 8339665Smsmith#endif 84126206Sgrehan 8539665Smsmith return((char *)res + MALLOCALIGN); 8639665Smsmith} 8739665Smsmith 8839665Smsmithvoid 89100394SpeterFree(void *ptr, const char *file, int line) 9039665Smsmith{ 9139665Smsmith size_t bytes; 9239665Smsmith 9339665Smsmith if (ptr != NULL) { 9439665Smsmith Guard *res = (void *)((char *)ptr - MALLOCALIGN); 9539665Smsmith 96100394Speter if (file == NULL) 97100394Speter file = "unknown"; 9839665Smsmith#ifdef USEGUARD 99100394Speter if (res->ga_Magic == GAFREE) { 100100394Speter printf("free: duplicate free @ %p from %s:%d\n", ptr, file, line); 101100394Speter return; 102100394Speter } 10339863Smsmith if (res->ga_Magic != GAMAGIC) 104124570Sjhb panic("free: guard1 fail @ %p from %s:%d", ptr, file, line); 105100394Speter res->ga_Magic = GAFREE; 10639665Smsmith#endif 10739665Smsmith#ifdef USEENDGUARD 108126206Sgrehan if (*((signed char *)res + res->ga_Bytes - 1) == -1) { 109100394Speter printf("free: duplicate2 free @ %p from %s:%d\n", ptr, file, line); 110100394Speter return; 111100394Speter } 112126206Sgrehan if (*((signed char *)res + res->ga_Bytes - 1) != -2) 113223151Savatar panic("free: guard2 fail @ %p + %zu from %s:%d", ptr, res->ga_Bytes - MALLOCALIGN, file, line); 114126206Sgrehan *((signed char *)res + res->ga_Bytes - 1) = -1; 11539665Smsmith#endif 11639665Smsmith 11739665Smsmith bytes = res->ga_Bytes; 11839665Smsmith zfree(&MallocPool, res, bytes); 11939665Smsmith#ifdef DMALLOCDEBUG 12039665Smsmith --MallocCount; 12139665Smsmith#endif 12239665Smsmith } 12339665Smsmith} 12439665Smsmith 12539665Smsmith 12639665Smsmithvoid * 127100394SpeterCalloc(size_t n1, size_t n2, const char *file, int line) 12839665Smsmith{ 129223905Savatar uintptr_t bytes = (uintptr_t)n1 * (uintptr_t)n2; 13039665Smsmith void *res; 13139665Smsmith 132100394Speter if ((res = Malloc(bytes, file, line)) != NULL) { 13339665Smsmith bzero(res, bytes); 13439665Smsmith#ifdef DMALLOCDEBUG 13539665Smsmith if (++MallocCount > MallocMax) 13639665Smsmith MallocMax = MallocCount; 13739665Smsmith#endif 13839665Smsmith } 13939665Smsmith return(res); 14039665Smsmith} 14139665Smsmith 14239665Smsmith/* 14339665Smsmith * realloc() - I could be fancier here and free the old buffer before 14439665Smsmith * allocating the new one (saving potential fragmentation 14539665Smsmith * and potential buffer copies). But I don't bother. 14639665Smsmith */ 14739665Smsmith 14839665Smsmithvoid * 149100394SpeterRealloc(void *ptr, size_t size, const char *file, int line) 15039665Smsmith{ 15139665Smsmith void *res; 15239665Smsmith size_t old; 15339665Smsmith 154100394Speter if ((res = Malloc(size, file, line)) != NULL) { 15539665Smsmith if (ptr) { 15639665Smsmith old = *(size_t *)((char *)ptr - MALLOCALIGN) - MALLOCALIGN; 15739665Smsmith if (old < size) 15839665Smsmith bcopy(ptr, res, old); 15939665Smsmith else 16039665Smsmith bcopy(ptr, res, size); 161100394Speter Free(ptr, file, line); 16239665Smsmith } else { 16339665Smsmith#ifdef DMALLOCDEBUG 16439665Smsmith if (++MallocCount > MallocMax) 16539665Smsmith MallocMax = MallocCount; 16639665Smsmith#ifdef EXITSTATS 16739665Smsmith if (DidAtExit == 0) { 16839665Smsmith DidAtExit = 1; 16939665Smsmith atexit(mallocstats); 17039665Smsmith } 17139665Smsmith#endif 17239665Smsmith#endif 17339665Smsmith } 17439665Smsmith } 17539665Smsmith return(res); 17639665Smsmith} 17739665Smsmith 17839665Smsmithvoid * 179100394SpeterReallocf(void *ptr, size_t size, const char *file, int line) 18039665Smsmith{ 18139665Smsmith void *res; 18239665Smsmith 183100394Speter if ((res = Realloc(ptr, size, file, line)) == NULL) 184100394Speter Free(ptr, file, line); 18539665Smsmith return(res); 18639665Smsmith} 18739665Smsmith 18839665Smsmith#ifdef DMALLOCDEBUG 18939665Smsmith 19039665Smsmithvoid 19139665Smsmithmallocstats(void) 19239665Smsmith{ 19339665Smsmith printf("Active Allocations: %d/%d\n", MallocCount, MallocMax); 19439665Smsmith#ifdef ZALLOCDEBUG 19539665Smsmith zallocstats(&MallocPool); 19639665Smsmith#endif 19739665Smsmith} 19839665Smsmith 19939665Smsmith#endif 20039665Smsmith 201