|
|
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: 7081 (0x1ba9)
Types: TextFile
Notes: UNIX file
Names: »malloc.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
└─⟦f4b8d8c84⟧ UNIX Filesystem
└─⟦this⟧ »unimenu/src/menu/malloc.c«
#ifndef LINT
static char sccs_id[] = "@(#)malloc.c 1.1 15:35:08 4/6/85";
#endif
/*
*
* malloc dynamic memory allocation function
*
* notes malloc allocates a block of nbytes and returns
* a pointer to it. Each block consists of a header
* and a data area of nbytes.
* malloc searches the list of blocks it has
* allocated and uses the first free block that is
* big enough. Adjacent free blocks are combined as we
* search, and large blocks are split if nbytes
* is smaller than the number of bytes available in the block.
* If no free block large enough is available, malloc
* calls sbrk to get more memory.
*
* This malloc keeps a "fence post" at each end of the
* header to try and determine if the header has been overwritten
*
* This is not the most efficent scheme speedwise, but it is
* fairly robust and does a good job of garbage collection.
*
* original code 11/12/84 dan mitchell
*/
/*#define DEBUG*/
#define BMAGIC 0x1234
#define EMAGIC 0x4321
#define NULL 0
/* NOTE: MINBLK should always be a multiple of 16 bytes
* due to the fact that sbrk rounds up to a paragraph
* boundary.
*/
#define MINBLK 16 /* smallest block we'll allocate */
typedef struct _m_hdr
{
int h_bmagic; /* valid header flag */
unsigned int h_siz; /* size of this block */
int h_inuse; /* in use flag */
char *h_data; /* pointer to the data */
struct _m_hdr *h_nxt; /* pointer to next header */
struct _m_hdr *h_prev; /* pointer to previous header */
int h_emagic; /* valid header flag */
unsigned int h_spare; /* round to 16 bytes */
} M_HDR;
static M_HDR mlist = { BMAGIC, 0, 1, 0, 0, 0, EMAGIC, 0 };
char *malloc( nbytes )
unsigned int nbytes;
{
M_HDR *hdrp, *tmp, *last;
char *sbrk();
unsigned int msize;
if ( nbytes < MINBLK )
msize = MINBLK + sizeof(M_HDR);
else
msize = nbytes + sizeof(M_HDR);
msize += 16 - (msize % 16); /* round for sbrk() */
last = hdrp = &mlist;
tmp = (M_HDR *) NULL;
while( hdrp ) /* search the list */
{
if ( hdrp->h_bmagic != BMAGIC || hdrp->h_emagic != EMAGIC)
{
/* header has been corrupted */
#ifdef DEBUG
write(2, "malloc: Header list corrupted\r\n", 31);
pnum(2, hdrp);
#endif
return (NULL);
}
if ( !(hdrp->h_inuse) )
{
if ( hdrp->h_siz >= msize )
{
/* block not in use and big enough */
tmp = hdrp;
break;
}
else if ( !(last->h_inuse) )
{
/* combine these two blocks */
if (combine(hdrp))
{
hdrp = last;
if (last->h_siz >= msize)
{
tmp = last;
break;
}
}
}
}
last = hdrp;
hdrp = hdrp->h_nxt;
}
/*
* if a block wasn't found then get more memory with sbrk
*/
if ( tmp == (M_HDR *) NULL )
{
/*
* this should probably sbrk for some minimum
* amount - like maybe 1k.
* for now just get enough for this block
*/
if ( (tmp = (M_HDR *) sbrk(msize)) == (M_HDR *) (-1) )
{
#ifdef DEBUG
write(2, "malloc: sbrk failed\r\n", 21);
#endif
return (NULL);
}
/*
* install the new block at the end of the list
*/
last->h_nxt = tmp;
tmp->h_bmagic = BMAGIC;
tmp->h_siz = msize;
tmp->h_nxt = NULL;
tmp->h_prev = last;
tmp->h_emagic = EMAGIC;
tmp->h_data = (char *) (((unsigned) tmp) + sizeof(M_HDR));
}
else if (tmp->h_siz > (msize + sizeof(M_HDR) + MINBLK) )
{
/* this block is big enough to split */
split(tmp, msize);
}
/*
* tmp now points to a big enough block
*/
tmp->h_inuse = 1;
#ifdef DEBUG
prnmlist();
#endif
return ( tmp->h_data );
}
/*
* combine combine unused blocks
* ptr and its previous block are combined if
* they are contiguous and both free
*
* (bwd <-> ptr <-> fwd) becomes (bwd <-> fwd)
*
*/
static int combine(ptr)
M_HDR *ptr;
{
M_HDR *bwd, *fwd;
#ifdef DEBUG
write(2, "combine: ", 9);
pnum(2, ptr);
write(2, "\n", 1);
#endif
bwd = ptr->h_prev;
fwd = ptr->h_nxt;
if (bwd == NULL || bwd->h_inuse || ptr->h_inuse)
return (0); /* sanity check */
if ( (M_HDR *) ((unsigned) bwd + bwd->h_siz) == ptr )
{
/* blocks are contiguous - join */
if ( fwd )
fwd->h_prev = ptr->h_prev;
bwd->h_nxt = fwd;
bwd->h_siz += ptr->h_siz;
return (1);
}
else
return (0);
}
/*
* split break up a large block into two smaller blocks
*
* (blk <--> nxt) becomes (blk <--> tmp <--> nxt)
*/
static int split(blk, size)
M_HDR *blk;
unsigned int size;
{
M_HDR *tmp;
#ifdef DEBUG
write(2, "split: ", 7);
pnum(2, blk); write(2, " ", 1);
pnum(2, size);
write(2, "\n", 1);
#endif
tmp = (M_HDR *)((unsigned int) blk + size);
tmp->h_nxt = blk->h_nxt;
tmp->h_prev = blk;
if (blk->h_nxt)
blk->h_nxt->h_prev = tmp;
blk->h_nxt = tmp;
tmp->h_siz = blk->h_siz - size;
blk->h_siz = size;
tmp->h_bmagic = BMAGIC;
tmp->h_emagic = EMAGIC;
tmp->h_inuse = 0;
tmp->h_data = (char *) ((unsigned) tmp + sizeof(M_HDR));
}
/*
* free free is the compainon routine to malloc
* it simply marks a block as unused so that
* the next call to malloc can use it if needed
*
* history original code 11/12/84 dan mitchell
*/
free(ptr)
char *ptr;
{
M_HDR *hdrp;
hdrp = (M_HDR *) ((unsigned) ptr - sizeof(M_HDR) );
if (hdrp->h_bmagic != BMAGIC || hdrp->h_emagic != EMAGIC )
{
/* not a valid looking header */
write(2, "free: bad address\r\n", 20);
#ifdef DEBUG
pnum(2, ptr);
write(2, "\n", 1);
prnmlist();
#endif
return (1);
}
hdrp->h_inuse = 0;
return (0);
}
#ifdef DEBUG
/* some debugging code that prints out the list */
prnmlist()
{
M_HDR *hdrp;
hdrp = &mlist;
printf("location, size, magicb, magice, prev, nxt, inuse\n");
while ( hdrp )
{
printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\n", hdrp, hdrp->h_siz,
hdrp->h_bmagic, hdrp->h_emagic, hdrp->prev, hdrp->h_nxt,
hdrp->h_inuse);
hdrp = hdrp->h_nxt;
}
}
#endif DEBUG
/*
* realloc this routine trys to make better use of memory
* it can be used to increase or decrease the block's
* size.
*/
char *realloc(ptr, size)
char *ptr;
unsigned size;
{
M_HDR *blk;
unsigned newsiz;
char *newptr, *tmp1, *tmp2;
int i;
blk = (M_HDR *) ( (unsigned) ptr - sizeof(M_HDR));
if (blk->h_bmagic != BMAGIC || blk->h_emagic != EMAGIC)
return (NULL);
newsiz = (size + sizeof(M_HDR));
/*
* see if we can split this block
*/
if ( blk->h_siz > (newsiz + sizeof(M_HDR) + MINBLK) )
{
blk->h_inuse = 1;
split(blk, newsiz);
return ( ptr );
}
/*
* if we can't split it but it's big enough already
* don't do anything
*/
if (blk->h_siz >= newsiz )
{
blk->h_inuse = 1;
return (ptr);
}
/*
* otherwise get some more memory
*/
if ( (newptr = malloc(size)) == NULL )
{
return (NULL); /* no more memory */
}
else
{
tmp1 = ptr; /* copy old into new */
tmp2 = newptr;
for ( i = 0; i < size; i++)
*tmp2++ = *tmp1++;
free ( ptr ); /* free up the old */
return (newptr);
}
}
char *calloc(nelem, elsize)
unsigned nelem;
unsigned elsize;
{
char *malloc();
char *ptr, *tmp;
int size;
size = nelem * elsize;
if ( (ptr = malloc(size)) )
{
for ( tmp = ptr; size; size--)
*tmp++ = '\0';
}
return ( ptr );
}
cfree(ptr)
char *ptr;
{
free(ptr);
}