diff options
Diffstat (limited to 'alloc.c')
-rw-r--r-- | alloc.c | 127 |
1 files changed, 127 insertions, 0 deletions
@@ -0,0 +1,127 @@ +/* $NetBSD: alloc.c,v 1.10 2007/12/12 22:55:42 lukem Exp $ */ + +/* + * Copyright (c) 2002 Marc Espie. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD + * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * area-based allocation built on malloc/free + */ +#include <sys/cdefs.h> +__RCSID("$NetBSD: alloc.c,v 1.10 2007/12/12 22:55:42 lukem Exp $"); + +#include "sh.h" + +struct link { + struct link *prev; + struct link *next; +}; + +Area * +ainit(Area *ap) +{ + ap->freelist = NULL; + return ap; +} + +void +afreeall(Area *ap) +{ + struct link *l, *l2; + + for (l = ap->freelist; l != NULL; l = l2) { + l2 = l->next; + free(l); + } + ap->freelist = NULL; +} + +#define L2P(l) ( (void *)(((char *)(l)) + sizeof(struct link)) ) +#define P2L(p) ( (struct link *)(((char *)(p)) - sizeof(struct link)) ) + +/* coverity[+alloc] */ +void * +alloc(size_t size, Area *ap) +{ + struct link *l; + + l = malloc(sizeof(struct link) + size); + if (l == NULL) + internal_errorf(1, "unable to allocate memory"); + l->next = ap->freelist; + l->prev = NULL; + if (ap->freelist) + ap->freelist->prev = l; + ap->freelist = l; + + return L2P(l); +} + +/* coverity[+alloc] */ +/* coverity[+free : arg-0] */ +void * +aresize(void *ptr, size_t size, Area *ap) +{ + struct link *l, *l2, *lprev, *lnext; + + if (ptr == NULL) + return alloc(size, ap); + + l = P2L(ptr); + lprev = l->prev; + lnext = l->next; + + l2 = realloc(l, sizeof(struct link) + size); + if (l2 == NULL) + internal_errorf(1, "unable to allocate memory"); + if (lprev) + lprev->next = l2; + else + ap->freelist = l2; + if (lnext) + lnext->prev = l2; + + return L2P(l2); +} + +/* coverity[+free : arg-0] */ +void +afree(void *ptr, Area *ap) +{ + struct link *l; + + if (!ptr) + return; + + l = P2L(ptr); + + if (l->prev) + l->prev->next = l->next; + else + ap->freelist = l->next; + if (l->next) + l->next->prev = l->prev; + + free(l); +} |