mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-22 16:04:18 +00:00
266 lines
11 KiB
C
266 lines
11 KiB
C
/********************************************************************
|
||
* malloc, free - memory allocator mechanism
|
||
*
|
||
* 9/83: fixed free bug, added check word whf
|
||
* 10/83: added debugging features: DEBUGMEM and MALLOCND hooks whf
|
||
*
|
||
* BYTE *malloc(numbytes)
|
||
* WORD numbytes
|
||
* Returns a pointer to an area of memory at least 'numbytes'
|
||
* in length. Returns NULLPTR if out of memory or corrupted freelist.
|
||
* Warning: the size of the area is right below the region:
|
||
* do not overwrite!
|
||
*
|
||
*
|
||
* WORD free(mptr)
|
||
* BYTE *mptr
|
||
* Frees the region pointed to by 'mptr'. Returns 0 (SUCCESS) if ok,
|
||
* FAILURE (-1) if corrupted freelist (or if mptr was not previously
|
||
* allocated by malloc).
|
||
*
|
||
*
|
||
* BYTE *realloc(mptr,numbytes)
|
||
* BYTE *mptr
|
||
* WORD numbytes
|
||
* Returns a pointer to a (probably different) region of memory
|
||
* (numbytes long) containing the same data as the old region
|
||
* pointed to by mptr. Returns NULLPTR if not enough memory, or
|
||
* if freelist was corrupted.
|
||
*
|
||
************************************************************************/
|
||
|
||
#include "portab.h"
|
||
|
||
/************************* #include "malloc.h" *****************************/
|
||
#define FB_HDR struct hdr /* free block header type */
|
||
#define NULLFBH ((FB_HDR *)0) /* Null of above struct */
|
||
/* */
|
||
FB_HDR { /* mem_block header */
|
||
struct hdr *ptr; /* ptr next blk (when freed)*/
|
||
UWORD size; /* block size (always) */
|
||
UWORD chksize; /* 1's complement of size */
|
||
}; /****************************/
|
||
/* */
|
||
FB_HDR _afreebase = {&_afreebase,0,~0 }; /* initial (empty) block */
|
||
FB_HDR *_aflistptr = &_afreebase; /* ptr into ring of freeblks*/
|
||
/* */
|
||
#define AOFFS 1L /* alignment offset: 0=byte, 1=word, 3=quad */
|
||
#define AMASK(c) ((char *)((long)(c) & ~AOFFS)) /* mask alignment bits */
|
||
#define AFUDGE 4 /* leeway for passing block as is */
|
||
#define ACHUNKS 64 /* chunks to alloc from O.S.*/
|
||
/* */
|
||
#define ERR_FINDBLOCK 1 /* error in 'findblock()' */
|
||
#define ERR_GETMEM 2 /* error in 'getmemory()' */
|
||
#define ERR_FREE 3 /* error in 'free()' */
|
||
/* */
|
||
/*** end of "malloc.h" ******/
|
||
/****************************************************************************/
|
||
/* malloc - general purpose memory allocator
|
||
* This function allocates the requested number of bytes (nbytes) and returns
|
||
* a pointer to this space to the calling function.
|
||
* The memory is requested from the O.S. in larger chunks, and
|
||
* free space is managed as a ring of free blocks. Each block
|
||
* contains a pointer to the next block (s.ptr), a block size (s.size),
|
||
* a check word (1's complement of size), and the space itself.
|
||
* Alignment is handled by assuming that sizeof(FB_HDR) is an aligned
|
||
* quantity, and allocating in multiples of that size.
|
||
************************************************** */
|
||
BYTE * malloc(nbytes) /* CLEAR FUNCTION ***********/
|
||
UWORD nbytes; /* number bytes requested */
|
||
{ /****************************/
|
||
REG UWORD nmults; /* multiples of FB_HDR size */
|
||
REG FB_HDR *pp; /* temporary ptr */
|
||
FB_HDR *findblock(); /* find free block */
|
||
BYTE *cutup(); /* cut free block to fit */
|
||
/* */
|
||
nmults = (nbytes+sizeof(FB_HDR)-1)/sizeof(FB_HDR)+1; /* */
|
||
if( (pp=findblock(nmults)) == NULLFBH ) /* find ptr to ptr to block */
|
||
return NULLPTR; /* no luck... */
|
||
return cutup(pp,nmults); /* cut block to fit & return*/
|
||
} /****************************/
|
||
|
||
/****************************************************************************/
|
||
/* findblock - local subr to find a free block that's big enough. */
|
||
/* It returns a pointer to the freeblock BEFORE the desired freeblock, */
|
||
/* in order to fix the pointer of the this freeblock. */
|
||
/************************************************* */
|
||
MLOCAL FB_HDR * /* */
|
||
findblock(units) /* find a free block */
|
||
UWORD units; /* at least this big */
|
||
{ /****************************/
|
||
REG FB_HDR *cp; /* ptr to current block */
|
||
REG FB_HDR *pp; /* ptr to previous block */
|
||
FB_HDR *getmemory(); /* get from OS, add to list */
|
||
/* */
|
||
pp = _aflistptr; /* start search here */
|
||
cp = pp->ptr; /* init current ptr */
|
||
while(1) /* do forever */
|
||
{ /* */
|
||
if(~(cp->size^cp->chksize)) /* does cp pt to valid blk? */
|
||
{ /* no... */
|
||
_errmalloc(ERR_FINDBLOCK); /* handle this error */
|
||
return NULLFBH; /* */
|
||
} /* */
|
||
if( cp->size >= units ) /* is this block big enough?*/
|
||
return pp; /* yes! NOTE: return prevptr*/
|
||
if( cp == _aflistptr ) /* end of list? */
|
||
if( (cp=getmemory(units)) == NULLFBH ) /* is there more? */
|
||
{ /* */
|
||
_errmalloc(ERR_GETMEM); /* */
|
||
return NULLFBH; /* no more memory... */
|
||
} /* */
|
||
pp = cp; /* */
|
||
cp = cp->ptr; /* move on down the list */
|
||
} /* */
|
||
} /****************************/
|
||
|
||
/****************************************************************************/
|
||
/* cutup - a local fn to cut up the free block (if its much bigger than the */
|
||
/* number of units requested), and to convert blk ptr to byte ptr. */
|
||
/************************************************* */
|
||
MLOCAL BYTE * /* */
|
||
cutup(pp,units) /* cut the block to fit */
|
||
FB_HDR *pp; /* ptr to ptr to block */
|
||
UWORD units; /* num units to cut to */
|
||
{ /****************************/
|
||
REG FB_HDR *cp; /* cur ptr */
|
||
REG FB_HDR *np; /* new ptr (if needed) */
|
||
/* */
|
||
cp = pp->ptr; /* get ptr to big block */
|
||
if( cp->size <= units+AFUDGE ) /* is size close enough? */
|
||
pp->ptr = cp->ptr; /* yes: cut cp from list */
|
||
else { /* o.w. cut block up */
|
||
np = cp + units; /* where it starts */
|
||
np->size = cp->size - units; /* how big it is */
|
||
np->chksize = ~np->size; /* it's a valid blk */
|
||
np->ptr = cp->ptr; /* it's linked into freelist*/
|
||
pp->ptr = np; /* from both sides */
|
||
cp->size = units; /* new size for cur block */
|
||
cp->chksize = ~cp->size; /* and make valid */
|
||
} /****************************/
|
||
_aflistptr = pp; /* search from here next tim*/
|
||
return cp+1; /* point to after header */
|
||
} /****************************/
|
||
|
||
|
||
/****************************************************************************/
|
||
/* getmemory - gets memory from O.S. */
|
||
/* This function requests memory from the O.S. in multiples (ACHUNKS) */
|
||
/* of the requested number of units (numu), in order to minimize */
|
||
/* the number of calls to the O.S. */
|
||
/* Function cleans up pointer alignment and adds to free list. */
|
||
/************************************************* */
|
||
MLOCAL FB_HDR *
|
||
getmemory(numu)
|
||
UWORD numu; /* number of units */
|
||
{
|
||
BYTE *sbrk(); /* obtain memory from O.S. */
|
||
REG BYTE *mmp; /* more memory pointer */
|
||
REG FB_HDR *fbp; /* free block pointer */
|
||
REG WORD utg; /* units to get */
|
||
|
||
utg = ((numu+(ACHUNKS-1)) / ACHUNKS) * ACHUNKS;
|
||
|
||
mmp = sbrk(utg * sizeof(FB_HDR)); /* sbrk wants number of bytes */
|
||
|
||
if( mmp == (char *)-1 ) /* sbrk = -1 means no memory available */
|
||
return( NULLFBH );
|
||
mmp = AMASK(mmp + AOFFS); /* alignment handling: nop if good sbrk */
|
||
fbp = (FB_HDR *)mmp;
|
||
fbp->size = utg;
|
||
fbp->chksize = ~fbp->size;
|
||
free( (BYTE *)(fbp+1) ); /* add to free list */
|
||
return(_aflistptr); /* set in 'free' */
|
||
}
|
||
|
||
|
||
/****************************************************************************/
|
||
/* free - adds memory back to free block list.
|
||
* This function assumes freed memory pointer (fmp) points to free space
|
||
* preceeded by a FB_HDR structure.
|
||
* Note that free block is inserted in memory address order,
|
||
* to facilitate compaction.
|
||
* Fails (-1 return) if you link in a random ptr.
|
||
************************************************* */
|
||
WORD free(fmp) /* CLEAR FUNCTION ***********/
|
||
BYTE *fmp; /* freed memory ptr */
|
||
{ /****************************/
|
||
REG FB_HDR *cp, /* current freeblk ptr */
|
||
*pp; /* previous freeblk ptr */
|
||
/****************************/
|
||
cp = (FB_HDR *)fmp - 1; /* ptr to (hdr of) freed blk*/
|
||
if(~(cp->size^cp->chksize)) /* is blk valid? */
|
||
{ /* */
|
||
_errmalloc(ERR_FREE); /* */
|
||
return FAILURE; /* no: fail... */
|
||
} /****************************/
|
||
for( pp=_aflistptr; ; pp=pp->ptr ) /* start through the list */
|
||
{ /* */
|
||
if( cp >= pp && cp < pp->ptr ) /* are we at correct place? */
|
||
break; /* yes... */
|
||
if( pp >= pp->ptr && /* at end of list? and */
|
||
(cp <= pp->ptr || cp >= pp) ) /* blk is off either end? */
|
||
break; /* yes... */
|
||
} /****************************/
|
||
if( cp>=pp && cp+cp->size <= pp+pp->size )/* block already freed? */
|
||
{ /* */
|
||
_aflistptr = pp; /* search from here next */
|
||
return SUCCESS; /* and do no more */
|
||
} /****************************/
|
||
/************************************************* */
|
||
/* Insert freed block back into list. Try to coalesce (merge) adjacent */
|
||
/* regions. */
|
||
/************************************************* */
|
||
if( cp+cp->size == pp->ptr ) /* end freed blk==start nxt?*/
|
||
{ /* then merge with nxt */
|
||
cp->size += pp->ptr->size; /* */
|
||
cp->chksize = ~cp->size; /* */
|
||
cp->ptr = pp->ptr->ptr; /* */
|
||
} else /***** */
|
||
cp->ptr = pp->ptr; /* else just point to nxt */
|
||
/****************************/
|
||
if( pp+pp->size == cp ) /* end prev plk==start cur? */
|
||
{ /* then merge with prev*/
|
||
pp->size += cp->size; /* */
|
||
pp->chksize = ~pp->size; /* */
|
||
pp->ptr = cp->ptr; /* */
|
||
} else /***** */
|
||
pp->ptr = cp; /* else point prev to cur */
|
||
/****************************/
|
||
_aflistptr = pp; /* search from here next time*/
|
||
return SUCCESS; /* say its ok */
|
||
} /****************************/
|
||
|
||
|
||
/****************************************************************************/
|
||
/* realloc - free memory, allocate again (with changed size maybe), */
|
||
/* preserve contents. */
|
||
/************************************************* */
|
||
BYTE * realloc(ptr,siz) /* CLEAR FUNCTION ***********/
|
||
REG BYTE *ptr; /* ptr to (prev malloc'd)mem*/
|
||
UWORD siz; /* size of mem */
|
||
{ /****************************/
|
||
REG BYTE *np; /* ptr to new allocation */
|
||
REG UWORD nmults; /* multiples if FB_HDR size */
|
||
FB_HDR *pp, *findblock(); /* find free block */
|
||
BYTE *cutup(); /* cut free block to fit */
|
||
/* */
|
||
free(ptr); /* stuff back into free list: any coalesce will not */
|
||
/* affect original data region */
|
||
nmults = (siz+sizeof(FB_HDR)-1)/sizeof(FB_HDR)+1; /* */
|
||
if( (pp=findblock(nmults)) == NULLFBH ) /* find ptr to ptr to block */
|
||
return NULLPTR; /* no luck... */
|
||
np = (pp->ptr)+1; /* convert to BYTE ptr */
|
||
if( ptr != np ) { /* if ptr changed */
|
||
if( np < ptr ) /* if new ptr in lower mem */
|
||
for( ; siz; siz-- ) /* copy up */
|
||
*np++ = *ptr++; /* */
|
||
else /* if new ptr in higher mem */
|
||
for( np+=siz, ptr+=siz; siz; siz-- ) /* copy down */
|
||
*--np = *--ptr; /* */
|
||
} /****************************/
|
||
return cutup(pp,nmults); /* cut block to fit & return*/
|
||
} /****************************/
|
||
************************/
|
||
************************/
|