138 lines
3.3 KiB
C
138 lines
3.3 KiB
C
|
/*
|
||
|
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||
|
*
|
||
|
* This product is part of the Amsterdam Compiler Kit.
|
||
|
*
|
||
|
* Permission to use, sell, duplicate or disclose this software must be
|
||
|
* obtained in writing. Requests for such permissions may be sent to
|
||
|
*
|
||
|
* Dr. Andrew S. Tanenbaum
|
||
|
* Wiskundig Seminarium
|
||
|
* Vrije Universiteit
|
||
|
* Postbox 7161
|
||
|
* 1007 MC Amsterdam
|
||
|
* The Netherlands
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
/* Core management for the EM assembler.
|
||
|
two routines:
|
||
|
getarea(size)
|
||
|
returns a pointer to a free area of 'size' bytes.
|
||
|
freearea(ptr,size)
|
||
|
free's the area of 'size' bytes pointed to by ptr
|
||
|
|
||
|
Free blocks are linked together and kept sorted.
|
||
|
Adjacent free blocks are collapsed.
|
||
|
Free blocks with a size smaller then the administration cannot
|
||
|
exist.
|
||
|
The algorithm is first fit.
|
||
|
*/
|
||
|
|
||
|
#include "ass00.h"
|
||
|
|
||
|
#ifdef MEMUSE
|
||
|
static unsigned m_used = 0 ;
|
||
|
static unsigned m_free = 0 ;
|
||
|
#endif
|
||
|
|
||
|
struct freeblock {
|
||
|
struct freeblock *f_next ;
|
||
|
unsigned f_size ;
|
||
|
} ;
|
||
|
|
||
|
static struct freeblock freexx[2] = {
|
||
|
{ freexx, 0 },
|
||
|
{ freexx+1, 0 }
|
||
|
} ;
|
||
|
|
||
|
#define freehead freexx[1]
|
||
|
|
||
|
#define CHUNK 2048 /* Smallest chunk to be gotten from UNIX */
|
||
|
|
||
|
area_t getarea(size) unsigned size ; {
|
||
|
register struct freeblock *c_ptr,*l_ptr ;
|
||
|
register char *ptr ;
|
||
|
unsigned rqsize ;
|
||
|
char *malloc() ;
|
||
|
|
||
|
#ifdef MEMUSE
|
||
|
m_used += size ;
|
||
|
m_free -= size ;
|
||
|
#endif
|
||
|
for(;;) {
|
||
|
for ( l_ptr= &freehead, c_ptr= freehead.f_next ;
|
||
|
c_ptr!= &freehead ; c_ptr = c_ptr->f_next ) {
|
||
|
if ( size==c_ptr->f_size ) {
|
||
|
l_ptr->f_next= c_ptr->f_next ;
|
||
|
return (area_t) c_ptr ;
|
||
|
}
|
||
|
if ( size+sizeof freehead <= c_ptr->f_size ) {
|
||
|
c_ptr->f_size -= size ;
|
||
|
return (area_t) ((char *) c_ptr + c_ptr->f_size) ;
|
||
|
}
|
||
|
l_ptr = c_ptr ;
|
||
|
}
|
||
|
rqsize = size<CHUNK ? CHUNK : size ;
|
||
|
for(;;){
|
||
|
ptr = malloc( rqsize ) ;
|
||
|
if ( ptr ) break ; /* request succesfull */
|
||
|
rqsize /= 2 ;
|
||
|
rqsize -= rqsize%sizeof (short) ;
|
||
|
if ( rqsize < sizeof freehead ) {
|
||
|
fatal("Out of memory") ;
|
||
|
}
|
||
|
}
|
||
|
freearea((area_t)ptr,rqsize) ;
|
||
|
#ifdef MEMUSE
|
||
|
m_used += rqsize ;
|
||
|
#endif
|
||
|
}
|
||
|
/* NOTREACHED */
|
||
|
}
|
||
|
|
||
|
freearea(ptr,size) register area_t ptr ; unsigned size ; {
|
||
|
register struct freeblock *c_ptr, *l_ptr ;
|
||
|
|
||
|
#ifdef MEMUSE
|
||
|
m_free += size ;
|
||
|
m_used -= size ;
|
||
|
#endif
|
||
|
for ( l_ptr= &freehead, c_ptr=freehead.f_next ;
|
||
|
c_ptr!= &freehead ; c_ptr= c_ptr->f_next ) {
|
||
|
if ( (area_t)c_ptr>ptr ) break ;
|
||
|
l_ptr= c_ptr ;
|
||
|
}
|
||
|
/* now insert between l_ptr and c_ptr */
|
||
|
/* Beware they may both point to freehead */
|
||
|
|
||
|
#ifdef MEMUSE
|
||
|
if ( ((char *)l_ptr)+l_ptr->f_size> (char *)ptr && l_ptr<=ptr )
|
||
|
fatal("Double freed") ;
|
||
|
if ( ((char *)ptr)+size > (char *)c_ptr && ptr<=c_ptr )
|
||
|
fatal("Frreed double") ;
|
||
|
#endif
|
||
|
/* Is the block before this one adjacent ? */
|
||
|
if ( ((char *)l_ptr) + l_ptr->f_size == (char *) ptr ) {
|
||
|
l_ptr->f_size += size ; /* yes */
|
||
|
} else {
|
||
|
/* No, create an entry */
|
||
|
((struct freeblock *)ptr)->f_next = c_ptr ;
|
||
|
((struct freeblock *)ptr)->f_size = size ;
|
||
|
l_ptr->f_next = (struct freeblock *)ptr ;
|
||
|
l_ptr = (struct freeblock *)ptr ;
|
||
|
}
|
||
|
/* Are the two entries adjacent ? */
|
||
|
if ( (char *)l_ptr + l_ptr->f_size == (char *) c_ptr ) {
|
||
|
/* the two entries are adjacent */
|
||
|
l_ptr->f_next = c_ptr->f_next ;
|
||
|
l_ptr->f_size += c_ptr->f_size ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#ifdef MEMUSE
|
||
|
memuse() {
|
||
|
printf("Free %7u, Used %7u, Total %7u\n",m_free,m_used,m_free+m_used);
|
||
|
}
|
||
|
#endif
|