scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

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 }