|
|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 2841 (0xb19)
Types: TextFile
Notes: UNIX file
Names: »malloc.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
└─⟦f4b8d8c84⟧ UNIX Filesystem
└─⟦this⟧ »libc/gen/malloc.c«
/*
* Memory allocator
* Maintains address order list of contiguous blocks, with discontinuities in
* arena represented as used blocks.
* Blocks are doubly linked, and marked busy by bit in first link.
* Last block consists of header only, is always marked used, linked to first.
* Allocated by circular first fit; coalesced when freed.
*/
#include <stdio.h>
#include <malloc.h>
#define roundup(i,j) (((i)+(j)-1)&~((j)-1)) /* j must be power of 2 */
alloc_t *_a_arena = NULL,
*_a_block = NULL;
char *
malloc(size)
unsigned int size;
{
register alloc_t *ap,
*bp;
register unsigned int len;
char sbrked = 0,
*sbrk();
if (size == 0)
return (NULL);
size = roundup(size + sizeof (alloc_t), sizeof (alloc_t));
ap = _a_block;
for (;;) { /* at most twice through */
if (_a_arena != NULL) do {
if (tstfree(ap) && size <= (len=alength(ap))) {
if (size + sizeof (alloc_t) < len) { /* slop */
bp = &((char *)ap)[size];
bp->a_next = ap->a_next;
bp->a_prev = ap;
ap->a_next =
ap->a_next->a_prev = bp;
}
_a_block = ap->a_next;
setused(ap);
return (&ap[1]);
}
ap = next(ap);
} while (ap != _a_block); /* scan whole arena */
if (sbrked++)
maunder("Corrupt arena in malloc\n");
if (_a_arena != NULL
&& sbrk(0) == &(bp=prev(_a_arena))[1]
&& tstfree(prev(bp))) /* free block at end of mem */
len = roundup(size - alength(prev(bp)), 1<<9);
else
len = roundup(size + sizeof (alloc_t), 1<<9);
if ((char*)(ap=sbrk(0))+len <= (char*)ap /* wraparound */
|| (ap=sbrk(len)) == NULL) /* no space */
return (NULL);
if (_a_arena == NULL) { /* first alloc */
_a_arena = ap;
} else if (ap != &bp[1]) { /* discontiguous new block */
register int tmp;
tmp = roundup(size + sizeof(alloc_t), 1<<9);
if (sbrk(tmp-len) == NULL)
return (NULL);
len = tmp;
bp->a_next = ap;
ap->a_prev = bp;
setused(bp);
} else if (tstfree(prev(bp))) { /* extend free block */
ap = prev(bp);
len += alength(ap) + sizeof (alloc_t);
} else { /* new free block */
ap = bp;
len += sizeof (alloc_t);
}
bp = &((char *) ap)[len - sizeof (alloc_t)]; /* end mark */
ap->a_next = bp;
bp->a_prev = ap;
bp->a_next = _a_arena;
_a_arena->a_prev = bp;
setused(bp);
}
}
free(cp)
char *cp;
{
register alloc_t *ap = cp,
*pp,
*np;
--ap;
if (!aligned(ap)
|| ap < _a_arena
|| prev(_a_arena) <= ap
|| next(pp=prev(ap)) != ap
|| prev(np=next(ap)) != ap
|| tstfree(ap))
maunder("Bad pointer in free\n");
setfree(ap);
if (tstfree(np)) { /* coalesce with next */
ap->a_next = np = np->a_next;
np->a_prev = ap;
}
if (tstfree(pp)) { /* coalesce with prev */
pp->a_next = np;
np->a_prev = ap = pp;
}
_a_block = ap;
}
static
maunder(plaint)
char *plaint;
{
write(2, plaint, strlen(plaint));
abort();
}