zalloc_malloc.c revision 223905
1139826Simp/*
253541Sshin * This module derived from code donated to the FreeBSD Project by
353541Sshin * Matthew Dillon <dillon@backplane.com>
453541Sshin *
553541Sshin * Copyright (c) 1998 The FreeBSD Project
653541Sshin * All rights reserved.
753541Sshin *
853541Sshin * Redistribution and use in source and binary forms, with or without
953541Sshin * modification, are permitted provided that the following conditions
1053541Sshin * are met:
1153541Sshin * 1. Redistributions of source code must retain the above copyright
1253541Sshin *    notice, this list of conditions and the following disclaimer.
1353541Sshin * 2. Redistributions in binary form must reproduce the above copyright
1453541Sshin *    notice, this list of conditions and the following disclaimer in the
1553541Sshin *    documentation and/or other materials provided with the distribution.
1653541Sshin *
1753541Sshin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1853541Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1953541Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2053541Sshin * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2153541Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2253541Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2353541Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2453541Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2553541Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2653541Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2753541Sshin * SUCH DAMAGE.
28174510Sobrien */
29174510Sobrien
3053541Sshin#include <sys/cdefs.h>
3153541Sshin__FBSDID("$FreeBSD: head/lib/libstand/zalloc_malloc.c 223905 2011-07-10 07:25:34Z avatar $");
32139826Simp
3353541Sshin/*
3453541Sshin * MALLOC.C - malloc equivalent, runs on top of zalloc and uses sbrk
3553541Sshin */
3653541Sshin
3753541Sshin#include "zalloc_defs.h"
3853541Sshin
3953541Sshinstatic MemPool	MallocPool;
4053541Sshin
4153541Sshin#ifdef DMALLOCDEBUG
4253541Sshinstatic int MallocMax;
4353541Sshinstatic int MallocCount;
4453541Sshin
4553541Sshinvoid mallocstats(void);
4653541Sshin#endif
4753541Sshin
4853541Sshin#ifdef malloc
4953541Sshin#undef malloc
5053541Sshin#undef free
5153541Sshin#endif
5253541Sshin
5353541Sshinvoid *
5453541SshinMalloc(size_t bytes, const char *file, int line)
5553541Sshin{
5653541Sshin    Guard *res;
5753541Sshin
5853541Sshin#ifdef USEENDGUARD
5953541Sshin    bytes += MALLOCALIGN + 1;
6053541Sshin#else
6153541Sshin    bytes += MALLOCALIGN;
6253541Sshin#endif
63174510Sobrien
64174510Sobrien    while ((res = znalloc(&MallocPool, bytes)) == NULL) {
65174510Sobrien	int incr = (bytes + BLKEXTENDMASK) & ~BLKEXTENDMASK;
6662587Sitojun	char *base;
6762587Sitojun
68225044Sbz	if ((base = sbrk(incr)) == (char *)-1)
6955009Sshin	    return(NULL);
70207828Skmacy	zextendPool(&MallocPool, base, incr);
7155009Sshin	zfree(&MallocPool, base, incr);
7253541Sshin    }
7353541Sshin#ifdef DMALLOCDEBUG
7478064Sume    if (++MallocCount > MallocMax)
7553541Sshin	MallocMax = MallocCount;
7683366Sjulian#endif
7753541Sshin#ifdef USEGUARD
7853541Sshin    res->ga_Magic = GAMAGIC;
7953541Sshin#endif
8053541Sshin    res->ga_Bytes = bytes;
8153541Sshin#ifdef USEENDGUARD
8253541Sshin    *((signed char *)res + bytes - 1) = -2;
8353541Sshin#endif
8453541Sshin
8553541Sshin    return((char *)res + MALLOCALIGN);
8653541Sshin}
8753541Sshin
8853541Sshinvoid
8953541SshinFree(void *ptr, const char *file, int line)
9053541Sshin{
9164060Sdarrenr    size_t bytes;
92185571Sbz
9353541Sshin    if (ptr != NULL) {
9453541Sshin	Guard *res = (void *)((char *)ptr - MALLOCALIGN);
95225044Sbz
9653541Sshin	if (file == NULL)
97186119Sqingli		file = "unknown";
9862587Sitojun#ifdef USEGUARD
9953541Sshin	if (res->ga_Magic == GAFREE) {
10053541Sshin	    printf("free: duplicate free @ %p from %s:%d\n", ptr, file, line);
10195023Ssuz	    return;
10262587Sitojun	}
10353541Sshin	if (res->ga_Magic != GAMAGIC)
10453541Sshin	    panic("free: guard1 fail @ %p from %s:%d", ptr, file, line);
10562587Sitojun	res->ga_Magic = GAFREE;
10662587Sitojun#endif
107121161Sume#ifdef USEENDGUARD
10853541Sshin	if (*((signed char *)res + res->ga_Bytes - 1) == -1) {
10953541Sshin	    printf("free: duplicate2 free @ %p from %s:%d\n", ptr, file, line);
11053541Sshin	    return;
111171167Sgnn	}
112105199Ssam	if (*((signed char *)res + res->ga_Bytes - 1) != -2)
113171133Sgnn	    panic("free: guard2 fail @ %p + %zu from %s:%d", ptr, res->ga_Bytes - MALLOCALIGN, file, line);
114105199Ssam	*((signed char *)res + res->ga_Bytes - 1) = -1;
115171167Sgnn#endif
116105199Ssam
11753541Sshin	bytes = res->ga_Bytes;
11853541Sshin	zfree(&MallocPool, res, bytes);
119207828Skmacy#ifdef DMALLOCDEBUG
120207828Skmacy	--MallocCount;
121208043Skmacy#endif
122207828Skmacy    }
123207828Skmacy}
124207828Skmacy
12562587Sitojun
12653541Sshinvoid *
12762587SitojunCalloc(size_t n1, size_t n2, const char *file, int line)
128207369Sbz{
129185088Szec    uintptr_t bytes = (uintptr_t)n1 * (uintptr_t)n2;
130193219Srwatson    void *res;
131193219Srwatson
132193219Srwatson    if ((res = Malloc(bytes, file, line)) != NULL) {
133193219Srwatson	bzero(res, bytes);
134193219Srwatson#ifdef DMALLOCDEBUG
135193219Srwatson	if (++MallocCount > MallocMax)
136193219Srwatson	    MallocMax = MallocCount;
137195699Srwatson#endif
138195727Srwatson    }
13978064Sume    return(res);
140207369Sbz}
141207369Sbz
142207369Sbz/*
143207369Sbz * realloc() - I could be fancier here and free the old buffer before
144194971Srwatson * 	       allocating the new one (saving potential fragmentation
145194971Srwatson *	       and potential buffer copies).  But I don't bother.
146194971Srwatson */
147175162Sobrien
148175162Sobrienvoid *
149238233SbzRealloc(void *ptr, size_t size, const char *file, int line)
150238233Sbz{
151238233Sbz    void *res;
152175162Sobrien    size_t old;
15362587Sitojun
154175162Sobrien    if ((res = Malloc(size, file, line)) != NULL) {
15553541Sshin	if (ptr) {
15653541Sshin	    old = *(size_t *)((char *)ptr - MALLOCALIGN) - MALLOCALIGN;
15753541Sshin	    if (old < size)
15853541Sshin		bcopy(ptr, res, old);
15953541Sshin	    else
16053541Sshin		bcopy(ptr, res, size);
16153541Sshin	    Free(ptr, file, line);
162171259Sdelphij	} else {
16353541Sshin#ifdef DMALLOCDEBUG
16478064Sume	    if (++MallocCount > MallocMax)
16578064Sume		MallocMax = MallocCount;
16653541Sshin#ifdef EXITSTATS
167185895Szec	    if (DidAtExit == 0) {
168185895Szec		DidAtExit = 1;
169253239Shrs		atexit(mallocstats);
170253239Shrs	    }
171185088Szec#endif
172207369Sbz#endif
173185088Szec	}
174207369Sbz    }
175207369Sbz    return(res);
176207369Sbz}
177207369Sbz
178207369Sbzvoid *
179207369SbzReallocf(void *ptr, size_t size, const char *file, int line)
180185088Szec{
181190787Szec    void *res;
182190787Szec
183190787Szec    if ((res = Realloc(ptr, size, file, line)) == NULL)
184190787Szec	Free(ptr, file, line);
185190787Szec    return(res);
186207828Skmacy}
187207902Skmacy
188207902Skmacy#ifdef DMALLOCDEBUG
189207902Skmacy
190207902Skmacyvoid
191207902Skmacymallocstats(void)
192207902Skmacy{
193207902Skmacy    printf("Active Allocations: %d/%d\n", MallocCount, MallocMax);
194207902Skmacy#ifdef ZALLOCDEBUG
195207902Skmacy    zallocstats(&MallocPool);
196207902Skmacy#endif
197207902Skmacy}
198207902Skmacy
199207902Skmacy#endif
200207902Skmacy
201208171Skmacy