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