malloc-lab/mm.c

421 lines
14 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* mm-naive.c - The fastest, least memory-efficient malloc package.
*
* In this naive approach, a block is allocated by simply incrementing
* the brk pointer. A block is pure payload. There are no headers or
* footers. Blocks are never coalesced or reused. Realloc is
* implemented directly using mm_malloc and mm_free.
*
* NOTE TO STUDENTS: Replace this header comment with your own header
* comment that gives a high level description of your solution.
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <string.h>
#include "mm.h"
#include "memlib.h"
/*********************************************************
* NOTE TO STUDENTS: Before you do anything else, please
* provide your team information in the following struct.
********************************************************/
team_t team = {
/* Team name */
"anna.schlittenhardt@stud.uni-due.de+tuan-dat.tran@stud.uni-due.de",
/* First member's full name */
"Anna Schlittenhardt",
/* First member's email address */
"anna.schlittenhardt@stud.uni-due.de",
/* Second member's full name (leave blank if none) */
"Tuan-Dat Tran",
/* Second member's email address (leave blank if none) */
"tuan-dat.tran@stud.uni-due.de"
};
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////// STRUCTURE //////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Filled Blk
// 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
// HEADER | SIZE | A|
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
// BP-> | ALLOCED MEMORY |
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
// FOOTER | SIZE | A|
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
//
// Empty Blk
// 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
// HEADER | SIZE | A|
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
// BP-> | PTR TO PREV FREE BLK |
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
// | PTR TO NEXT FREE BLK |
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
// | UNALLOC MEMORY |
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
// FOOTER | SIZE | A|
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////// DEFINES ///////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/* single word (4) or double word (8) alignment */
#define ALIGNMENT 8
/* rounds up to the nearest multiple of ALIGNMENT */
#define ALIGN(size) (((size) + (ALIGNMENT-1)) & ~0x7)
#define SIZE_T_SIZE (ALIGN(sizeof(size_t)))
/* Page 830, Pearson R. Bryant D. OHallaron. Computer Systems: A Programmers Perspective.3rd Edition, Pearson, 2003. */
/* Basic constants and macros */
#define WSIZE 4 /* Word and header/footer size (bytes) */
#define DSIZE 8 /* Double word size (bytes) */
#define CHUNKSIZE (1<<12) /* Extend heap by this amount (bytes) */
#define MAX(x, y) ((x) > (y)? (x) : (y))
#define MIN(x, y) ((x) < (y)? (x) : (y))
/* Pack a size and allocated bit into a word */
#define PACK(size, alloc) ((size) | (alloc))
/* Read and write a word at address p */
#define GET(p) (*(unsigned int *)(p))
#define PUT(p, val) (*(unsigned int *)(p) = (val))
#define PUTT(p, val) (*(unsigned int *)(p) = (val))
/* Read the size and allocated fields from address p */
#define GET_SIZE(p) (GET(p) & ~0x7)
#define GET_ALLOC(p) (GET(p) & 0x1)
/* Given block ptr bp, compute address of its header and footer */
#define HDRP(bp) ((char *)(bp) - WSIZE)
#define FTRP(bp) ((char *)(bp) + GET_SIZE(HDRP(bp)) - DSIZE)
/* Given block ptr bp, compute address of next and previous blocks */
#define NEXT_BLKP(bp) ((char *)(bp) + GET_SIZE(((char *)(bp) - WSIZE)))
#define PREV_BLKP(bp) ((char *)(bp) - GET_SIZE(((char *)(bp) - DSIZE)))
#define PUT_PTR(p, ptr) (*(unsigned int *)(p) = (unsigned int)(ptr))
#define PRV_PTR(ptr) ((char *)(ptr))
#define NXT_PTR(ptr) ((char *)(ptr) + WSIZE)
#define PRV_BLK(ptr) (*(char **)(ptr))
#define NXT_BLK(ptr) (*(char **)(NXT_PTR(ptr)))
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////// GLOBAL VARS /////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
#define LISTSIZE 20
static char* heap_listp;
char* seg_list[LISTSIZE];
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////// HELPER PREDEF ////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/* Page 856-858, Pearson R. Bryant D. OHallaron. Computer Systems: A Programmers Perspective.3rd Edition, Pearson, 2003. */
static void* place(void *bp, size_t asize);
/* Page 833, Pearson R. Bryant D. OHallaron. Computer Systems: A Programmers Perspective.3rd Edition, Pearson, 2003. */
static void* coalesce(void *bp);
/* Page 831, Pearson R. Bryant D. OHallaron. Computer Systems: A Programmers Perspective.3rd Edition, Pearson, 2003. */
static void* extend_heap(size_t words);
static void add_free(void* bp, size_t asize);
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////// HELPER FUNCTIONS ///////////////////////////////
////////////////////////////////////////////////////////////////////////////////
static void *extend_heap(size_t size)
{
size_t asize;
asize = ALIGN(size);
void *ptr;
if ((ptr = mem_sbrk(asize)) == (void *)-1)
return NULL;
/* Set Header and Footer*/
PUTT(HDRP(ptr), PACK(asize, 0));
PUTT(FTRP(ptr), PACK(asize, 0));
PUTT(HDRP(NEXT_BLKP(ptr)), PACK(0, 1));
add_free(ptr, asize);
return coalesce(ptr);
}
static void add_free(void *ptr, size_t size) {
int list = 0;
void *searching_ptr = ptr;
void *in_ptr = NULL;
/* Select List*/
while ((list < LISTSIZE - 1) && (size > 1)) {
size >>= 1;
list++;
}
/* Search in size-ascending order*/
searching_ptr = seg_list[list];
while ((searching_ptr != NULL) && (size > GET_SIZE(HDRP(searching_ptr)))) {
in_ptr = searching_ptr;
searching_ptr = PRV_BLK(searching_ptr);
}
/* Set previous and next*/
if (searching_ptr != NULL && in_ptr != NULL) {
PUT_PTR(NXT_PTR(searching_ptr), ptr);
PUT_PTR(NXT_PTR(ptr), in_ptr);
PUT_PTR(PRV_PTR(ptr), searching_ptr);
PUT_PTR(PRV_PTR(in_ptr), ptr);
}
else if (searching_ptr != NULL && in_ptr == NULL) {
PUT_PTR(PRV_PTR(ptr), searching_ptr);
PUT_PTR(NXT_PTR(searching_ptr), ptr);
PUT_PTR(NXT_PTR(ptr), NULL);
seg_list[list] = ptr;
}
else if(searching_ptr == NULL && in_ptr != NULL) {
PUT_PTR(NXT_PTR(ptr), in_ptr);
PUT_PTR(PRV_PTR(ptr), NULL);
PUT_PTR(PRV_PTR(in_ptr), ptr);
}
else {
PUT_PTR(NXT_PTR(ptr), NULL);
PUT_PTR(PRV_PTR(ptr), NULL);
seg_list[list] = ptr;
}
return;
}
static void remove_free(void *ptr) {
int list = 0;
size_t size = GET_SIZE(HDRP(ptr));
/* Select List*/
while ((list < LISTSIZE - 1) && (size > 1)) {
size >>= 1;
list++;
}
if (PRV_BLK(ptr) != NULL && NXT_BLK(ptr) != NULL) {
PUT_PTR(NXT_PTR(PRV_BLK(ptr)), NXT_BLK(ptr));
PUT_PTR(PRV_PTR(NXT_BLK(ptr)), PRV_BLK(ptr));
} else if(PRV_BLK(ptr) != NULL && NXT_BLK(ptr) == NULL) {
PUT_PTR(NXT_PTR(PRV_BLK(ptr)), NULL);
seg_list[list] = PRV_BLK(ptr);
}
else if(PRV_BLK(ptr) == NULL && NXT_BLK(ptr) != NULL) {
PUT_PTR(PRV_PTR(NXT_BLK(ptr)), NULL);
} else {
seg_list[list] = NULL;
}
return;
}
static void *coalesce(void *ptr)
{
size_t prev_alloc = GET_ALLOC(HDRP(PREV_BLKP(ptr)));
size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(ptr)));
size_t size = GET_SIZE(HDRP(ptr));
if (prev_alloc && next_alloc) { // Case 1
return ptr;
}
else if (prev_alloc && !next_alloc) { // Case 2
remove_free(ptr);
remove_free(NEXT_BLKP(ptr));
size += GET_SIZE(HDRP(NEXT_BLKP(ptr)));
PUT(HDRP(ptr), PACK(size, 0));
PUT(FTRP(ptr), PACK(size, 0));
} else if (!prev_alloc && next_alloc) { // Case 3
remove_free(ptr);
remove_free(PREV_BLKP(ptr));
size += GET_SIZE(HDRP(PREV_BLKP(ptr)));
PUT(FTRP(ptr), PACK(size, 0));
PUT(HDRP(PREV_BLKP(ptr)), PACK(size, 0));
ptr = PREV_BLKP(ptr);
} else { // Case 4
remove_free(ptr);
remove_free(PREV_BLKP(ptr));
remove_free(NEXT_BLKP(ptr));
size += GET_SIZE(HDRP(PREV_BLKP(ptr))) + GET_SIZE(HDRP(NEXT_BLKP(ptr)));
PUT(HDRP(PREV_BLKP(ptr)), PACK(size, 0));
PUT(FTRP(NEXT_BLKP(ptr)), PACK(size, 0));
ptr = PREV_BLKP(ptr);
}
add_free(ptr, size);
return ptr;
}
static void *place(void *ptr, size_t asize)
{
size_t ptr_size = GET_SIZE(HDRP(ptr));
size_t remainder = ptr_size - asize;
remove_free(ptr);
if (remainder <= DSIZE * 2) {
// Do not split block
PUT(HDRP(ptr), PACK(ptr_size, 1));
PUT(FTRP(ptr), PACK(ptr_size, 1));
}
else if (asize >= 100) {
// Split block
PUT(HDRP(ptr), PACK(remainder, 0));
PUT(FTRP(ptr), PACK(remainder, 0));
PUTT(HDRP(NEXT_BLKP(ptr)), PACK(asize, 1));
PUTT(FTRP(NEXT_BLKP(ptr)), PACK(asize, 1));
add_free(ptr, remainder);
return NEXT_BLKP(ptr);
}
else {
// Split block
PUT(HDRP(ptr), PACK(asize, 1));
PUT(FTRP(ptr), PACK(asize, 1));
PUTT(HDRP(NEXT_BLKP(ptr)), PACK(remainder, 0));
PUTT(FTRP(NEXT_BLKP(ptr)), PACK(remainder, 0));
add_free(NEXT_BLKP(ptr), remainder);
}
return ptr;
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////// MAIN FUNCTIONALITY //////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/* Page 831, Pearson R. Bryant D. OHallaron. Computer Systems: A Programmers Perspective.3rd Edition, Pearson, 2003. */
/*
* mm_init - initialize the malloc package.
*/
int mm_init(void)
{
// init seg_list
for (size_t i = 0; i < LISTSIZE; ++i) {
seg_list[i] = NULL;
}
/* Create the initial empty heap */
if ((heap_listp = mem_sbrk(4*WSIZE)) == (void *)-1)
return -1;
PUT(heap_listp, 0); /* Alignment padding */
PUT(heap_listp + (1*WSIZE), PACK(DSIZE, 1)); /* Prologue header */
PUT(heap_listp + (2*WSIZE), PACK(DSIZE, 1)); /* Prologue footer */
PUT(heap_listp + (3*WSIZE), PACK(0, 1)); /* Epilogue header */
heap_listp += (2*WSIZE);
/* Extend the empty heap with a free block of CHUNKSIZE bytes */
if (extend_heap(CHUNKSIZE/WSIZE) == NULL)
return -1;
return 0;
}
/* Page 834, Pearson R. Bryant D. OHallaron. Computer Systems: A Programmers Perspective.3rd Edition, Pearson, 2003. */
/*
* mm_malloc - Allocate a block by incrementing the brk pointer.
* Always allocate a block whose size is a multiple of the alignment.
*/
void *mm_malloc(size_t size)
{
size_t asize; /* Adjusted block size */
size_t extendsize; /* Amount to extend heap if no fit */
void *ptr = NULL; /* Pointer */
// Ignore size 0 cases
if (size == 0)
return NULL;
// Align block size
if (size <= DSIZE) {
asize = 2 * DSIZE;
} else {
asize = ALIGN(size+DSIZE);
}
int list = 0;
size_t searchsize = asize;
// Search for free block in segregated list
while (list < LISTSIZE) {
if ((list == LISTSIZE- 1) || ((searchsize <= 1) && (seg_list[list] != NULL))) {
ptr = seg_list[list];
// Ignore blocks that are too small or marked with the reallocation bit
while ((ptr != NULL) && (asize > GET_SIZE(HDRP(ptr))))
{
ptr = PRV_BLK(ptr);
}
if (ptr != NULL)
break;
}
searchsize >>= 1;
list++;
}
// if free block is not found, extend the heap
if (ptr == NULL) {
extendsize = MAX(asize, CHUNKSIZE);
if ((ptr = extend_heap(extendsize)) == NULL)
return NULL;
}
// Place and divide block
ptr = place(ptr, asize);
// Return pointer to newly allocated block
return ptr;
}
/* Page 833, Pearson R. Bryant D. OHallaron. Computer Systems: A Programmers Perspective.3rd Edition, Pearson, 2003. */
/*
* mm_free - Freeing a block does nothing.
*/
void mm_free(void *ptr)
{
size_t size = GET_SIZE(HDRP(ptr));
add_free(ptr, size);
PUT(HDRP(ptr), PACK(size, 0));
PUT(FTRP(ptr), PACK(size, 0));
coalesce(ptr);
}
/*
* mm_realloc - Implemented simply in terms of mm_malloc and mm_free
*/
void *mm_realloc(void *ptr, size_t size)
{
/*
* ATTENTION: You do not need to implement realloc for this assignment
*/
void *oldptr = ptr;
void *newptr;
size_t copySize;
newptr = mm_malloc(size);
if (newptr == NULL)
return NULL;
copySize = *(size_t *)((char *)oldptr - SIZE_T_SIZE);
if (size < copySize)
copySize = size;
memcpy(newptr, oldptr, copySize);
mm_free(oldptr);
return newptr;
}