/* * (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 = sizef_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