Пример #1
0
/**********************************************************
 * find_fit
 * Traverse the heap searching for a block to fit asize
 * Return NULL if no free blocks can handle that size
 * Assumed that asize is aligned
 * Uses fit bit option
 * If we find a block that is close to the request size (4*sizethreshold)
 *   we will use that block
 * If we can't find a block close to request size then we return the closest
 *    size and split the block before using it
 **********************************************************/
void * find_fit(size_t asize, int *list_broken)
{
    if(asize>maxBlockSize1)
        return NULL;
    size_t bestfit = mem_heapsize(); 
    size_t curfit;

    void *bestfitptr = NULL;
    void *free_bp;
    int sizethreshold = 2*DSIZE;
    for (free_bp = free_listp; free_bp != NULL; free_bp = *((void **)free_bp))
    {
        if (asize <= GET_SIZE(HDRP(free_bp)))
        {
            curfit = GET_SIZE(HDRP(free_bp)) - asize;
            if (curfit < 4*sizethreshold) {
                bestfitptr = free_bp;
                break;
            }
            if (curfit < bestfit) {
                bestfit = curfit;
                bestfitptr = free_bp;
            }
        }
    }
    if ((bestfitptr != NULL) && (GET_SIZE(HDRP(bestfitptr)) - asize >= sizethreshold)) {
        bestfitptr = split_block (bestfitptr, asize);
        *list_broken = 1;
    }
    return bestfitptr;
}
Пример #2
0
// Return a pointer to the memory malloc should return
static inline uint32_t* block_mem(uint32_t* const block) {
    REQUIRES(block != NULL);
    REQUIRES(in_heap(block));
    REQUIRES(aligned(block + 1));
    if (VERBOSE)
        printf("Heap size = %d bytes \n", (int)mem_heapsize());
    return block + 1;
}
Пример #3
0
/*
 * mem_sbrk - simple model of the sbrk function. Extends the heap
 *    by incr bytes and returns the start address of the new area. In
 *    this model, the heap cannot be shrunk.
 */
void *mem_sbrk(int incr)
{
  char *old_brk = __sync_fetch_and_add(&mem_brk, incr);

  if ((incr < 0) || (mem_brk > mem_max_addr)) {
    errno = ENOMEM;
    fprintf(stderr, "ERROR: mem_sbrk failed. Ran out of memory... (%ld)\n", mem_heapsize());
    __sync_fetch_and_add(&mem_brk, -incr);
    return (void *)-1;
  }

  return (void *)old_brk;
}
Пример #4
0
/* check_heap - Check the heap for consistency etc. Convenient to manually call while running GDB but is not called otherwise */
void check_heap() {  

  listBlock* ptr;
  int *footer;
  listBlock* heapStart = (listBlock*)mem_heap_lo();
  listBlock* heapEnd = (listBlock*)mem_heap_hi();

  printf("Address       Block size      Allocated\n");
  ptr = heapStart;
  while (ptr < heapEnd) {
    footer = (int *)(((char *)ptr) + (ptr->header&~0x1) - WORD_SIZE);
    printf("%5p%14d%12d%10s\n", ptr, (int)(ptr->header & ~0x1), ptr->header & 0x1, ptr->header == *footer?"OK":"corrupt");
    ptr = (listBlock*)((char*)ptr + (ptr->header & ~0x1));
  }
  
  printf("Heap Size Total: %5d\n", (int)mem_heapsize());
}
Пример #5
0
static void *extend_heap(size_t words) //extend heap
{
	char *bp;
	size_t size;
	size = (words % 2) ? (words + 1)*WSIZE : words * WSIZE; 
#ifdef __DEBUG__
	fprintf(stderr, "Extending heap by %u...\n",size);
	printf("Heap size now : %u\n",mem_heapsize());
#endif
	if((long)(bp = mem_sbrk(size)) == -1) return NULL; //sbrk : gathering moar spaces
	set(getBlockHeader(bp), setMask(size, 0));
	set(getBlockFooter(bp), setMask(size, 0));
	set(getBlockHeader(getNextBlock(bp)), setMask(0, 1));
	push_back(size, bp); //empty block to the list
	void* result = coalesce(bp); //coalesces!
//	push_back(getSize(getBlockHeader(result)), result);
	return result;
}
Пример #6
0
/*
 * findFit
 * findFit finds a free block that has size at least asize bytes.
 * It uses an algorithm that is a slight combination of best fit
 * and first fit. The function traverses the list from the free_listp
 * and once it hits a free block of large enough size we traverse a
 * CONSTANT number of times. I used trial and error to find a constant
 * that would give me the most throughput.
 */
static void *findFit(size_t asize)
{
  void *bp = NULL;
  void *temp = free_listp;
  size_t minSize = mem_heapsize(); // maximum size
  /* First fit search */
  size_t size;
  int counter = 0;  /* counter for CONSTANT number of traversals */
  int flag = 0;     /* flag is set if we come across a fit. */

  while(!GET_ALLOC(HDRP(temp)))  /* While we are pointing to a free block */
    {
      if(asize <= (size = (size_t)GET_SIZE(HDRP(temp))) && size < minSize)
	{
	  /* If we have a block that fits perfectly,
	   * then there is no point in searching for
	   * a smaller block because we have found the smallest possible one
	   */
	  if(asize == size)
	    return temp;

	  bp = temp;
	  minSize = size;
	  flag = 1;
	}

      if(flag == 1)
	counter++;

      /* We have traversed enough. */
      if(counter == CONSTANT)
	return bp;

      temp = NEXT_FREE(temp);
    }
  return bp;
}
Пример #7
0
/* 
 * eval_mm_util - Evaluate the space utilization of the student's package
 *   The idea is to remember the high water mark "hwm" of the heap for 
 *   an optimal allocator, i.e., no gaps and no internal fragmentation.
 *   Utilization is the ratio hwm/heapsize, where heapsize is the 
 *   size of the heap in bytes after running the student's malloc 
 *   package on the trace. Note that our implementation of mem_sbrk() 
 *   doesn't allow the students to decrement the brk pointer, so brk
 *   is always the high water mark of the heap. 
 *   
 */
static double eval_mm_util(trace_t *trace, int tracenum, range_t **ranges) {
    assert((int)tracenum || 1);
    assert((int)ranges || 1);

    int i;
    int index;
    int size, newsize, oldsize;
    int max_total_size = 0;
    int total_size = 0;
    char *p;
    char *newp, *oldp;

    /* initialize the heap and the mm malloc package */
    mem_reset_brk();
    if (mm_init() < 0)
	app_error("mm_init failed in eval_mm_util");

    for (i = 0;  i < trace->num_ops;  i++) {
        switch (trace->ops[i].type) {

        case ALLOC: /* mm_alloc */
	    index = trace->ops[i].index;
	    size = trace->ops[i].size;

	    if ((p = mm_malloc(size)) == NULL) 
		app_error("mm_malloc failed in eval_mm_util");
	    
	    /* Remember region and size */
	    trace->blocks[index] = p;
	    trace->block_sizes[index] = size;
	    
	    /* Keep track of current total size
	     * of all allocated blocks */
	    total_size += size;
	    
	    /* Update statistics */
	    max_total_size = (total_size > max_total_size) ?
		total_size : max_total_size;
	    break;

	case REALLOC: /* mm_realloc */
	    index = trace->ops[i].index;
	    newsize = trace->ops[i].size;
	    oldsize = trace->block_sizes[index];

	    oldp = trace->blocks[index];
	    if ((newp = mm_realloc(oldp,newsize)) == NULL)
		app_error("mm_realloc failed in eval_mm_util");

	    /* Remember region and size */
	    trace->blocks[index] = newp;
	    trace->block_sizes[index] = newsize;
	    
	    /* Keep track of current total size
	     * of all allocated blocks */
	    total_size += (newsize - oldsize);
	    
	    /* Update statistics */
	    max_total_size = (total_size > max_total_size) ?
		total_size : max_total_size;
	    break;

        case FREE: /* mm_free */
	    index = trace->ops[i].index;
	    size = trace->block_sizes[index];
	    p = trace->blocks[index];
	    
	    mm_free(p);
	    
	    /* Keep track of current total size
	     * of all allocated blocks */
	    total_size -= size;
	    
	    break;

	default:
	    app_error("Nonexistent request type in eval_mm_util");

        }
    }

    return ((double)max_total_size / (double)mem_heapsize());
}
/*
 * mm_checkheap
 *
 * @param verbose mask:
 *  val         func desc
 *  0x1         Check Prologue and Epilogue
 *  0x2         Check heap boundaries
 *  0x4         Check each block's address alignment
 *  0x8         Check each block’s header and footer
 *  0x10(16)    Check coalescing: no two consecutive free blocks in the heap.
 *  0x20(32)    Check next/previous pointers are consistent
 */
void mm_checkheap(int verbose) {
    
    if (!verbose) {
        return;
    }
    
    verbose = verbose;
    
    char *bp = heap_listp;
    int i = 1;
    int hd_size, hd_alloc, ft_size, ft_alloc;
    /*char *blkp = root;*/
    
    if (heap_listp == NULL) {
        dbg_printf("Heap Uninitialized!\n");
    }
    
    /* check prologue and epilogue blocks */
    if (verbose & 0x1) {
        
        dbg_printf("Prologue Header size = %d, alloc = %d\n", (int)GET_SIZE(GET_HEADER(heap_listp)), (int)GET_ALLOC(GET_HEADER(heap_listp)));
        dbg_printf("Prologue Footer size = %d, alloc = %d\n", (int)GET_SIZE(GET_FOOTER(heap_listp)), (int)GET_ALLOC(GET_FOOTER(heap_listp)));
        
        bp = heap_listp;
        while (GET_SIZE(GET_HEADER(NEXT_BLKP(bp))) > 0)
            bp = NEXT_BLKP(bp);
        bp = NEXT_BLKP(bp);
        dbg_printf("Epilogue Header size = %d, alloc = %d\n", (int)GET_SIZE(GET_HEADER(bp)), (int)GET_ALLOC(GET_HEADER(bp)));
    }
    
    /* Check heap size and boundary */
    if (verbose & 0x2) {
        dbg_printf("Heap Information:\n");
        dbg_printf("Heap size(long) = %ld\n Heap first address = 0x%lx\n Heap last address = 0x%lx\n", mem_heapsize(), (unsigned long)mem_heap_lo(), (unsigned long)mem_heap_hi());
    }
    
    /* Check each block's information */
    if (verbose & 0xc) {
        i = 1;
        bp = heap_listp;
        
        while (GET_SIZE(GET_HEADER(NEXT_BLKP(bp))) > 0) {
            bp = NEXT_BLKP(bp);
            
            hd_size = (int)GET_SIZE(GET_HEADER(bp));
            hd_alloc = (int)GET_ALLOC(GET_HEADER(bp));
            ft_size = (int)GET_SIZE(GET_FOOTER(bp));
            ft_alloc = (int)GET_ALLOC(GET_FOOTER(bp));
            
            if (verbose & 0x8) {
                if (!hd_alloc) {
                    if (hd_size - ft_size) {
                        dbg_printf("SIZE NOT MATCH!!! Block (%d), addr = 0x%lx, header_size = %d footer_size = %d \n", i, (unsigned long)bp , hd_size, ft_size);
                        exit(1);
                    }
                    if (hd_alloc - ft_alloc) {
                        dbg_printf("ALLOC NOT MATCH!!! Block (%d), addr = 0x%lx, header_alloc = %d footer_alloc = %d \n", i, (unsigned long)bp, hd_alloc, ft_alloc);
                        exit(1);
                    }
                }
                
            }
            
            if (verbose & 0x4) {
                dbg_printf("Block %d, addr = 0x%lx, size = %d, alloc = %d \n", i, (unsigned long)bp, hd_size, hd_alloc);
            }
            
            
            ++i;
        }
    }
    
    /* Check coalescing */
    if (verbose & 0x10) {
        bp = heap_listp;
        while (GET_SIZE(GET_HEADER(NEXT_BLKP(bp))) > 0) {
            bp = NEXT_BLKP(bp);
            if ((GET_ALLOC(GET_HEADER(bp)) == 0) && (GET_ALLOC(GET_HEADER(NEXT_BLKP(bp))) == 0)) {
                dbg_printf("Not coalesced: (%lx) and (%lx)\n", (unsigned long)bp, (unsigned long)NEXT_BLKP(bp));
            }
        }
    }
    
    /* Check pred, succ pointers */
    if (verbose & 0x20) {
        
        for (i = 0; i < CLASS_NUM; i++) {
            dbg_printf("CLASS No. %d, class_address = 0x%lx ,root block address = 0x%lx\n", i, (size_t)GET_CLASS(i), (size_t)GET_CLASS_ROOT_BLK(GET_CLASS(i)));
        }
        
        /*i = 1;
         blkp = root;
         
         if (root != NULL) {
         dbg_printf("root address = 0x%lx\n", (size_t)root);
         
         do {
         dbg_printf("Check Free Block %d\n",i);
         check_bp_pred_succ(blkp);
         i++;
         if (i > 100) {
         exit(1);
         }
         } while ((blkp = GET_SUCC_BLK(blkp)) != NULL);
         }*/
    }
    
    /* Check each block’s address alignment */
    
    dbg_printf("******************\n");
}
Пример #9
0
/*
 * eval_mm_util - Evaluate the space utilization of the student's package
 *   The idea is to remember the high water mark "hwm" of the heap for
 *   an optimal allocator, i.e., no gaps and no internal fragmentation.
 *   Utilization is the ratio hwm/heapsize, where heapsize is the
 *   size of the heap in bytes after running the student's malloc
 *   package on the trace.
 *
 */
static double eval_mm_util(trace_t *trace, int tracenum) {
  int i;
  int index;
  int size, newsize, oldsize;
  int max_total_size = 0;
  int total_size = 0;
  size_t heap_size = 0 ;
  char *p;
  char *newp, *oldp;

  /* initialize the heap and the mm malloc package */
  mem_reset_brk();
  if (my_impl.init() < 0) {
    app_error("init failed in eval_mm_util");
  }

  for (i = 0; i < trace->num_ops; i++) {
    switch (trace->ops[i].type) {

      case ALLOC: /* alloc */
        index = trace->ops[i].index;
        size = trace->ops[i].size;

        if ((p = (char *) my_impl.malloc(size)) == NULL) {
          app_error("malloc failed in eval_mm_util");
        }

        /* Remember region and size */
        trace->blocks[index] = p;
        trace->block_sizes[index] = size;

        /* Keep track of current total size
         * of all allocated blocks */
        total_size += size;

        /* Update statistics */
        max_total_size = (total_size > max_total_size) ?
            total_size : max_total_size;
        break;

      case REALLOC: /* realloc */
        index = trace->ops[i].index;
        newsize = trace->ops[i].size;
        oldsize = trace->block_sizes[index];

        oldp = trace->blocks[index];
        if ((newp = (char *) my_impl.realloc(oldp,newsize)) == NULL)
          app_error("realloc failed in eval_mm_util");

        /* Remember region and size */
        trace->blocks[index] = newp;
        trace->block_sizes[index] = newsize;

        /* Keep track of current total size
         * of all allocated blocks */
        total_size += (newsize - oldsize);

        /* Update statistics */
        max_total_size = (total_size > max_total_size) ?
            total_size : max_total_size;
        break;

      case FREE: /* free */
        index = trace->ops[i].index;
        size = trace->block_sizes[index];
        p = trace->blocks[index];

        my_impl.free(p);

        /* Keep track of current total size
         * of all allocated blocks */
        total_size -= size;

        break;

      default:
        app_error("Nonexistent request type in eval_mm_util");
    }
  }
  max_total_size = (max_total_size > MEM_ALLOWANCE) ?
    max_total_size : MEM_ALLOWANCE ;
  heap_size = mem_heapsize() ;
  heap_size = (heap_size > MEM_ALLOWANCE) ?
    heap_size : MEM_ALLOWANCE ;
  return ((double)max_total_size / (double)heap_size);
}
Пример #10
0
/**********************************************************
 * mm_check
 * Check the consistency of the memory heap
 * Return nonzero if the heap is consistant.
 *********************************************************/
int mm_check(void)
{
#ifdef DEBUG_BUILD

    int i;
    dlist *current;
    void *bp; //To point at the start of the heap
    size_t size = 0; //To measure the total size of blocks on the heap

    // Check if every block in free list is actually marked free.
    // If a allocated block is in the free list then it may result in segmentation faults
    // while accessing the prev and next pointers. It will also result in the allocater manipulating 
    // memory allocated to user which will be nasty!

    for(i = 0; i < NUM_SEG_LIST; i++) {
        current = sep_list_head[i];
    
        while (current != NULL) {
            // Check if block is in heap
            if (is_in_heap((void*)current) == 0)
                return 0;

            if (GET_ALLOC(HDRP((void*)current))) {
                PRINTDBG (("block (%p) in free list is allocated!\n", current));
                return 0;
            }
            current = current->next;
        }
    }

    // Check if there exist any free blocks that may have escaped coalescing. 
    // If found, these cases result in internal fragmentation.
    for (bp = heap_listp; GET_SIZE(HDRP(bp)) > 0; bp = NEXT_BLKP(bp))
    {
        // Check if the current block is free and the next block is also free
        // Since this is done in a sequential manner, we don't need to check the previous blk
        if (!GET_ALLOC(HDRP(bp)) && (!GET_ALLOC(HDRP(NEXT_BLKP(bp))))) {
            PRINTDBG (("Consecutive blocks (%p, %p) have escaped coalescing!\n", bp, NEXT_BLKP(bp)));
            return 0;
        }
    }

    for (bp = heap_listp; GET_SIZE(HDRP(bp)) > 0; bp = NEXT_BLKP(bp)) {
        if (bp < mem_heap_lo() || bp > mem_heap_hi()) {
            PRINTDBG (("Block is outside the heap.\n"));
            return 0;
        }
        else {
            size += GET_SIZE(HDRP(bp));     //Add the size of the current block to the total size of the calculated blocks on the heap so far
        }
    }
            
    if (size == mem_heapsize())
        PRINTDBG (("The total size of all blocks on the heap match the heap size.\n"));

    if (mem_heapsize() > mem_pagesize())   //Check if heap size exceeded systems page size  
        PRINTDBG (("Heap size is more than page size. TLB misses might occur\n"));

    char c;
    scanf("%c\n", &c);

#endif
    return 1;
}