DataMuseum.dk

Presents historical artifacts from the history of:

Commodore CBM-900

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Commodore CBM-900

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦10b134d7d⟧ TextFile

    Length: 2770 (0xad2)
    Types: TextFile
    Notes: UNIX file
    Names: »malloc.c«

Derivation

└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
    └─⟦f4b8d8c84⟧ UNIX V7 Filesystem
        └─ ⟦this⟧ »cmd/rsh/malloc.c« 
        └─ ⟦this⟧ »cmd/sh/malloc.c« 

TextFile

/*
 * 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;
	unsigned int	len;
	char		sbrked = 0;

	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) { /* extra */
					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++)
			complain("Corrupt arena in malloc\n");
		ap = sbrk(len = roundup(size+sizeof(alloc_t), 1<<9));
		if ((int)ap == 0  ||  (int)ap == -1)
			return (NULL);
		if (_a_arena == NULL) {
			_a_arena = ap;
		} else if (ap == &(bp=prev(_a_arena))[1]) {	/* no gap */
			ap = bp;
		} else {	/* someone else also sbrk'd; mark his used */
			bp->a_next = ap;
			ap->a_prev = bp;
			setused(bp);
		}
		bp = &((char *)ap)[len-sizeof(alloc_t)];	/* end marker */
		ap->a_next = bp;
		bp->a_prev = ap;
		bp->a_next = _a_arena;
		_a_arena->a_prev = bp;
		setused(bp);
		{	register alloc_t *cp;
			if (tstfree(cp=ap->a_prev)) {	/* coalesce with prev */
				cp->a_next = bp;
				bp->a_prev = ap = cp;
			}
		}
	}
}

free(cp)
char	*cp;
{
	register alloc_t *ap = cp,
			 *pp,
			 *np;

	--ap;
	if ((unsigned)ap & 1
	 || ap < _a_arena
	 || prev(_a_arena) <= ap
	 || next(pp=prev(ap)) != ap
	 || prev(np=next(ap)) != ap
	 || tstfree(ap))
		complain("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
complain(plaint)
char	*plaint;
{
	write(2, plaint, strlen(plaint));
	abort();
}

/*
 * Tell if this block of memory is in the malloc arena.
 */
notmem(cp)
char	*cp;
{
	register alloc_t *ap = cp,
			 *pp,
			 *np;

	if (ap == NULL
	 || (unsigned)ap & 1
	 || --ap < _a_arena
	 || prev(_a_arena) <= ap
	 || next(pp=prev(ap)) != ap
	 || prev(np=next(ap)) != ap
	 || tstfree(ap))
		return (1);
	return (0);
}