1*10497fd2Schristos /* $NetBSD: alloc.c,v 1.28 2019/03/31 20:08:45 christos Exp $ */
26668f51cScgd
3ea27b7aaScgd /*
4aad01611Sagc * Copyright (c) 1993
5aad01611Sagc * The Regents of the University of California. All rights reserved.
6aad01611Sagc *
7aad01611Sagc * This code is derived from software contributed to Berkeley by
8aad01611Sagc * The Mach Operating System project at Carnegie-Mellon University.
9aad01611Sagc *
10aad01611Sagc * Redistribution and use in source and binary forms, with or without
11aad01611Sagc * modification, are permitted provided that the following conditions
12aad01611Sagc * are met:
13aad01611Sagc * 1. Redistributions of source code must retain the above copyright
14aad01611Sagc * notice, this list of conditions and the following disclaimer.
15aad01611Sagc * 2. Redistributions in binary form must reproduce the above copyright
16aad01611Sagc * notice, this list of conditions and the following disclaimer in the
17aad01611Sagc * documentation and/or other materials provided with the distribution.
18aad01611Sagc * 3. Neither the name of the University nor the names of its contributors
19aad01611Sagc * may be used to endorse or promote products derived from this software
20aad01611Sagc * without specific prior written permission.
21aad01611Sagc *
22aad01611Sagc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23aad01611Sagc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24aad01611Sagc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25aad01611Sagc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26aad01611Sagc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27aad01611Sagc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28aad01611Sagc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29aad01611Sagc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30aad01611Sagc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31aad01611Sagc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32aad01611Sagc * SUCH DAMAGE.
33aad01611Sagc *
34aad01611Sagc * @(#)alloc.c 8.1 (Berkeley) 6/11/93
35aad01611Sagc *
36aad01611Sagc *
37ea27b7aaScgd * Copyright (c) 1997 Christopher G. Demetriou. All rights reserved.
38ea27b7aaScgd * Copyright (c) 1996
39ea27b7aaScgd * Matthias Drochner. All rights reserved.
4036b52a82Sbrezak *
4136b52a82Sbrezak * This code is derived from software contributed to Berkeley by
4236b52a82Sbrezak * The Mach Operating System project at Carnegie-Mellon University.
4336b52a82Sbrezak *
4436b52a82Sbrezak * Redistribution and use in source and binary forms, with or without
4536b52a82Sbrezak * modification, are permitted provided that the following conditions
4636b52a82Sbrezak * are met:
4736b52a82Sbrezak * 1. Redistributions of source code must retain the above copyright
4836b52a82Sbrezak * notice, this list of conditions and the following disclaimer.
4936b52a82Sbrezak * 2. Redistributions in binary form must reproduce the above copyright
5036b52a82Sbrezak * notice, this list of conditions and the following disclaimer in the
5136b52a82Sbrezak * documentation and/or other materials provided with the distribution.
5236b52a82Sbrezak * 3. All advertising materials mentioning features or use of this software
5336b52a82Sbrezak * must display the following acknowledgement:
5436b52a82Sbrezak * This product includes software developed by the University of
5536b52a82Sbrezak * California, Berkeley and its contributors.
5636b52a82Sbrezak * 4. Neither the name of the University nor the names of its contributors
5736b52a82Sbrezak * may be used to endorse or promote products derived from this software
5836b52a82Sbrezak * without specific prior written permission.
5936b52a82Sbrezak *
6036b52a82Sbrezak * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
6136b52a82Sbrezak * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
6236b52a82Sbrezak * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
6336b52a82Sbrezak * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
6436b52a82Sbrezak * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
6536b52a82Sbrezak * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
6636b52a82Sbrezak * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
6736b52a82Sbrezak * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
6836b52a82Sbrezak * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
6936b52a82Sbrezak * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
7036b52a82Sbrezak * SUCH DAMAGE.
7136b52a82Sbrezak *
726668f51cScgd * @(#)alloc.c 8.1 (Berkeley) 6/11/93
7336b52a82Sbrezak *
7436b52a82Sbrezak *
7536b52a82Sbrezak * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University
7636b52a82Sbrezak * All Rights Reserved.
7736b52a82Sbrezak *
7836b52a82Sbrezak * Author: Alessandro Forin
7936b52a82Sbrezak *
8036b52a82Sbrezak * Permission to use, copy, modify and distribute this software and its
8136b52a82Sbrezak * documentation is hereby granted, provided that both the copyright
8236b52a82Sbrezak * notice and this permission notice appear in all copies of the
8336b52a82Sbrezak * software, derivative works or modified versions, and any portions
8436b52a82Sbrezak * thereof, and that both notices appear in supporting documentation.
8536b52a82Sbrezak *
8636b52a82Sbrezak * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
8736b52a82Sbrezak * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
8836b52a82Sbrezak * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
8936b52a82Sbrezak *
9036b52a82Sbrezak * Carnegie Mellon requests users of this software to return to
9136b52a82Sbrezak *
9236b52a82Sbrezak * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
9336b52a82Sbrezak * School of Computer Science
9436b52a82Sbrezak * Carnegie Mellon University
9536b52a82Sbrezak * Pittsburgh PA 15213-3890
9636b52a82Sbrezak *
9736b52a82Sbrezak * any improvements or extensions that they make and grant Carnegie the
9836b52a82Sbrezak * rights to redistribute these changes.
9936b52a82Sbrezak */
10036b52a82Sbrezak
101ea27b7aaScgd /*
102ea27b7aaScgd * Dynamic memory allocator.
103ea27b7aaScgd *
104ea27b7aaScgd * Compile options:
105ea27b7aaScgd *
106ea27b7aaScgd * HEAP_LIMIT heap limit address (defaults to "no limit").
107ea27b7aaScgd *
108ea27b7aaScgd * HEAP_START start address of heap (defaults to '&end').
109ea27b7aaScgd *
110ea27b7aaScgd * DEBUG enable debugging sanity checks.
111ea27b7aaScgd */
112ea27b7aaScgd
11320b21822Scgd #include <sys/param.h>
1148347a747Sdrochner #include "stand.h"
11520b21822Scgd
11636b52a82Sbrezak /*
117db898c55Stsutsui * Each block actually has ALIGN(unsigned int) + ALIGN(size) bytes allocated
118ea27b7aaScgd * to it, as follows:
119ea27b7aaScgd *
120db898c55Stsutsui * 0 ... (sizeof(unsigned int) - 1)
121ea27b7aaScgd * allocated or unallocated: holds size of user-data part of block.
122ea27b7aaScgd *
123db898c55Stsutsui * sizeof(unsigned int) ... (ALIGN(sizeof(unsigned int)) - 1)
124ea27b7aaScgd * allocated: unused
125ea27b7aaScgd * unallocated: depends on packing of struct fl
126ea27b7aaScgd *
127db898c55Stsutsui * ALIGN(sizeof(unsigned int)) ...
128db898c55Stsutsui * (ALIGN(sizeof(unsigned int)) + ALIGN(data size) - 1)
129ea27b7aaScgd * allocated: user data
130ea27b7aaScgd * unallocated: depends on packing of struct fl
131ea27b7aaScgd *
132ea27b7aaScgd * 'next' is only used when the block is unallocated (i.e. on the free list).
133db898c55Stsutsui * However, note that ALIGN(sizeof(unsigned int)) + ALIGN(data size) must
134ea27b7aaScgd * be at least 'sizeof(struct fl)', so that blocks can be used as structures
135ea27b7aaScgd * when on the free list.
1366896e29dSmaxv *
1376896e29dSmaxv * When HEAP_LIMIT is defined and the heap limit is reached, alloc() panics.
1386896e29dSmaxv * Otherwise, it never fails.
13936b52a82Sbrezak */
14036b52a82Sbrezak struct fl {
141db898c55Stsutsui unsigned int size;
142ea27b7aaScgd struct fl *next;
143bb7cdd7cScgd } *freelist;
14436b52a82Sbrezak
145a1d00666Sdrochner #ifdef HEAP_VARIABLE
146a8ac47ddSdrochner static char *top, *heapstart, *heaplimit;
1471c038e68Sisaki void
setheap(void * start,void * limit)1481c038e68Sisaki setheap(void *start, void *limit)
149a1d00666Sdrochner {
150a8ac47ddSdrochner heapstart = top = start;
151a1d00666Sdrochner heaplimit = limit;
152a1d00666Sdrochner }
153a8ac47ddSdrochner #define HEAP_START heapstart
154a1d00666Sdrochner #define HEAP_LIMIT heaplimit
155a8ac47ddSdrochner #else /* !HEAP_VARIABLE */
156a8ac47ddSdrochner #ifndef HEAP_START
157a8ac47ddSdrochner extern char end[];
158a8ac47ddSdrochner #define HEAP_START end
159a1d00666Sdrochner #endif
160a8ac47ddSdrochner static char *top = (char *)HEAP_START;
161a8ac47ddSdrochner #endif /* HEAP_VARIABLE */
16236b52a82Sbrezak
163c97378d0Sjoerg __compactcall void *
alloc(size_t size)1646645a4f3Schristos alloc(size_t size)
16536b52a82Sbrezak {
1661279e67bSaugustss struct fl **f = &freelist, **bestf = NULL;
167db898c55Stsutsui unsigned int bestsize = 0xffffffff; /* greater than any real size */
168ea27b7aaScgd char *help;
169ea27b7aaScgd int failed;
17036b52a82Sbrezak
171ea27b7aaScgd /* scan freelist */
172ea27b7aaScgd while (*f) {
1736645a4f3Schristos if ((size_t)(*f)->size >= size) {
1746645a4f3Schristos if ((size_t)(*f)->size == size) /* exact match */
175ea27b7aaScgd goto found;
176ea27b7aaScgd
177ea27b7aaScgd if ((*f)->size < bestsize) {
178ea27b7aaScgd /* keep best fit */
179ea27b7aaScgd bestf = f;
180ea27b7aaScgd bestsize = (*f)->size;
18136b52a82Sbrezak }
182ea27b7aaScgd }
183ea27b7aaScgd f = &((*f)->next);
184ea27b7aaScgd }
185ea27b7aaScgd
186ea27b7aaScgd /* no match in freelist if bestsize unchanged */
187ea27b7aaScgd failed = (bestsize == 0xffffffff);
188ea27b7aaScgd
189ea27b7aaScgd if (failed) { /* nothing found */
190ea27b7aaScgd /*
191ea27b7aaScgd * allocate from heap, keep chunk len in
192ea27b7aaScgd * first word
193ea27b7aaScgd */
194ea27b7aaScgd help = top;
195ea27b7aaScgd
196ea27b7aaScgd /* make _sure_ the region can hold a struct fl. */
197ea27b7aaScgd if (size < ALIGN(sizeof (struct fl *)))
198ea27b7aaScgd size = ALIGN(sizeof (struct fl *));
199db898c55Stsutsui top += ALIGN(sizeof(unsigned int)) + ALIGN(size);
200ea27b7aaScgd #ifdef HEAP_LIMIT
201ea27b7aaScgd if (top > (char *)HEAP_LIMIT)
202fbe9cca8Sjakllsch panic("heap full (%p+%zu)", help, size);
203ea27b7aaScgd #endif
204db898c55Stsutsui *(unsigned int *)(void *)help = (unsigned int)ALIGN(size);
205db898c55Stsutsui return help + ALIGN(sizeof(unsigned int));
206ea27b7aaScgd }
207ea27b7aaScgd
208ea27b7aaScgd /* we take the best fit */
209ea27b7aaScgd f = bestf;
210ea27b7aaScgd
211ea27b7aaScgd found:
212ea27b7aaScgd /* remove from freelist */
213049fd5ebSchristos help = (char *)(void *)*f;
214ea27b7aaScgd *f = (*f)->next;
215db898c55Stsutsui return help + ALIGN(sizeof(unsigned int));
21636b52a82Sbrezak }
21736b52a82Sbrezak
218c97378d0Sjoerg __compactcall void
219049fd5ebSchristos /*ARGSUSED*/
dealloc(void * ptr,size_t size)2206645a4f3Schristos dealloc(void *ptr, size_t size)
22136b52a82Sbrezak {
2221279e67bSaugustss struct fl *f =
223db898c55Stsutsui (struct fl *)(void *)((char *)(void *)ptr -
224db898c55Stsutsui ALIGN(sizeof(unsigned int)));
225ea27b7aaScgd #ifdef DEBUG
2261c038e68Sisaki if (size > (size_t)f->size) {
227*10497fd2Schristos printf("%s: %zu bytes @%p, should be <=%u\n", __func__,
228*10497fd2Schristos size, ptr, f->size);
2291c038e68Sisaki }
230a8ac47ddSdrochner
23163930d7dSthorpej if (ptr < (void *)HEAP_START)
232*10497fd2Schristos printf("%s: %p before start of heap.\n", __func__, ptr);
23363930d7dSthorpej
23463930d7dSthorpej #ifdef HEAP_LIMIT
23563930d7dSthorpej if (ptr > (void *)HEAP_LIMIT)
236*10497fd2Schristos printf("%s: %p beyond end of heap.\n", __func__, ptr);
23763930d7dSthorpej #endif
23863930d7dSthorpej #endif /* DEBUG */
239ea27b7aaScgd /* put into freelist */
24036b52a82Sbrezak f->next = freelist;
24136b52a82Sbrezak freelist = f;
24236b52a82Sbrezak }
243