Thorsten Glaser | ba2627c | 2010-08-24 18:21:37 +0200 | [diff] [blame^] | 1 | /*- |
| 2 | * Copyright © 2009 |
| 3 | * Thorsten Glaser <tg@mirbsd.org> |
| 4 | * |
| 5 | * Provided that these terms and disclaimer and all copyright notices |
| 6 | * are retained or reproduced in an accompanying document, permission |
| 7 | * is granted to deal in this work without restriction, including un‐ |
| 8 | * limited rights to use, publicly perform, distribute, sell, modify, |
| 9 | * merge, give away, or sublicence. |
| 10 | * |
| 11 | * This work is provided “AS IS” and WITHOUT WARRANTY of any kind, to |
| 12 | * the utmost extent permitted by applicable law, neither express nor |
| 13 | * implied; without malicious intent or gross negligence. In no event |
| 14 | * may a licensor, author or contributor be held liable for indirect, |
| 15 | * direct, other damage, loss, or other issues arising in any way out |
| 16 | * of dealing in the work, even if advised of the possibility of such |
| 17 | * damage or existence of a defect, except proven that it results out |
| 18 | * of said person’s immediate fault when using the work as intended. |
| 19 | */ |
| 20 | |
| 21 | #include "sh.h" |
| 22 | |
| 23 | __RCSID("$MirOS: src/bin/mksh/lalloc.c,v 1.11 2009/08/08 13:08:51 tg Exp $"); |
| 24 | |
| 25 | /* build with CPPFLAGS+= -DUSE_REALLOC_MALLOC=0 on ancient systems */ |
| 26 | #if defined(USE_REALLOC_MALLOC) && (USE_REALLOC_MALLOC == 0) |
| 27 | #define remalloc(p,n) ((p) == NULL ? malloc(n) : realloc((p), (n))) |
| 28 | #else |
| 29 | #define remalloc(p,n) realloc((p), (n)) |
| 30 | #endif |
| 31 | |
| 32 | #define ALLOC_ISUNALIGNED(p) (((ptrdiff_t)(p)) % ALLOC_SIZE) |
| 33 | |
| 34 | static ALLOC_ITEM *findptr(ALLOC_ITEM **, char *, Area *); |
| 35 | |
| 36 | void |
| 37 | ainit(Area *ap) |
| 38 | { |
| 39 | /* area pointer is an ALLOC_ITEM, just the head of the list */ |
| 40 | ap->next = NULL; |
| 41 | } |
| 42 | |
| 43 | static ALLOC_ITEM * |
| 44 | findptr(ALLOC_ITEM **lpp, char *ptr, Area *ap) |
| 45 | { |
| 46 | void *lp; |
| 47 | |
| 48 | #ifndef MKSH_SMALL |
| 49 | if (ALLOC_ISUNALIGNED(ptr)) |
| 50 | goto fail; |
| 51 | #endif |
| 52 | /* get address of ALLOC_ITEM from user item */ |
| 53 | /* |
| 54 | * note: the alignment of "ptr" to ALLOC_SIZE is checked |
| 55 | * above; the "void *" gets us rid of a gcc 2.95 warning |
| 56 | */ |
| 57 | *lpp = (lp = ptr - ALLOC_SIZE); |
| 58 | /* search for allocation item in group list */ |
| 59 | while (ap->next != lp) |
| 60 | if ((ap = ap->next) == NULL) { |
| 61 | #ifndef MKSH_SMALL |
| 62 | fail: |
| 63 | #endif |
| 64 | internal_errorf("rogue pointer %p", ptr); |
| 65 | } |
| 66 | return (ap); |
| 67 | } |
| 68 | |
| 69 | void * |
| 70 | aresize(void *ptr, size_t numb, Area *ap) |
| 71 | { |
| 72 | ALLOC_ITEM *lp = NULL; |
| 73 | |
| 74 | /* resizing (true) or newly allocating? */ |
| 75 | if (ptr != NULL) { |
| 76 | ALLOC_ITEM *pp; |
| 77 | |
| 78 | pp = findptr(&lp, ptr, ap); |
| 79 | pp->next = lp->next; |
| 80 | } |
| 81 | |
| 82 | if ((numb >= SIZE_MAX - ALLOC_SIZE) || |
| 83 | (lp = remalloc(lp, numb + ALLOC_SIZE)) == NULL |
| 84 | #ifndef MKSH_SMALL |
| 85 | || ALLOC_ISUNALIGNED(lp) |
| 86 | #endif |
| 87 | ) |
| 88 | internal_errorf("cannot allocate %lu data bytes", |
| 89 | (unsigned long)numb); |
| 90 | /* this only works because Area is an ALLOC_ITEM */ |
| 91 | lp->next = ap->next; |
| 92 | ap->next = lp; |
| 93 | /* return user item address */ |
| 94 | return ((char *)lp + ALLOC_SIZE); |
| 95 | } |
| 96 | |
| 97 | void |
| 98 | afree(void *ptr, Area *ap) |
| 99 | { |
| 100 | if (ptr != NULL) { |
| 101 | ALLOC_ITEM *lp, *pp; |
| 102 | |
| 103 | pp = findptr(&lp, ptr, ap); |
| 104 | /* unhook */ |
| 105 | pp->next = lp->next; |
| 106 | /* now free ALLOC_ITEM */ |
| 107 | free(lp); |
| 108 | } |
| 109 | } |
| 110 | |
| 111 | void |
| 112 | afreeall(Area *ap) |
| 113 | { |
| 114 | ALLOC_ITEM *lp; |
| 115 | |
| 116 | /* traverse group (linked list) */ |
| 117 | while ((lp = ap->next) != NULL) { |
| 118 | /* make next ALLOC_ITEM head of list */ |
| 119 | ap->next = lp->next; |
| 120 | /* free old head */ |
| 121 | free(lp); |
| 122 | } |
| 123 | } |