Commit c57e5571 authored by Shivaji's avatar Shivaji

realloc for mm2.c

parent 54d4563a
/*
* 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
......@@ -35,6 +35,85 @@ team_t team = {
"member_2@cse.iitb.ac.in"
};
typedef struct tree_node_
{
struct tree_node_ *left_node;
struct tree_node_ *right_node;
struct tree_node_ *parent_node;
}tree_node_t;
typedef enum
{
MM_FALSE,
MM_TRUE
} vm_bool_t;
typedef struct block_meta_data_
{
vm_bool_t is_free;
uint32_t block_size;
struct block_meta_data_ *prev_block;
struct block_meta_data_ *next_block;
tree_node_t tree_node;
} block_meta_data_t;
typedef struct printer{
int rollno;
char *name;
struct printer *next;
}printer;
typedef struct block_end_meta_data_
{
uint32_t block_size;
} block_end_meta_data_t;
#define NEXT_META_BLOCK_BY_SIZE(block_meta_data_ptr) \
(block_meta_data_t *)((char *)(block_meta_data_ptr+1) \
+ block_meta_data_ptr->block_size \
+sizeof(block_end_meta_data_t))
#define mm_bind_blocks_for_allocation(allocated_meta_block,free_meta_block) \
free_meta_block->prev_block=allocated_meta_block; \
free_meta_block->next_block=allocated_meta_block->next_block; \
allocated_meta_block->next_block=free_meta_block; \
if(free_meta_block->next_block) \
free_meta_block->next_block->prev_block=free_meta_block
#define offsetof(struct_name,field_name) \
(unsigned int)&((struct_name *)0)->field_name
#define meta_data_block_addr(free_node_addr) \
(block_meta_data_t *) ((char *)(free_node_addr)-offsetof(block_meta_data_t,tree_node))
#define end_meta_data_addr(meta_data_addr) \
(block_end_meta_data_t *)((char *)(meta_data_addr+1) \
+meta_data_addr->block_size)
#define start_meta_data_addr(end_meta_data_addr) \
(block_meta_data_t *)((char *)(end_meta_data_addr) \
-end_meta_data_addr->block_size \
-sizeof(block_meta_data_t))
#define META_DATA_OVERHEAD \
(uint32_t)(sizeof(block_end_meta_data_t)+sizeof(block_meta_data_t))
#define TOTAL_COMBINE_SIZE_OF_BLOCKS(base) \
base->block_size \
+sizeof(block_end_meta_data_t) \
+sizeof(block_meta_data_t)
#define TOTAL_COMBINED_SIZE_OF_BLOCKS(base) \
base->next_block->block_size \
+base->prev_block->block_size \
+2*sizeof(block_end_meta_data_t) \
+2*sizeof(block_meta_data_t)
/* single word (4) or double word (8) alignment */
#define ALIGNMENT 8
......@@ -44,36 +123,645 @@ team_t team = {
#define SIZE_T_SIZE (ALIGN(sizeof(size_t)))
/*
/*
* mm_init - initialize the malloc package.
*/
tree_node_t init_free_node(void)
{
tree_node_t treenode;
treenode.left_node=NULL;
treenode.right_node=NULL;
treenode.parent_node=NULL;
return treenode;
}
void remove_block_from_tree(tree_node_t **root,tree_node_t *del_node);
void *init_mem_sbrk_break = NULL;
tree_node_t **root=NULL;
void LL_rotate(tree_node_t *parent,tree_node_t *node)
{
printf("Came to LL\n");
tree_node_t *p_parent=parent->parent_node;
tree_node_t *temp=parent->left_node;
tree_node_t *temp_right=temp->right_node;
if(p_parent==NULL)
{
*root=temp;
temp->parent_node=NULL;
}
else
{
block_meta_data_t *p_parent_meta_data=meta_data_block_addr(p_parent);
block_meta_data_t *temp_meta_data=meta_data_block_addr(temp);
temp->parent_node=p_parent;
if(temp_meta_data->block_size<=p_parent_meta_data->block_size)
{
p_parent->left_node=temp;
}
else
{
p_parent->right_node=temp;
}
}
temp->right_node=parent;
parent->parent_node=temp;
parent->left_node=temp_right;
}
void LR_Rotate(tree_node_t *parent,tree_node_t *node)
{
printf("Came to LR\n");
tree_node_t *p_parent=parent->parent_node;
tree_node_t *temp=parent->left_node;
block_meta_data_t *meta_data=meta_data_block_addr(temp);
tree_node_t *node_left=node->left_node;
tree_node_t *node_right=node->right_node;
if(p_parent==NULL)
{
*root=node;
node->parent_node=NULL;
}
else
{
block_meta_data_t *p_parent_meta_data=meta_data_block_addr(p_parent);
block_meta_data_t *node_meta_data=meta_data_block_addr(node);
node->parent_node=p_parent;
if(node_meta_data->block_size<=p_parent_meta_data->block_size)
{
p_parent->left_node=node;
}
else
{
p_parent->right_node=node;
}
}
node->right_node=parent;
parent->parent_node=node;
node->left_node=temp;
temp->parent_node=node;
parent->left_node=node_right;
temp->right_node=node_left;
}
void RR_Rotate(tree_node_t *parent,tree_node_t *node)
{
printf("Came to RR\n");
tree_node_t *p_parent=parent->parent_node;
tree_node_t *temp=parent->right_node;
tree_node_t *temp_left=temp->left_node;
if(p_parent==NULL)
{
*root=temp;
temp->parent_node=NULL;
}
else
{
temp->parent_node=p_parent;
block_meta_data_t *p_parent_meta_data=meta_data_block_addr(p_parent);
block_meta_data_t *temp_meta_data=meta_data_block_addr(temp);
if(temp_meta_data->block_size<=p_parent_meta_data->block_size)
{
p_parent->left_node=temp;
}
else
{
p_parent->right_node=temp;
}
temp->left_node=parent;
parent->parent_node=temp;
parent->right_node=temp_left;
}
}
void RL_Rotate(tree_node_t *parent,tree_node_t *node)
{
printf("Came to RL\n");
tree_node_t *p_parent=parent->parent_node;
tree_node_t *temp=parent->right_node;
tree_node_t *temp_right=temp->right_node;
tree_node_t *node_left=node->left_node;
tree_node_t *node_right=node->right_node;
if(p_parent==NULL)
{
*root=node;
node->parent_node=NULL;
}
else
{
node->parent_node=p_parent;
block_meta_data_t *p_parent_meta_data=meta_data_block_addr(p_parent);
block_meta_data_t *node_meta_data=meta_data_block_addr(node);
if(node_meta_data->block_size<=p_parent_meta_data->block_size)
{
p_parent->left_node=node;
}
else
{
p_parent->right_node=node;
}
}
node->left_node=parent;
parent->parent_node=node;
node->right_node=temp;
temp->parent_node=node;
parent->right_node=node_right;
temp->left_node=node_left;
}
void rotate(tree_node_t *parent,tree_node_t *node)
{
block_meta_data_t *parent_meta_data=meta_data_block_addr(parent);
block_meta_data_t *node_meta_data=meta_data_block_addr(node);
if(parent_meta_data->block_size<node_meta_data->block_size)
{
tree_node_t *temp=parent->right_node;
block_meta_data_t *temp_meta_data=meta_data_block_addr(temp);
if(temp_meta_data->block_size<node_meta_data->block_size)
{
RR_Rotate(parent,node);
}
else
{
RL_Rotate(parent,node);
}
}
else
{
tree_node_t *temp=parent->left_node;
block_meta_data_t *temp_meta_data=meta_data_block_addr(temp);
if(temp_meta_data->block_size<node_meta_data->block_size)
{
inorderTraversal(*root);
LR_Rotate(parent,node);
}
else
{
LL_rotate(parent,node);
}
}
}
int getHeight(tree_node_t *node)
{
if(node==NULL)
{
return 0;
}
int left_height=getHeight(node->left_node);
int right_height=getHeight(node->right_node);
return 1+(left_height>=right_height?left_height:right_height);
}
int get_balance(tree_node_t *node)
{
if(node!=NULL)
{
inorderTraversal(*root);
int left_height=getHeight(node->left_node);
int right_height=getHeight(node->right_node);
return (left_height-right_height);
}
return 0;
}
void inorderTraversal(tree_node_t *node)
{
if(node!=NULL)
{
block_meta_data_t *meta_data_block=meta_data_block_addr(node);
printf("Block size=%d\n",(int)meta_data_block->block_size);
inorderTraversal(node->left_node);
inorderTraversal(node->right_node);
}
}
void insert_node_in_freelist(tree_node_t **root,block_meta_data_t *new_metadata_block)
{
tree_node_t *tree_root=*root;
if(tree_root==NULL)
{
*root=&(new_metadata_block->tree_node);
}
else
{
tree_node_t *temp=tree_root;
while(temp)
{
block_meta_data_t *meta_data=meta_data_block_addr(temp);
if(new_metadata_block->block_size<=meta_data->block_size)
{
if(temp->left_node==NULL)
{
new_metadata_block->tree_node.parent_node=temp;
temp->left_node=&(new_metadata_block->tree_node);
temp=temp->left_node;
break;
}
else
{
temp=temp->left_node;
}
}
else if(new_metadata_block->block_size>meta_data->block_size)
{
if(temp->right_node==NULL)
{
new_metadata_block->tree_node.parent_node=temp;
temp->right_node=&(new_metadata_block->tree_node);
temp=temp->right_node;
break;
}
else
{
temp=temp->right_node;
}
}
}
tree_node_t *parent=temp->parent_node;
while(parent)
{
int b=get_balance(parent);
if(b>=2||b<=-2)
{
rotate(parent,temp);
}
parent=parent->parent_node;
}
}
}
block_meta_data_t *get_node_from_tree(tree_node_t **root,uint32_t reqsize)
{
tree_node_t *temp=*root;
while(temp->right_node!=NULL)
{
temp=temp->right_node;
}
block_meta_data_t *meta_data=NULL;
meta_data=meta_data_block_addr(temp);
return meta_data;
}
tree_node_t *get_min_node(tree_node_t *root)
{
tree_node_t *temp=root;
while(temp->left_node!=NULL)
{
temp=temp->left_node;
}
return temp;
}
void remove_block_from_tree(tree_node_t **root,tree_node_t *del_node)
{
tree_node_t *parent_node=del_node->parent_node;
block_meta_data_t *parent_meta_data=meta_data_block_addr(parent_node);
block_meta_data_t *del_meta_data=meta_data_block_addr(del_node);
if(del_node->left_node==NULL||del_node->right_node==NULL)
{
tree_node_t *temp=del_node->left_node!=NULL?del_node->left_node:del_node->right_node;
//Deleting a leaf node
if(temp==NULL)
{
if(parent_node==NULL)
{
*root=NULL;
return;
}
if(parent_meta_data->block_size<del_meta_data->block_size)
{
parent_node->right_node=NULL;
}
else
{
parent_node->left_node=NULL;
}
}
//Deleting node having 1 child
else
{
if(del_node->left_node!=NULL)
{
del_node->left_node->parent_node=parent_node;
if(parent_node==NULL)
{
*root=del_node->left_node;
del_node->left_node=NULL;
del_node->right_node=NULL;
del_node->parent_node=NULL;
return;
}
else if(parent_meta_data->block_size<del_meta_data->block_size)
{
parent_node->right_node=del_node->left_node;
}
else
{
parent_node->left_node=del_node->left_node;
}
}
else
{
del_node->right_node->parent_node=parent_node;
if(parent_node==NULL)
{
*root=del_node->right_node;
del_node->left_node=NULL;
del_node->right_node=NULL;
del_node->parent_node=NULL;
return;
}
else if(parent_meta_data->block_size<del_meta_data->block_size)
{
parent_node->right_node=del_node->right_node;
}
else
{
parent_node->left_node=del_node->right_node;
}
}
}
//Balancing parent node
while(parent_node)
{
int b=get_balance(parent_node);
if(b<-1)
{
if(parent_node->right_node->right_node!=NULL)
{
RR_Rotate(parent_node,parent_node->right_node->right_node);
}
else
{
RL_Rotate(parent_node,parent_node->right_node->left_node);
}
}
if(b>1)
{
if(parent_node->left_node->left_node!=NULL)
{
LL_rotate(parent_node,parent_node->left_node->left_node);
}
else
{
LR_Rotate(parent_node,parent_node->left_node->right_node);
}
}
parent_node=parent_node->parent_node;
}
}
//Deleting node having two children
else
{
tree_node_t *min_right_node=get_min_node(del_node->right_node);
remove_block_from_tree(root,min_right_node);
tree_node_t *parent_node_1=del_node->parent_node;
block_meta_data_t *parent_meta_data_1=meta_data_block_addr(parent_node_1);
if(parent_node_1==NULL)
{
*root=min_right_node;
}
else if(parent_meta_data_1->block_size<del_meta_data->block_size)
{
parent_node_1->right_node=min_right_node;
}
else
{
parent_node_1->left_node=min_right_node;
}
min_right_node->left_node=del_node->left_node;
if(del_node->left_node!=NULL)
{
del_node->left_node->parent_node=min_right_node;
}
min_right_node->right_node=del_node->right_node;
if(del_node->right_node!=NULL)
{
del_node->right_node->parent_node=min_right_node;
}
min_right_node->parent_node=parent_node_1;
}
del_node->left_node=NULL;
del_node->right_node=NULL;
del_node->parent_node=NULL;
}
int get_internal_fragmented_size(block_meta_data_t *block1,block_meta_data_t *block2)
{
block_meta_data_t *next_meta_block_by_size=NEXT_META_BLOCK_BY_SIZE(block1);
return (int)((char *)block2-(char *)next_meta_block_by_size);
}
void merge_free_blocks(block_meta_data_t *first,block_meta_data_t *second)
{
assert(first->is_free==MM_TRUE&&second->is_free==MM_TRUE);
first->block_size+=sizeof(block_meta_data_t) + second->block_size+sizeof(block_end_meta_data_t);
first->next_block=second->next_block;
if(second->next_block!=NULL)
{
second->next_block->prev_block=first;
}
}
void create_new_block_and_insert_into_freelist(block_meta_data_t *meta_data_block,block_meta_data_t *free_block,uint32_t final_remain,int c)
{
block_meta_data_t *new_block = (block_meta_data_t *)NEXT_META_BLOCK_BY_SIZE(meta_data_block);
if(meta_data_block->is_free == MM_TRUE)
meta_data_block->is_free = MM_FALSE;
if(c == 0)
meta_data_block->next_block = free_block->next_block->next_block;
else
meta_data_block->next_block = free_block->next_block;
new_block->block_size = (uint32_t)final_remain;
new_block->tree_node = init_free_node();
new_block->is_free = MM_TRUE;
mm_bind_blocks_for_allocation(meta_data_block, new_block);
assert(meta_data_block->next_block->block_size == new_block->block_size);
block_end_meta_data_t *new_end_meta_data_block = (block_end_meta_data_t *)end_meta_data_addr(new_block);
new_end_meta_data_block->block_size = new_block->block_size;
insert_node_in_freelist(root,new_block);
}
void *allocate_requested_size(size_t size)
{
size_t sys_page_size=mem_pagesize();
int no_of_pages_req=((size+sizeof(block_end_meta_data_t)+sizeof(block_meta_data_t)+sys_page_size-1)/sys_page_size);
size_t extra_size_req=(int)no_of_pages_req*sys_page_size;
void *brk= mem_sbrk(extra_size_req);
if(*(int *)brk==-1)
return NULL;
return brk;
}
int mm_init(void)
{
//This function is called every time before each test run of the trace.
//It should reset the entire state of your malloc or the consecutive trace runs will give wrong answer.
//It should reset the entire state of your malloc or the consecutive trace runs will give wrong answer.
/*
/*
* This function should initialize and reset any data structures used to represent the starting state(empty heap)
*
*
* This function will be called multiple time in the driver code "mdriver.c"
*/
if(init_mem_sbrk_break==NULL)
{
mem_init();
}
mem_reset_brk();
init_mem_sbrk_break=mem_sbrk(mem_pagesize());
if(*(int *)init_mem_sbrk_break==-1)
{
return -1;
}
root=(tree_node_t **)init_mem_sbrk_break;
block_meta_data_t *metadata=(block_meta_data_t *)(root+1);
metadata->is_free=MM_TRUE;
metadata->block_size=mem_pagesize()-sizeof(block_meta_data_t)-sizeof(block_end_meta_data_t)-sizeof(root);
metadata->tree_node=init_free_node();
metadata->next_block=NULL;
metadata->prev_block=NULL;
*root=&(metadata->tree_node);
block_end_meta_data_t *end_meta_data=end_meta_data_addr(metadata);
end_meta_data->block_size=metadata->block_size;
return 0; //Returns 0 on successfull initialization.
}
//---------------------------------------------------------------------------------------------------------------
/*
/*
* 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)
{
/*
{
/*
* This function should keep track of the allocated memory blocks.
* The block allocation should minimize the number of holes (chucks of unusable memory) in the heap memory.
* The previously freed memory blocks should be reused.
......@@ -85,66 +773,381 @@ void *mm_malloc(size_t size)
return NULL;
}
size = ((size+7)/8)*8; //size alligned to 8 bytes
return mem_sbrk(size); //mem_sbrk() is wrapper function for the sbrk() system call.
//Please use mem_sbrk() instead of sbrk() otherwise the evaluation results
//may give wrong results
block_meta_data_t *free_metadata_block=get_node_from_tree(root,size);
//If No free block available then we will request new pages by calling mem_sbrk()
if(free_metadata_block==NULL||free_metadata_block->block_size<(size+sizeof(block_end_meta_data_t)+sizeof(block_meta_data_t)))
{
void *brk = allocate_requested_size(size);
block_end_meta_data_t *prev_end_meta_data=NULL;
prev_end_meta_data=(block_end_meta_data_t *)((char *)brk-sizeof(block_end_meta_data_t));
block_meta_data_t *prev_start_meta_data=NULL;
prev_start_meta_data=start_meta_data_addr(prev_end_meta_data);
block_meta_data_t *next_meta_data_block=(block_meta_data_t *)brk;
next_meta_data_block->is_free=MM_FALSE;
next_meta_data_block->block_size=size;
next_meta_data_block->tree_node=init_free_node();
next_meta_data_block->prev_block=prev_start_meta_data;
prev_start_meta_data->next_block=next_meta_data_block;
next_meta_data_block->next_block=NULL;
block_end_meta_data_t *next_end_meta_data_block=end_meta_data_addr(next_meta_data_block);
next_end_meta_data_block->block_size=next_meta_data_block->block_size;
block_meta_data_t *new_free_meta_block=NEXT_META_BLOCK_BY_SIZE(next_meta_data_block);
new_free_meta_block->is_free=MM_TRUE;
// new_free_meta_block->block_size=(uint32_t)(extra_size_req-size-(2*sizeof(block_meta_data_t))-(2*sizeof(block_end_meta_data_t)));
new_free_meta_block->block_size= (uint32_t)((char *)mem_heap_hi()-(char *)brk+1-size-(2*(uint32_t)sizeof(block_meta_data_t))-(2*(uint32_t)sizeof(block_end_meta_data_t)));
new_free_meta_block->tree_node=init_free_node();
new_free_meta_block->prev_block=NULL;
block_end_meta_data_t *new_end_free_meta_block=end_meta_data_addr(new_free_meta_block);
new_end_free_meta_block->block_size=new_free_meta_block->block_size;
insert_node_in_freelist(root,new_free_meta_block);
mm_bind_blocks_for_allocation(next_meta_data_block,new_free_meta_block);
return (void *)(next_meta_data_block+1);
}
assert(free_metadata_block->is_free==MM_TRUE);
printf("Free Data block size=%d\n",(int)free_metadata_block->block_size);
uint32_t remaining_size=free_metadata_block->block_size-size;
free_metadata_block->is_free=MM_FALSE;
free_metadata_block->block_size=size;
block_end_meta_data_t *end_meta_data=end_meta_data_addr(free_metadata_block);
end_meta_data->block_size=size;
remove_block_from_tree(root,&free_metadata_block->tree_node);
//Here we will created new block by splitting previous block
if(sizeof(block_meta_data_t)+sizeof(block_end_meta_data_t)<remaining_size){
block_meta_data_t *next_meta_block=NULL;
block_end_meta_data_t *next_end_meta_block=NULL;
next_meta_block=NEXT_META_BLOCK_BY_SIZE(free_metadata_block);
next_meta_block->is_free=MM_TRUE;
next_meta_block->block_size=remaining_size-sizeof(block_meta_data_t)-sizeof(block_end_meta_data_t);
next_meta_block->tree_node=init_free_node();
next_end_meta_block=end_meta_data_addr(next_meta_block);
next_end_meta_block->block_size=next_meta_block->block_size;
insert_node_in_freelist(root,next_meta_block);
mm_bind_blocks_for_allocation(free_metadata_block,next_meta_block);
}
return (void *)(free_metadata_block+1);
//mem_sbrk() is wrapper function for the sbrk() system call.
//Please use mem_sbrk() instead of sbrk() otherwise the evaluation results
//may give wrong results
}
void mm_free(void *ptr)
{
/*
/*
* Searches the previously allocated node for memory block with base address ptr.
*
* It should also perform coalesceing on both ends i.e. if the consecutive memory blocks are
*
* It should also perform coalesceing on both ends i.e. if the consecutive memory blocks are
* free(not allocated) then they should be combined into a single block.
*
*
* It should also keep track of all the free memory blocks.
* If the freed block is at the end of the heap then you can also decrease the heap size
* If the freed block is at the end of the heap then you can also decrease the heap size
* using 'mem_sbrk(-size)'.
*/
block_meta_data_t *meta_data_block=(block_meta_data_t *)((char *)ptr-sizeof(block_meta_data_t));
assert(meta_data_block->is_free==MM_FALSE);
meta_data_block->is_free=MM_TRUE;
block_meta_data_t *prev_meta_data_block=meta_data_block->prev_block;
block_meta_data_t *next_meta_data_block=meta_data_block->next_block;
block_meta_data_t *merged_meta_data_block=NULL;
block_end_meta_data_t *merged_end_meta_data_block=NULL;
if(next_meta_data_block!=NULL)
{
meta_data_block->block_size+= get_internal_fragmented_size(meta_data_block,next_meta_data_block);
}
//If block being free is upper most block
else
{
int fragmented_size=(int)((char *)mem_heap_hi()+1-((char *)end_meta_data_addr(meta_data_block)+sizeof(block_end_meta_data_t)));
meta_data_block->block_size+=fragmented_size;
}
merged_meta_data_block=meta_data_block;
if(next_meta_data_block!=NULL&&next_meta_data_block->is_free==MM_TRUE)
{
remove_block_from_tree(root,&next_meta_data_block->tree_node);
merge_free_blocks(meta_data_block,next_meta_data_block);
merged_meta_data_block=meta_data_block;
}
if(prev_meta_data_block!=NULL&&prev_meta_data_block->is_free==MM_TRUE)
{
remove_block_from_tree(root,&prev_meta_data_block->tree_node);
merge_free_blocks(prev_meta_data_block,meta_data_block);
merged_meta_data_block=prev_meta_data_block;
}
merged_end_meta_data_block=(block_end_meta_data_t *)(end_meta_data_addr(merged_meta_data_block));
merged_end_meta_data_block->block_size=merged_meta_data_block->block_size;
insert_node_in_freelist(root,merged_meta_data_block);
}
/*
* mm_realloc - Implemented simply in terms of mm_malloc and mm_free
*/
void *mm_realloc(void *ptr, size_t size)
{
size = ((size+7)/8)*8; //8-byte alignement
{
size = ((size+7)/8)*8; //8-byte alignement
if(ptr == NULL){ //memory was not previously allocated
return mm_malloc(size);
}
if(size == 0){ //new size is zero
mm_free(ptr);
return NULL;
}
/*
* This function should also copy the content of the previous memory block into the new block.
* You can use 'memcpy()' for this purpose.
*
* The data structures corresponding to free memory blocks and allocated memory
*
* The data structures corresponding to free memory blocks and allocated memory
* blocks should also be updated.
*/
mm_free(ptr);
return mem_sbrk(size);
}
block_meta_data_t *meta_data_block=(block_meta_data_t *)((char *)ptr-sizeof(block_meta_data_t));
if(size == meta_data_block->block_size)
return (void *)(meta_data_block+1);
if(size < meta_data_block->block_size)
{
uint32_t original_size = (uint32_t)meta_data_block->block_size;
uint32_t inter_frag = (uint32_t)get_internal_fragmented_size(meta_data_block,meta_data_block->next_block);
meta_data_block->block_size = size;
block_end_meta_data_t *end_meta_data_block = (block_end_meta_data_t *)end_meta_data_addr(meta_data_block);
end_meta_data_block->block_size = meta_data_block->block_size;
if(meta_data_block->next_block && meta_data_block->next_block->is_free==MM_TRUE)
{
block_meta_data_t *new_block = NEXT_META_BLOCK_BY_SIZE(meta_data_block);
remove_block_from_tree(root, &meta_data_block->next_block->tree_node);
new_block->block_size = meta_data_block->next_block->block_size + inter_frag + (original_size - size);
meta_data_block->next_block = meta_data_block->next_block->next_block;
new_block->is_free = MM_TRUE;
new_block->tree_node= init_free_node();
mm_bind_blocks_for_allocation(meta_data_block, new_block);
block_end_meta_data_t *new_end_meta_data_block = (block_end_meta_data_t *)end_meta_data_addr(new_block);
new_end_meta_data_block->block_size = new_block->block_size;
insert_node_in_freelist(root,new_block);
return (void *)(meta_data_block+1);
}
else
{
uint32_t inter_frag =0;
int fragmented_size=(int)((char *)mem_heap_hi()+1-((char *)end_meta_data_addr(meta_data_block)+sizeof(block_end_meta_data_t)));
if(!meta_data_block->next_block){
if( (fragmented_size+original_size-size) < (sizeof(block_end_meta_data_t)+sizeof(end_meta_data_block)) )
return meta_data_block;
}
else{
uint32_t inter_frag = get_internal_fragmented_size(meta_data_block,meta_data_block->next_block);
if( (inter_frag+original_size-size) < (sizeof(block_end_meta_data_t)+sizeof(end_meta_data_block)) )
return meta_data_block;
fragmented_size = 0;
}
meta_data_block->block_size = size;
block_end_meta_data_t *end_meta_data_block = (block_end_meta_data_t *)end_meta_data_addr(meta_data_block);
end_meta_data_block->block_size = meta_data_block->block_size;
if((original_size- size + inter_frag + fragmented_size) > META_DATA_OVERHEAD)
{
block_meta_data_t *new_block = (block_meta_data_t *)NEXT_META_BLOCK_BY_SIZE(meta_data_block);
new_block->tree_node = init_free_node();
new_block->is_free = MM_TRUE;
new_block->block_size = original_size- size + inter_frag + fragmented_size - META_DATA_OVERHEAD;
mm_bind_blocks_for_allocation(meta_data_block, new_block);
block_end_meta_data_t *new_end_meta_data_block = (block_end_meta_data_t *)end_meta_data_addr(new_block);
new_end_meta_data_block->block_size = new_block->block_size;
insert_node_in_freelist(root,new_block);
}
return (void *)(meta_data_block+1);
}
}
else
{
uint32_t req_rem_size = size-meta_data_block->block_size;
uint32_t inter_frag = 0;
if(meta_data_block->next_block)
inter_frag = get_internal_fragmented_size(meta_data_block,meta_data_block->next_block);
else
inter_frag = (uint32_t)((char *)mem_heap_hi()+1-((char *)end_meta_data_addr(meta_data_block)+sizeof(block_end_meta_data_t)));
if(req_rem_size <= inter_frag)
{
// TODO check sizeof function once
meta_data_block->block_size += req_rem_size;
block_end_meta_data_t *end_meta_data_block = (block_end_meta_data_t *)end_meta_data_addr(meta_data_block);
end_meta_data_block->block_size = meta_data_block->block_size;
return (void *)(meta_data_block+1); // Not handling adding remaining free part to free list because it is small in size to handle even headers, so skkipping.
}
if(meta_data_block->next_block && meta_data_block->next_block->is_free == MM_TRUE && \
req_rem_size <= (TOTAL_COMBINE_SIZE_OF_BLOCKS(meta_data_block->next_block)+inter_frag))
{
remove_block_from_tree(root,&meta_data_block->next_block->tree_node);
uint32_t final_remain = TOTAL_COMBINE_SIZE_OF_BLOCKS(meta_data_block->next_block) - req_rem_size;
meta_data_block->block_size += req_rem_size;
req_rem_size -= inter_frag;
block_end_meta_data_t *end_meta_data_block = (block_end_meta_data_t *)end_meta_data_addr(meta_data_block);
end_meta_data_block->block_size = meta_data_block->block_size;
if( final_remain > META_DATA_OVERHEAD)
{
create_new_block_and_insert_into_freelist(meta_data_block,meta_data_block->next_block,final_remain,1);
}
return (void *)(meta_data_block+1);
}
if(meta_data_block->prev_block && meta_data_block->prev_block->is_free == MM_TRUE && \
req_rem_size <= (TOTAL_COMBINE_SIZE_OF_BLOCKS(meta_data_block->prev_block)+inter_frag)){
remove_block_from_tree(root,&meta_data_block->prev_block->tree_node);
meta_data_block->prev_block->block_size += req_rem_size;
req_rem_size -= inter_frag;
uint32_t final_remain = abs(TOTAL_COMBINE_SIZE_OF_BLOCKS(meta_data_block->prev_block) - req_rem_size);
memcpy((char *)(meta_data_block->prev_block+1), (char *)(meta_data_block+1),meta_data_block->block_size);
block_end_meta_data_t *end_meta_data_block = (block_end_meta_data_t *)end_meta_data_addr(meta_data_block);
end_meta_data_block->block_size = meta_data_block->block_size;
meta_data_block = meta_data_block->prev_block;
if( final_remain > META_DATA_OVERHEAD)
create_new_block_and_insert_into_freelist(meta_data_block,meta_data_block->next_block,final_remain,1);
return (void *)(meta_data_block+1);
}
if(meta_data_block->next_block && meta_data_block->next_block->is_free && meta_data_block->prev_block && meta_data_block->prev_block->is_free && \
req_rem_size <= TOTAL_COMBINED_SIZE_OF_BLOCKS(meta_data_block)+inter_frag)
{
remove_block_from_tree(root,&meta_data_block->prev_block->tree_node);
remove_block_from_tree(root,&meta_data_block->next_block->tree_node);
req_rem_size = abs(meta_data_block->prev_block->block_size-size);
meta_data_block->prev_block->block_size += req_rem_size;
req_rem_size -= inter_frag;
uint32_t final_remain = abs(meta_data_block->next_block->block_size+meta_data_block->prev_block->block_size+(uint32_t)sizeof(block_end_meta_data_t) \
+(uint32_t)sizeof(block_meta_data_t) - req_rem_size);
memcpy((char *)(meta_data_block->prev_block+1), (char *)(meta_data_block+1),meta_data_block->block_size);
block_end_meta_data_t *end_meta_data_block = (block_end_meta_data_t *)end_meta_data_addr(meta_data_block);
end_meta_data_block->block_size = meta_data_block->block_size;
meta_data_block = meta_data_block->prev_block;
if( final_remain > META_DATA_OVERHEAD)
create_new_block_and_insert_into_freelist(meta_data_block,meta_data_block->next_block,final_remain,0);
return (void *)(meta_data_block+1);
}
void *ptr = mm_malloc(size);
block_meta_data_t *new_meta_data_block = (block_meta_data_t *)((char *)ptr-sizeof(block_meta_data_t));
uint32_t amount_to_be_copied = meta_data_block->block_size;
memcpy((char *)(new_meta_data_block+1), (char *)(meta_data_block+1),amount_to_be_copied);
mm_free((void *)(meta_data_block+1));
return (void *)(new_meta_data_block+1);
}
mm_free(ptr);
return mem_sbrk(size);
}
int main()
{
mm_init();
void *p1=mm_malloc(40);
void *p3=mm_malloc(60);
void *p4=mm_malloc(100);
void *p5=mm_malloc(20);
void *p6=mm_malloc(90);
void *p7=mm_malloc(3500);
printf("Above Call Executed\n");
// mm_free(p2);
mm_free(p4);
mm_free(p6);
mm_free(p1);
// mm_free(p3);
// mm_free(p5);
// mm_free(p7);
printf("[FINAL INORDER TRAVERSAL]\n");
inorderTraversal(*root);
//mm_free(p2);
//mm_free(p2);
//void *p4=mm_malloc(40);
return 0;
}
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