Commit 6c942fb0 authored by Caleb C. Sander's avatar Caleb C. Sander
Browse files

Clean up starter code

parent e6a41d57
No related merge requests found
Showing with 183 additions and 106 deletions
+183 -106
......@@ -2,7 +2,7 @@
# Makefile for the malloc lab driver
#
CC = clang
CFLAGS = -Werror -Wall -Wextra -O3 -g -DDRIVER
CFLAGS = -Werror -Wall -Wextra -O3 -g
all: bin/mdriver-implicit bin/mdriver-explicit
......@@ -15,7 +15,7 @@ bin/mdriver-explicit: out/mdriver-explicit.o out/mm-explicit.o out/memlib.o out/
out/mdriver-implicit.o: driver/mdriver.c
$(CC) $(CFLAGS) -c -DSTAGE0 $^ -o $@
out/mdriver-explicit.o: driver/mdriver.c
out/mdriver-explicit.o: driver/mdriver.c
$(CC) $(CFLAGS) -c -DSTAGE1 $^ -o $@
out/%.o: src/%.c
......@@ -25,4 +25,4 @@ out/%.o: driver/%.c
$(CC) $(CFLAGS) -c $^ -o $@
clean:
rm -f *~ out/*.o bin/*
rm -f out/* bin/*
#include <stddef.h>
#include <sys/types.h>
void mem_init(void);
void mem_deinit(void);
......
#ifndef MM_H
#define MM_H
#include <stdio.h>
#include <stdbool.h>
#include <stddef.h>
extern bool mm_init(void);
extern void *mm_malloc(size_t size);
extern void mm_free(void *ptr);
extern void *mm_realloc(void *ptr, size_t size);
extern void *mm_calloc(size_t nmemb, size_t size);
extern void mm_checkheap();
bool mm_init(void);
void *mm_malloc(size_t size);
void mm_free(void *ptr);
void *mm_realloc(void *ptr, size_t size);
void *mm_calloc(size_t nmemb, size_t size);
void mm_checkheap(void);
#endif /* MM_H */
......@@ -4,120 +4,158 @@
* TODO (bug): Uh..this is an implicit list???
*/
#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);
/** The required alignment of heap payloads */
const size_t ALIGNMENT = 2 * sizeof(size_t);
/** The layout of each block allocated on the heap */
typedef struct {
/** The size of the block and whether it is allocated (stored in the low bit) */
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[];
uint8_t payload[];
} block_t;
/** The first and last blocks on the heap */
static block_t *mm_heap_first = NULL;
static block_t *mm_heap_last = NULL;
/** Rounds up `size` to the nearest multiple of `n` */
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;
return (size + (n - 1)) / n * n;
}
/** Set's a block's header with the given size and allocation state */
static void set_header(block_t *block, size_t size, bool is_allocated) {
block->header = size | is_allocated;
}
/** Extracts a block's size from its header */
static size_t get_size(block_t *block) {
return block->header & ~1;
}
/** Extracts a block's allocation state from its header */
static bool is_allocated(block_t *block) {
return block->header & 0x1;
return block->header & 1;
}
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) {
/**
* Finds the first free block in the heap with at least the given size.
* If no block is large enough, returns NULL.
*/
static block_t *find_fit(size_t size) {
// Traverse the blocks in the heap using the implicit list
for (
block_t *curr = mm_heap_first;
mm_heap_last != NULL && curr <= mm_heap_last;
curr = (void *) curr + get_size(curr)
) {
// If the block is free and large enough for the allocation, return it
if (!is_allocated(curr) && get_size(curr) >= size) {
return curr;
}
}
return NULL;
}
/** Gets the header corresponding to a given payload pointer */
static block_t *block_from_payload(void *ptr) {
return ptr - offsetof(block_t, payload);
}
/**
* mm_init - Initializes the allocator state
*/
bool mm_init(void) {
mm_heap_first = mem_sbrk(8);
set_header(mm_heap_first, 8, true);
// We want the first payload to start at ALIGNMENT bytes from the start of the heap
void *padding = mem_sbrk(ALIGNMENT - sizeof(block_t));
if (padding == (void *) -1) {
return false;
}
// Initialize the heap with no blocks
mm_heap_first = NULL;
mm_heap_last = NULL;
return true;
}
/**
* mm_malloc - Allocates a block with the given size
*/
void *mm_malloc(size_t size) {
size_t asize = round_up(size + sizeof(word_t), ALIGNMENT);
// The block must have enough space for a header and be 16-byte aligned
size = round_up(sizeof(block_t) + size, ALIGNMENT);
// If there is a large enough free block, use it
block_t *block = find_fit(size);
if (block != NULL) {
set_header(block, get_size(block), true);
return block->payload;
}
block_t *block = find_fit(asize);
// Otherwise, a new block needs to be allocated at the end of the heap
block = mem_sbrk(size);
if (block == (void *) -1) {
return NULL;
}
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);
// Update mm_heap_first and mm_heap_last since we extended the heap
if (mm_heap_first == NULL) {
mm_heap_first = block;
}
mm_heap_last = block;
set_header(block, get_size(block), true);
// Initialize the block with the allocated size
set_header(block, size, true);
return block->payload;
}
/**
* mm_free - Releases a block to be reused for future allocations
*/
void mm_free(void *ptr) {
if (!ptr) {
// mm_free(NULL) does nothing
if (ptr == NULL) {
return;
}
block_t *block = (block_t *)(ptr - offsetof(block_t, payload));
size_t block_size = get_size(block);
set_header(block, block_size, false);
// Mark the block as unallocated
block_t *block = block_from_payload(ptr);
set_header(block, get_size(block), 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;
(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;
(void) nmemb;
(void) size;
return NULL;
}
/*
/**
* mm_checkheap - So simple, it doesn't need a checker!
*/
void mm_checkheap() {
void mm_checkheap(void) {
}
......@@ -5,120 +5,158 @@
* 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);
/** The required alignment of heap payloads */
const size_t ALIGNMENT = 2 * sizeof(size_t);
/** The layout of each block allocated on the heap */
typedef struct {
/** The size of the block and whether it is allocated (stored in the low bit) */
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[];
uint8_t payload[];
} block_t;
/** The first and last blocks on the heap */
static block_t *mm_heap_first = NULL;
static block_t *mm_heap_last = NULL;
/** Rounds up `size` to the nearest multiple of `n` */
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;
return (size + (n - 1)) / n * n;
}
/** Set's a block's header with the given size and allocation state */
static void set_header(block_t *block, size_t size, bool is_allocated) {
block->header = size | is_allocated;
}
/** Extracts a block's size from its header */
static size_t get_size(block_t *block) {
return block->header & ~1;
}
/** Extracts a block's allocation state from its header */
static bool is_allocated(block_t *block) {
return block->header & 0x1;
return block->header & 1;
}
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) {
/**
* Finds the first free block in the heap with at least the given size.
* If no block is large enough, returns NULL.
*/
static block_t *find_fit(size_t size) {
// Traverse the blocks in the heap using the implicit list
for (
block_t *curr = mm_heap_first;
mm_heap_last != NULL && curr <= mm_heap_last;
curr = (void *) curr + get_size(curr)
) {
// If the block is free and large enough for the allocation, return it
if (!is_allocated(curr) && get_size(curr) >= size) {
return curr;
}
}
return NULL;
}
/** Gets the header corresponding to a given payload pointer */
static block_t *block_from_payload(void *ptr) {
return ptr - offsetof(block_t, payload);
}
/**
* mm_init - Initializes the allocator state
*/
bool mm_init(void) {
mm_heap_first = mem_sbrk(8);
set_header(mm_heap_first, 8, true);
// We want the first payload to start at ALIGNMENT bytes from the start of the heap
void *padding = mem_sbrk(ALIGNMENT - sizeof(block_t));
if (padding == (void *) -1) {
return false;
}
// Initialize the heap with no blocks
mm_heap_first = NULL;
mm_heap_last = NULL;
return true;
}
/**
* mm_malloc - Allocates a block with the given size
*/
void *mm_malloc(size_t size) {
size_t asize = round_up(size + sizeof(word_t), ALIGNMENT);
// The block must have enough space for a header and be 16-byte aligned
size = round_up(sizeof(block_t) + size, ALIGNMENT);
// If there is a large enough free block, use it
block_t *block = find_fit(size);
if (block != NULL) {
set_header(block, get_size(block), true);
return block->payload;
}
block_t *block = find_fit(asize);
// Otherwise, a new block needs to be allocated at the end of the heap
block = mem_sbrk(size);
if (block == (void *) -1) {
return NULL;
}
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);
// Update mm_heap_first and mm_heap_last since we extended the heap
if (mm_heap_first == NULL) {
mm_heap_first = block;
}
mm_heap_last = block;
set_header(block, get_size(block), true);
// Initialize the block with the allocated size
set_header(block, size, true);
return block->payload;
}
/**
* mm_free - Releases a block to be reused for future allocations
*/
void mm_free(void *ptr) {
if (!ptr) {
// mm_free(NULL) does nothing
if (ptr == NULL) {
return;
}
block_t *block = (block_t *)(ptr - offsetof(block_t, payload));
size_t block_size = get_size(block);
set_header(block, block_size, false);
// Mark the block as unallocated
block_t *block = block_from_payload(ptr);
set_header(block, get_size(block), 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;
(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;
(void) nmemb;
(void) size;
return NULL;
}
/*
/**
* mm_checkheap - So simple, it doesn't need a checker!
*/
void mm_checkheap() {
void mm_checkheap(void) {
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment