xref: /titanic_51/usr/src/boot/lib/libstand/zalloc_malloc.c (revision 4a5d661a82b942b6538acd26209d959ce98b593a)
1*4a5d661aSToomas Soome /*
2*4a5d661aSToomas Soome  * This module derived from code donated to the FreeBSD Project by
3*4a5d661aSToomas Soome  * Matthew Dillon <dillon@backplane.com>
4*4a5d661aSToomas Soome  *
5*4a5d661aSToomas Soome  * Copyright (c) 1998 The FreeBSD Project
6*4a5d661aSToomas Soome  * All rights reserved.
7*4a5d661aSToomas Soome  *
8*4a5d661aSToomas Soome  * Redistribution and use in source and binary forms, with or without
9*4a5d661aSToomas Soome  * modification, are permitted provided that the following conditions
10*4a5d661aSToomas Soome  * are met:
11*4a5d661aSToomas Soome  * 1. Redistributions of source code must retain the above copyright
12*4a5d661aSToomas Soome  *    notice, this list of conditions and the following disclaimer.
13*4a5d661aSToomas Soome  * 2. Redistributions in binary form must reproduce the above copyright
14*4a5d661aSToomas Soome  *    notice, this list of conditions and the following disclaimer in the
15*4a5d661aSToomas Soome  *    documentation and/or other materials provided with the distribution.
16*4a5d661aSToomas Soome  *
17*4a5d661aSToomas Soome  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18*4a5d661aSToomas Soome  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19*4a5d661aSToomas Soome  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20*4a5d661aSToomas Soome  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21*4a5d661aSToomas Soome  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*4a5d661aSToomas Soome  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23*4a5d661aSToomas Soome  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24*4a5d661aSToomas Soome  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25*4a5d661aSToomas Soome  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26*4a5d661aSToomas Soome  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27*4a5d661aSToomas Soome  * SUCH DAMAGE.
28*4a5d661aSToomas Soome  */
29*4a5d661aSToomas Soome 
30*4a5d661aSToomas Soome #include <sys/cdefs.h>
31*4a5d661aSToomas Soome __FBSDID("$FreeBSD$");
32*4a5d661aSToomas Soome 
33*4a5d661aSToomas Soome /*
34*4a5d661aSToomas Soome  * MALLOC.C - malloc equivalent, runs on top of zalloc and uses sbrk
35*4a5d661aSToomas Soome  */
36*4a5d661aSToomas Soome 
37*4a5d661aSToomas Soome #include "zalloc_defs.h"
38*4a5d661aSToomas Soome 
39*4a5d661aSToomas Soome static MemPool	MallocPool;
40*4a5d661aSToomas Soome 
41*4a5d661aSToomas Soome #ifdef DMALLOCDEBUG
42*4a5d661aSToomas Soome static int MallocMax;
43*4a5d661aSToomas Soome static int MallocCount;
44*4a5d661aSToomas Soome 
45*4a5d661aSToomas Soome void mallocstats(void);
46*4a5d661aSToomas Soome #endif
47*4a5d661aSToomas Soome 
48*4a5d661aSToomas Soome #ifdef malloc
49*4a5d661aSToomas Soome #undef malloc
50*4a5d661aSToomas Soome #undef free
51*4a5d661aSToomas Soome #endif
52*4a5d661aSToomas Soome 
53*4a5d661aSToomas Soome void *
54*4a5d661aSToomas Soome Malloc(size_t bytes, const char *file, int line)
55*4a5d661aSToomas Soome {
56*4a5d661aSToomas Soome     Guard *res;
57*4a5d661aSToomas Soome 
58*4a5d661aSToomas Soome #ifdef USEENDGUARD
59*4a5d661aSToomas Soome     bytes += MALLOCALIGN + 1;
60*4a5d661aSToomas Soome #else
61*4a5d661aSToomas Soome     bytes += MALLOCALIGN;
62*4a5d661aSToomas Soome #endif
63*4a5d661aSToomas Soome 
64*4a5d661aSToomas Soome     while ((res = znalloc(&MallocPool, bytes)) == NULL) {
65*4a5d661aSToomas Soome 	int incr = (bytes + BLKEXTENDMASK) & ~BLKEXTENDMASK;
66*4a5d661aSToomas Soome 	char *base;
67*4a5d661aSToomas Soome 
68*4a5d661aSToomas Soome 	if ((base = sbrk(incr)) == (char *)-1)
69*4a5d661aSToomas Soome 	    return(NULL);
70*4a5d661aSToomas Soome 	zextendPool(&MallocPool, base, incr);
71*4a5d661aSToomas Soome 	zfree(&MallocPool, base, incr);
72*4a5d661aSToomas Soome     }
73*4a5d661aSToomas Soome #ifdef DMALLOCDEBUG
74*4a5d661aSToomas Soome     if (++MallocCount > MallocMax)
75*4a5d661aSToomas Soome 	MallocMax = MallocCount;
76*4a5d661aSToomas Soome #endif
77*4a5d661aSToomas Soome #ifdef USEGUARD
78*4a5d661aSToomas Soome     res->ga_Magic = GAMAGIC;
79*4a5d661aSToomas Soome #endif
80*4a5d661aSToomas Soome     res->ga_Bytes = bytes;
81*4a5d661aSToomas Soome #ifdef USEENDGUARD
82*4a5d661aSToomas Soome     *((signed char *)res + bytes - 1) = -2;
83*4a5d661aSToomas Soome #endif
84*4a5d661aSToomas Soome 
85*4a5d661aSToomas Soome     return((char *)res + MALLOCALIGN);
86*4a5d661aSToomas Soome }
87*4a5d661aSToomas Soome 
88*4a5d661aSToomas Soome void
89*4a5d661aSToomas Soome Free(void *ptr, const char *file, int line)
90*4a5d661aSToomas Soome {
91*4a5d661aSToomas Soome     size_t bytes;
92*4a5d661aSToomas Soome 
93*4a5d661aSToomas Soome     if (ptr != NULL) {
94*4a5d661aSToomas Soome 	Guard *res = (void *)((char *)ptr - MALLOCALIGN);
95*4a5d661aSToomas Soome 
96*4a5d661aSToomas Soome 	if (file == NULL)
97*4a5d661aSToomas Soome 		file = "unknown";
98*4a5d661aSToomas Soome #ifdef USEGUARD
99*4a5d661aSToomas Soome 	if (res->ga_Magic == GAFREE) {
100*4a5d661aSToomas Soome 	    printf("free: duplicate free @ %p from %s:%d\n", ptr, file, line);
101*4a5d661aSToomas Soome 	    return;
102*4a5d661aSToomas Soome 	}
103*4a5d661aSToomas Soome 	if (res->ga_Magic != GAMAGIC)
104*4a5d661aSToomas Soome 	    panic("free: guard1 fail @ %p from %s:%d", ptr, file, line);
105*4a5d661aSToomas Soome 	res->ga_Magic = GAFREE;
106*4a5d661aSToomas Soome #endif
107*4a5d661aSToomas Soome #ifdef USEENDGUARD
108*4a5d661aSToomas Soome 	if (*((signed char *)res + res->ga_Bytes - 1) == -1) {
109*4a5d661aSToomas Soome 	    printf("free: duplicate2 free @ %p from %s:%d\n", ptr, file, line);
110*4a5d661aSToomas Soome 	    return;
111*4a5d661aSToomas Soome 	}
112*4a5d661aSToomas Soome 	if (*((signed char *)res + res->ga_Bytes - 1) != -2)
113*4a5d661aSToomas Soome 	    panic("free: guard2 fail @ %p + %zu from %s:%d", ptr, res->ga_Bytes - MALLOCALIGN, file, line);
114*4a5d661aSToomas Soome 	*((signed char *)res + res->ga_Bytes - 1) = -1;
115*4a5d661aSToomas Soome #endif
116*4a5d661aSToomas Soome 
117*4a5d661aSToomas Soome 	bytes = res->ga_Bytes;
118*4a5d661aSToomas Soome 	zfree(&MallocPool, res, bytes);
119*4a5d661aSToomas Soome #ifdef DMALLOCDEBUG
120*4a5d661aSToomas Soome 	--MallocCount;
121*4a5d661aSToomas Soome #endif
122*4a5d661aSToomas Soome     }
123*4a5d661aSToomas Soome }
124*4a5d661aSToomas Soome 
125*4a5d661aSToomas Soome 
126*4a5d661aSToomas Soome void *
127*4a5d661aSToomas Soome Calloc(size_t n1, size_t n2, const char *file, int line)
128*4a5d661aSToomas Soome {
129*4a5d661aSToomas Soome     uintptr_t bytes = (uintptr_t)n1 * (uintptr_t)n2;
130*4a5d661aSToomas Soome     void *res;
131*4a5d661aSToomas Soome 
132*4a5d661aSToomas Soome     if ((res = Malloc(bytes, file, line)) != NULL) {
133*4a5d661aSToomas Soome 	bzero(res, bytes);
134*4a5d661aSToomas Soome #ifdef DMALLOCDEBUG
135*4a5d661aSToomas Soome 	if (++MallocCount > MallocMax)
136*4a5d661aSToomas Soome 	    MallocMax = MallocCount;
137*4a5d661aSToomas Soome #endif
138*4a5d661aSToomas Soome     }
139*4a5d661aSToomas Soome     return(res);
140*4a5d661aSToomas Soome }
141*4a5d661aSToomas Soome 
142*4a5d661aSToomas Soome /*
143*4a5d661aSToomas Soome  * realloc() - I could be fancier here and free the old buffer before
144*4a5d661aSToomas Soome  * 	       allocating the new one (saving potential fragmentation
145*4a5d661aSToomas Soome  *	       and potential buffer copies).  But I don't bother.
146*4a5d661aSToomas Soome  */
147*4a5d661aSToomas Soome 
148*4a5d661aSToomas Soome void *
149*4a5d661aSToomas Soome Realloc(void *ptr, size_t size, const char *file, int line)
150*4a5d661aSToomas Soome {
151*4a5d661aSToomas Soome     void *res;
152*4a5d661aSToomas Soome     size_t old;
153*4a5d661aSToomas Soome 
154*4a5d661aSToomas Soome     if ((res = Malloc(size, file, line)) != NULL) {
155*4a5d661aSToomas Soome 	if (ptr) {
156*4a5d661aSToomas Soome 	    old = *(size_t *)((char *)ptr - MALLOCALIGN) - MALLOCALIGN;
157*4a5d661aSToomas Soome 	    if (old < size)
158*4a5d661aSToomas Soome 		bcopy(ptr, res, old);
159*4a5d661aSToomas Soome 	    else
160*4a5d661aSToomas Soome 		bcopy(ptr, res, size);
161*4a5d661aSToomas Soome 	    Free(ptr, file, line);
162*4a5d661aSToomas Soome 	} else {
163*4a5d661aSToomas Soome #ifdef DMALLOCDEBUG
164*4a5d661aSToomas Soome 	    if (++MallocCount > MallocMax)
165*4a5d661aSToomas Soome 		MallocMax = MallocCount;
166*4a5d661aSToomas Soome #ifdef EXITSTATS
167*4a5d661aSToomas Soome 	    if (DidAtExit == 0) {
168*4a5d661aSToomas Soome 		DidAtExit = 1;
169*4a5d661aSToomas Soome 		atexit(mallocstats);
170*4a5d661aSToomas Soome 	    }
171*4a5d661aSToomas Soome #endif
172*4a5d661aSToomas Soome #endif
173*4a5d661aSToomas Soome 	}
174*4a5d661aSToomas Soome     }
175*4a5d661aSToomas Soome     return(res);
176*4a5d661aSToomas Soome }
177*4a5d661aSToomas Soome 
178*4a5d661aSToomas Soome void *
179*4a5d661aSToomas Soome Reallocf(void *ptr, size_t size, const char *file, int line)
180*4a5d661aSToomas Soome {
181*4a5d661aSToomas Soome     void *res;
182*4a5d661aSToomas Soome 
183*4a5d661aSToomas Soome     if ((res = Realloc(ptr, size, file, line)) == NULL)
184*4a5d661aSToomas Soome 	Free(ptr, file, line);
185*4a5d661aSToomas Soome     return(res);
186*4a5d661aSToomas Soome }
187*4a5d661aSToomas Soome 
188*4a5d661aSToomas Soome #ifdef DMALLOCDEBUG
189*4a5d661aSToomas Soome 
190*4a5d661aSToomas Soome void
191*4a5d661aSToomas Soome mallocstats(void)
192*4a5d661aSToomas Soome {
193*4a5d661aSToomas Soome     printf("Active Allocations: %d/%d\n", MallocCount, MallocMax);
194*4a5d661aSToomas Soome #ifdef ZALLOCDEBUG
195*4a5d661aSToomas Soome     zallocstats(&MallocPool);
196*4a5d661aSToomas Soome #endif
197*4a5d661aSToomas Soome }
198*4a5d661aSToomas Soome 
199*4a5d661aSToomas Soome #endif
200*4a5d661aSToomas Soome 
201