scc

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

alloc.c (2117B)


      1 static char sccsid[] = "@(#) ./lib/scc/alloc.c";
      2 #include <stdlib.h>
      3 #include <scc/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 }