1984-07-02 15:35:56 +00:00
|
|
|
/*
|
1987-03-10 01:26:51 +00:00
|
|
|
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
|
|
|
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
1984-07-02 15:35:56 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* 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"
|
|
|
|
|
1984-11-08 12:08:31 +00:00
|
|
|
#ifndef NORCSID
|
1994-06-24 11:31:16 +00:00
|
|
|
static char rcs_id[] = "$Id$" ;
|
1984-11-08 12:08:31 +00:00
|
|
|
#endif
|
|
|
|
|
1984-07-02 15:35:56 +00:00
|
|
|
#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 ;
|
|
|
|
|
1988-04-25 10:41:33 +00:00
|
|
|
size = ((size + (sizeof(int) - 1)) / sizeof(int)) * sizeof(int);
|
1984-07-02 15:35:56 +00:00
|
|
|
#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 ;
|
1988-04-25 10:41:33 +00:00
|
|
|
rqsize -= rqsize%sizeof (int) ;
|
1984-07-02 15:35:56 +00:00
|
|
|
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 ;
|
|
|
|
|
1988-04-25 10:41:33 +00:00
|
|
|
size = ((size + (sizeof(int) - 1)) / sizeof(int)) * sizeof(int);
|
1984-07-02 15:35:56 +00:00
|
|
|
#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
|
1991-08-27 09:45:37 +00:00
|
|
|
if ( ((char *)l_ptr)+l_ptr->f_size> (char *)ptr && (char *)l_ptr<=(char *)ptr )
|
1984-07-02 15:35:56 +00:00
|
|
|
fatal("Double freed") ;
|
1991-08-27 09:45:37 +00:00
|
|
|
if ( ((char *)ptr)+size > (char *)c_ptr && (char *)ptr<=(char *)c_ptr )
|
1984-07-02 15:35:56 +00:00
|
|
|
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
|