Beispiel #1
0
/*Removes the free block pointer int the free_list*/
static void removeFromFree(void *bp){
  if (GET_PREV_FREE(bp))
    SET_NEXT_FREE(GET_PREV_FREE(bp), GET_NEXT_FREE(bp));
  else
    free_listp = GET_NEXT_FREE(bp);
  SET_PREV_FREE(GET_NEXT_FREE(bp), GET_PREV_FREE(bp));
}
Beispiel #2
0
/*
 * add_block - add a block to the list in order of address
 */
static void add_block(void *bp) {
    int list = get_list(GET_SIZE(HDRP(bp)));
    void *next = free_lists[list];

    while (next != LIST_END) {
        /* Insert bp in middle of list, or beginning if prev(next) is NULL */
        if (next > bp) {
            if (GET_PREV_FREE(next) == LIST_END)
                free_lists[list] = bp; /* Update list head */
            else
                SET_NEXT_FREE(GET_PREV_FREE(next), bp);
            SET_PREV_FREE(bp, GET_PREV_FREE(next));
            SET_PREV_FREE(next, bp);
            SET_NEXT_FREE(bp, next);    
            return;
        /* Reached end of list, add bp to the end using saved block */
        } else if (GET_NEXT_FREE(next) == LIST_END) {
            SET_PREV_FREE(bp, next);
            SET_NEXT_FREE(next, bp);
            SET_NEXT_FREE(bp, LIST_END); 
            return;
        } 
        next = GET_NEXT_FREE(next);
    }

    /* Edge case: list is empty, add bp */
    SET_PREV_FREE(bp, LIST_END);
    SET_NEXT_FREE(bp, LIST_END);
    free_lists[list] = bp;
}
static void delete_free_block(void *ptr)
{
    void *next_free = GET_NEXT_FREE(ptr);
    void *prev_free = GET_PREV_FREE(ptr);

    if (ptr == free_headp && ptr == free_tailp)
    {
        free_headp = NULL;
        free_tailp = NULL;
    }
    else if (ptr == free_headp)
    {
        free_headp = next_free;
        PUT_PREV_FREE(free_headp, NULL);
    }
    else if (ptr == free_tailp)
    {
        free_tailp = prev_free;
        PUT_NEXT_FREE(free_tailp, NULL);
    }
    else
    {
        PUT_NEXT_FREE(prev_free, next_free);
        PUT_PREV_FREE(next_free, prev_free);
    }
}
Beispiel #4
0
/*
 * delete_block - delete a block from the free list
 */
static void delete_block(void *bp) {
    void *prev = GET_PREV_FREE(bp);
    void *next = GET_NEXT_FREE(bp);

    int list = get_list(GET_SIZE(HDRP(bp)));

    /* Case 1: bp is the only block in list */
    if ((prev == LIST_END) && (next == LIST_END)) {
        free_lists[list] = NULL;
        return;
    /* Case 2: bp is the first block in the list */
    } else if (prev == LIST_END) {
        SET_PREV_FREE(next, LIST_END);
        free_lists[list] = next;
        return;
    /* Case 3: bp is the last block in the list */
    } else if (next == LIST_END) {
        SET_NEXT_FREE(prev, LIST_END);
        return;
    /* Case 4: bp is in the middle of the list */
    } else {
        SET_NEXT_FREE(prev, next);
        SET_PREV_FREE(next, prev);
        return;
    }
}
Beispiel #5
0
/*
 * Scan the heap until we find a block large enough to fulfill the
 * request.
 */
void *
malloc(unsigned sz)
{
    block_header_t *header, *next;

    /* Align the request. */
    sz += MIN_REQUEST - 1;
    sz &= ~(MIN_REQUEST - 1);

    /* First fit. */
    for (header = (block_header_t *) heap_start;
         (char *) header < heap_end;
         header = next) {
        next = (block_header_t *)
            ((char *) header
             + sizeof(block_header_t)
             + GET_BLOCK_SIZE(*header));

        if (GET_PREV_FREE(*next) && sz <= GET_BLOCK_SIZE(*header)) {
            /* We can fit the request in this block. */
            void *result = (void *)((char *) header + sizeof(block_header_t));

            if (GET_BLOCK_SIZE(*header) < sz + sizeof(block_header_t) + MIN_REQUEST) {
                /* We can't fit any other requests here, though. */
                CLEAR_PREV_FREE(*next);
            }
            else {
                /* Split the block. */
                struct block_footer *footer =
                    (struct block_footer *)
                    ((char *) next - sizeof(struct block_footer));

                unsigned remaining = GET_BLOCK_SIZE(*header) - sz - sizeof(block_header_t);

                SET_BLOCK_SIZE(*header, sz);

                header = (block_header_t *)
                    ((char *) header
                     + sizeof(block_header_t)
                     + sz);

                ASSERT(remaining % 2 == 0, ("odd block size"));
                INIT_BLOCK_HEADER(*header, remaining, 0);

                footer->header = header;
            }

            return result;
        }
    }

    /* Uh oh, couldn't allocate! */
    panic();
    return 0;
}
Beispiel #6
0
/*
 * Free the block, coalescing with the previous and next blocks if
 * possible.
 */
void
free(void *ptr)
{
    block_header_t *header = (block_header_t *)
        ((char *) ptr - sizeof(block_header_t));

    block_header_t *next = (block_header_t *)
        ((char *) ptr + GET_BLOCK_SIZE(*header));

    block_header_t *next_next = (block_header_t *)
        ((char *) next + sizeof(block_header_t) + GET_BLOCK_SIZE(*next));

    struct block_footer *footer;
    unsigned size;

    if ((char *) next_next < heap_end && GET_PREV_FREE(*next_next)) {
        /* The block following us is free. */
        next = next_next;
    }

    if (GET_PREV_FREE(*header)) {
        /* The block prior to us is free. */
        footer = (struct block_footer *)
            ((char *) header - sizeof(struct block_footer));

        header = footer->header;
    }

    footer = (struct block_footer *)
        ((char *) next - sizeof(struct block_footer));

    footer->header = header;

    /* Expand the block to encompass the reclaimed space. */
    size = (char *) next - (char *) header - sizeof(block_header_t);
    ASSERT(size % 2 == 0, ("odd block size"));
    SET_BLOCK_SIZE(*header, size);

    /* Note in the header of the _next_ block that this block is free. */
    MARK_PREV_FREE(*next);
}
Beispiel #7
0
/*
 * Dump the heap to debug it.
 */
void
heap_walk()
{
    block_header_t *header, *next;

    printf("heap_begin=0x%p, heap_end=0x%p\n",
           heap_start, heap_end);

    for (header = (block_header_t *) heap_start;
         (char *) header < heap_end;
         header = next) {
        next = (block_header_t *)
            ((char *) header
             + sizeof(block_header_t)
             + GET_BLOCK_SIZE(*header));

        printf("%p heap_start+%04x size=%04x %s",
               header,
               (char *) header - heap_start,
               GET_BLOCK_SIZE(*header),
               GET_PREV_FREE(*next) ? "free" : "in use");

        if (GET_PREV_FREE(*next)) {
            struct block_footer *footer =
                (struct block_footer *)
                ((char *) next - sizeof(struct block_footer));

            if (footer->header != header) {
                printf(" BAD FOOTER, footer->header=%p heap_start+%04x",
                       footer->header,
                       (char *) footer->header - heap_start);
            }
        }

        printf("\n");
    }
}
Beispiel #8
0
/*
 * Return the amount of free space in the heap.
 */
int
heap_free()
{
    int nfree = 0;
    block_header_t *header, *next;

    for (header = (block_header_t *) heap_start;
         (char *) header < heap_end;
         header = next) {
        next = (block_header_t *)
            ((char *) header
             + sizeof(block_header_t)
             + GET_BLOCK_SIZE(*header));

        if (GET_PREV_FREE(*next))
            nfree += GET_BLOCK_SIZE(*header);
    }

    return nfree;
}
/*
 * mm_check - TODO
 */
static int mm_check()
{    
    /* Check that the blocks are properly organized & that epilogue is present */
    void *ptr = heap_listp;
    int prev_alloced;
    int freecount = 0;
    while (ptr < mem_heap_hi())
    {
        size_t size = GET_SIZE(HDRP(ptr));
        size_t size2 = GET_SIZE(FTRP(ptr));
        int allocated = GET_ALLOC(HDRP(ptr));
        int allocated2 = GET_ALLOC(FTRP(ptr));

        if (size == 0)
        {
            if (ptr != mem_heap_hi() - WSIZE)
            {
                mm_log("mm_check error: ran into size 0 (epilogue) at %p, which is not heap_hi().\n",ptr);
                return -1;
            }
            if (!allocated)
            {
                mm_log("mm_check error: epilogue at %p is marked as free\n",ptr);
                return -1;
            }
        }

        if (size != size2)
        {
            mm_log("mm_check error: %p size in header %d != footer %d\n", ptr, (int)size, (int)size2);
            return -1;
        }

        if (allocated != allocated2)
        {
            mm_log("mm_check error: %p alloc in header %d != footer %d\n", ptr, allocated, allocated2);
            return -1;
        }


        if (!allocated && !prev_alloced)
        {
            mm_log("mm_check error: two contiguous free blocks that should be coalesced. %p and prev.\n",ptr);
        }

        if (allocated)
        {
            //mm_log("block %p (%d,%d)\n", ptr, (int)size, allocated);
        }
        else
        {
            mm_log("block %p (%d,%d). prev=%p next=%p\n", ptr, (int)size, allocated, GET_PREV_FREE(ptr), GET_NEXT_FREE(ptr));
            freecount++;
        }

        prev_alloced = allocated;
        ptr += size;
    }

    /* Check the free list */
    int count = 0;
    ptr = free_headp;
    void *prev = NULL;
    while (ptr != NULL)
    {
        count++;
        size_t bsize = GET_SIZE(HDRP(ptr));

        if (GET_NEXT_FREE(ptr) && GET_PREV_FREE(GET_NEXT_FREE(ptr)) != ptr)
        {
            mm_log("mm_check error: prev of next of %p is %p\n", ptr, GET_PREV_FREE(GET_NEXT_FREE(ptr)));
            return -1;
        }

        if (GET_PREV_FREE(ptr) && GET_NEXT_FREE(GET_PREV_FREE(ptr)) != ptr)
        {
            mm_log("mm_check error: next of prev of %p is %p\n", ptr, GET_NEXT_FREE(GET_PREV_FREE(ptr)));
            return -1;
        }

        if (bsize == 0)
        {
            mm_log("mm_check error: block size 0 at %p\n", ptr);
            return -1;
        }
        if (GET_ALLOC(HDRP(ptr)) || GET_ALLOC(FTRP(ptr)))
        {
            mm_log("mm_check error: block at %p on the freelist is marked allocated\n", ptr);
            return -1;
        }
        if (GET_PREV_FREE(ptr) != prev)
        {
            mm_log("mm_check error: block at %p does not point to prev %p (points to %p)\n", ptr, prev, GET_PREV_FREE(ptr));
            return -1;
        }

        prev = ptr;
        ptr = GET_NEXT_FREE(ptr);
    }

    if (prev != free_tailp)
    {
        mm_log("mm_check error: last free block (%p) should == free_tailp (%p)\n", prev, free_tailp);
        return -1;
    }

    if (freecount != count)
    {
        mm_log("mm_check error: found %d free blocks, but only %d on the freelist.\n",freecount, count);
        return -1;
    }

    mm_log("mm_check says %d free block(s)\n",count);

    return 0;
}
Beispiel #10
0
/* 
 * mm_checkheap - Check the heap for correctness. It prints a nice grid
 *                representation of the heap at the moment in time it is
 *                called, as well as the block pointer and epilogue
 *                pointer. It takes __LINE__ as input, allowing it to print
 *                the number of the line it is called at. It also silently
 *                checks for errors and exits the program if any error
 *                is found. If silent is 0, it will only print the results
 *                upon finding an error.
 *
 *                NOTE: if mm_checkheap is called ANYWHERE besides malloc and
 *                free, it will find errors because of intermediate states
 *                that trigger error conditions. Therefore error_check should
 *                be 0 if you call it anywhere besides inside malloc and free.
 */
void mm_checkheap(int lineno)  
{ 
    char *bp;
    char alloc_char;
    char aligned;
    char hef;
    int payload;
    int size;
    int num_head = 0, num_tail = 0;
    int link_error_flag = 0;
    int alignment_flag = 0;
    int error_flag = 0;
    int error_check = 1; /* set to 0 if called outside malloc() and free() */
    int silent = 1;

    /* Silently check for errors */
    if (error_check) {
        for (bp = heap_listp; GET_SIZE(HDRP(bp)) > 0; bp = NEXT_BLKP(bp)) {
            if (!ALIGNED(bp))
                alignment_flag = 1;

            if (!GET_ALLOC(HDRP(bp))) {
                /* Check for linked list errors in free blocks */
                if (GET_NEXT_FREE(bp) == NULL)
                    num_tail++;
                else if (GET_PREV_FREE(GET_NEXT_FREE(bp)) != bp)
                    link_error_flag = 1;    
                if (GET_PREV_FREE(bp) == NULL)
                    num_head++;
                else if (GET_NEXT_FREE(GET_PREV_FREE(bp)) != bp)
                    link_error_flag = 1;
            }
            if (num_tail > 1||num_head > 1||link_error_flag||alignment_flag)
                error_flag = 1;
        }
    }

    if (error_flag || !silent) {
        printf("\n");
        printf("========================================"
            "==========================================\n");
        printf("                            HEAP CONSISTENCY CHECKER\n");
        printf("========================================"
            "==========================================\n");
        printf("Line number = %d\n", lineno);
        printf("Head of free list = %p\n",free_list);
        printf("Epilogue pointer  = %p\n", eptr);
        printf("----------------------------------------"
            "-----------------------------------------\n");
        printf("T |  Block pointer   | Size  |Payload|"
            "       Prev       |       Next       |A|HEF\n"); 
        printf("--|------------------|-------|-------|--"
            "----------------|------------------|-|---\n");

        for (bp = heap_listp; GET_SIZE(HDRP(bp)) > 0; bp = NEXT_BLKP(bp)) {
           payload = FTRP(bp)-bp;
           size = GET_SIZE(HDRP(bp));
           alloc_char = ALLOC_CHAR(HDRP(bp));
           aligned = ALIGNED_CHAR(bp); /* Check for alignment */
           hef = HEF(bp); /* Check that header = footer */
           if (GET_ALLOC(HDRP(bp))) {
               printf("%c |%18p|%7d|%7d|%18s|%18s|%c| %c \n",
                   alloc_char,
                   bp,
                   size,
                   payload,
                   "",
                   "",
                   aligned,
                   hef);
           } else {
               printf("%c |%18p|%7d|%7d|%18p|%18p|%c| %c \n",
                   alloc_char,
                   bp,
                   size,
                   payload,
                   GET_PREV_FREE(bp),
                   GET_NEXT_FREE(bp),
                   aligned,
                   hef);
          }
        }
        printf("----------------------------------------"
            "-----------------------------------------\n");
        printf("Key: T = (a)llocated or (f)ree. A = aligned to double word."
            " HEF = H/F tags match.\n");

        /* If there is a problem with the free list, print details and exit. */
        if (error_flag) {
            printf("----------------------------------------"
                "-----------------------------------------\n");
            printf("Heap integrity errors found:\n"); 
            if (num_tail > 1)
                printf("    [List error] More than one list tail.\n");
            if (num_head > 1)
                printf("    [List error] More than one list head.\n");
            if (link_error_flag)
                printf("    [List error] Links don't match up in "
                    "at least one block.\n"); 
            if (alignment_flag)
                printf("    [Alignment error] Unaligned block detected.\n");
            printf("----------------------------------------"
                "-----------------------------------------\n");
            printf("\n");
            exit(0);
        }  
    }
}