zalloc_malloc.c revision 124570
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 124570 2004-01-15 18:35:32Z jhb $");
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    *((char *)res + bytes - 1) = -2;
92#endif
93    return((char *)res + MALLOCALIGN);
94}
95
96void
97Free(void *ptr, const char *file, int line)
98{
99    size_t bytes;
100
101    if (ptr != NULL) {
102	Guard *res = (void *)((char *)ptr - MALLOCALIGN);
103
104	if (file == NULL)
105		file = "unknown";
106#ifdef USEGUARD
107	if (res->ga_Magic == GAFREE) {
108	    printf("free: duplicate free @ %p from %s:%d\n", ptr, file, line);
109	    return;
110	}
111	if (res->ga_Magic != GAMAGIC)
112	    panic("free: guard1 fail @ %p from %s:%d", ptr, file, line);
113	res->ga_Magic = GAFREE;
114#endif
115#ifdef USEENDGUARD
116	if (*((char *)res + res->ga_Bytes - 1) == -1) {
117	    printf("free: duplicate2 free @ %p from %s:%d\n", ptr, file, line);
118	    return;
119	}
120	if (*((char *)res + res->ga_Bytes - 1) != -2)
121	    panic("free: guard2 fail @ %p + %d from %s:%d", ptr, res->ga_Bytes - MALLOCALIGN, file, line);
122	*((char *)res + res->ga_Bytes - 1) = -1;
123#endif
124
125	bytes = res->ga_Bytes;
126	zfree(&MallocPool, res, bytes);
127#ifdef DMALLOCDEBUG
128	--MallocCount;
129#endif
130    }
131}
132
133
134void *
135Calloc(size_t n1, size_t n2, const char *file, int line)
136{
137    iaddr_t bytes = (iaddr_t)n1 * (iaddr_t)n2;
138    void *res;
139
140    if ((res = Malloc(bytes, file, line)) != NULL) {
141	bzero(res, bytes);
142#ifdef DMALLOCDEBUG
143	if (++MallocCount > MallocMax)
144	    MallocMax = MallocCount;
145#endif
146    }
147    return(res);
148}
149
150/*
151 * realloc() - I could be fancier here and free the old buffer before
152 * 	       allocating the new one (saving potential fragmentation
153 *	       and potential buffer copies).  But I don't bother.
154 */
155
156void *
157Realloc(void *ptr, size_t size, const char *file, int line)
158{
159    void *res;
160    size_t old;
161
162    if ((res = Malloc(size, file, line)) != NULL) {
163	if (ptr) {
164	    old = *(size_t *)((char *)ptr - MALLOCALIGN) - MALLOCALIGN;
165	    if (old < size)
166		bcopy(ptr, res, old);
167	    else
168		bcopy(ptr, res, size);
169	    Free(ptr, file, line);
170	} else {
171#ifdef DMALLOCDEBUG
172	    if (++MallocCount > MallocMax)
173		MallocMax = MallocCount;
174#ifdef EXITSTATS
175	    if (DidAtExit == 0) {
176		DidAtExit = 1;
177		atexit(mallocstats);
178	    }
179#endif
180#endif
181	}
182    }
183    return(res);
184}
185
186void *
187Reallocf(void *ptr, size_t size, const char *file, int line)
188{
189    void *res;
190
191    if ((res = Realloc(ptr, size, file, line)) == NULL)
192	Free(ptr, file, line);
193    return(res);
194}
195
196#ifdef DMALLOCDEBUG
197
198void
199mallocstats(void)
200{
201    printf("Active Allocations: %d/%d\n", MallocCount, MallocMax);
202#ifdef ZALLOCDEBUG
203    zallocstats(&MallocPool);
204#endif
205}
206
207#endif
208
209