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