From aa8ffbba68d83d271650d9d20ec39c02e72a0777 Mon Sep 17 00:00:00 2001 From: Micah Moore Date: Wed, 9 Nov 2022 09:21:04 -0500 Subject: [PATCH] mm_malloc and related code --- mm.c | 216 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 mm.c diff --git a/mm.c b/mm.c new file mode 100644 index 0000000..c831db1 --- /dev/null +++ b/mm.c @@ -0,0 +1,216 @@ +#include +#include +#include + +#include "mm.h" +#include "memlib.h" +#include "list.h" +#include "config.h" + + +struct boundary_tag { + int inuse:1; + int size:31; +}; + +/* FENCE is used for heap prologue/epilogue. */ +const struct boundary_tag FENCE = { + .inuse = 1, + .size = 0 +}; + +struct block { + struct boundary_tag header; + char payload[0]; + struct list_elem elem; +}; + +/* Basic constants and macros */ +#define WSIZE sizeof(struct boundary_tag) /* Word and header/footer size (bytes) */ +#define DSIZE 2*WSIZE +#define MIN_BLOCK_SIZE_WORDS 8 /* Minimum block size in words */ +#define CHUNKSIZE (1<<10) /* Extend heap by this amount (words) */ + +#define NUM_LISTS 8 /* Number of free lists */ + +static inline size_t max(size_t x, size_t y) { + return x > y ? x : y; +} + + + +static size_t align(size_t size) { + return (size + ALIGNMENT - 1) & ~(ALIGNMENT - 1); +} + + +static struct list free_lists[NUM_LISTS]; +static size_t list_sizes[NUM_LISTS]; + +/* Function prototypes for internal helper routines */ +static struct block *extend_heap(size_t words, int realloc); +static void place(struct block *blck, size_t asize); +static struct list* find_list(int not_empty, size_t size); +static struct block *find_fit(size_t num_words); + +/* Return size of block is free */ +static size_t blk_size(struct block *blk) { + return blk->header.size; +} + + + + +/* Given a block, obtain pointer to next block. + Not meaningful for right-most block. */ +static struct block *next_blk(struct block *blk) { + assert(blk_size(blk) != 0); + return (struct block *)((void *)blk + WSIZE * blk->header.size); +} + +/* Given a block, obtain its footer boundary tag */ +static struct boundary_tag * get_footer(struct block *blk) { + return ((void *)blk + WSIZE * blk->header.size) + - sizeof(struct boundary_tag); +} + + +/* Set a block's size and inuse bit in header and footer */ +static void set_header_and_footer(struct block *blk, int size, int inuse) { + blk->header.inuse = inuse; + blk->header.size = size; + * get_footer(blk) = blk->header; /* Copy header to footer */ +} + + + +/* Mark a block as used and set its size. */ +static void set_block_used(struct block *blk, int size) { + set_header_and_footer(blk, size, 1); +} + + +/* Mark a block as free and set its size. */ +static void set_block_free(struct block *blk, int size) { + set_header_and_footer(blk, size, 0); +} + + +/* +* The mm malloc routine returns a pointer to an allocated block payload of at +* least size bytes. The entire allocated block should lie within the heap region and should +* not overlap with any other allocated chunk. +*/ +void *mm_malloc(size_t size) { + struct block *blck; + + if (size == 0) { + return NULL; + } + + size_t words = max(MIN_BLOCK_SIZE_WORDS, align(size + DSIZE) / WSIZE); + + /* Find fit for size */ + if ((blck = find_fit(words)) != NULL) { + place(blck, words); + return blck->payload; + } + + if ((blck = extend_heap(words, 0)) == NULL){ + return NULL; + } + place(blck, words); + return blck->payload; +} + + + +/* + * Extend heap with free block and return its block pointer + * Does not add new block to free list if called by realloc + */ +static struct block *extend_heap(size_t words, int realloc) +{ + void *blck = mem_sbrk(words * WSIZE); + + if (blck == NULL) + return NULL; + + /* Initialize free block header, footer and epilogue header. */ + struct block * blk = blck - sizeof(FENCE); + set_block_free(blk, words); + next_blk(blk)->header = FENCE; + + if (realloc) { + return blk; + } + list_push_front(find_list(0, words), &blk->elem); + + // NOT IMPLEMENTED YET + //return coalesce(blk); + return NULL; +} + + +/* + * Allocate block of memory at address blck + */ +static void place(struct block *blck, size_t asize) { + size_t csize = blk_size(blck); + + /* Remove block from free list */ + list_remove(&blck->elem); + + size_t remaining_size = csize - asize; + if (remaining_size >= MIN_BLOCK_SIZE_WORDS) { + set_block_used(blck, asize); + blck = next_blk(blck); + set_block_free(blck, remaining_size); + + /* Add remaining free block back into list */ + list_push_front(find_list(0, remaining_size), &blck->elem); + } + else { + set_block_used(blck, csize); + } +} + +/** + * Find free list with blocks of given size + */ +static struct list* find_list(int not_empty, size_t n_words) { + + for (int i = 0; i < NUM_LISTS; i++) { + if ((n_words < list_sizes[i]) || (i == (NUM_LISTS - 1))) { + if (not_empty && list_empty(&free_lists[i])) { + continue; + } + return &free_lists[i]; + } + } + return NULL; +} + +/* + * Find a fit for a block with num_words + */ +static struct block *find_fit(size_t num_words) +{ + struct list* free_list = find_list(1, num_words); + + if (free_list == NULL) { + return NULL; + } + + /* Search for block from selected free list*/ + for (struct list_elem* e = list_back(free_list); e != list_head(free_list); e = list_prev(e)) { + struct block* bp = list_entry(e, struct block, elem); + if (num_words <= blk_size(bp)) { + return bp; + } + } + return NULL; +} + + +