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