]> git.saurik.com Git - apple/bootx.git/blame - bootx.tproj/libclite.subproj/zalloc.c
BootX-81.tar.gz
[apple/bootx.git] / bootx.tproj / libclite.subproj / zalloc.c
CommitLineData
04fee52e
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
8be739c0
A
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
04fee52e 11 *
8be739c0
A
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
04fee52e
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
8be739c0
A
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
04fee52e
A
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
23 * Copyright 1993 NeXT Computer, Inc.
24 * All rights reserved.
25 *
26 * Sam's simple memory allocator.
27 *
28 */
29/*
30 * zalloc.c - malloc functions.
31 *
71019aa0 32 * Copyright (c) 1998-2003 Apple Computer, Inc.
04fee52e
A
33 *
34 * DRI: Josh de Cesare
35 */
36
37#include <libclite.h>
38
71019aa0 39#define ZALLOC_NODES 768
04fee52e
A
40
41#define ZDEBUG 0
42
43#if ZDEBUG
44int zout;
45#endif
46
47typedef struct {
48 char *start;
49 int size;
50} zmem;
51
52static int zalloc_addr;
53static int zalloc_len;
54static zmem *zalloced;
55static zmem *zavailable;
56static short availableNodes, allocedNodes, totalNodes;
57static char *zalloc_base;
58static void (*zerror)();
59
60static void zallocate(char *start,int size);
61static void zinsert(zmem *zp, int ndx);
62static void zdelete(zmem *zp, int ndx);
63static void zcoalesce(void);
64
65
66// define the block of memory that the allocator will use
67void malloc_init(char *start, int size)
68{
69 int nodes = ZALLOC_NODES;
70
71 zalloc_addr = (int)start;
72 zalloc_len = size;
73
74 zalloc_base = start;
75 totalNodes = nodes;
76 zalloced = (zmem *)zalloc_base;
77 start += sizeof(zmem) * nodes;
78 zavailable = (zmem *)start;
79 start += sizeof(zmem) * nodes;
80 zavailable[0].start = start;
81 zavailable[0].size = size;
82 availableNodes = 1;
83 allocedNodes = 0;
84}
85
86void malloc_error_init(void (*error_fn)())
87{
88 zerror = error_fn;
89}
90
91void * malloc(size_t size)
92{
93 int i;
94 char *ret = 0;
95#if 0
96 extern char _DATA__end;
97#endif
98 if (!zalloc_base) {
99 // return error until malloc_init is called.
100 return NULL;
101 }
102
103 size = ((size + 0xf) & ~0xf);
104
105 for (i=0; i<availableNodes; i++)
106 {
107 // uses first possible node, doesn't try to find best fit
108 if (zavailable[i].size == size)
109 {
110 zallocate(ret = zavailable[i].start, size);
111 zdelete(zavailable, i); availableNodes--;
112 goto done;
113 }
114 else if (zavailable[i].size > size)
115 {
116 zallocate(ret = zavailable[i].start, size);
117 zavailable[i].start += size;
118 zavailable[i].size -= size;
119 goto done;
120 }
121 }
122
123done:
124/* if (ret + size >= (char*)_sp()) _stop("stack clobbered"); */
125 if ((ret == 0) || (ret + size >= (char *)(zalloc_addr + zalloc_len)))
126 if (zerror)
127 (*zerror)(ret);
128 if (ret != 0)
129 bzero(ret, size);
130 return (void *)ret;
131}
132
133void
134free(void *pointer)
135{
8be739c0 136 int i, tsize = 0, found = 0;
04fee52e
A
137 char *start = pointer;
138
139 if (!zalloc_base) {
140 // return until malloc_init is called.
141 return;
142 }
143
144 if (!start) return;
145
146 for (i=0; i<allocedNodes; i++)
147 {
148 if (zalloced[i].start == start)
149 {
150 tsize = zalloced[i].size;
151#if ZDEBUG
152 zout -= tsize;
153 printf(" zz out %d\n",zout);
154#endif
155 zdelete(zalloced, i); allocedNodes--;
156 found = 1;
157 break;
158 }
159 }
160 if (!found) return;
161
162 for (i=0; i<availableNodes; i++)
163 {
164 if ((start+tsize) == zavailable[i].start) // merge it in
165 {
166 zavailable[i].start = start;
167 zavailable[i].size += tsize;
168 zcoalesce();
169 return;
170 }
171
172 if (i>0 && (zavailable[i-1].start + zavailable[i-1].size ==
173 start))
174 {
175 zavailable[i-1].size += tsize;
176 zcoalesce();
177 return;
178 }
179
180 if ((start+tsize) < zavailable[i].start)
181 {
182 zinsert(zavailable, i); availableNodes++;
183 zavailable[i].start = start;
184 zavailable[i].size = tsize;
185 return;
186 }
187 }
188
189 zavailable[i].start = start;
190 zavailable[i].size = tsize;
191 availableNodes++;
192 zcoalesce();
193 return;
194}
195
196
197static void
198zallocate(char *start,int size)
199{
200#if ZDEBUG
201 zout += size;
202 printf(" alloc %d, total 0x%x\n",size,zout);
203#endif
204 zalloced[allocedNodes].start = start;
205 zalloced[allocedNodes].size = size;
206 allocedNodes++;
207}
208
209static void
210zinsert(zmem *zp, int ndx)
211{
212 int i;
213 zmem *z1, *z2;
214
215 i=totalNodes-2;
216 z1 = zp + i;
217 z2 = z1+1;
218
219 for (; i>= ndx; i--, z1--, z2--)
220 {
221 z2->start = z1->start;
222 z2->size = z1->size;
223 }
224}
225
226static void
227zdelete(zmem *zp, int ndx)
228{
229 int i;
230 zmem *z1, *z2;
231
232 z1 = zp + ndx;
233 z2 = z1+1;
234
235 for (i=ndx; i<totalNodes-1; i++, z1++, z2++)
236 {
237 z1->start = z2->start;
238 z1->size = z2->size;
239 }
240}
241
242static void
243zcoalesce(void)
244{
245 int i;
246 for (i=0; i<availableNodes-1; i++)
247 {
248 if (zavailable[i].start + zavailable[i].size ==
249 zavailable[i+1].start)
250 {
251 zavailable[i].size += zavailable[i+1].size;
252 zdelete(zavailable, i+1); availableNodes--;
253 return;
254 }
255 }
256}
257
258/* This is the simplest way possible. Should fix this. */
259void *realloc(void *start, size_t newsize)
260{
261 void *newstart;
262
263 if (!zalloc_base) {
264 // return error until malloc_init is called.
265 return NULL;
266 }
267
268 newstart = malloc(newsize);
269 bcopy(start, newstart, newsize);
270 free(start);
271 return newstart;
272}
273
274