tomtetlaw -1 Posting Pro

I'm looking for feedback on my code. I wrote a custom memory allocator (out of pure boredom) that is faster than the STD one (malloc, free). It's pretty simple in the way it works, it has a base block of memory which is where everything is allocated from, and it keeps track of empty spaces after freeing memory. I'm wondering if there is anything that could be improved, optimized etc..

EDIT: Sorry if it's hard to read. For some reason all the newlines are being ignored.

#include "pch.h"

typedef struct memblock_s
{
    void *data;
    int location;
    int size;

    struct memblock_s *next, *prev;
} memblock_t;

typedef struct freespace_s
{
    int location;
    int size;

    struct freespace_s *next;
} freespace_t;

#define MEM_DEFAULT_SIZE 1024*1024*256 // 256mb in bytes

int mem_basesize;
void *mem_base;

int mem_top;

memblock_t *mem_blocks;
memblock_t *mem_firstblock;

freespace_t *mem_spaces;

void Mem_Init (void)
{
    int i;

    mem_basesize = MEM_DEFAULT_SIZE; 
    mem_base = malloc (mem_basesize);

    mem_top = 0;
    mem_blocks = NULL;
    mem_firstblock = NULL;
    mem_spaces = NULL;
}

void Mem_Shutdown (void)
{
    freespace_t *sp, *temp;
    memblock_t *b, *temp2;

    for (sp = mem_spaces; sp; sp = temp)
    {
        temp = sp->next;
        free (sp);
    }

    for (b = mem_firstblock; b; b = temp2)
    {
        temp2 = b->next;
        free (b);
    }

    free (mem_base);
}

void _Mem_Alloc (memblock_t *block, int size)
{
    freespace_t *sp;
    int diff;

    // first try to find an empty space
    for (sp = mem_spaces; sp; sp = sp->next)
    {
        if (sp->size == size)
        {
            // if the empty space is the same as the requested size,
            // just allocate the block
            block->location = sp->location;
            block->size = size;
            block->data = (char *)mem_base + block->location;

            // don't use this free space again
            sp->size = 0;
            sp->location = 0;
            break;
        }
        else
        {
            // if the empty space is bigger then the requested size,
            // allocate the block and make the empty space smaller
            if (sp->size > size)
            {
                block->location = sp->location;
                block->size = size;
                block->data = (char *)mem_base + block->location;

                diff = sp->size - size;
                sp->size = diff;
                sp->location += size;
                break;
            }
        }
    }

    if (!sp) // a free space wasn't found, add it to the end
    {
        // fill in the block
        block->location = mem_top + size;
        block->data = (char *)mem_base + block->location;
        block->size = size;
        mem_top += size;
    }

    // link the block into the list
    block->next = NULL;
    if (!mem_blocks)
    {
        block->next = NULL;
        block->prev = NULL;
        mem_blocks = block;
        mem_firstblock = block;
    }
    else
    {
        mem_blocks->next = block;
        block->prev = mem_blocks;
        block->next = NULL;
        mem_blocks = block;
    }
}

void *Mem_Alloc (int size)
{
    memblock_t *block;

    block = malloc (sizeof(memblock_t));
    _Mem_Alloc (block, size);
    return block->data;
}

void _Mem_Free (memblock_t *block)
{
    freespace_t *sp;

    // create an empty space to keep track of the hole in mem_base
    if (block->next || block->prev) // if there's only one block and it's just been freed, there's no point in doing all this
    {
        // take the block out of the list
        if (block->prev)
            block->prev->next = block->next;
        if (block->next)
            block->next->prev = block->prev;

        sp = malloc (sizeof(freespace_t));
        sp->location = block->location;
        sp->size = block->size;

        sp->next = mem_spaces;
        mem_spaces = sp;
        mem_spaces->next = NULL;
    }
    else // mark the list as empty as there's no more blocks
    {
        mem_blocks = NULL;
        mem_firstblock = NULL;
    }

    free (block);
}

void Mem_Free (void *mem)
{
    memblock_t *b;

    for (b = mem_firstblock; b; b = b->next)
        if (mem == b->data)
            _Mem_Free (b);
}