132 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			132 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | 
						|
 * See the copyright notice in the ACK home directory, in the file "Copyright".
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
/*  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"
 | 
						|
 | 
						|
#ifndef NORCSID
 | 
						|
static char rcs_id[] = "$Header$" ;
 | 
						|
#endif
 | 
						|
 | 
						|
#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() ;
 | 
						|
 | 
						|
	size = ((size + (sizeof(short) - 1)) / sizeof(short)) * sizeof(short);
 | 
						|
#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 ;
 | 
						|
 | 
						|
	size = ((size + (sizeof(short) - 1)) / sizeof(short)) * sizeof(short);
 | 
						|
#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
 |