1ca987d46SWarner Losh /*
2ca987d46SWarner Losh * This module derived from code donated to the FreeBSD Project by
3ca987d46SWarner Losh * Matthew Dillon <dillon@backplane.com>
4ca987d46SWarner Losh *
5ca987d46SWarner Losh * Copyright (c) 1998 The FreeBSD Project
6ca987d46SWarner Losh * All rights reserved.
7ca987d46SWarner Losh *
8ca987d46SWarner Losh * Redistribution and use in source and binary forms, with or without
9ca987d46SWarner Losh * modification, are permitted provided that the following conditions
10ca987d46SWarner Losh * are met:
11ca987d46SWarner Losh * 1. Redistributions of source code must retain the above copyright
12ca987d46SWarner Losh * notice, this list of conditions and the following disclaimer.
13ca987d46SWarner Losh * 2. Redistributions in binary form must reproduce the above copyright
14ca987d46SWarner Losh * notice, this list of conditions and the following disclaimer in the
15ca987d46SWarner Losh * documentation and/or other materials provided with the distribution.
16ca987d46SWarner Losh *
17ca987d46SWarner Losh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18ca987d46SWarner Losh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19ca987d46SWarner Losh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20ca987d46SWarner Losh * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21ca987d46SWarner Losh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22ca987d46SWarner Losh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23ca987d46SWarner Losh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24ca987d46SWarner Losh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25ca987d46SWarner Losh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26ca987d46SWarner Losh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27ca987d46SWarner Losh * SUCH DAMAGE.
28ca987d46SWarner Losh */
29ca987d46SWarner Losh
30ca987d46SWarner Losh /*
31ca987d46SWarner Losh * MALLOC.C - malloc equivalent, runs on top of zalloc and uses sbrk
32ca987d46SWarner Losh */
33ca987d46SWarner Losh
34ca987d46SWarner Losh #include "zalloc_defs.h"
35ca987d46SWarner Losh
36ca987d46SWarner Losh static MemPool MallocPool;
37ca987d46SWarner Losh
38ca987d46SWarner Losh #ifdef DMALLOCDEBUG
39ca987d46SWarner Losh static int MallocMax;
40ca987d46SWarner Losh static int MallocCount;
41ca987d46SWarner Losh
42ca987d46SWarner Losh void mallocstats(void);
43ca987d46SWarner Losh #endif
44ca987d46SWarner Losh
45ca987d46SWarner Losh #ifdef malloc
46ca987d46SWarner Losh #undef malloc
47ca987d46SWarner Losh #undef free
48ca987d46SWarner Losh #endif
49ca987d46SWarner Losh
5011db1a16SToomas Soome static void *Malloc_align(size_t, size_t);
5111db1a16SToomas Soome
52*ed19b7c5SSimon J. Gerraty #ifndef MIN
53*ed19b7c5SSimon J. Gerraty # define MIN(a,b) ((a) <= (b)) ? (a) : (b)
54*ed19b7c5SSimon J. Gerraty #endif
55*ed19b7c5SSimon J. Gerraty
56ca987d46SWarner Losh void *
Malloc(size_t bytes,const char * file __unused,int line __unused)5711db1a16SToomas Soome Malloc(size_t bytes, const char *file __unused, int line __unused)
5811db1a16SToomas Soome {
5911db1a16SToomas Soome return (Malloc_align(bytes, 1));
6011db1a16SToomas Soome }
6111db1a16SToomas Soome
6211db1a16SToomas Soome void *
Memalign(size_t alignment,size_t bytes,const char * file __unused,int line __unused)6311db1a16SToomas Soome Memalign(size_t alignment, size_t bytes, const char *file __unused,
6411db1a16SToomas Soome int line __unused)
6511db1a16SToomas Soome {
6611db1a16SToomas Soome if (alignment == 0)
6711db1a16SToomas Soome alignment = 1;
6811db1a16SToomas Soome
6911db1a16SToomas Soome return (Malloc_align(bytes, alignment));
7011db1a16SToomas Soome }
7111db1a16SToomas Soome
7211db1a16SToomas Soome static void *
Malloc_align(size_t bytes,size_t alignment)7311db1a16SToomas Soome Malloc_align(size_t bytes, size_t alignment)
74ca987d46SWarner Losh {
75ca987d46SWarner Losh Guard *res;
76ca987d46SWarner Losh
77ca987d46SWarner Losh #ifdef USEENDGUARD
78ca987d46SWarner Losh bytes += MALLOCALIGN + 1;
79ca987d46SWarner Losh #else
80ca987d46SWarner Losh bytes += MALLOCALIGN;
81ca987d46SWarner Losh #endif
82ca987d46SWarner Losh
8311db1a16SToomas Soome while ((res = znalloc(&MallocPool, bytes, alignment)) == NULL) {
84ca987d46SWarner Losh int incr = (bytes + BLKEXTENDMASK) & ~BLKEXTENDMASK;
85ca987d46SWarner Losh char *base;
86ca987d46SWarner Losh
87ca987d46SWarner Losh if ((base = sbrk(incr)) == (char *)-1)
88ca987d46SWarner Losh return (NULL);
89ca987d46SWarner Losh zextendPool(&MallocPool, base, incr);
90ca987d46SWarner Losh zfree(&MallocPool, base, incr);
91ca987d46SWarner Losh }
92ca987d46SWarner Losh #ifdef DMALLOCDEBUG
93ca987d46SWarner Losh if (++MallocCount > MallocMax)
94ca987d46SWarner Losh MallocMax = MallocCount;
95ca987d46SWarner Losh #endif
96ca987d46SWarner Losh #ifdef USEGUARD
97ca987d46SWarner Losh res->ga_Magic = GAMAGIC;
98ca987d46SWarner Losh #endif
99ca987d46SWarner Losh res->ga_Bytes = bytes;
100ca987d46SWarner Losh #ifdef USEENDGUARD
101ca987d46SWarner Losh *((signed char *)res + bytes - 1) = -2;
102ca987d46SWarner Losh #endif
103ca987d46SWarner Losh
104ca987d46SWarner Losh return ((char *)res + MALLOCALIGN);
105ca987d46SWarner Losh }
106ca987d46SWarner Losh
107ca987d46SWarner Losh void
Free(void * ptr,const char * file,int line)108ca987d46SWarner Losh Free(void *ptr, const char *file, int line)
109ca987d46SWarner Losh {
110ca987d46SWarner Losh size_t bytes;
111ca987d46SWarner Losh
112ca987d46SWarner Losh if (ptr != NULL) {
113ca987d46SWarner Losh Guard *res = (void *)((char *)ptr - MALLOCALIGN);
114ca987d46SWarner Losh
115ca987d46SWarner Losh if (file == NULL)
116ca987d46SWarner Losh file = "unknown";
117ca987d46SWarner Losh #ifdef USEGUARD
118ca987d46SWarner Losh if (res->ga_Magic == GAFREE) {
119e57c0c2aSToomas Soome printf("free: duplicate free @ %p from %s:%d\n",
120e57c0c2aSToomas Soome ptr, file, line);
121ca987d46SWarner Losh return;
122ca987d46SWarner Losh }
123*ed19b7c5SSimon J. Gerraty if (res->ga_Magic != GAMAGIC) {
124*ed19b7c5SSimon J. Gerraty size_t dump_bytes;
125*ed19b7c5SSimon J. Gerraty
126*ed19b7c5SSimon J. Gerraty dump_bytes = MIN((ptr - MallocPool.mp_Base), 512);
127*ed19b7c5SSimon J. Gerraty hexdump(ptr - dump_bytes, dump_bytes);
128e57c0c2aSToomas Soome panic("free: guard1 fail @ %p from %s:%d",
129e57c0c2aSToomas Soome ptr, file, line);
130*ed19b7c5SSimon J. Gerraty }
131ca987d46SWarner Losh res->ga_Magic = GAFREE;
132ca987d46SWarner Losh #endif
133ca987d46SWarner Losh #ifdef USEENDGUARD
134ca987d46SWarner Losh if (*((signed char *)res + res->ga_Bytes - 1) == -1) {
135e57c0c2aSToomas Soome printf("free: duplicate2 free @ %p from %s:%d\n",
136e57c0c2aSToomas Soome ptr, file, line);
137ca987d46SWarner Losh return;
138ca987d46SWarner Losh }
139ca987d46SWarner Losh if (*((signed char *)res + res->ga_Bytes - 1) != -2)
140e57c0c2aSToomas Soome panic("free: guard2 fail @ %p + %zu from %s:%d",
141e57c0c2aSToomas Soome ptr, res->ga_Bytes - MALLOCALIGN, file, line);
142ca987d46SWarner Losh *((signed char *)res + res->ga_Bytes - 1) = -1;
143ca987d46SWarner Losh #endif
144ca987d46SWarner Losh
145ca987d46SWarner Losh bytes = res->ga_Bytes;
146ca987d46SWarner Losh zfree(&MallocPool, res, bytes);
147ca987d46SWarner Losh #ifdef DMALLOCDEBUG
148ca987d46SWarner Losh --MallocCount;
149ca987d46SWarner Losh #endif
150ca987d46SWarner Losh }
151ca987d46SWarner Losh }
152ca987d46SWarner Losh
153ca987d46SWarner Losh
154ca987d46SWarner Losh void *
Calloc(size_t n1,size_t n2,const char * file,int line)155ca987d46SWarner Losh Calloc(size_t n1, size_t n2, const char *file, int line)
156ca987d46SWarner Losh {
157ca987d46SWarner Losh uintptr_t bytes = (uintptr_t)n1 * (uintptr_t)n2;
158ca987d46SWarner Losh void *res;
159ca987d46SWarner Losh
160ca987d46SWarner Losh if ((res = Malloc(bytes, file, line)) != NULL) {
161ca987d46SWarner Losh bzero(res, bytes);
162ca987d46SWarner Losh #ifdef DMALLOCDEBUG
163ca987d46SWarner Losh if (++MallocCount > MallocMax)
164ca987d46SWarner Losh MallocMax = MallocCount;
165ca987d46SWarner Losh #endif
166ca987d46SWarner Losh }
167ca987d46SWarner Losh return (res);
168ca987d46SWarner Losh }
169ca987d46SWarner Losh
170ca987d46SWarner Losh /*
171ca987d46SWarner Losh * realloc() - I could be fancier here and free the old buffer before
172ca987d46SWarner Losh * allocating the new one (saving potential fragmentation
173ca987d46SWarner Losh * and potential buffer copies). But I don't bother.
174ca987d46SWarner Losh */
175ca987d46SWarner Losh
176ca987d46SWarner Losh void *
Realloc(void * ptr,size_t size,const char * file,int line)177ca987d46SWarner Losh Realloc(void *ptr, size_t size, const char *file, int line)
178ca987d46SWarner Losh {
179ca987d46SWarner Losh void *res;
180ca987d46SWarner Losh size_t old;
181ca987d46SWarner Losh
182ca987d46SWarner Losh if ((res = Malloc(size, file, line)) != NULL) {
183e57c0c2aSToomas Soome if (ptr != NULL) {
184144c4ca0SToomas Soome Guard *g = (Guard *)((char *)ptr - MALLOCALIGN);
185144c4ca0SToomas Soome
186144c4ca0SToomas Soome old = g->ga_Bytes - MALLOCALIGN;
187ca987d46SWarner Losh if (old < size)
188ca987d46SWarner Losh bcopy(ptr, res, old);
189ca987d46SWarner Losh else
190ca987d46SWarner Losh bcopy(ptr, res, size);
191ca987d46SWarner Losh Free(ptr, file, line);
192ca987d46SWarner Losh } else {
193ca987d46SWarner Losh #ifdef DMALLOCDEBUG
194ca987d46SWarner Losh if (++MallocCount > MallocMax)
195ca987d46SWarner Losh MallocMax = MallocCount;
196ca987d46SWarner Losh #ifdef EXITSTATS
197ca987d46SWarner Losh if (DidAtExit == 0) {
198ca987d46SWarner Losh DidAtExit = 1;
199ca987d46SWarner Losh atexit(mallocstats);
200ca987d46SWarner Losh }
201ca987d46SWarner Losh #endif
202ca987d46SWarner Losh #endif
203ca987d46SWarner Losh }
204ca987d46SWarner Losh }
205ca987d46SWarner Losh return (res);
206ca987d46SWarner Losh }
207ca987d46SWarner Losh
208ca987d46SWarner Losh void *
Reallocf(void * ptr,size_t size,const char * file,int line)209ca987d46SWarner Losh Reallocf(void *ptr, size_t size, const char *file, int line)
210ca987d46SWarner Losh {
211ca987d46SWarner Losh void *res;
212ca987d46SWarner Losh
213ca987d46SWarner Losh if ((res = Realloc(ptr, size, file, line)) == NULL)
214ca987d46SWarner Losh Free(ptr, file, line);
215ca987d46SWarner Losh return (res);
216ca987d46SWarner Losh }
217ca987d46SWarner Losh
218ca987d46SWarner Losh #ifdef DMALLOCDEBUG
219ca987d46SWarner Losh
220ca987d46SWarner Losh void
mallocstats(void)221ca987d46SWarner Losh mallocstats(void)
222ca987d46SWarner Losh {
223ca987d46SWarner Losh printf("Active Allocations: %d/%d\n", MallocCount, MallocMax);
224ca987d46SWarner Losh #ifdef ZALLOCDEBUG
225ca987d46SWarner Losh zallocstats(&MallocPool);
226ca987d46SWarner Losh #endif
227ca987d46SWarner Losh }
228ca987d46SWarner Losh
229ca987d46SWarner Losh #endif
230