1 1.28 christos /* $NetBSD: alloc.c,v 1.28 2019/03/31 20:08:45 christos Exp $ */ 2 1.3 cgd 3 1.5 cgd /* 4 1.17 agc * Copyright (c) 1993 5 1.17 agc * The Regents of the University of California. All rights reserved. 6 1.17 agc * 7 1.17 agc * This code is derived from software contributed to Berkeley by 8 1.17 agc * The Mach Operating System project at Carnegie-Mellon University. 9 1.17 agc * 10 1.17 agc * Redistribution and use in source and binary forms, with or without 11 1.17 agc * modification, are permitted provided that the following conditions 12 1.17 agc * are met: 13 1.17 agc * 1. Redistributions of source code must retain the above copyright 14 1.17 agc * notice, this list of conditions and the following disclaimer. 15 1.17 agc * 2. Redistributions in binary form must reproduce the above copyright 16 1.17 agc * notice, this list of conditions and the following disclaimer in the 17 1.17 agc * documentation and/or other materials provided with the distribution. 18 1.17 agc * 3. Neither the name of the University nor the names of its contributors 19 1.17 agc * may be used to endorse or promote products derived from this software 20 1.17 agc * without specific prior written permission. 21 1.17 agc * 22 1.17 agc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 1.17 agc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 1.17 agc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 1.17 agc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 1.17 agc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 1.17 agc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 1.17 agc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 1.17 agc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 1.17 agc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 1.17 agc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 1.17 agc * SUCH DAMAGE. 33 1.17 agc * 34 1.17 agc * @(#)alloc.c 8.1 (Berkeley) 6/11/93 35 1.19 perry * 36 1.17 agc * 37 1.5 cgd * Copyright (c) 1997 Christopher G. Demetriou. All rights reserved. 38 1.5 cgd * Copyright (c) 1996 39 1.5 cgd * Matthias Drochner. All rights reserved. 40 1.1 brezak * 41 1.1 brezak * This code is derived from software contributed to Berkeley by 42 1.1 brezak * The Mach Operating System project at Carnegie-Mellon University. 43 1.1 brezak * 44 1.1 brezak * Redistribution and use in source and binary forms, with or without 45 1.1 brezak * modification, are permitted provided that the following conditions 46 1.1 brezak * are met: 47 1.1 brezak * 1. Redistributions of source code must retain the above copyright 48 1.1 brezak * notice, this list of conditions and the following disclaimer. 49 1.1 brezak * 2. Redistributions in binary form must reproduce the above copyright 50 1.1 brezak * notice, this list of conditions and the following disclaimer in the 51 1.1 brezak * documentation and/or other materials provided with the distribution. 52 1.1 brezak * 3. All advertising materials mentioning features or use of this software 53 1.1 brezak * must display the following acknowledgement: 54 1.1 brezak * This product includes software developed by the University of 55 1.1 brezak * California, Berkeley and its contributors. 56 1.1 brezak * 4. Neither the name of the University nor the names of its contributors 57 1.1 brezak * may be used to endorse or promote products derived from this software 58 1.1 brezak * without specific prior written permission. 59 1.1 brezak * 60 1.1 brezak * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 61 1.1 brezak * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 62 1.1 brezak * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 63 1.1 brezak * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 64 1.1 brezak * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 65 1.1 brezak * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 66 1.1 brezak * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 67 1.1 brezak * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 68 1.1 brezak * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 69 1.1 brezak * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 70 1.1 brezak * SUCH DAMAGE. 71 1.1 brezak * 72 1.3 cgd * @(#)alloc.c 8.1 (Berkeley) 6/11/93 73 1.19 perry * 74 1.1 brezak * 75 1.1 brezak * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University 76 1.1 brezak * All Rights Reserved. 77 1.1 brezak * 78 1.1 brezak * Author: Alessandro Forin 79 1.19 perry * 80 1.1 brezak * Permission to use, copy, modify and distribute this software and its 81 1.1 brezak * documentation is hereby granted, provided that both the copyright 82 1.1 brezak * notice and this permission notice appear in all copies of the 83 1.1 brezak * software, derivative works or modified versions, and any portions 84 1.1 brezak * thereof, and that both notices appear in supporting documentation. 85 1.19 perry * 86 1.1 brezak * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 87 1.1 brezak * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 88 1.1 brezak * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 89 1.19 perry * 90 1.1 brezak * Carnegie Mellon requests users of this software to return to 91 1.19 perry * 92 1.1 brezak * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU 93 1.1 brezak * School of Computer Science 94 1.1 brezak * Carnegie Mellon University 95 1.1 brezak * Pittsburgh PA 15213-3890 96 1.19 perry * 97 1.1 brezak * any improvements or extensions that they make and grant Carnegie the 98 1.1 brezak * rights to redistribute these changes. 99 1.1 brezak */ 100 1.1 brezak 101 1.5 cgd /* 102 1.5 cgd * Dynamic memory allocator. 103 1.5 cgd * 104 1.5 cgd * Compile options: 105 1.5 cgd * 106 1.5 cgd * HEAP_LIMIT heap limit address (defaults to "no limit"). 107 1.5 cgd * 108 1.5 cgd * HEAP_START start address of heap (defaults to '&end'). 109 1.5 cgd * 110 1.5 cgd * DEBUG enable debugging sanity checks. 111 1.5 cgd */ 112 1.5 cgd 113 1.2 cgd #include <sys/param.h> 114 1.8 drochner #include "stand.h" 115 1.2 cgd 116 1.1 brezak /* 117 1.23 tsutsui * Each block actually has ALIGN(unsigned int) + ALIGN(size) bytes allocated 118 1.5 cgd * to it, as follows: 119 1.5 cgd * 120 1.23 tsutsui * 0 ... (sizeof(unsigned int) - 1) 121 1.5 cgd * allocated or unallocated: holds size of user-data part of block. 122 1.5 cgd * 123 1.23 tsutsui * sizeof(unsigned int) ... (ALIGN(sizeof(unsigned int)) - 1) 124 1.5 cgd * allocated: unused 125 1.5 cgd * unallocated: depends on packing of struct fl 126 1.5 cgd * 127 1.23 tsutsui * ALIGN(sizeof(unsigned int)) ... 128 1.23 tsutsui * (ALIGN(sizeof(unsigned int)) + ALIGN(data size) - 1) 129 1.5 cgd * allocated: user data 130 1.5 cgd * unallocated: depends on packing of struct fl 131 1.5 cgd * 132 1.5 cgd * 'next' is only used when the block is unallocated (i.e. on the free list). 133 1.23 tsutsui * However, note that ALIGN(sizeof(unsigned int)) + ALIGN(data size) must 134 1.5 cgd * be at least 'sizeof(struct fl)', so that blocks can be used as structures 135 1.5 cgd * when on the free list. 136 1.27 maxv * 137 1.27 maxv * When HEAP_LIMIT is defined and the heap limit is reached, alloc() panics. 138 1.27 maxv * Otherwise, it never fails. 139 1.1 brezak */ 140 1.1 brezak struct fl { 141 1.23 tsutsui unsigned int size; 142 1.1 brezak struct fl *next; 143 1.14 cgd } *freelist; 144 1.1 brezak 145 1.9 drochner #ifdef HEAP_VARIABLE 146 1.10 drochner static char *top, *heapstart, *heaplimit; 147 1.22 isaki void 148 1.22 isaki setheap(void *start, void *limit) 149 1.9 drochner { 150 1.22 isaki heapstart = top = start; 151 1.22 isaki heaplimit = limit; 152 1.9 drochner } 153 1.10 drochner #define HEAP_START heapstart 154 1.9 drochner #define HEAP_LIMIT heaplimit 155 1.10 drochner #else /* !HEAP_VARIABLE */ 156 1.10 drochner #ifndef HEAP_START 157 1.10 drochner extern char end[]; 158 1.10 drochner #define HEAP_START end 159 1.5 cgd #endif 160 1.22 isaki static char *top = (char *)HEAP_START; 161 1.10 drochner #endif /* HEAP_VARIABLE */ 162 1.1 brezak 163 1.25 joerg __compactcall void * 164 1.21 christos alloc(size_t size) 165 1.1 brezak { 166 1.15 augustss struct fl **f = &freelist, **bestf = NULL; 167 1.23 tsutsui unsigned int bestsize = 0xffffffff; /* greater than any real size */ 168 1.5 cgd char *help; 169 1.5 cgd int failed; 170 1.5 cgd 171 1.5 cgd /* scan freelist */ 172 1.5 cgd while (*f) { 173 1.21 christos if ((size_t)(*f)->size >= size) { 174 1.21 christos if ((size_t)(*f)->size == size) /* exact match */ 175 1.5 cgd goto found; 176 1.5 cgd 177 1.5 cgd if ((*f)->size < bestsize) { 178 1.5 cgd /* keep best fit */ 179 1.22 isaki bestf = f; 180 1.22 isaki bestsize = (*f)->size; 181 1.22 isaki } 182 1.22 isaki } 183 1.22 isaki f = &((*f)->next); 184 1.5 cgd } 185 1.1 brezak 186 1.5 cgd /* no match in freelist if bestsize unchanged */ 187 1.5 cgd failed = (bestsize == 0xffffffff); 188 1.5 cgd 189 1.5 cgd if (failed) { /* nothing found */ 190 1.22 isaki /* 191 1.5 cgd * allocate from heap, keep chunk len in 192 1.5 cgd * first word 193 1.5 cgd */ 194 1.22 isaki help = top; 195 1.5 cgd 196 1.5 cgd /* make _sure_ the region can hold a struct fl. */ 197 1.5 cgd if (size < ALIGN(sizeof (struct fl *))) 198 1.5 cgd size = ALIGN(sizeof (struct fl *)); 199 1.23 tsutsui top += ALIGN(sizeof(unsigned int)) + ALIGN(size); 200 1.5 cgd #ifdef HEAP_LIMIT 201 1.22 isaki if (top > (char *)HEAP_LIMIT) 202 1.24 jakllsch panic("heap full (%p+%zu)", help, size); 203 1.5 cgd #endif 204 1.23 tsutsui *(unsigned int *)(void *)help = (unsigned int)ALIGN(size); 205 1.23 tsutsui return help + ALIGN(sizeof(unsigned int)); 206 1.1 brezak } 207 1.5 cgd 208 1.5 cgd /* we take the best fit */ 209 1.5 cgd f = bestf; 210 1.5 cgd 211 1.5 cgd found: 212 1.22 isaki /* remove from freelist */ 213 1.22 isaki help = (char *)(void *)*f; 214 1.5 cgd *f = (*f)->next; 215 1.23 tsutsui return help + ALIGN(sizeof(unsigned int)); 216 1.1 brezak } 217 1.1 brezak 218 1.25 joerg __compactcall void 219 1.18 christos /*ARGSUSED*/ 220 1.21 christos dealloc(void *ptr, size_t size) 221 1.1 brezak { 222 1.15 augustss struct fl *f = 223 1.23 tsutsui (struct fl *)(void *)((char *)(void *)ptr - 224 1.23 tsutsui ALIGN(sizeof(unsigned int))); 225 1.5 cgd #ifdef DEBUG 226 1.22 isaki if (size > (size_t)f->size) { 227 1.28 christos printf("%s: %zu bytes @%p, should be <=%u\n", __func__, 228 1.28 christos size, ptr, f->size); 229 1.22 isaki } 230 1.10 drochner 231 1.6 thorpej if (ptr < (void *)HEAP_START) 232 1.28 christos printf("%s: %p before start of heap.\n", __func__, ptr); 233 1.6 thorpej 234 1.6 thorpej #ifdef HEAP_LIMIT 235 1.6 thorpej if (ptr > (void *)HEAP_LIMIT) 236 1.28 christos printf("%s: %p beyond end of heap.\n", __func__, ptr); 237 1.5 cgd #endif 238 1.6 thorpej #endif /* DEBUG */ 239 1.5 cgd /* put into freelist */ 240 1.1 brezak f->next = freelist; 241 1.1 brezak freelist = f; 242 1.1 brezak } 243