diff --git a/Heap_manager/Makefile b/Heap_manager/Makefile new file mode 100644 index 0000000..2702acc --- /dev/null +++ b/Heap_manager/Makefile @@ -0,0 +1,10 @@ +final: main.o mm.o heap.o + cc main.o mm.o heap.o -o final +main.o: main.c + cc -c main.c +mm.o: mm.h mm.c + cc -c mm.c +heap.o: heap.h heap.c + cc -c heap.c +clean: + rm *.o final diff --git a/Heap_manager/final b/Heap_manager/final new file mode 100755 index 0000000..da8742b Binary files /dev/null and b/Heap_manager/final differ diff --git a/Heap_manager/heap.c b/Heap_manager/heap.c new file mode 100644 index 0000000..59b20d3 --- /dev/null +++ b/Heap_manager/heap.c @@ -0,0 +1,146 @@ +#include +#include "heap.h" + +#define max(a, b) (a) > b ? a : b + +void heapifyup(heap *h) +{ + int i = h->rear; + int parent = (i - 1) / 2; + while (h->arr[i]->size > h->arr[parent]->size) + { + meta_block *temp = h->arr[i]; + h->arr[i] = h->arr[parent]; + h->arr[parent] = temp; + i = parent; + parent = (i - 1) / 2; + } + return; +} + +void heapifydown(heap *h) +{ + int i = 0; + while (1) + { + int left = i * 2 + 1; + int right = i * 2 + 2; + int maxi = h->arr[i]->size; + if (left <= h->rear) + maxi = max(maxi, h->arr[left]->size); + if (right <= h->rear) + maxi = max(maxi, h->arr[right]->size); + if (maxi == h->arr[i]->size) + return; + if (left <= h->rear && maxi == h->arr[left]->size) + { + meta_block *temp = h->arr[i]; + h->arr[i] = h->arr[left]; + h->arr[left] = temp; + i = left; + } + else + { + meta_block *temp = h->arr[i]; + h->arr[i] = h->arr[right]; + h->arr[right] = temp; + i = right; + } + } +} + +void remove_heap(heap *h) +{ + if (h->rear == -1) + return; + meta_block *ans = h->arr[0]; + h->arr[0] = h->arr[h->rear]; + h->rear--; + if (h->rear != -1) + heapifydown(h); +} + +void insert_heap(heap *h, meta_block *mb) +{ + if (h->rear == h->size - 1) + return; + h->arr[++h->rear] = mb; + heapifyup(h); + return; +} + +meta_block *top_heap(heap *h) +{ + if (h->rear == -1) + return NULL; + return h->arr[0]; +} + +int findindex(heap *h, meta_block *mb) +{ + for (int i = 0; i <= h->rear; i++) + { + if (h->arr[i] == mb) + return i; + } + return -1; +} + +void goup(heap *h, int i) +{ + int parent = (i - 1) / 2; + while (h->arr[parent]->size < h->arr[i]->size) + { + meta_block *temp = h->arr[i]; + h->arr[i] = h->arr[parent]; + h->arr[parent] = temp; + i = parent; + parent = (i - 1) / 2; + } + return; +} + +void godown(heap *h, int i) +{ + while (1) + { + int left = i * 2 + 1; + int right = i * 2 + 2; + int maxi = h->arr[i]->size; + if (left <= h->rear) + maxi = max(maxi, h->arr[left]->size); + if (right <= h->rear) + maxi = max(maxi, h->arr[right]->size); + if (maxi == h->arr[i]->size) + return; + if (left <= h->rear && maxi == h->arr[left]->size) + { + meta_block *temp = h->arr[i]; + h->arr[i] = h->arr[left]; + h->arr[left] = temp; + i = left; + } + else + { + meta_block *temp = h->arr[i]; + h->arr[i] = h->arr[right]; + h->arr[right] = temp; + i = right; + } + } +} + +void findandremove(heap *h, meta_block *mb) +{ + int index = findindex(h, mb); + if (index == -1) + return; + h->arr[index] = h->arr[h->rear]; + h->rear--; + int parent = (index - 1) / 2; + if (h->arr[parent]->size < h->arr[index]->size) + goup(h, index); + else + godown(h, index); + return; +} \ No newline at end of file diff --git a/Heap_manager/heap.h b/Heap_manager/heap.h new file mode 100644 index 0000000..94d2772 --- /dev/null +++ b/Heap_manager/heap.h @@ -0,0 +1,25 @@ +#ifndef heaph +#define heaph +#include "mm.h" + +// heap structure +typedef struct heap +{ + int size; + int rear; + meta_block *arr[0]; +} heap; + +// insert in heap +void insert_heap(heap *h, meta_block *mb); + +// finding top element from heap +meta_block *top_heap(heap *h); + +// remove top element from heap +void remove_heap(heap *h); + +// deleting some intermidiate element from heap +void findandremove(heap *h, meta_block *mb); + +#endif \ No newline at end of file diff --git a/Heap_manager/heap.o b/Heap_manager/heap.o new file mode 100644 index 0000000..e8165b5 Binary files /dev/null and b/Heap_manager/heap.o differ diff --git a/Heap_manager/main.c b/Heap_manager/main.c new file mode 100644 index 0000000..a6a209f --- /dev/null +++ b/Heap_manager/main.c @@ -0,0 +1,80 @@ +#include +#include +#include "mm.h" + +typedef struct student // size 16 kb +{ + char name[10]; + int id; +} student; + +int main() +{ + mm_init(); + // printf("%d",sizeof(student)); + + + + + // For malloc Testing + // student* st1=Malloc(sizeof(student)*1); + // st1->id = 12; + // strcpy(st1->name, "siddhesh"); + // printf("%d %s\n", st1->id, st1->name); + // student* st2=Malloc(sizeof(student)*2); + // student* st3=Malloc(sizeof(student)*3); + // student* st4=Malloc(sizeof(student)*4); + // student* st5=Malloc(sizeof(student)*5); + // student* st6=Malloc(sizeof(student)*6); + // Free(st1); + // Free(st3); + // Free(st5); + // printheap(); + + + + + // // for Free Testing + // student* st1=Malloc(sizeof(student)*1); + // student* st2=Malloc(sizeof(student)*2); + // student* st3=Malloc(sizeof(student)*3); + // student* st4=Malloc(sizeof(student)*1); + // // student* st5=Malloc(sizeof(student)*5); + // // student* st6=Malloc(sizeof(student)*6); + // Free(st2); + // Free(st1); + // // Free(st3); + // // Free(st5); + // // student* st7=Malloc(4496); + // printheap(); + + + + + + // // for Calloc testing + // student *st1 = Calloc(1,sizeof(student));; + // student *st2 = Calloc(2,sizeof(student)); + // printf("%d %s\n",st1->id,st1->name); + // st1->id = 12; + // strcpy(st1->name, "siddhesh"); + // printf("%d %s\n", st1->id, st1->name); + + + + + // For Realloc + // student* st1=Malloc(sizeof(student)*10); + // st1->id = 12; + // strcpy(st1->name, "siddhesh"); + // printf("%d %s\n", st1->id, st1->name); + // printheap(); + // st1=Realloc(st1,sizeof(student)*2); + // printf("%d %s\n", st1->id, st1->name); + // printheap(); + // st1=Realloc(st1,sizeof(student)*5); + // printf("%d %s\n", st1->id, st1->name); + // printheap(); + + return 0; +} \ No newline at end of file diff --git a/Heap_manager/main.o b/Heap_manager/main.o new file mode 100644 index 0000000..d572f26 Binary files /dev/null and b/Heap_manager/main.o differ diff --git a/Heap_manager/mm.c b/Heap_manager/mm.c new file mode 100644 index 0000000..209282b --- /dev/null +++ b/Heap_manager/mm.c @@ -0,0 +1,290 @@ +#include +#include +#include //for getting one memory page +#include //for using mmap +#include "mm.h" +#include "heap.h" + +// global variables for heap and storing size of one memory page +heap *pointer_to_heap; +int sizeofonememorypage; + +// function to get memory page from system +void *get_page_from_system(int units) +{ + + void *vm_page = mmap(0, units * sizeofonememorypage, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, 0, 0); + if (vm_page == MAP_FAILED) + { + printf("Error: VM page allocation failed\n"); + return NULL; + } + return (void *)vm_page; +} + +// Function for initializing heap +void setheap() +{ + + pointer_to_heap = get_page_from_system(1); + pointer_to_heap->size = (sizeofonememorypage - sizeof(heap)) / sizeof(meta_block *); + pointer_to_heap->rear = -1; +} + +// Function for initializing our memory manager and getting one memory page size +void mm_init2(int size) +{ + // sizeofonememorypage=getpagesize(); + sizeofonememorypage = size+sizeof(meta_block); + setheap(); +} + +void mm_init1() +{ + // 5000 is default memory page size we decide to allocate + mm_init2(5000); +} +// Function for returning memory back to system +void *return_page_to_system(void *vm_page, int units) +{ + + if (munmap(vm_page, sizeofonememorypage * units) == -1) + printf("Error:could not free vm_page\n"); +} + +// Function for initializing new memory page get from system with meta-block and and inserting its meta block in heap +void initialize_new_page(page_for_memory *newpage) +{ + + meta_block *mb = (meta_block *)newpage; + mb->is_free = 1; + mb->next = NULL; + mb->prev = NULL; + mb->size = sizeofonememorypage - (sizeof(page_for_memory) + sizeof(meta_block)); + insert_heap(pointer_to_heap, mb); +} + +// function to allocate required memory to user + +void *Malloc(int size) +{ + + meta_block *block = top_heap(pointer_to_heap); + if (!block || block->size < size) + { // if heap is empty or user request more amount free memory than available to us + page_for_memory *newpage = get_page_from_system(1); // get new memory from system + initialize_new_page(newpage); + block = top_heap(pointer_to_heap); + if (block->size < size) + { // if still can not allocate then not possible to allocate memory as requested memory is huge + printf("Could not allocate that much amount of size of structure size == %d \n", size); + return NULL; + } + } + block->is_free = 0; // initializing free block get from heap and removing from heap + remove_heap(pointer_to_heap); + int remaining_size = block->size - size; + if (size + sizeof(meta_block) <= block->size) + { // checking if free block can be splitted into smaller blocks or not + block->size = size; + meta_block *newblockadd = (char *)get_actual_add(block) + size; // finding address for meta-block of remaining size after allocation + newblockadd->prev = block; + newblockadd->next = block->next; + newblockadd->is_free = 1; + newblockadd->size = remaining_size - (sizeof(meta_block)); + if(block->next) + block->next->prev=newblockadd; + block->next = newblockadd; + insert_heap(pointer_to_heap, newblockadd); // inserting remaining free memory in heap + } + return get_actual_add(block); +} + +void Free(void *ptr) +{ + + meta_block *mbcurr = (char *)ptr - sizeof(meta_block); // finding address of meta-block from give address + mbcurr->is_free = 1; // updating it to free memory + meta_block *mbnext = mbcurr->next; + meta_block *mbprev = mbcurr->prev; + + if (!mbnext && !mbprev) + { + return_page_to_system(mbcurr, 1); + return; + } + + int flag1 = 0, flag2 = 0; + if (mbprev && mbprev->is_free) + { // check if prev and next blocks are free or not + flag1 = 1; + findandremove(pointer_to_heap, mbprev); + } + + if (mbnext && mbnext->is_free) + { + flag2 = 1; + findandremove(pointer_to_heap, mbnext); + } + + // if anyone of the prev or next or both blocks are free then memory merging will happen. + + // 1) if both prev and next block are free + if (flag1 && flag2) + { + int total_size = mbprev->size + mbcurr->size + mbnext->size + 2 * (sizeof(meta_block)); // finding new size of merged block + mbprev->size = total_size; + if (mbprev->size == sizeofonememorypage - (sizeof(page_for_memory) + sizeof(meta_block))) + { // if our whole system page get free then return it back to system + return_page_to_system(mbprev, 1); + return; + } + mbprev->next = mbnext->next; // adjusting pointers + if (mbnext->next) + mbnext->next->prev = mbprev; + insert_heap(pointer_to_heap, mbprev); + return; + } + + // 2) if only prev block is free + if (flag1) + { + int total_size = mbprev->size + mbcurr->size + sizeof(meta_block); // finding new size of merged block + mbprev->size = total_size; + if (mbprev->size == sizeofonememorypage - (sizeof(page_for_memory) + sizeof(meta_block))) + { + return_page_to_system(mbprev, 1); + return; + } + mbprev->next = mbcurr->next; // adjusting pointers + if (mbnext) + mbnext->prev = mbprev; + insert_heap(pointer_to_heap, mbprev); + return; + } + + // 3) if only next block is free + if (flag2) + { + int total_size = mbnext->size + mbcurr->size + sizeof(meta_block); // finding new size of merged block + mbcurr->size = total_size; + if (mbcurr->size == sizeofonememorypage - (sizeof(page_for_memory) + sizeof(meta_block))) + { + return_page_to_system(mbcurr, 1); + return; + } + mbcurr->next = mbnext->next; // adjusting pointers + if (mbnext->next) + mbnext->next->prev = mbcurr; + insert_heap(pointer_to_heap, mbcurr); + return; + } + + // 4) if no one is free + insert_heap(pointer_to_heap, mbcurr); + return; +} + +void *Realloc(void *ptr, int size) +{ + + meta_block *mb = (char *)ptr - sizeof(meta_block); + int mbsize = mb->size; + meta_block *next = mb->next; + + //if realloc size is same as current size + if (mbsize == size) + return ptr; + + // if realloc size is more than current size + if (mbsize < size) + { + int nextblocksize = next ? next->size : 0; + meta_block *nextnextblockadd = next ? next->next : NULL; + + // if next block is free can merge to form relloc size + if (next && next->is_free && mbsize + sizeof(meta_block) + nextblocksize >= size) + { + findandremove(pointer_to_heap, next); + + // if new meta-free block can be created + if (mbsize + sizeof(meta_block) + nextblocksize >= size + sizeof(meta_block)) + { + mb->size = size; + meta_block *newmb = (char *)mb + size + sizeof(meta_block); + newmb->is_free = 1; + newmb->next = nextnextblockadd; + newmb->prev = mb; + newmb->size = mbsize + sizeof(meta_block) + nextblocksize - size - sizeof(meta_block); + mb->next = newmb; + if (nextnextblockadd) + nextnextblockadd->prev = newmb; + Free(get_actual_add(newmb)); + return ptr; + } + + // if new-meta block can not be created then allocate all free memory of next block to curr block + else + { + mb->size = mbsize + sizeof(meta_block) + nextblocksize; + mb->next = nextnextblockadd; + if (nextnextblockadd) + nextnextblockadd->prev = mb; + return ptr; + } + } + // if next block is not free then mallocate required size of memory, copy content of current memory to that location and free current one + else + { + void *newadd = Malloc(size); + if (!newadd) + return NULL; + memcpy(newadd, ptr, mbsize); + mb->is_free = 1; + Free(ptr); + return newadd; + } + } + // if realloc size is less than current size + + // if meta-data block can be created then split current block and Free newly created block + if (mbsize >= sizeof(meta_block) + size) + { + mb->size = size; + meta_block *newmb = (char *)mb + size + sizeof(meta_block); + newmb->is_free = 1; + newmb->size = mbsize - size - sizeof(meta_block); + newmb->next = next; + newmb->prev = mb; + if (next) + next->prev = newmb; + mb->next = newmb; + Free(get_actual_add(newmb)); + return ptr; + } + + // else return same ptr without any changes + return ptr; +} + +void *Calloc(int n, int size) +{ + + // allocate n*size of memory using malloc + void *mem = Malloc(size * n); + + // set all the bytes in allocated memory to 0 as required in calloc + memset(mem, 0, size * n); + return mem; +} + + +// print heap used for checking whether block remove or add in right way or not + +void printheap() +{ + + // printf("%d\n",pointer_to_heap->rear); + for (int i = 0; i <= pointer_to_heap->rear; i++) + printf("sizeofblock %d\n", pointer_to_heap->arr[i]->size); +} diff --git a/Heap_manager/mm.h b/Heap_manager/mm.h new file mode 100644 index 0000000..093c998 --- /dev/null +++ b/Heap_manager/mm.h @@ -0,0 +1,44 @@ +#ifndef mmh +#define mmh + + +// used to find actual memory address from given meta block address of specific block +#define get_actual_add(memadd) ((char *)memadd + sizeof(meta_block)) + +// struct which points to memory get through mmap call +typedef struct page_for_memory +{ // size 0 kb + char meta_data_block[0]; +} page_for_memory; + + +// struct to store content of meta-block +typedef struct meta_block +{ // size 24 kb + struct meta_block *next; + struct meta_block *prev; + int size; + int is_free; +} meta_block; + + +// For Initialization of memory manager +// Macros to call for specific Function based on argument passed to mm_init function +#define GET_MACRO(_0, _1, NAME, ...) NAME +#define mm_init(...) GET_MACRO(_0, ##__VA_ARGS__, mm_init2, mm_init1)(__VA_ARGS__) + +// For mallocation +void *Malloc(int size); + +// For free memory +void Free(void *ptr); + +// for reallocation of memory +void *Realloc(void *ptr, int size); + +// for calloc call +void *Calloc(int n, int size); + +// void printheap(); + +#endif \ No newline at end of file diff --git a/Heap_manager/mm.o b/Heap_manager/mm.o new file mode 100644 index 0000000..75951d7 Binary files /dev/null and b/Heap_manager/mm.o differ diff --git a/Heap_manager/references.txt b/Heap_manager/references.txt new file mode 100644 index 0000000..07e668e --- /dev/null +++ b/Heap_manager/references.txt @@ -0,0 +1,5 @@ +1) Meta-Data Block concept: https://tharikasblogs.blogspot.com/p/how-to-write-your-own-malloc-and-free.html +2) Zero length array: https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html +3) mmap and munmap: https://man7.org/linux/man-pages/man2/mmap.2.html https://www.tutorialspoint.com/unix_system_calls/mmap.htm +4) getpagesize :https://man7.org/linux/man-pages/man2/getpagesize.2.html +5) fordeleteinternalnodinHeap: http://www.mathcs.emory.edu/~cheung/Courses/171/Syllabus/9-BinTree/heap-delete.html \ No newline at end of file