123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- /*
- * (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[] = "$Id$" ;
- #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(int) - 1)) / sizeof(int)) * sizeof(int);
- #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 (int) ;
- 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(int) - 1)) / sizeof(int)) * sizeof(int);
- #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 && (char *)l_ptr<=(char *)ptr )
- fatal("Double freed") ;
- if ( ((char *)ptr)+size > (char *)c_ptr && (char *)ptr<=(char *)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
|