mm-implicit.c 2.71 KB
/*
 * mm-implicit.c - The best malloc package EVAR!
 *
 * TODO (bug): mm_realloc and mm_calloc don't seem to be working...
 * TODO (bug): The allocator doesn't re-use space very well...
 */

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <unistd.h>

#include "mm.h"
#include "memlib.h"

typedef uint64_t word_t;
const size_t ALIGNMENT = 2 * sizeof(word_t);

typedef struct {
    size_t header;
    /*
     * We don't know what the size of the payload will be, so we will
     * declare it as a zero-length array.  This allow us to obtain a
     * pointer to the start of the payload.
     */
    word_t payload[];
} block_t;

static block_t *mm_heap_first = NULL;
static block_t *mm_heap_last = NULL;

static size_t round_up(size_t size, size_t n) {
    return n * ((size + (n-1)) / n);
}

static size_t get_size(block_t *block) {
    return block->header & ~0x7;
}

static void set_header(block_t *block, size_t size, bool is_allocated) {
    block->header = size | is_allocated;
}

static bool is_allocated(block_t *block) {
    return block->header & 0x1;
}

block_t *find_fit(size_t size) {
    for (block_t *curr = mm_heap_first; mm_heap_last && curr <= mm_heap_last; curr = ((void *)curr + get_size(curr))) {
        size_t curr_size = get_size(curr);
        if (!is_allocated(curr) && curr_size >= size) {
            return curr;
        }
    }
    return NULL;
}


bool mm_init(void) {
    mm_heap_first = mem_sbrk(8);
    set_header(mm_heap_first, 8, true);
    mm_heap_last = NULL;
    return true;
}

void *mm_malloc(size_t size) {
    size_t asize = round_up(size + sizeof(word_t), ALIGNMENT);

    block_t *block = find_fit(asize);

    if (!block) {
        void * ptr = mem_sbrk(asize);
        if (ptr == (void *)-1) {
            return NULL;
        }
        mm_heap_last = (block_t *)ptr;
        block = mm_heap_last;
        set_header(block, asize, true);
    }

    set_header(block, get_size(block), true);
    return block->payload;
}

void mm_free(void *ptr) {
    if (!ptr) {
        return;
    }

    block_t *block = (block_t *)(ptr - offsetof(block_t, payload));
    size_t block_size = get_size(block);
    set_header(block, block_size, false);
}

/*
 * mm_realloc - Change the size of the block by mm_mallocing a new block,
 *      copying its data, and mm_freeing the old block.
 **/
void *mm_realloc(void *old_ptr, size_t size) {
    (void)old_ptr;
    (void)size;
    return NULL;
}


/*
 * mm_calloc - Allocate the block and set it to zero.
 */
void *mm_calloc(size_t nmemb, size_t size) {
    (void)nmemb;
    (void)size;
    return NULL;
}

/*
 * mm_checkheap - So simple, it doesn't need a checker!
 */
void mm_checkheap() {

}