1 /* $OpenBSD: alloc.c,v 1.8 2008/07/21 17:30:08 millert Exp $ */ 2 /* 3 * Copyright (c) 2002 Marc Espie. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS 15 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD 18 * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 20 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 /* 28 * area-based allocation built on malloc/free 29 */ 30 31 #include "sh.h" 32 33 struct link { 34 struct link *prev; 35 struct link *next; 36 }; 37 38 Area * 39 ainit(Area *ap) 40 { 41 ap->freelist = NULL; 42 return ap; 43 } 44 45 void 46 afreeall(Area *ap) 47 { 48 struct link *l, *l2; 49 50 for (l = ap->freelist; l != NULL; l = l2) { 51 l2 = l->next; 52 free(l); 53 } 54 ap->freelist = NULL; 55 } 56 57 #define L2P(l) ( (void *)(((char *)(l)) + sizeof(struct link)) ) 58 #define P2L(p) ( (struct link *)(((char *)(p)) - sizeof(struct link)) ) 59 60 void * 61 alloc(size_t size, Area *ap) 62 { 63 struct link *l; 64 65 l = malloc(sizeof(struct link) + size); 66 if (l == NULL) 67 internal_errorf(1, "unable to allocate memory"); 68 l->next = ap->freelist; 69 l->prev = NULL; 70 if (ap->freelist) 71 ap->freelist->prev = l; 72 ap->freelist = l; 73 74 return L2P(l); 75 } 76 77 void * 78 aresize(void *ptr, size_t size, Area *ap) 79 { 80 struct link *l, *l2, *lprev, *lnext; 81 82 if (ptr == NULL) 83 return alloc(size, ap); 84 85 l = P2L(ptr); 86 lprev = l->prev; 87 lnext = l->next; 88 89 l2 = realloc(l, sizeof(struct link) + size); 90 if (l2 == NULL) 91 internal_errorf(1, "unable to allocate memory"); 92 if (lprev) 93 lprev->next = l2; 94 else 95 ap->freelist = l2; 96 if (lnext) 97 lnext->prev = l2; 98 99 return L2P(l2); 100 } 101 102 void 103 afree(void *ptr, Area *ap) 104 { 105 struct link *l, *l2; 106 107 if (!ptr) 108 return; 109 110 l = P2L(ptr); 111 112 for (l2 = ap->freelist; l2 != NULL; l2 = l2->next) { 113 if (l == l2) 114 break; 115 } 116 if (l2 == NULL) 117 internal_errorf(1, "afree: %p not present in area %p", ptr, ap); 118 119 if (l->prev) 120 l->prev->next = l->next; 121 else 122 ap->freelist = l->next; 123 if (l->next) 124 l->next->prev = l->prev; 125 126 free(l); 127 } 128