From 842b52324299458586cfbecde37d95865cb2b3c5 Mon Sep 17 00:00:00 2001 From: Oliver Lehmann Date: Wed, 22 Aug 1990 11:37:05 +0000 Subject: [PATCH] add LCC - a better C-Compiler for WEGA --- WEGA/contrib/lcc/lib/libc/u8k/gen/malloc.c | 279 +++++++++++++++++++++ 1 file changed, 279 insertions(+) create mode 100644 WEGA/contrib/lcc/lib/libc/u8k/gen/malloc.c diff --git a/WEGA/contrib/lcc/lib/libc/u8k/gen/malloc.c b/WEGA/contrib/lcc/lib/libc/u8k/gen/malloc.c new file mode 100644 index 0000000..bca4ed0 --- /dev/null +++ b/WEGA/contrib/lcc/lib/libc/u8k/gen/malloc.c @@ -0,0 +1,279 @@ +/* C storage allocator + * circular first-fit strategy + * works with noncontiguous, but monotonically linked, arena + * each block is preceded by a ptr to the (pointer of) + * the next following block + * blocks are exact number of words long + * aligned to the data type requirements of ALIGN + * pointers to blocks must have BUSY bit 0 + * bit in ptr is 1 for busy, 0 for idle + * gaps in arena are merely noted as busy blocks + * last block of arena (pointed to by alloct) is empty and + * has a pointer to first + * idle blocks are coalesced during space search + * + * a different implementation may need to redefine + * ALIGN, NALIGN, BLOCK, BUSY, INT + * where INT is integer type to which a pointer can be cast +*/ +#define INT long +#define ALIGN long +#define NALIGN 1 +#define WORD sizeof(union store) +#define BLOCK 2048 /* a multiple of WORD*/ +#define BUSY 1 +#define testbusy(p) ((unsigned)(p)&BUSY) +#define setbusy(p) (union store *)(((INT)(p))|BUSY) +#define clearbusy(p) (union store *)((INT)(p)&~BUSY) + +union store { + union store *ptr; + ALIGN dummy[NALIGN]; + int calloc; /*calloc clears an array of integers*/ + char c[4]; +}; + +extern union store *ssgbrk(); +extern union store *mkseg(); + +static union store newseg; /*pointer into new segment*/ +static union store allocs[2]; /*initial arena*/ +static union store *allocp; /*search ptr*/ +static union store *alloct; /*arena top*/ +static union store *allocx; /* for saving overwritten INT */ +static int Lw48; /* != 0 if alloct points to real last block */ + +char * +malloc(nbytes) +unsigned nbytes; +{ + register union store *p, *q; + unsigned nw; + int i = 0; /* 1, wenn noch ein INT fuer letzten */ + /* (Null Block)-Pointer benoetigt wird */ + unsigned j; + union store *P; /* hier neuen Speicher anhaengen */ + union store *T; + + if (nbytes > 0xfff8) + return(0); /* 8 Bytes aus 64KB Segment fuer * + /* ersten und letzten Zeiger */ + if (!allocp || !Lw48) + /* noch kein echter Null-Block fuer alloct da */ + i++; + if (!allocp) + { + allocp = &allocs[0]; + alloct = &allocs[1]; + allocs[0].ptr = setbusy(&allocs[1]); + allocs[1].ptr = setbusy(&allocs[0]); + newseg.ptr = mkseg(0, 0); + } + nw = (nbytes + WORD + (WORD -1)) / WORD; /* no of items */ + /* to allocate */ + p = allocp; + q = clearbusy(p->ptr); + /* if p points to free block, then (q-p)-1 == no of free items */ + P = alloct; + /* if not enough free, append new block to block pointed to by P */ + + /* search first free block with at least nw elements */ + /* idle blocks are coalesced during search space */ + do + { + if (testbusy(p->ptr)) + continue; + for (; !testbusy(q->ptr); ) + { + /* Nachfolgeblock ist auch frei, */ + /* deshalb an p-Block anhaengen */ + /* da jetzt q-Block vernichtet werden wird, */ + /* muss evtl allocp neu eingerichtet werden */ + T = q; + q = clearbusy(q->ptr); + p->ptr = q; /* hier erfolgt die Vereinigung */ + if (T == allocp) + allocp = q; + } + /* q zeigt nun auf ersten belegten Block */ + /* p zeigt nach wie vor auf freien Block, der auf */ + /* den q-Block weist */ + if (q >= p + nw) + /* ohne wrap around waere p gross genug */ + if ( p <= p + nw) + goto found; /* tatsaechlich gefunden */ + if (q == alloct) + /* Ende allen verwalteten Speichers erreicht */ + /* An Block auf den P weist, evtl. zusaetzlichen */ + /* anfuegen */ + P = p; + } + while (p = q, q = clearbusy(p->ptr), p!= allocp) ; + /* dieses p ist abgehandelt, naechstes nehmen */ + /* nicht genuegend Speicher vorhanden, einen grossen Hieb holen */ + j = ((((long)(nw+i-(alloct-P)))*WORD)+(BLOCK-1))/BLOCK; + /* no of requested (+i) - no of already available items rounded */ + /* to BLOCKs (only 32 BLOCKs in one Segment !) */ + if (j > 32) + return(0); + nbytes = (j * BLOCK) - 1; + p = ssgbrk(newseg.c[0], nbytes); + if ((long)p == -1L) + { + j = (((long)(nw+1))*WORD + (BLOCK-1))/BLOCK; + /* 1 item fuer alloct block schon beruecksichtigt */ + nbytes = j * BLOCK; + p = mkseg(0, nbytes - 1); + if ((unsigned)p == -1) + return(0); + newseg.ptr = p; + i = 1; /* alloct block erforderlich */ + } + if (i) + { + /* bisherigen alloct block (dummy) dicht machen */ + /* und vor neu erhaltenen block ketten */ + alloct->ptr = setbusy(p); + q = p; + Lw48++; + } + else + { + p = P; + q = alloct; + } + q = (union store *)((char *)q + j*BLOCK); + if (i) + q--; + q->ptr = setbusy(&allocs[0]); + alloct = q; +found: + allocp = p + nw; + if (q > allocp) + { + allocx = allocp->ptr; + allocp->ptr = q; + } + p->ptr = setbusy(allocp); + return((char *)(p+1)); +} + +free(ap) +register union store *ap; +{ + + allocp = --ap; /* strategy tuned for LIFO allocation */ + ap->ptr = clearbusy(ap->ptr); +} + +static char * +find_nc_block(nc) +unsigned nc; +{ + register union store *p, *q; + unsigned wc; + + wc = (nc + WORD + (WORD-1)) / WORD; + p = allocp; + q = clearbusy(p->ptr); + do + { + if (testbusy(p->ptr)) + continue; + while (!testbusy(q->ptr)) + { + if (q == allocp) + { + q = q->ptr; + allocp = q; + } else + q = q->ptr; + p->ptr = q; + } + if (q < p+wc) + continue; + if (p <= p+wc) + return((char *)p); + } while (p=q, q=clearbusy(p->ptr), p!=allocp) ; + return(0); +} + +char * +realloc(p, nbytes) +register union store *p; +unsigned nbytes; +{ + register union store *q; + union store *X, *Y; + unsigned own; + int i; + + X = (p-1)->ptr; + if (!testbusy(X)) + return((char *)0); + X = clearbusy(X); + Y = X->ptr; + free(p); + own = (char *)X - (char *)p; + /* size of old block */ + q = (union store *)malloc(nbytes); + if (q == p) + return((char *)q); + if ((long)q == 0) + { + X->ptr = Y; + Y = p - 1; + Y->ptr = setbusy(X); + for (q=allocs; q != alloct; q=p) + { + p = clearbusy(q->ptr); + if (p == Y) + return((char *)0); + if ( p > Y) + { + q->ptr = setbusy(Y); + break; + } + } + return((char *)0); + } + nbytes = ((nbytes + WORD - 1) / WORD) * WORD; + /* size of new block */ + i = (nbytes < own) ? nbytes : own; + q = (union store *)((char *)q + i); + p = (union store *)((char *)p + i); + i /= WORD; + while (i--) + { + p--; + q--; + *((INT *)q) = *(INT *)p; + } + if((char *)q+nbytes > (char *)p && (char *)q+nbytes < (char *)p+own) + ((union store *)((char *)q+((char *)q+nbytes-(char *)p)))->ptr + = allocx; + return((char *)q); +} + +/* + * calloc - allocate and clear memory block + */ + +char * +calloc(num, size) +register unsigned num; +register unsigned size; +{ + register INT *q; + + num *= size; + q = (INT *)(malloc(num)); + if((INT)q == 0) + return((char *)0); + num = ((num+WORD-1)/WORD)*WORD; + q = (INT *)((char *)q + num); + num /= WORD; + while((int)(--num) >= 0) + *--q = 0; + return((char *)q); +}