1#include <stdlib.h>2#include <scc/scc.h>34/*5 * This is the most pedantic piece of code that I have written6 * in my life. The next union is used to enforce the alignment7 * of the address returned by new(). A union has the alignment8 * of the field with the biggest alignment. This union has all9 * the types that we use in scc, and we round all the addresses10 * to the alignment of this struct, so we can be sure that any11 * pointer using that address will be safe. The field ap is12 * in the union to be sure that struct pointers are included13 * in the list, although they will have the same alignment or14 * smaller than void *, but I wanted to be pedantic.15 */16union 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};3031struct arena {32 struct arena *next;33 union hdr *array;34};3536struct alloc {37 size_t size;38 size_t nmemb;39 size_t padding;40 struct arena *arena;41 union hdr *freep;42};4344static void45newarena(Alloc *allocp)46{47 struct arena *ap;48 union hdr *bp, *lim;49 size_t unit, n = allocp->nmemb;5051 unit = (allocp->size-1) / sizeof(union hdr) + 1;52 ap = xmalloc(sizeof(struct arena));53 ap->array = xmalloc(unit * sizeof(union hdr) * n);5455 bp = ap->array;56 for (lim = &bp[unit * (n-1)]; bp < lim; bp += unit)57 bp->next = bp + unit;58 bp->next = NULL;5960 ap->next = allocp->arena;61 allocp->arena = ap;62 allocp->freep = ap->array;63}6465Alloc *66alloc(size_t size, size_t nmemb)67{68 Alloc *allocp = xmalloc(sizeof(*allocp));6970 allocp->size = size;71 allocp->nmemb = nmemb;72 allocp->arena = NULL;73 allocp->freep = NULL;7475 return allocp;76}7778void79dealloc(Alloc *allocp)80{81 struct arena *ap, *next;8283 for (ap = allocp->arena; ap; ap = next) {84 next = ap->next;85 free(ap->array);86 free(ap);87 }88 free(allocp);89}9091void *92new(Alloc *allocp)93{94 union hdr *bp;9596 if (!allocp->freep)97 newarena(allocp);98 bp = allocp->freep;99 allocp->freep = bp->next;100101 return bp;102}103104void105delete(Alloc *allocp, void *p)106{107 union hdr *bp = p;108109 bp->next = allocp->freep;110 allocp->freep = bp;111}