zalloc_malloc.c revision 126206
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: head/lib/libstand/zalloc_malloc.c 126206 2004-02-25 00:52:14Z grehan $");
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
53#ifdef __alpha__
54void
55free_region(void *start, void *end)
56{
57    zextendPool(&MallocPool, start, (caddr_t)end - (caddr_t)start);
58    zfree(&MallocPool, start, (caddr_t)end - (caddr_t)start);
59}
60#endif
61
62void *
63Malloc(size_t bytes, const char *file, int line)
64{
65    Guard *res;
66
67#ifdef USEENDGUARD
68    bytes += MALLOCALIGN + 1;
69#else
70    bytes += MALLOCALIGN;
71#endif
72
73    while ((res = znalloc(&MallocPool, bytes)) == NULL) {
74	int incr = (bytes + BLKEXTENDMASK) & ~BLKEXTENDMASK;
75	char *base;
76
77	if ((base = sbrk(incr)) == (char *)-1)
78	    return(NULL);
79	zextendPool(&MallocPool, base, incr);
80	zfree(&MallocPool, base, incr);
81    }
82#ifdef DMALLOCDEBUG
83    if (++MallocCount > MallocMax)
84	MallocMax = MallocCount;
85#endif
86#ifdef USEGUARD
87    res->ga_Magic = GAMAGIC;
88#endif
89    res->ga_Bytes = bytes;
90#ifdef USEENDGUARD
91    *((signed char *)res + bytes - 1) = -2;
92#endif
93
94    return((char *)res + MALLOCALIGN);
95}
96
97void
98Free(void *ptr, const char *file, int line)
99{
100    size_t bytes;
101
102    if (ptr != NULL) {
103	Guard *res = (void *)((char *)ptr - MALLOCALIGN);
104
105	if (file == NULL)
106		file = "unknown";
107#ifdef USEGUARD
108	if (res->ga_Magic == GAFREE) {
109	    printf("free: duplicate free @ %p from %s:%d\n", ptr, file, line);
110	    return;
111	}
112	if (res->ga_Magic != GAMAGIC)
113	    panic("free: guard1 fail @ %p from %s:%d", ptr, file, line);
114	res->ga_Magic = GAFREE;
115#endif
116#ifdef USEENDGUARD
117	if (*((signed char *)res + res->ga_Bytes - 1) == -1) {
118	    printf("free: duplicate2 free @ %p from %s:%d\n", ptr, file, line);
119	    return;
120	}
121	if (*((signed char *)res + res->ga_Bytes - 1) != -2)
122	    panic("free: guard2 fail @ %p + %d from %s:%d", ptr, res->ga_Bytes - MALLOCALIGN, file, line);
123	*((signed char *)res + res->ga_Bytes - 1) = -1;
124#endif
125
126	bytes = res->ga_Bytes;
127	zfree(&MallocPool, res, bytes);
128#ifdef DMALLOCDEBUG
129	--MallocCount;
130#endif
131    }
132}
133
134
135void *
136Calloc(size_t n1, size_t n2, const char *file, int line)
137{
138    iaddr_t bytes = (iaddr_t)n1 * (iaddr_t)n2;
139    void *res;
140
141    if ((res = Malloc(bytes, file, line)) != NULL) {
142	bzero(res, bytes);
143#ifdef DMALLOCDEBUG
144	if (++MallocCount > MallocMax)
145	    MallocMax = MallocCount;
146#endif
147    }
148    return(res);
149}
150
151/*
152 * realloc() - I could be fancier here and free the old buffer before
153 * 	       allocating the new one (saving potential fragmentation
154 *	       and potential buffer copies).  But I don't bother.
155 */
156
157void *
158Realloc(void *ptr, size_t size, const char *file, int line)
159{
160    void *res;
161    size_t old;
162
163    if ((res = Malloc(size, file, line)) != NULL) {
164	if (ptr) {
165	    old = *(size_t *)((char *)ptr - MALLOCALIGN) - MALLOCALIGN;
166	    if (old < size)
167		bcopy(ptr, res, old);
168	    else
169		bcopy(ptr, res, size);
170	    Free(ptr, file, line);
171	} else {
172#ifdef DMALLOCDEBUG
173	    if (++MallocCount > MallocMax)
174		MallocMax = MallocCount;
175#ifdef EXITSTATS
176	    if (DidAtExit == 0) {
177		DidAtExit = 1;
178		atexit(mallocstats);
179	    }
180#endif
181#endif
182	}
183    }
184    return(res);
185}
186
187void *
188Reallocf(void *ptr, size_t size, const char *file, int line)
189{
190    void *res;
191
192    if ((res = Realloc(ptr, size, file, line)) == NULL)
193	Free(ptr, file, line);
194    return(res);
195}
196
197#ifdef DMALLOCDEBUG
198
199void
200mallocstats(void)
201{
202    printf("Active Allocations: %d/%d\n", MallocCount, MallocMax);
203#ifdef ZALLOCDEBUG
204    zallocstats(&MallocPool);
205#endif
206}
207
208#endif
209
210