mm_init, mm_free, coalesce
This commit is contained in:
parent
aa8ffbba68
commit
cabd49cb4f
154
mm.c
154
mm.c
@ -25,6 +25,8 @@ struct block {
|
|||||||
struct list_elem elem;
|
struct list_elem elem;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct block *heap_listp = 0;
|
||||||
|
|
||||||
/* Basic constants and macros */
|
/* Basic constants and macros */
|
||||||
#define WSIZE sizeof(struct boundary_tag) /* Word and header/footer size (bytes) */
|
#define WSIZE sizeof(struct boundary_tag) /* Word and header/footer size (bytes) */
|
||||||
#define DSIZE 2*WSIZE
|
#define DSIZE 2*WSIZE
|
||||||
@ -50,16 +52,34 @@ static size_t list_sizes[NUM_LISTS];
|
|||||||
/* Function prototypes for internal helper routines */
|
/* Function prototypes for internal helper routines */
|
||||||
static struct block *extend_heap(size_t words, int realloc);
|
static struct block *extend_heap(size_t words, int realloc);
|
||||||
static void place(struct block *blck, size_t asize);
|
static void place(struct block *blck, size_t asize);
|
||||||
static struct list* find_list(int not_empty, size_t size);
|
static struct list* find_list(size_t size);
|
||||||
static struct block *find_fit(size_t num_words);
|
static struct block *find_fit(size_t num_words);
|
||||||
|
//~ static void coalesce_free_lists();
|
||||||
|
static struct block *coalesce(struct block *bp);
|
||||||
|
|
||||||
|
/* Given a block, obtain previous's block footer.
|
||||||
|
Works for left-most block also. */
|
||||||
|
static struct boundary_tag * prev_blk_footer(struct block *blk) {
|
||||||
|
return &blk->header - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return if block is free */
|
||||||
|
static bool blk_free(struct block *blk) {
|
||||||
|
return !blk->header.inuse;
|
||||||
|
}
|
||||||
|
|
||||||
/* Return size of block is free */
|
/* Return size of block is free */
|
||||||
static size_t blk_size(struct block *blk) {
|
static size_t blk_size(struct block *blk) {
|
||||||
return blk->header.size;
|
return blk->header.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Given a block, obtain pointer to previous block.
|
||||||
|
Not meaningful for left-most block. */
|
||||||
|
static struct block *prev_blk(struct block *blk) {
|
||||||
|
struct boundary_tag *prevfooter = prev_blk_footer(blk);
|
||||||
|
assert(prevfooter->size != 0);
|
||||||
|
return (struct block *)((void *)blk - WSIZE * prevfooter->size);
|
||||||
|
}
|
||||||
|
|
||||||
/* Given a block, obtain pointer to next block.
|
/* Given a block, obtain pointer to next block.
|
||||||
Not meaningful for right-most block. */
|
Not meaningful for right-most block. */
|
||||||
@ -95,6 +115,41 @@ static void set_block_free(struct block *blk, int size) {
|
|||||||
set_header_and_footer(blk, size, 0);
|
set_header_and_footer(blk, size, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mm_init(void)
|
||||||
|
{
|
||||||
|
assert (offsetof(struct block, payload) == 4);
|
||||||
|
assert (sizeof(struct boundary_tag) == 4);
|
||||||
|
|
||||||
|
/* Create the initial empty heap */
|
||||||
|
struct boundary_tag * initial = mem_sbrk(4 * sizeof(struct boundary_tag));
|
||||||
|
if (initial == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* We use a slightly different strategy than suggested in the book.
|
||||||
|
* Rather than placing a min-sized prologue block at the beginning
|
||||||
|
* of the heap, we simply place two fences.
|
||||||
|
* The consequence is that coalesce() must call prev_blk_footer()
|
||||||
|
* and not prev_blk() because prev_blk() cannot be called on the
|
||||||
|
* left-most block.
|
||||||
|
*/
|
||||||
|
initial[2] = FENCE; /* Prologue footer */
|
||||||
|
heap_listp = (struct block *)&initial[3];
|
||||||
|
initial[3] = FENCE; /* Epilogue header */
|
||||||
|
|
||||||
|
for (int i = 0; i < NUM_LISTS; i++) {
|
||||||
|
struct list current_list;
|
||||||
|
list_init(¤t_list);
|
||||||
|
free_lists[i] = current_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < NUM_LISTS; i++)
|
||||||
|
list_sizes[i] = MIN_BLOCK_SIZE_WORDS * (i + 1);
|
||||||
|
|
||||||
|
/* Extend the empty heap with a free block of CHUNKSIZE bytes */
|
||||||
|
if (extend_heap(CHUNKSIZE, 1) == NULL)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The mm malloc routine returns a pointer to an allocated block payload of at
|
* The mm malloc routine returns a pointer to an allocated block payload of at
|
||||||
@ -116,6 +171,12 @@ void *mm_malloc(size_t size) {
|
|||||||
return blck->payload;
|
return blck->payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//~ coalesce_free_lists();
|
||||||
|
//~ if ((blck = find_fit(words)) != NULL) {
|
||||||
|
//~ place(blck, words);
|
||||||
|
//~ return blck->payload;
|
||||||
|
//~ }
|
||||||
|
|
||||||
if ((blck = extend_heap(words, 0)) == NULL){
|
if ((blck = extend_heap(words, 0)) == NULL){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -123,7 +184,75 @@ void *mm_malloc(size_t size) {
|
|||||||
return blck->payload;
|
return blck->payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mm_free(void *bp)
|
||||||
|
{
|
||||||
|
assert (heap_listp != 0); // assert that mm_init was called
|
||||||
|
if (bp == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Find block from user pointer */
|
||||||
|
struct block *blk = bp - offsetof(struct block, payload);
|
||||||
|
size_t size = blk_size(blk);
|
||||||
|
|
||||||
|
set_block_free(blk, size);
|
||||||
|
|
||||||
|
list_push_front(find_list(size), &blk->elem);
|
||||||
|
|
||||||
|
coalesce(blk);
|
||||||
|
}
|
||||||
|
|
||||||
|
//~ static void coalesce_free_lists()
|
||||||
|
//~ {
|
||||||
|
//~ for (int i = 0; i < NUM_LISTS; i++) {
|
||||||
|
//~ struct list* current_list = &free_lists[i];
|
||||||
|
//~ for (struct list_elem* e = list_begin(current_list); e != list_back(current_list); e = list_next(e)) {
|
||||||
|
//~ struct block* bp = list_entry(e, struct block, elem);
|
||||||
|
//~ coalesce(bp);
|
||||||
|
//~ }
|
||||||
|
//~ }
|
||||||
|
//~ }
|
||||||
|
|
||||||
|
static struct block *coalesce(struct block *bp)
|
||||||
|
{
|
||||||
|
bool prev_alloc = prev_blk_footer(bp)->inuse; /* is previous block allocated? */
|
||||||
|
bool next_alloc = ! blk_free(next_blk(bp)); /* is next block allocated? */
|
||||||
|
size_t size = blk_size(bp);
|
||||||
|
|
||||||
|
if (prev_alloc && next_alloc) { /* Case 1 */
|
||||||
|
// both are allocated, nothing to coalesce
|
||||||
|
return bp;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (prev_alloc && !next_alloc) { /* Case 2 */
|
||||||
|
// combine this block and next block by extending it
|
||||||
|
list_remove(&bp->elem);
|
||||||
|
set_block_free(bp, size + blk_size(next_blk(bp)));
|
||||||
|
list_remove(&next_blk(bp)->elem);
|
||||||
|
list_push_front(find_list(size + blk_size(next_blk(bp))), &bp->elem);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (!prev_alloc && next_alloc) { /* Case 3 */
|
||||||
|
// combine previous and this block by extending previous
|
||||||
|
list_remove(&bp->elem);
|
||||||
|
bp = prev_blk(bp);
|
||||||
|
set_block_free(bp, size + blk_size(bp));
|
||||||
|
list_remove(&bp->elem);
|
||||||
|
list_push_front(find_list(size + blk_size(next_blk(bp))), &bp->elem);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
else { /* Case 4 */
|
||||||
|
// combine all previous, this, and next block into one
|
||||||
|
list_remove(&bp->elem);
|
||||||
|
set_block_free(prev_blk(bp),
|
||||||
|
size + blk_size(next_blk(bp)) + blk_size(prev_blk(bp)));
|
||||||
|
bp = prev_blk(bp);
|
||||||
|
list_remove(&bp->elem);
|
||||||
|
list_remove(&next_blk(bp)->elem);
|
||||||
|
list_push_front(find_list(size + blk_size(next_blk(bp))), &bp->elem);
|
||||||
|
}
|
||||||
|
return bp;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Extend heap with free block and return its block pointer
|
* Extend heap with free block and return its block pointer
|
||||||
@ -144,7 +273,7 @@ static struct block *extend_heap(size_t words, int realloc)
|
|||||||
if (realloc) {
|
if (realloc) {
|
||||||
return blk;
|
return blk;
|
||||||
}
|
}
|
||||||
list_push_front(find_list(0, words), &blk->elem);
|
list_push_front(find_list(words), &blk->elem);
|
||||||
|
|
||||||
// NOT IMPLEMENTED YET
|
// NOT IMPLEMENTED YET
|
||||||
//return coalesce(blk);
|
//return coalesce(blk);
|
||||||
@ -168,7 +297,7 @@ static void place(struct block *blck, size_t asize) {
|
|||||||
set_block_free(blck, remaining_size);
|
set_block_free(blck, remaining_size);
|
||||||
|
|
||||||
/* Add remaining free block back into list */
|
/* Add remaining free block back into list */
|
||||||
list_push_front(find_list(0, remaining_size), &blck->elem);
|
list_push_front(find_list(remaining_size), &blck->elem);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
set_block_used(blck, csize);
|
set_block_used(blck, csize);
|
||||||
@ -178,11 +307,11 @@ static void place(struct block *blck, size_t asize) {
|
|||||||
/**
|
/**
|
||||||
* Find free list with blocks of given size
|
* Find free list with blocks of given size
|
||||||
*/
|
*/
|
||||||
static struct list* find_list(int not_empty, size_t n_words) {
|
static struct list* find_list(size_t n_words) {
|
||||||
|
|
||||||
for (int i = 0; i < NUM_LISTS; i++) {
|
for (int i = 0; i < NUM_LISTS; i++) {
|
||||||
if ((n_words < list_sizes[i]) || (i == (NUM_LISTS - 1))) {
|
if ((n_words < list_sizes[i]) || (i == (NUM_LISTS - 1))) {
|
||||||
if (not_empty && list_empty(&free_lists[i])) {
|
if (list_empty(&free_lists[i])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
return &free_lists[i];
|
return &free_lists[i];
|
||||||
@ -196,7 +325,7 @@ static struct list* find_list(int not_empty, size_t n_words) {
|
|||||||
*/
|
*/
|
||||||
static struct block *find_fit(size_t num_words)
|
static struct block *find_fit(size_t num_words)
|
||||||
{
|
{
|
||||||
struct list* free_list = find_list(1, num_words);
|
struct list* free_list = find_list(num_words);
|
||||||
|
|
||||||
if (free_list == NULL) {
|
if (free_list == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -212,5 +341,10 @@ static struct block *find_fit(size_t num_words)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
team_t team = {
|
||||||
|
"?", // team name
|
||||||
|
"Micah Moore",
|
||||||
|
"micahmoore@vt.edu",
|
||||||
|
"Felicia Seo",
|
||||||
|
"seofelicia@vt.edu",
|
||||||
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user