alloc.c (2123B)
1 static char sccsid[] = "@(#) ./lib/scc/alloc.c"; 2 #include <stdlib.h> 3 #include "../../inc/scc.h" 4 5 /* 6 * This is the most pedantic piece of code that I have written 7 * in my life. The next union is used to enforce the aligmnet 8 * of the address returned by new(). A union has the aligment 9 * of the field with the biggest aligment. This union has all 10 * the types that we use in scc, and we round all the address 11 * to the aligment of this struct, so we can be sure that any 12 * pointer using that address will be safe. The field ap is 13 * in the union to be sure that struct pointers are included 14 * in the list, although they will have the same aligment or 15 * smaller than void *, but I wanted to be pedantic. 16 */ 17 union hdr { 18 union hdr *next; 19 struct arena *ap; 20 char c; 21 unsigned char uc; 22 int i; 23 short s; 24 long l; 25 long long ll; 26 float f; 27 double d; 28 long double ld; 29 void *vp; 30 }; 31 32 struct arena { 33 struct arena *next; 34 union hdr *array; 35 }; 36 37 struct alloc { 38 size_t size; 39 size_t nmemb; 40 size_t padding; 41 struct arena *arena; 42 union hdr *freep; 43 }; 44 45 static void 46 newarena(Alloc *allocp) 47 { 48 struct arena *ap; 49 union hdr *bp, *lim; 50 size_t unit, n = allocp->nmemb; 51 52 unit = (allocp->size-1) / sizeof(union hdr) + 1; 53 ap = xmalloc(sizeof(struct arena)); 54 ap->array = xmalloc(unit * sizeof(union hdr) * n); 55 56 bp = ap->array; 57 for (lim = &bp[unit * (n-1)]; bp < lim; bp += unit) 58 bp->next = bp + unit; 59 bp->next = NULL; 60 61 ap->next = allocp->arena; 62 allocp->arena = ap; 63 allocp->freep = ap->array; 64 } 65 66 Alloc * 67 alloc(size_t size, size_t nmemb) 68 { 69 Alloc *allocp = xmalloc(sizeof(*allocp)); 70 71 allocp->size = size; 72 allocp->nmemb = nmemb; 73 allocp->arena = NULL; 74 allocp->freep = NULL; 75 76 return allocp; 77 } 78 79 void 80 dealloc(Alloc *allocp) 81 { 82 struct arena *ap, *next; 83 84 for (ap = allocp->arena; ap; ap = next) { 85 next = ap->next; 86 free(ap->array); 87 free(ap); 88 } 89 free(allocp); 90 } 91 92 void * 93 new(Alloc *allocp) 94 { 95 union hdr *bp; 96 97 if (!allocp->freep) 98 newarena(allocp); 99 bp = allocp->freep; 100 allocp->freep = bp->next; 101 102 return bp; 103 } 104 105 void 106 delete(Alloc *allocp, void *p) 107 { 108 union hdr *bp = p; 109 110 bp->next = allocp->freep; 111 allocp->freep = bp; 112 }