From beae0a6811b0d070b5a9e0a7c07ef9b18e9e676a Mon Sep 17 00:00:00 2001 From: memoz1981 Date: Mon, 1 Apr 2024 19:01:02 +0400 Subject: [PATCH 01/18] added separate header files and updated c file name to make design implementation free --- Makefile | 4 ++-- chunk_lists.h | 37 ++++++++++++++++++++++++++++++ heap.h | 31 +------------------------ heap.c => heap_using_chunk_lists.c | 1 + main.c | 1 + 5 files changed, 42 insertions(+), 32 deletions(-) create mode 100644 chunk_lists.h rename heap.c => heap_using_chunk_lists.c (99%) diff --git a/Makefile b/Makefile index 1c88b02..101e9b5 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ CFLAGS=-Wall -Wextra -Werror -std=c11 -pedantic -ggdb -heap: main.c heap.c heap.h - $(CC) $(CFLAGS) -o heap main.c heap.c +heap: main.c heap_using_chunk_lists.c heap.h + $(CC) $(CFLAGS) -o heap main.c heap_using_chunk_lists.c diff --git a/chunk_lists.h b/chunk_lists.h new file mode 100644 index 0000000..4068cf7 --- /dev/null +++ b/chunk_lists.h @@ -0,0 +1,37 @@ +#ifndef CHUNK_LISTS_H_ +#define CHUNK_LISTS_H_ + +#include +#include +#include + +#define UNIMPLEMENTED \ + do { \ + fprintf(stderr, "%s:%d: %s is not implemented yet\n", \ + __FILE__, __LINE__, __func__); \ + abort(); \ + } while(0) + +#define CHUNK_LIST_CAP 1024 + +typedef struct { + uintptr_t *start; + size_t size; +} Chunk; + +typedef struct { + size_t count; + Chunk chunks[CHUNK_LIST_CAP]; +} Chunk_List; + +extern Chunk_List alloced_chunks; +extern Chunk_List freed_chunks; +extern Chunk_List tmp_chunks; + +void chunk_list_insert(Chunk_List *list, void *start, size_t size); +void chunk_list_merge(Chunk_List *dst, const Chunk_List *src); +void chunk_list_dump(const Chunk_List *list, const char *name); +int chunk_list_find(const Chunk_List *list, uintptr_t *ptr); +void chunk_list_remove(Chunk_List *list, size_t index); + +#endif //CHUNK_LISTS_H_ \ No newline at end of file diff --git a/heap.h b/heap.h index 9aec6d0..70ea9d2 100644 --- a/heap.h +++ b/heap.h @@ -5,13 +5,6 @@ #include #include -#define UNIMPLEMENTED \ - do { \ - fprintf(stderr, "%s:%d: %s is not implemented yet\n", \ - __FILE__, __LINE__, __func__); \ - abort(); \ - } while(0) - #define HEAP_CAP_BYTES 640000 static_assert(HEAP_CAP_BYTES % sizeof(uintptr_t) == 0, "The heap capacity is not divisible by " @@ -25,26 +18,4 @@ void *heap_alloc(size_t size_bytes); void heap_free(void *ptr); void heap_collect(); -#define CHUNK_LIST_CAP 1024 - -typedef struct { - uintptr_t *start; - size_t size; -} Chunk; - -typedef struct { - size_t count; - Chunk chunks[CHUNK_LIST_CAP]; -} Chunk_List; - -extern Chunk_List alloced_chunks; -extern Chunk_List freed_chunks; -extern Chunk_List tmp_chunks; - -void chunk_list_insert(Chunk_List *list, void *start, size_t size); -void chunk_list_merge(Chunk_List *dst, const Chunk_List *src); -void chunk_list_dump(const Chunk_List *list, const char *name); -int chunk_list_find(const Chunk_List *list, uintptr_t *ptr); -void chunk_list_remove(Chunk_List *list, size_t index); - -#endif // HEAP_H_ +#endif // HEAP_H_ \ No newline at end of file diff --git a/heap.c b/heap_using_chunk_lists.c similarity index 99% rename from heap.c rename to heap_using_chunk_lists.c index a0fc33a..ec574f8 100644 --- a/heap.c +++ b/heap_using_chunk_lists.c @@ -2,6 +2,7 @@ #include #include #include "./heap.h" +#include "./chunk_lists.h" uintptr_t heap[HEAP_CAP_WORDS] = {0}; const uintptr_t *stack_base = 0; diff --git a/main.c b/main.c index 6ec6187..c8749a7 100644 --- a/main.c +++ b/main.c @@ -5,6 +5,7 @@ #include #include "./heap.h" +#include "./chunk_lists.h" #define JIM_IMPLEMENTATION #include "jim.h" From a23dfe865d8919c0f319f95f98913f3f1025a5ff Mon Sep 17 00:00:00 2001 From: memoz1981 Date: Mon, 1 Apr 2024 20:25:51 +0400 Subject: [PATCH 02/18] Added new linked list header file and empty heap implemntation using linked lists --- Makefile | 4 ++-- heap_using_chunk_lists.c | 5 ++--- heap_using_linked_lists.c | 9 +++++++++ linked_list.h | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 heap_using_linked_lists.c create mode 100644 linked_list.h diff --git a/Makefile b/Makefile index 101e9b5..846b45c 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ CFLAGS=-Wall -Wextra -Werror -std=c11 -pedantic -ggdb -heap: main.c heap_using_chunk_lists.c heap.h - $(CC) $(CFLAGS) -o heap main.c heap_using_chunk_lists.c +heap: main.c heap_using_linked_lists.c heap.h + $(CC) $(CFLAGS) -o heap main.c heap_using_linked_lists.c diff --git a/heap_using_chunk_lists.c b/heap_using_chunk_lists.c index ec574f8..a12fa67 100644 --- a/heap_using_chunk_lists.c +++ b/heap_using_chunk_lists.c @@ -147,9 +147,8 @@ static void mark_region(const uintptr_t *start, const uintptr_t *end) void heap_collect() { - const uintptr_t *stack_start = (const uintptr_t*)__builtin_frame_address(0); - memset(reachable_chunks, 0, sizeof(reachable_chunks)); - mark_region(stack_start, stack_base + 1); + const uintptr_t *stack_start = (coNode* Get(LinkedList* list, size_t size); +Node* se + 1); to_free_count = 0; for (size_t i = 0; i < alloced_chunks.count; ++i) { diff --git a/heap_using_linked_lists.c b/heap_using_linked_lists.c new file mode 100644 index 0000000..ce825c1 --- /dev/null +++ b/heap_using_linked_lists.c @@ -0,0 +1,9 @@ +#include +#include +#include +#include "./heap.h" +#include "./linked_list.h" + +uintptr_t heap[HEAP_CAP_WORDS] = {0}; +const uintptr_t *stack_base = 0; + diff --git a/linked_list.h b/linked_list.h new file mode 100644 index 0000000..59ab632 --- /dev/null +++ b/linked_list.h @@ -0,0 +1,33 @@ +/* +Although this may seem like an infrastructure header file, actually this is a specific +implementation for the project. The node structure is specifically designed to hold +a start offset for the memory location and size of the memory (could be in bytes... ) +*/ + +#ifndef LINKED_LIST_H_ +#define LINKED_LIST_H_ + +#define MAX_CONCURRENT_ALLOCATIONS 1024 +#define MAX_MEMORY_TO_SUPPORT_HEAP 64000 + +extern void* allocation_array[MAX_CONCURRENT_ALLOCATIONS]; + +#include + +typedef struct { + int start_offset; + size_t size; + struct Node* next; + struct Node* previous; +} Node; + +typedef struct { + Node* head; + int count; +} SortedLinkedList; + +void AddNode(SortedLinkedList* list, void* value); +void RemoveNode(SortedLinkedList* list, Node* node); +Node* FindNode(SortedLinkedList* list, Node* node); + +#endif \ No newline at end of file From b06dacd7f6a02aa04d0fab91a9b87704dc467223 Mon Sep 17 00:00:00 2001 From: memoz1981 Date: Mon, 1 Apr 2024 22:38:54 +0400 Subject: [PATCH 03/18] Added general functions and function to add a new node to the linked list - pending is merging to adjacent nodes --- heap_using_linked_lists.c | 91 ++++++++++++++++++++++++++++++++++++++- linked_list.h | 28 ++++++++---- 2 files changed, 109 insertions(+), 10 deletions(-) diff --git a/heap_using_linked_lists.c b/heap_using_linked_lists.c index ce825c1..c6afff0 100644 --- a/heap_using_linked_lists.c +++ b/heap_using_linked_lists.c @@ -1,9 +1,98 @@ #include -#include +#include #include #include "./heap.h" #include "./linked_list.h" +#include uintptr_t heap[HEAP_CAP_WORDS] = {0}; const uintptr_t *stack_base = 0; +/* +The intention is as below: +1) Have a linked list to manage heap allocations - having linked list sorted will make the search +O(log2(n)) - this will keep Allocated Slots. +2) Important Notes about the linked list: +- Obviously since we are re-writing malloc function - we need to have a way to initialize the +linked list - as a start we will start with an array. As second stage, we would allocate the +linked list in the allocated memory for the heap. +- How are we going to track the allocation of the linked list - since it will be a list +implemented on a memory array. We will need a fixed size array (int/bool) to track the allocation +status of the list. -> by index (again considering this is implemented on the memory array) +3) When adding / removing memory segments - we would need to check the linked list for current status +4) When removing (allocating a memory slot) -> +a) first available slot will be returned +b) if the slot size is larger than required, slot start will be adjusted. +5) When adding (re-instating the memory slot back to heap) -> +a) We need to find the correct location (O(log(n))) +b) +*/ + +/* ------------------------------ HEAP FUNCTIONS --------------------------------*/ + + + +//Define + +void *heap_alloc(size_t size_bytes); +void heap_free(void *ptr); +void heap_collect(); + +/* ------------------------------ LINKED LIST FUNCTIONS --------------------------------*/ + +void AddNode(SortedLinkedList* list, Node* node) +{ + assert(list != NULL); + assert(node != NULL); + + if(list->head == NULL) + { + list->head = node; + list->tail = node; + list->count++; + return; + } + + Node* temp = list->head; + + while(temp != NULL) + { + if(temp->next == NULL) + break; + + if(temp->next->start_offset > node->start_offset) + break; + } + + node->previous = temp; + node->next = temp->next; + temp->next = node; + + list->count++; +} + +void RemoveNode(SortedLinkedList* list, Node* node); + + +/*-------------------------FUNCTIONS/VARIABLES TO MANAGE THE HEAP-------------------------------*/ +SortedLinkedList list = {.head = NULL, .tail = NULL, .count = 0}; +int mem_alloc[MAX_CONCURRENT_ALLOCATIONS] = {0}; +Node node_alloc[MAX_CONCURRENT_ALLOCATIONS] = {{.size=0, .start_offset=0, .next=NULL, .previous=NULL}}; + +int return_first_free_index(void) +{ + for(int i=0; i=0 && index < MAX_CONCURRENT_ALLOCATIONS); + assert(mem_alloc[index] == 0); + mem_alloc[index] = 1; +} \ No newline at end of file diff --git a/linked_list.h b/linked_list.h index 59ab632..ddaed3e 100644 --- a/linked_list.h +++ b/linked_list.h @@ -6,28 +6,38 @@ a start offset for the memory location and size of the memory (could be in bytes #ifndef LINKED_LIST_H_ #define LINKED_LIST_H_ - #define MAX_CONCURRENT_ALLOCATIONS 1024 #define MAX_MEMORY_TO_SUPPORT_HEAP 64000 -extern void* allocation_array[MAX_CONCURRENT_ALLOCATIONS]; +/*-------------------------LINKED LIST DECLARATION-------------------------------*/ -#include +typedef struct Node Node; -typedef struct { +struct Node { int start_offset; size_t size; - struct Node* next; - struct Node* previous; -} Node; + Node* next; + Node* previous; +}; typedef struct { Node* head; + Node* tail; int count; } SortedLinkedList; -void AddNode(SortedLinkedList* list, void* value); +void AddNode(SortedLinkedList* list, Node* node); +void RemoveNode(SortedLinkedList* list, Node* node); +void AddNode(SortedLinkedList* list, Node* node); void RemoveNode(SortedLinkedList* list, Node* node); -Node* FindNode(SortedLinkedList* list, Node* node); + +/*-------------------------FUNCTIONS/VARIABLES TO MANAGE THE HEAP-------------------------------*/ + +extern SortedLinkedList list; +extern int mem_alloc[MAX_CONCURRENT_ALLOCATIONS]; +extern Node node_alloc[MAX_CONCURRENT_ALLOCATIONS]; + +extern int return_first_free_index(void); +extern void mark_index_allocated(int index); #endif \ No newline at end of file From 9b0559bcc6c7d53d248e7033f70cf5f7c9b52ffd Mon Sep 17 00:00:00 2001 From: memoz1981 Date: Tue, 2 Apr 2024 21:41:58 +0400 Subject: [PATCH 04/18] Drafted new design using linked lists - some functions not implemented yet. Also would probably need to define an empty head for the sorted linked list, just to keep that reference for ease of management --- README.md | 4 + heap_using_linked_lists.c | 172 +++++++++++++++++++++++++++----------- linked_list.h | 27 +++--- 3 files changed, 143 insertions(+), 60 deletions(-) diff --git a/README.md b/README.md index d5b01f0..d7ad6bc 100644 --- a/README.md +++ b/README.md @@ -16,3 +16,7 @@ $ ./heap - No tricks that obscure the pointers (like XOR Linked Lists). - Probably works only on x86_64 - Probably works only when compiled with GCC + +## Linked List Implementation + +1) diff --git a/heap_using_linked_lists.c b/heap_using_linked_lists.c index c6afff0..d8b69dc 100644 --- a/heap_using_linked_lists.c +++ b/heap_using_linked_lists.c @@ -5,13 +5,16 @@ #include "./linked_list.h" #include +Node* initialize_head_node(void); + uintptr_t heap[HEAP_CAP_WORDS] = {0}; const uintptr_t *stack_base = 0; +size_t convert_bytes_to_words_size(size_t size_in_bytes); /* The intention is as below: 1) Have a linked list to manage heap allocations - having linked list sorted will make the search -O(log2(n)) - this will keep Allocated Slots. +O(log2(n)) - this will keep Allocated Slots. Important note is linked list will hold empty spaces... 2) Important Notes about the linked list: - Obviously since we are re-writing malloc function - we need to have a way to initialize the linked list - as a start we will start with an array. As second stage, we would allocate the @@ -19,80 +22,149 @@ linked list in the allocated memory for the heap. - How are we going to track the allocation of the linked list - since it will be a list implemented on a memory array. We will need a fixed size array (int/bool) to track the allocation status of the list. -> by index (again considering this is implemented on the memory array) -3) When adding / removing memory segments - we would need to check the linked list for current status -4) When removing (allocating a memory slot) -> -a) first available slot will be returned -b) if the slot size is larger than required, slot start will be adjusted. -5) When adding (re-instating the memory slot back to heap) -> -a) We need to find the correct location (O(log(n))) -b) -*/ +3) When allocating memory segments (this would remove/modify a linked list node), +there can be 2 strategies to follow: +- Return first available time slot same or greater than required +- Return the time slot that would optimally fit the request -> this will not be implemented, as +would require O(n) with planned data structures. +4) When free'ing memory slots (this would add/modify a node) +- a new node would be added to the linked list. +- at first stage the node will be added +- as second stage, adjacent nodes would be checked, if possible those will be merged. + +IMPORTANT NOTE: AIM IS TO MOVE THE DATA STRUCTURE ALLOCATION TO PART OF THE HEAP +ARRAY - SO WE HAVE AN ALTOGERHER ALLOCATION MANAGEMENT... +THIS WILL BE DONE AS SECOND STAGE...*/ /* ------------------------------ HEAP FUNCTIONS --------------------------------*/ +void *heap_alloc(size_t size_bytes) +{ + if(list.count >= MAX_CONCURRENT_ALLOCATIONS - 1) + return NULL; + + size_t size_in_words = convert_bytes_to_words_size(size_bytes); + + Node* node = FindNode(&list, size_in_words); + if(node == NULL) + return NULL; + + if(node->size_in_words == size_in_words) + { + MarkNodeAsAllocated(node); + return node; + } + //here it's clear that node size is greater than required + //thus we need to split it into two + //we would need to split the node into 2... -//Define + Node* emptyNode = alloc_node(); -void *heap_alloc(size_t size_bytes); -void heap_free(void *ptr); -void heap_collect(); + emptyNode->is_allocated = true; + emptyNode->next = node->next; + emptyNode->previous = node; + emptyNode->size_in_words = size_in_words; + emptyNode->start = node->start + (node->size_in_words - size_in_words); -/* ------------------------------ LINKED LIST FUNCTIONS --------------------------------*/ + node->size_in_words = node->size_in_words - size_in_words; + node->next = emptyNode; + list.count++; -void AddNode(SortedLinkedList* list, Node* node) + return emptyNode->start; +} + +size_t convert_bytes_to_words_size(size_t size_in_bytes) { - assert(list != NULL); - assert(node != NULL); + size_t words = (size_t)size_in_bytes / (sizeof(uintptr_t)); - if(list->head == NULL) - { - list->head = node; - list->tail = node; - list->count++; - return; - } + if(size_in_bytes % sizeof(uintptr_t) != 0) + words++; - Node* temp = list->head; + return words; +} + +void heap_free(void *ptr) +{ + +} +void heap_collect(); //at this stage this will not be implemented, not that necessary. + +/* ------------------------------ LINKED LIST FUNCTIONS --------------------------------*/ +Node* FindNode(SortedLinkedList* list, size_t size_in_words) +{ + Node* temp = list->head; while(temp != NULL) { - if(temp->next == NULL) - break; - - if(temp->next->start_offset > node->start_offset) - break; + if(!temp->is_allocated && temp->size_in_words >= size_in_words) + return temp; + + temp = temp->next; } - - node->previous = temp; - node->next = temp->next; - temp->next = node; - - list->count++; + return temp; } -void RemoveNode(SortedLinkedList* list, Node* node); - +void MarkNodeAsAllocated(Node* node) +{ + node->is_allocated = true; +} /*-------------------------FUNCTIONS/VARIABLES TO MANAGE THE HEAP-------------------------------*/ -SortedLinkedList list = {.head = NULL, .tail = NULL, .count = 0}; +//this is the sorted linked list for + +SortedLinkedList list = {.head = NULL, .count = 0}; int mem_alloc[MAX_CONCURRENT_ALLOCATIONS] = {0}; -Node node_alloc[MAX_CONCURRENT_ALLOCATIONS] = {{.size=0, .start_offset=0, .next=NULL, .previous=NULL}}; +Node node_alloc[MAX_CONCURRENT_ALLOCATIONS] = +{ + { + .is_allocated=false, + .next = NULL, + .previous = NULL, + .size_in_words = 0, + .start = NULL, + .allocated_index = 0 + } +}; +void InitializeAllocators(void) +{ + for(int i = 0; i < MAX_CONCURRENT_ALLOCATIONS; i++) + { + node_alloc[i].allocated_index = i; + } + list.head = initialize_head_node(); +} + +Node* initialize_head_node(void) +{ + node_alloc[0].size_in_words = HEAP_CAP_WORDS; + node_alloc[0].start = &heap[0]; + return &node_alloc[0]; +} -int return_first_free_index(void) +Node* alloc_node(void) { - for(int i=0; i=0 && index < MAX_CONCURRENT_ALLOCATIONS); - assert(mem_alloc[index] == 0); - mem_alloc[index] = 1; -} \ No newline at end of file + assert(node != NULL && node->allocated_index >= 0 && node->allocated_index < MAX_CONCURRENT_ALLOCATIONS); + + mem_alloc[node->allocated_index] = 0; +} \ No newline at end of file diff --git a/linked_list.h b/linked_list.h index ddaed3e..0e3d650 100644 --- a/linked_list.h +++ b/linked_list.h @@ -9,27 +9,32 @@ a start offset for the memory location and size of the memory (could be in bytes #define MAX_CONCURRENT_ALLOCATIONS 1024 #define MAX_MEMORY_TO_SUPPORT_HEAP 64000 -/*-------------------------LINKED LIST DECLARATION-------------------------------*/ +#include +#include + +/*-------------------------LINKED LIST DECLARATION AND FUNCTIONS-------------------------------*/ typedef struct Node Node; struct Node { - int start_offset; - size_t size; + uintptr_t* start; + size_t size_in_words; Node* next; Node* previous; + int allocated_index; + bool is_allocated; }; typedef struct { Node* head; - Node* tail; int count; } SortedLinkedList; -void AddNode(SortedLinkedList* list, Node* node); -void RemoveNode(SortedLinkedList* list, Node* node); -void AddNode(SortedLinkedList* list, Node* node); -void RemoveNode(SortedLinkedList* list, Node* node); +// void AddNode(SortedLinkedList* list, Node* node); +// int RemoveNode(SortedLinkedList* list, Node* node); +Node* FindNode(SortedLinkedList* list, size_t size_in_words); +void MarkNodeAsAllocated(Node* node); + /*-------------------------FUNCTIONS/VARIABLES TO MANAGE THE HEAP-------------------------------*/ @@ -37,7 +42,9 @@ extern SortedLinkedList list; extern int mem_alloc[MAX_CONCURRENT_ALLOCATIONS]; extern Node node_alloc[MAX_CONCURRENT_ALLOCATIONS]; -extern int return_first_free_index(void); -extern void mark_index_allocated(int index); + +extern void InitializeAllocators(); +extern Node* alloc_node(void); +extern void de_alloc_node(Node* node); #endif \ No newline at end of file From 4028031b6a10d0651417bc1d3b1dc0640da8cc63 Mon Sep 17 00:00:00 2001 From: memoz1981 Date: Tue, 2 Apr 2024 21:50:51 +0400 Subject: [PATCH 05/18] all functions drafted, main will need to be re-done --- heap_using_linked_lists.c | 12 +++- main.c | 120 +++++++++++++++++++------------------- 2 files changed, 70 insertions(+), 62 deletions(-) diff --git a/heap_using_linked_lists.c b/heap_using_linked_lists.c index d8b69dc..78dea20 100644 --- a/heap_using_linked_lists.c +++ b/heap_using_linked_lists.c @@ -86,9 +86,17 @@ size_t convert_bytes_to_words_size(size_t size_in_bytes) void heap_free(void *ptr) { - + uintptr_t* casted = (uintptr_t*)ptr; + + int index = casted - list.head->start; + + node_alloc[index].is_allocated = false; + + //to-do --- combine with adjacent nodes... + + mem_alloc[index] = 0; } -void heap_collect(); //at this stage this will not be implemented, not that necessary. +void heap_collect() {} //at this stage this will not be implemented, not that necessary. /* ------------------------------ LINKED LIST FUNCTIONS --------------------------------*/ diff --git a/main.c b/main.c index c8749a7..de503c6 100644 --- a/main.c +++ b/main.c @@ -5,85 +5,85 @@ #include #include "./heap.h" -#include "./chunk_lists.h" +#include "./linked_list.h" -#define JIM_IMPLEMENTATION -#include "jim.h" +// #define JIM_IMPLEMENTATION +// #include "jim.h" -typedef struct Node Node; +// typedef struct Node Node; -struct Node { - char x; - Node *left; - Node *right; -}; +// struct Node { +// char x; +// Node *left; +// Node *right; +// }; -Node *generate_tree(size_t level_cur, size_t level_max) -{ - if (level_cur < level_max) { - Node *root = heap_alloc(sizeof(*root)); - assert((char) level_cur - 'a' <= 'z'); - root->x = level_cur + 'a'; - root->left = generate_tree(level_cur + 1, level_max); - root->right = generate_tree(level_cur + 1, level_max); - return root; - } else { - return NULL; - } -} +// Node *generate_tree(size_t level_cur, size_t level_max) +// { +// if (level_cur < level_max) { +// Node *root = heap_alloc(sizeof(*root)); +// assert((char) level_cur - 'a' <= 'z'); +// root->x = level_cur + 'a'; +// root->left = generate_tree(level_cur + 1, level_max); +// root->right = generate_tree(level_cur + 1, level_max); +// return root; +// } else { +// return NULL; +// } +// } -void print_tree(Node *root, Jim *jim) -{ - if (root != NULL) { - jim_object_begin(jim); +// void print_tree(Node *root, Jim *jim) +// { +// if (root != NULL) { +// jim_object_begin(jim); - jim_member_key(jim, "value"); - jim_string_sized(jim, &root->x, 1); +// jim_member_key(jim, "value"); +// jim_string_sized(jim, &root->x, 1); - jim_member_key(jim, "left"); - print_tree(root->left, jim); +// jim_member_key(jim, "left"); +// print_tree(root->left, jim); - jim_member_key(jim, "right"); - print_tree(root->right, jim); +// jim_member_key(jim, "right"); +// print_tree(root->right, jim); - jim_object_end(jim); - } else { - jim_null(jim); - } -} +// jim_object_end(jim); +// } else { +// jim_null(jim); +// } +// } -#define N 10 +// #define N 10 -void *ptrs[N] = {0}; +// void *ptrs[N] = {0}; int main() { - stack_base = (const uintptr_t*)__builtin_frame_address(0); + // stack_base = (const uintptr_t*)__builtin_frame_address(0); - for (size_t i = 0; i < 10; ++i) { - heap_alloc(i); - } + // for (size_t i = 0; i < 10; ++i) { + // heap_alloc(i); + // } - Node *root = generate_tree(0, 3); + // // Node *root = generate_tree(0, 3); - printf("root: %p\n", (void*)root); + // printf("root: %p\n", (void*)root); - Jim jim = { - .sink = stdout, - .write = (Jim_Write) fwrite, - }; + // Jim jim = { + // .sink = stdout, + // .write = (Jim_Write) fwrite, + // }; - print_tree(root, &jim); + // print_tree(root, &jim); - printf("\n------------------------------\n"); - heap_collect(); - chunk_list_dump(&alloced_chunks, "Alloced"); - chunk_list_dump(&freed_chunks, "Freed"); - printf("------------------------------\n"); - root = NULL; - heap_collect(); - chunk_list_dump(&alloced_chunks, "Alloced"); - chunk_list_dump(&freed_chunks, "Freed"); + // printf("\n------------------------------\n"); + // heap_collect(); + // // chunk_list_dump(&alloced_chunks, "Alloced"); + // // chunk_list_dump(&freed_chunks, "Freed"); + // printf("------------------------------\n"); + // // root = NULL; + // heap_collect(); + // // chunk_list_dump(&alloced_chunks, "Alloced"); + // // chunk_list_dump(&freed_chunks, "Freed"); - return 0; + // return 0; } From 43cc7734a2c6b657757db40b2ef9354f4a84b7c1 Mon Sep 17 00:00:00 2001 From: memoz1981 Date: Wed, 3 Apr 2024 22:50:04 +0400 Subject: [PATCH 06/18] Got it partially working - need to sort out how to scan characters to use in menu --- heap_using_chunk_lists.c | 1 + heap_using_linked_lists.c | 48 +++++++++++++-- linked_list.h | 8 ++- logger.c | 35 +++++++++++ logger.h | 8 +++ main.c | 119 +++++++++++++++----------------------- 6 files changed, 140 insertions(+), 79 deletions(-) create mode 100644 logger.c create mode 100644 logger.h diff --git a/heap_using_chunk_lists.c b/heap_using_chunk_lists.c index a12fa67..93da7f6 100644 --- a/heap_using_chunk_lists.c +++ b/heap_using_chunk_lists.c @@ -90,6 +90,7 @@ void chunk_list_remove(Chunk_List *list, size_t index) void *heap_alloc(size_t size_bytes) { + printf("Received request to allocate size in bytes %d", (int)size_bytes); const size_t size_words = (size_bytes + sizeof(uintptr_t) - 1) / sizeof(uintptr_t); if (size_words > 0) { diff --git a/heap_using_linked_lists.c b/heap_using_linked_lists.c index 78dea20..0d541f3 100644 --- a/heap_using_linked_lists.c +++ b/heap_using_linked_lists.c @@ -4,11 +4,10 @@ #include "./heap.h" #include "./linked_list.h" #include - -Node* initialize_head_node(void); +#include "logger.h" uintptr_t heap[HEAP_CAP_WORDS] = {0}; -const uintptr_t *stack_base = 0; +Node* initialize_head_node(void); size_t convert_bytes_to_words_size(size_t size_in_bytes); /* @@ -39,18 +38,21 @@ THIS WILL BE DONE AS SECOND STAGE...*/ /* ------------------------------ HEAP FUNCTIONS --------------------------------*/ void *heap_alloc(size_t size_bytes) { + printf("\nRequested to allocate heap of byte size %d\n", (int)size_bytes); if(list.count >= MAX_CONCURRENT_ALLOCATIONS - 1) return NULL; size_t size_in_words = convert_bytes_to_words_size(size_bytes); - Node* node = FindNode(&list, size_in_words); + print_node(node); + if(node == NULL) return NULL; if(node->size_in_words == size_in_words) { + printf("Node size %d is same as requested %d\n", (int)node->size_in_words, (int)size_in_words); MarkNodeAsAllocated(node); return node; } @@ -59,6 +61,7 @@ void *heap_alloc(size_t size_bytes) //thus we need to split it into two //we would need to split the node into 2... + printf("Node size is greater than requested...\n"); Node* emptyNode = alloc_node(); emptyNode->is_allocated = true; @@ -118,6 +121,25 @@ void MarkNodeAsAllocated(Node* node) node->is_allocated = true; } +void print_node(Node* node) +{ + printf("{start:%p, size_in_words: %d, allocated_index: %d, isAllocated: %d}", + (void*)node->start, (int)node->size_in_words, node->allocated_index, node->is_allocated); +} + +void print_linked_list(SortedLinkedList* list) +{ + printf("\nLinkedList: "); + Node* temp = list->head; + while(temp != NULL) + { + print_node(temp); + printf(" -> "); + temp = temp->next; + } + printf("NULL\n"); +} + /*-------------------------FUNCTIONS/VARIABLES TO MANAGE THE HEAP-------------------------------*/ //this is the sorted linked list for @@ -147,11 +169,13 @@ Node* initialize_head_node(void) { node_alloc[0].size_in_words = HEAP_CAP_WORDS; node_alloc[0].start = &heap[0]; + mem_alloc[0] = 1; return &node_alloc[0]; } Node* alloc_node(void) { + printf("\nRequested to allocate a node\n"); int i = 0; for(; iallocated_index >= 0 && node->allocated_index < MAX_CONCURRENT_ALLOCATIONS); mem_alloc[node->allocated_index] = 0; +} + +void print_allocations(void) +{ + printf("\nAllocations Array: "); + for(int i = 0; i < MAX_CONCURRENT_ALLOCATIONS; i++) + { + printf("{%d, %d}", i, mem_alloc[i]); + } + + printf("\nLinked List Allocations: "); + for(int i = 0; i < MAX_CONCURRENT_ALLOCATIONS; i++) + { + print_node(&node_alloc[i]); + } + printf("\n"); } \ No newline at end of file diff --git a/linked_list.h b/linked_list.h index 0e3d650..ccf18df 100644 --- a/linked_list.h +++ b/linked_list.h @@ -6,7 +6,7 @@ a start offset for the memory location and size of the memory (could be in bytes #ifndef LINKED_LIST_H_ #define LINKED_LIST_H_ -#define MAX_CONCURRENT_ALLOCATIONS 1024 +#define MAX_CONCURRENT_ALLOCATIONS 4 #define MAX_MEMORY_TO_SUPPORT_HEAP 64000 #include @@ -34,6 +34,8 @@ typedef struct { // int RemoveNode(SortedLinkedList* list, Node* node); Node* FindNode(SortedLinkedList* list, size_t size_in_words); void MarkNodeAsAllocated(Node* node); +void print_node(Node* node); +void print_linked_list(SortedLinkedList* list); /*-------------------------FUNCTIONS/VARIABLES TO MANAGE THE HEAP-------------------------------*/ @@ -41,10 +43,12 @@ void MarkNodeAsAllocated(Node* node); extern SortedLinkedList list; extern int mem_alloc[MAX_CONCURRENT_ALLOCATIONS]; extern Node node_alloc[MAX_CONCURRENT_ALLOCATIONS]; +extern void print_list(); -extern void InitializeAllocators(); +extern void InitializeAllocators(void); extern Node* alloc_node(void); extern void de_alloc_node(Node* node); +extern void print_allocations(void); #endif \ No newline at end of file diff --git a/logger.c b/logger.c new file mode 100644 index 0000000..18a4bd6 --- /dev/null +++ b/logger.c @@ -0,0 +1,35 @@ +#include +#include "logger.h" +#include + +void log_level(char* message, enum LogLevel level) +{ + int length = strlen(message) + 20; + char* output = (char*)malloc(length * sizeof(char)); + memset(output, 0, length); + + switch(level) { + case Debug: + strcat(output, "Debug: "); + break; + + case Information: + strcat(output, "Information: "); + break; + + case Warning: + strcat(output, "Warning: "); + break; + + case Error: + strcat(output, "Error: "); + break; + + default: + break; + } + + strcat(output, message); + + puts(output); +} \ No newline at end of file diff --git a/logger.h b/logger.h new file mode 100644 index 0000000..d902c1c --- /dev/null +++ b/logger.h @@ -0,0 +1,8 @@ +#ifndef LOGGER_H_ +#define LOGGER_H_ + +enum LogLevel { Debug, Information, Warning, Error}; + +void log_level(char* message, enum LogLevel level); + +#endif diff --git a/main.c b/main.c index de503c6..6d96c42 100644 --- a/main.c +++ b/main.c @@ -3,87 +3,60 @@ #include #include #include +#include #include "./heap.h" #include "./linked_list.h" -// #define JIM_IMPLEMENTATION -// #include "jim.h" - -// typedef struct Node Node; - -// struct Node { -// char x; -// Node *left; -// Node *right; -// }; - -// Node *generate_tree(size_t level_cur, size_t level_max) -// { -// if (level_cur < level_max) { -// Node *root = heap_alloc(sizeof(*root)); -// assert((char) level_cur - 'a' <= 'z'); -// root->x = level_cur + 'a'; -// root->left = generate_tree(level_cur + 1, level_max); -// root->right = generate_tree(level_cur + 1, level_max); -// return root; -// } else { -// return NULL; -// } -// } - -// void print_tree(Node *root, Jim *jim) -// { -// if (root != NULL) { -// jim_object_begin(jim); - -// jim_member_key(jim, "value"); -// jim_string_sized(jim, &root->x, 1); - -// jim_member_key(jim, "left"); -// print_tree(root->left, jim); - -// jim_member_key(jim, "right"); -// print_tree(root->right, jim); - -// jim_object_end(jim); -// } else { -// jim_null(jim); -// } -// } - -// #define N 10 - -// void *ptrs[N] = {0}; +int run_cycle(void); int main() { - // stack_base = (const uintptr_t*)__builtin_frame_address(0); - - // for (size_t i = 0; i < 10; ++i) { - // heap_alloc(i); - // } - - // // Node *root = generate_tree(0, 3); + InitializeAllocators(); - // printf("root: %p\n", (void*)root); + int result = 0; - // Jim jim = { - // .sink = stdout, - // .write = (Jim_Write) fwrite, - // }; - - // print_tree(root, &jim); - - // printf("\n------------------------------\n"); - // heap_collect(); - // // chunk_list_dump(&alloced_chunks, "Alloced"); - // // chunk_list_dump(&freed_chunks, "Freed"); - // printf("------------------------------\n"); - // // root = NULL; - // heap_collect(); - // // chunk_list_dump(&alloced_chunks, "Alloced"); - // // chunk_list_dump(&freed_chunks, "Freed"); + while(result != -1) + { + result = run_cycle(); + print_linked_list(&list); + } + +} - // return 0; +int run_cycle(void) +{ + printf("\n\n\nChoose one of the options below: \n"); + printf("[c] to clear the screen\n"); + printf("[a]_[size_in_bytes] to allocate...(a 10 will allocate 10 bytes)\n"); + printf("[d]_[index] to de-allocate...(d 0 will de-allocate 0th index)\n"); + printf("[e] to exit\n"); + + char command = '\0'; + scanf("%c", &command); + + if(command == 'e') + return -1; + + if(command == 'c') + system("clear"); + + if(command == 'a') + { + int num; + scanf("Enter the size in bytes: %d", &num); + + void * pointer = heap_alloc(num); + if(pointer == NULL) + { + printf("Memory could not be allocated...\n"); + return -1; + } + + printf("Memory with address %p was allocated.", pointer); + return 0; + } + + + return 0; } From dd18c318b17c88b5362d5838fdfa7bf7788ec4e2 Mon Sep 17 00:00:00 2001 From: memoz1981 Date: Fri, 5 Apr 2024 11:05:19 +0400 Subject: [PATCH 07/18] Got allocation working, some clean up is required --- heap_using_linked_lists.c | 47 ++++++++++++++++++++++++++++++--------- linked_list.h | 4 ++-- main.c | 45 +++++++++++++++++++++++++++---------- 3 files changed, 71 insertions(+), 25 deletions(-) diff --git a/heap_using_linked_lists.c b/heap_using_linked_lists.c index 0d541f3..9f5b656 100644 --- a/heap_using_linked_lists.c +++ b/heap_using_linked_lists.c @@ -38,18 +38,32 @@ THIS WILL BE DONE AS SECOND STAGE...*/ /* ------------------------------ HEAP FUNCTIONS --------------------------------*/ void *heap_alloc(size_t size_bytes) { - printf("\nRequested to allocate heap of byte size %d\n", (int)size_bytes); - if(list.count >= MAX_CONCURRENT_ALLOCATIONS - 1) + //Validation 1 - size should be greater than zero + if(size_bytes <= 0) + { + printf("\nInvalid request, size should be greater than or equal to zero.\n"); + return NULL; + } + + //Validation 2 - we shouldn't have more than Max + if(list.count_allocated >= MAX_CONCURRENT_ALLOCATIONS) + { + printf("Currently there are %d allocations - we cannot have more than that\n", list.count_allocated); return NULL; + } size_t size_in_words = convert_bytes_to_words_size(size_bytes); + Node* node = FindNode(&list, size_in_words); - print_node(node); - + //Validation 3 - check if any node could be allocated if(node == NULL) + { + printf("Memory with requested size doesn't exit.\n"); return NULL; + } + //check for exast match if(node->size_in_words == size_in_words) { printf("Node size %d is same as requested %d\n", (int)node->size_in_words, (int)size_in_words); @@ -72,7 +86,7 @@ void *heap_alloc(size_t size_bytes) node->size_in_words = node->size_in_words - size_in_words; node->next = emptyNode; - list.count++; + list.count_allocated++; return emptyNode->start; } @@ -113,7 +127,8 @@ Node* FindNode(SortedLinkedList* list, size_t size_in_words) temp = temp->next; } - return temp; + + return NULL; } void MarkNodeAsAllocated(Node* node) @@ -123,8 +138,17 @@ void MarkNodeAsAllocated(Node* node) void print_node(Node* node) { - printf("{start:%p, size_in_words: %d, allocated_index: %d, isAllocated: %d}", - (void*)node->start, (int)node->size_in_words, node->allocated_index, node->is_allocated); + if(node == NULL) + printf("NULL"); + + Node* node_address = node; + int node_address_offset = (int)(node_address - &node_alloc[0]); + + int start_offset = (int)(node->start - heap); + + printf("{start:%p, size_in_words: %d, allocated_index: %d, is_allocated: %d, node_address: %p, node_address_offset: %d, start_offset: %d}", + (void*)node->start, (int)node->size_in_words, node->allocated_index, node->is_allocated, + (void*)node_address, node_address_offset, start_offset); } void print_linked_list(SortedLinkedList* list) @@ -143,7 +167,7 @@ void print_linked_list(SortedLinkedList* list) /*-------------------------FUNCTIONS/VARIABLES TO MANAGE THE HEAP-------------------------------*/ //this is the sorted linked list for -SortedLinkedList list = {.head = NULL, .count = 0}; +SortedLinkedList list = {.head = NULL, .count_allocated = 0}; int mem_alloc[MAX_CONCURRENT_ALLOCATIONS] = {0}; Node node_alloc[MAX_CONCURRENT_ALLOCATIONS] = { @@ -168,7 +192,7 @@ void InitializeAllocators(void) Node* initialize_head_node(void) { node_alloc[0].size_in_words = HEAP_CAP_WORDS; - node_alloc[0].start = &heap[0]; + node_alloc[0].start = heap; mem_alloc[0] = 1; return &node_alloc[0]; } @@ -188,7 +212,6 @@ Node* alloc_node(void) if(i == MAX_CONCURRENT_ALLOCATIONS) return NULL; - node_alloc[i].allocated_index = i; mem_alloc[i] = 1; //mark node as allocated return &node_alloc[i]; @@ -199,6 +222,7 @@ void de_alloc_node(Node* node) assert(node != NULL && node->allocated_index >= 0 && node->allocated_index < MAX_CONCURRENT_ALLOCATIONS); mem_alloc[node->allocated_index] = 0; + node->is_allocated = false; } void print_allocations(void) @@ -212,6 +236,7 @@ void print_allocations(void) printf("\nLinked List Allocations: "); for(int i = 0; i < MAX_CONCURRENT_ALLOCATIONS; i++) { + printf("\n%d'th node: ", i); print_node(&node_alloc[i]); } printf("\n"); diff --git a/linked_list.h b/linked_list.h index ccf18df..2acfd8a 100644 --- a/linked_list.h +++ b/linked_list.h @@ -6,7 +6,7 @@ a start offset for the memory location and size of the memory (could be in bytes #ifndef LINKED_LIST_H_ #define LINKED_LIST_H_ -#define MAX_CONCURRENT_ALLOCATIONS 4 +#define MAX_CONCURRENT_ALLOCATIONS 16 #define MAX_MEMORY_TO_SUPPORT_HEAP 64000 #include @@ -27,7 +27,7 @@ struct Node { typedef struct { Node* head; - int count; + int count_allocated; } SortedLinkedList; // void AddNode(SortedLinkedList* list, Node* node); diff --git a/main.c b/main.c index 6d96c42..4e85ad1 100644 --- a/main.c +++ b/main.c @@ -9,6 +9,7 @@ #include "./linked_list.h" int run_cycle(void); +int read_integer(char* command); int main() { @@ -19,7 +20,11 @@ int main() while(result != -1) { result = run_cycle(); + printf("Printing linked list: \n"); print_linked_list(&list); + printf("Printing allocations: \n"); + + print_allocations(); } } @@ -28,35 +33,51 @@ int run_cycle(void) { printf("\n\n\nChoose one of the options below: \n"); printf("[c] to clear the screen\n"); - printf("[a]_[size_in_bytes] to allocate...(a 10 will allocate 10 bytes)\n"); - printf("[d]_[index] to de-allocate...(d 0 will de-allocate 0th index)\n"); + printf("[a]_[size_in_bytes] to allocate...(a_10 will allocate 10 bytes)\n"); + printf("[d]_[index] to de-allocate...(d_0 will de-allocate 0th index)\n"); printf("[e] to exit\n"); - char command = '\0'; - scanf("%c", &command); - - if(command == 'e') + char command[20]; + memset(command, '\0', 20); + scanf("%s", command); + + if(strcmp("e", command) == 0) return -1; - if(command == 'c') + else if(strcmp("c", command) == 0) system("clear"); - if(command == 'a') + else if(command[0] == 'a') { - int num; - scanf("Enter the size in bytes: %d", &num); + int num = read_integer(command); void * pointer = heap_alloc(num); if(pointer == NULL) { printf("Memory could not be allocated...\n"); - return -1; + return 0; } printf("Memory with address %p was allocated.", pointer); return 0; } - + else + { + printf("Entered command %s is invalid", command); + } return 0; } + +int read_integer(char* command) +{ + int result = 0; + + for(int i =0; i<= (int)strlen(command); i++) + { + if(command[i] >=48 && command[i] <= 57) + result = result *10 + command[i] - 48; + } + + return result; +} From d1eb104cac1274d8558e433bcca0f4e0c0d25a1a Mon Sep 17 00:00:00 2001 From: memoz1981 Date: Fri, 5 Apr 2024 12:25:50 +0400 Subject: [PATCH 08/18] Alloc & de-alloc works --- heap_using_linked_lists.c | 66 +++++++++++++++++++++++++++------------ linked_list.h | 1 + main.c | 21 ++++++++++--- 3 files changed, 63 insertions(+), 25 deletions(-) diff --git a/heap_using_linked_lists.c b/heap_using_linked_lists.c index 9f5b656..536b3be 100644 --- a/heap_using_linked_lists.c +++ b/heap_using_linked_lists.c @@ -62,7 +62,11 @@ void *heap_alloc(size_t size_bytes) printf("Memory with requested size doesn't exit.\n"); return NULL; } - + + printf("Found space in node below: \n"); + print_node(node); + printf("\n"); + //check for exast match if(node->size_in_words == size_in_words) { @@ -75,9 +79,18 @@ void *heap_alloc(size_t size_bytes) //thus we need to split it into two //we would need to split the node into 2... - printf("Node size is greater than requested...\n"); Node* emptyNode = alloc_node(); + if(emptyNode == NULL) + { + printf("Error during memory allocation"); + return NULL; + } + + printf("Will use following node to accommodate new allocation: \n"); + print_node(emptyNode); + printf("\n"); + emptyNode->is_allocated = true; emptyNode->next = node->next; emptyNode->previous = node; @@ -103,16 +116,20 @@ size_t convert_bytes_to_words_size(size_t size_in_bytes) void heap_free(void *ptr) { - uintptr_t* casted = (uintptr_t*)ptr; - - int index = casted - list.head->start; + Node* node = find_node_by_pointer(&list, ptr); - node_alloc[index].is_allocated = false; + if(node == NULL) + { + printf("Provided pointer is not valid. "); + return; + } - //to-do --- combine with adjacent nodes... + node->is_allocated = false; + list.count_allocated--; - mem_alloc[index] = 0; + //to-do --- combine with adjacent nodes...then can return node to the array... } + void heap_collect() {} //at this stage this will not be implemented, not that necessary. /* ------------------------------ LINKED LIST FUNCTIONS --------------------------------*/ @@ -153,7 +170,7 @@ void print_node(Node* node) void print_linked_list(SortedLinkedList* list) { - printf("\nLinkedList: "); + printf("\nLinkedList: allocated count = %d\n", list->count_allocated); Node* temp = list->head; while(temp != NULL) { @@ -164,6 +181,21 @@ void print_linked_list(SortedLinkedList* list) printf("NULL\n"); } +Node* find_node_by_pointer(SortedLinkedList* list, void* ptr) +{ + uintptr_t* start = (uintptr_t*)ptr; + Node* temp = list->head; + + while(temp != NULL) + { + if(temp->start == start) + return temp; + + temp = temp->next; + } + return NULL; +} + /*-------------------------FUNCTIONS/VARIABLES TO MANAGE THE HEAP-------------------------------*/ //this is the sorted linked list for @@ -199,22 +231,16 @@ Node* initialize_head_node(void) Node* alloc_node(void) { - printf("\nRequested to allocate a node\n"); - int i = 0; - for(; i Date: Fri, 5 Apr 2024 12:55:57 +0400 Subject: [PATCH 09/18] De-coupled memory array size --- heap_using_linked_lists.c | 25 +++++++++++++++++-------- linked_list.h | 9 ++++----- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/heap_using_linked_lists.c b/heap_using_linked_lists.c index 536b3be..1e18b7a 100644 --- a/heap_using_linked_lists.c +++ b/heap_using_linked_lists.c @@ -197,11 +197,10 @@ Node* find_node_by_pointer(SortedLinkedList* list, void* ptr) } /*-------------------------FUNCTIONS/VARIABLES TO MANAGE THE HEAP-------------------------------*/ -//this is the sorted linked list for SortedLinkedList list = {.head = NULL, .count_allocated = 0}; -int mem_alloc[MAX_CONCURRENT_ALLOCATIONS] = {0}; -Node node_alloc[MAX_CONCURRENT_ALLOCATIONS] = +int mem_alloc[MAX_NUMBER_OF_NODES] = {0}; +Node node_alloc[MAX_NUMBER_OF_NODES] = { { .is_allocated=false, @@ -212,9 +211,11 @@ Node node_alloc[MAX_CONCURRENT_ALLOCATIONS] = .allocated_index = 0 } }; + void InitializeAllocators(void) { - for(int i = 0; i < MAX_CONCURRENT_ALLOCATIONS; i++) + int array_size = sizeof(node_alloc)/sizeof(node_alloc[0]); + for(int i = 0; i < array_size; i++) { node_alloc[i].allocated_index = i; } @@ -231,7 +232,8 @@ Node* initialize_head_node(void) Node* alloc_node(void) { - for(int i = 0; i < MAX_CONCURRENT_ALLOCATIONS; i++) + int array_size = sizeof(node_alloc)/sizeof(node_alloc[0]); + for(int i = 0; i < array_size; i++) { if(mem_alloc[i] == 0) //corresponding node is free { @@ -245,7 +247,13 @@ Node* alloc_node(void) void de_alloc_node(Node* node) { - assert(node != NULL && node->allocated_index >= 0 && node->allocated_index < MAX_CONCURRENT_ALLOCATIONS); + int array_size = sizeof(node_alloc)/sizeof(node_alloc[0]); + + assert(node != NULL + && node->allocated_index >= 0 + && node->allocated_index < array_size + && node->is_allocated == true + && mem_alloc[node->allocated_index] == 1); mem_alloc[node->allocated_index] = 0; node->is_allocated = false; @@ -253,14 +261,15 @@ void de_alloc_node(Node* node) void print_allocations(void) { + int array_size = sizeof(node_alloc)/sizeof(node_alloc[0]); printf("\nAllocations Array: "); - for(int i = 0; i < MAX_CONCURRENT_ALLOCATIONS; i++) + for(int i = 0; i < array_size; i++) { printf("{%d, %d}", i, mem_alloc[i]); } printf("\nLinked List Allocations: "); - for(int i = 0; i < MAX_CONCURRENT_ALLOCATIONS; i++) + for(int i = 0; i < array_size; i++) { printf("\n%d'th node: ", i); print_node(&node_alloc[i]); diff --git a/linked_list.h b/linked_list.h index bc078bb..f06a31f 100644 --- a/linked_list.h +++ b/linked_list.h @@ -6,8 +6,9 @@ a start offset for the memory location and size of the memory (could be in bytes #ifndef LINKED_LIST_H_ #define LINKED_LIST_H_ -#define MAX_CONCURRENT_ALLOCATIONS 16 +#define MAX_CONCURRENT_ALLOCATIONS 20 #define MAX_MEMORY_TO_SUPPORT_HEAP 64000 +#define MAX_NUMBER_OF_NODES 20 #include #include @@ -30,8 +31,6 @@ typedef struct { int count_allocated; } SortedLinkedList; -// void AddNode(SortedLinkedList* list, Node* node); -// int RemoveNode(SortedLinkedList* list, Node* node); Node* FindNode(SortedLinkedList* list, size_t size_in_words); void MarkNodeAsAllocated(Node* node); void print_node(Node* node); @@ -42,8 +41,8 @@ Node* find_node_by_pointer(SortedLinkedList* list, void* ptr); /*-------------------------FUNCTIONS/VARIABLES TO MANAGE THE HEAP-------------------------------*/ extern SortedLinkedList list; -extern int mem_alloc[MAX_CONCURRENT_ALLOCATIONS]; -extern Node node_alloc[MAX_CONCURRENT_ALLOCATIONS]; +extern int mem_alloc[MAX_NUMBER_OF_NODES]; +extern Node node_alloc[MAX_NUMBER_OF_NODES]; extern void print_list(); From 7a1e68a3bfe2cce89a488eaed663baba852096f6 Mon Sep 17 00:00:00 2001 From: memoz1981 Date: Fri, 5 Apr 2024 13:19:45 +0400 Subject: [PATCH 10/18] Addional properties to linked list to track all node counts --- heap_using_linked_lists.c | 31 +++++++++++++++++++++++-------- linked_list.h | 4 ++-- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/heap_using_linked_lists.c b/heap_using_linked_lists.c index 1e18b7a..59c1f2e 100644 --- a/heap_using_linked_lists.c +++ b/heap_using_linked_lists.c @@ -63,7 +63,7 @@ void *heap_alloc(size_t size_bytes) return NULL; } - printf("Found space in node below: \n"); + printf("Found memory in node below: \n"); print_node(node); printf("\n"); @@ -100,6 +100,7 @@ void *heap_alloc(size_t size_bytes) node->size_in_words = node->size_in_words - size_in_words; node->next = emptyNode; list.count_allocated++; + list.count_total++; return emptyNode->start; } @@ -124,8 +125,7 @@ void heap_free(void *ptr) return; } - node->is_allocated = false; - list.count_allocated--; + de_alloc_node(node); //to-do --- combine with adjacent nodes...then can return node to the array... } @@ -170,7 +170,8 @@ void print_node(Node* node) void print_linked_list(SortedLinkedList* list) { - printf("\nLinkedList: allocated count = %d\n", list->count_allocated); + printf("\nLinkedList: count(total) = %d, count(all.)=%d, count(de-all.) = %d\n", + list->count_total, list->count_allocated, list->count_de_allocated); Node* temp = list->head; while(temp != NULL) { @@ -198,7 +199,13 @@ Node* find_node_by_pointer(SortedLinkedList* list, void* ptr) /*-------------------------FUNCTIONS/VARIABLES TO MANAGE THE HEAP-------------------------------*/ -SortedLinkedList list = {.head = NULL, .count_allocated = 0}; +SortedLinkedList list = + { + .head = NULL, + .count_allocated = 0, + .count_total = 0, + .count_de_allocated = 0 + }; int mem_alloc[MAX_NUMBER_OF_NODES] = {0}; Node node_alloc[MAX_NUMBER_OF_NODES] = { @@ -220,6 +227,8 @@ void InitializeAllocators(void) node_alloc[i].allocated_index = i; } list.head = initialize_head_node(); + list.count_total++; + list.count_de_allocated++; } Node* initialize_head_node(void) @@ -251,10 +260,16 @@ void de_alloc_node(Node* node) assert(node != NULL && node->allocated_index >= 0 - && node->allocated_index < array_size - && node->is_allocated == true - && mem_alloc[node->allocated_index] == 1); + && node->allocated_index < array_size); + + if(node->is_allocated == false || mem_alloc[node->allocated_index] == 0) + { + printf("Invalid selection, node is not allocated. "); + return; + } + list.count_allocated--; + list.count_de_allocated++; mem_alloc[node->allocated_index] = 0; node->is_allocated = false; } diff --git a/linked_list.h b/linked_list.h index f06a31f..e5740c8 100644 --- a/linked_list.h +++ b/linked_list.h @@ -29,6 +29,8 @@ struct Node { typedef struct { Node* head; int count_allocated; + int count_total; + int count_de_allocated; } SortedLinkedList; Node* FindNode(SortedLinkedList* list, size_t size_in_words); @@ -37,7 +39,6 @@ void print_node(Node* node); void print_linked_list(SortedLinkedList* list); Node* find_node_by_pointer(SortedLinkedList* list, void* ptr); - /*-------------------------FUNCTIONS/VARIABLES TO MANAGE THE HEAP-------------------------------*/ extern SortedLinkedList list; @@ -45,7 +46,6 @@ extern int mem_alloc[MAX_NUMBER_OF_NODES]; extern Node node_alloc[MAX_NUMBER_OF_NODES]; extern void print_list(); - extern void InitializeAllocators(void); extern Node* alloc_node(void); extern void de_alloc_node(Node* node); From de24b49a23df7805b1abf9104211967fad866382 Mon Sep 17 00:00:00 2001 From: memoz1981 Date: Fri, 5 Apr 2024 13:35:43 +0400 Subject: [PATCH 11/18] cleanup up function names to camelCase (except for main functions - which cannot be changed) --- heap_using_linked_lists.c | 51 ++++++++++++++++++--------------------- linked_list.h | 19 ++++++--------- main.c | 21 ++++++++-------- 3 files changed, 41 insertions(+), 50 deletions(-) diff --git a/heap_using_linked_lists.c b/heap_using_linked_lists.c index 59c1f2e..2404467 100644 --- a/heap_using_linked_lists.c +++ b/heap_using_linked_lists.c @@ -7,8 +7,8 @@ #include "logger.h" uintptr_t heap[HEAP_CAP_WORDS] = {0}; -Node* initialize_head_node(void); -size_t convert_bytes_to_words_size(size_t size_in_bytes); +Node* initializeHeadNode(void); +size_t convertBytesToWords(size_t size_in_byprint_allocationstes); /* The intention is as below: @@ -52,9 +52,9 @@ void *heap_alloc(size_t size_bytes) return NULL; } - size_t size_in_words = convert_bytes_to_words_size(size_bytes); + size_t size_in_words = convertBytesToWords(size_bytes); - Node* node = FindNode(&list, size_in_words); + Node* node = findNode(&list, size_in_words); //Validation 3 - check if any node could be allocated if(node == NULL) @@ -64,14 +64,14 @@ void *heap_alloc(size_t size_bytes) } printf("Found memory in node below: \n"); - print_node(node); + printNode(node); printf("\n"); //check for exast match if(node->size_in_words == size_in_words) { printf("Node size %d is same as requested %d\n", (int)node->size_in_words, (int)size_in_words); - MarkNodeAsAllocated(node); + node->is_allocated = true; return node; } @@ -79,7 +79,7 @@ void *heap_alloc(size_t size_bytes) //thus we need to split it into two //we would need to split the node into 2... - Node* emptyNode = alloc_node(); + Node* emptyNode = allocateNode(); if(emptyNode == NULL) { @@ -88,7 +88,7 @@ void *heap_alloc(size_t size_bytes) } printf("Will use following node to accommodate new allocation: \n"); - print_node(emptyNode); + printNode(emptyNode); printf("\n"); emptyNode->is_allocated = true; @@ -105,7 +105,7 @@ void *heap_alloc(size_t size_bytes) return emptyNode->start; } -size_t convert_bytes_to_words_size(size_t size_in_bytes) +size_t convertBytesToWords(size_t size_in_bytes) { size_t words = (size_t)size_in_bytes / (sizeof(uintptr_t)); @@ -117,7 +117,7 @@ size_t convert_bytes_to_words_size(size_t size_in_bytes) void heap_free(void *ptr) { - Node* node = find_node_by_pointer(&list, ptr); + Node* node = findNodeByPointer(&list, ptr); if(node == NULL) { @@ -125,7 +125,7 @@ void heap_free(void *ptr) return; } - de_alloc_node(node); + deAllocateNode(node); //to-do --- combine with adjacent nodes...then can return node to the array... } @@ -134,7 +134,7 @@ void heap_collect() {} //at this stage this will not be implemented, not that ne /* ------------------------------ LINKED LIST FUNCTIONS --------------------------------*/ -Node* FindNode(SortedLinkedList* list, size_t size_in_words) +Node* findNode(SortedLinkedList* list, size_t size_in_words) { Node* temp = list->head; while(temp != NULL) @@ -148,12 +148,7 @@ Node* FindNode(SortedLinkedList* list, size_t size_in_words) return NULL; } -void MarkNodeAsAllocated(Node* node) -{ - node->is_allocated = true; -} - -void print_node(Node* node) +void printNode(Node* node) { if(node == NULL) printf("NULL"); @@ -168,21 +163,21 @@ void print_node(Node* node) (void*)node_address, node_address_offset, start_offset); } -void print_linked_list(SortedLinkedList* list) +void printLinkedList(SortedLinkedList* list) { printf("\nLinkedList: count(total) = %d, count(all.)=%d, count(de-all.) = %d\n", list->count_total, list->count_allocated, list->count_de_allocated); Node* temp = list->head; while(temp != NULL) { - print_node(temp); + printNode(temp); printf(" -> "); temp = temp->next; } printf("NULL\n"); } -Node* find_node_by_pointer(SortedLinkedList* list, void* ptr) +Node* findNodeByPointer(SortedLinkedList* list, void* ptr) { uintptr_t* start = (uintptr_t*)ptr; Node* temp = list->head; @@ -219,19 +214,19 @@ Node node_alloc[MAX_NUMBER_OF_NODES] = } }; -void InitializeAllocators(void) +void initialize(void) { int array_size = sizeof(node_alloc)/sizeof(node_alloc[0]); for(int i = 0; i < array_size; i++) { node_alloc[i].allocated_index = i; } - list.head = initialize_head_node(); + list.head = initializeHeadNode(); list.count_total++; list.count_de_allocated++; } -Node* initialize_head_node(void) +Node* initializeHeadNode(void) { node_alloc[0].size_in_words = HEAP_CAP_WORDS; node_alloc[0].start = heap; @@ -239,7 +234,7 @@ Node* initialize_head_node(void) return &node_alloc[0]; } -Node* alloc_node(void) +Node* allocateNode(void) { int array_size = sizeof(node_alloc)/sizeof(node_alloc[0]); for(int i = 0; i < array_size; i++) @@ -254,7 +249,7 @@ Node* alloc_node(void) return NULL; } -void de_alloc_node(Node* node) +void deAllocateNode(Node* node) { int array_size = sizeof(node_alloc)/sizeof(node_alloc[0]); @@ -274,7 +269,7 @@ void de_alloc_node(Node* node) node->is_allocated = false; } -void print_allocations(void) +void printAllocations(void) { int array_size = sizeof(node_alloc)/sizeof(node_alloc[0]); printf("\nAllocations Array: "); @@ -287,7 +282,7 @@ void print_allocations(void) for(int i = 0; i < array_size; i++) { printf("\n%d'th node: ", i); - print_node(&node_alloc[i]); + printNode(&node_alloc[i]); } printf("\n"); } \ No newline at end of file diff --git a/linked_list.h b/linked_list.h index e5740c8..f375147 100644 --- a/linked_list.h +++ b/linked_list.h @@ -33,22 +33,19 @@ typedef struct { int count_de_allocated; } SortedLinkedList; -Node* FindNode(SortedLinkedList* list, size_t size_in_words); -void MarkNodeAsAllocated(Node* node); -void print_node(Node* node); -void print_linked_list(SortedLinkedList* list); -Node* find_node_by_pointer(SortedLinkedList* list, void* ptr); +Node* findNode(SortedLinkedList* list, size_t size_in_words); +void printNode(Node* node); +void printLinkedList(SortedLinkedList* list); +Node* findNodeByPointer(SortedLinkedList* list, void* ptr); /*-------------------------FUNCTIONS/VARIABLES TO MANAGE THE HEAP-------------------------------*/ extern SortedLinkedList list; extern int mem_alloc[MAX_NUMBER_OF_NODES]; extern Node node_alloc[MAX_NUMBER_OF_NODES]; -extern void print_list(); - -extern void InitializeAllocators(void); -extern Node* alloc_node(void); -extern void de_alloc_node(Node* node); -extern void print_allocations(void); +extern void initialize(void); +extern Node* allocateNode(void); +extern void deAllocateNode(Node* node); +extern void printAllocations(void); #endif \ No newline at end of file diff --git a/main.c b/main.c index 825271d..f982514 100644 --- a/main.c +++ b/main.c @@ -8,28 +8,27 @@ #include "./heap.h" #include "./linked_list.h" -int run_cycle(void); -int read_integer(char* command); +int run(void); +int readInteger(char* command); int main() { - InitializeAllocators(); + initialize(); int result = 0; while(result != -1) { - result = run_cycle(); + result = run(); printf("Printing linked list: \n"); - print_linked_list(&list); + printLinkedList(&list); printf("Printing allocations: \n"); - - print_allocations(); + printAllocations(); } } -int run_cycle(void) +int run(void) { printf("\n\n\nChoose one of the options below: \n"); printf("[c] to clear the screen\n"); @@ -48,7 +47,7 @@ int run_cycle(void) else if(command[0] == 'a') { system("clear"); - int num = read_integer(command); + int num = readInteger(command); printf("Requested to allocate memory of %d bytes \n", num); @@ -64,7 +63,7 @@ int run_cycle(void) else if(command[0] == 'd') { system("clear"); - int num = read_integer(command); + int num = readInteger(command); printf("Requested to free node with allocation index %d \n", num); @@ -80,7 +79,7 @@ int run_cycle(void) return 0; } -int read_integer(char* command) +int readInteger(char* command) { int result = 0; From e7f5b2376722ebd8a6b43b7e4926968f8f208695 Mon Sep 17 00:00:00 2001 From: memoz1981 Date: Fri, 5 Apr 2024 14:23:02 +0400 Subject: [PATCH 12/18] Drafted merging logic - need to fix bugs --- heap_using_linked_lists.c | 64 +++++++++++++++++++++++++++++++++------ linked_list.h | 3 +- 2 files changed, 56 insertions(+), 11 deletions(-) diff --git a/heap_using_linked_lists.c b/heap_using_linked_lists.c index 2404467..0461845 100644 --- a/heap_using_linked_lists.c +++ b/heap_using_linked_lists.c @@ -121,13 +121,22 @@ void heap_free(void *ptr) if(node == NULL) { - printf("Provided pointer is not valid. "); + printf("Provided pointer is not valid. \n"); return; } - deAllocateNode(node); + if(deAllocateNode(node) == false) + { + return; + } - //to-do --- combine with adjacent nodes...then can return node to the array... + //check previous node - if both are free -> can be combined (to prevent de-fragmentation) + bool mergedWithPrevious = tryDeFragment(node->previous, node); + + if(mergedWithPrevious) + tryDeFragment(node->previous, node->next); + else + tryDeFragment(node, node->next); } void heap_collect() {} //at this stage this will not be implemented, not that necessary. @@ -249,24 +258,29 @@ Node* allocateNode(void) return NULL; } -void deAllocateNode(Node* node) +bool deAllocateNode(Node* node) { int array_size = sizeof(node_alloc)/sizeof(node_alloc[0]); - assert(node != NULL - && node->allocated_index >= 0 - && node->allocated_index < array_size); + if(node->allocated_index < 0 || node->allocated_index >= array_size) + { + printf("Index out of bounds... "); + return false; + } if(node->is_allocated == false || mem_alloc[node->allocated_index] == 0) { printf("Invalid selection, node is not allocated. "); - return; + return false; } - list.count_allocated--; - list.count_de_allocated++; mem_alloc[node->allocated_index] = 0; node->is_allocated = false; + + list.count_allocated--; + list.count_de_allocated++; + + return true; } void printAllocations(void) @@ -285,4 +299,34 @@ void printAllocations(void) printNode(&node_alloc[i]); } printf("\n"); +} + +bool tryDeFragment(Node* prev, Node* current) +{ + if(prev == NULL || current == NULL || prev->is_allocated == true + || current->is_allocated == true) + return false; + + int diff = (int)(current->start - prev->start); + + if(diff != (int)prev->size_in_words) + return false; + + //we are ready to merge the nodes. + + //1. move node to previous + prev->next = current->next; + prev->size_in_words += current->size_in_words; + + //2. return node to array + current->next = NULL; + current->previous = NULL; + current->size_in_words = 0; + current->start = NULL; + mem_alloc[current->allocated_index] = 0; + + list.count_total--; + list.count_de_allocated--; + + return true; } \ No newline at end of file diff --git a/linked_list.h b/linked_list.h index f375147..7e7b63c 100644 --- a/linked_list.h +++ b/linked_list.h @@ -45,7 +45,8 @@ extern int mem_alloc[MAX_NUMBER_OF_NODES]; extern Node node_alloc[MAX_NUMBER_OF_NODES]; extern void initialize(void); extern Node* allocateNode(void); -extern void deAllocateNode(Node* node); +extern bool deAllocateNode(Node* node); extern void printAllocations(void); +extern bool tryDeFragment(Node* prev, Node* current); //returns 0 if success. #endif \ No newline at end of file From d7b6fd7895755ca1b9fa3f16dd800a1fcb98afb0 Mon Sep 17 00:00:00 2001 From: memoz1981 Date: Fri, 5 Apr 2024 15:43:57 +0400 Subject: [PATCH 13/18] Allocation and de-allocation working --- heap_using_linked_lists.c | 81 +++++++++++++++++++++++++++++++++------ 1 file changed, 70 insertions(+), 11 deletions(-) diff --git a/heap_using_linked_lists.c b/heap_using_linked_lists.c index 0461845..c782281 100644 --- a/heap_using_linked_lists.c +++ b/heap_using_linked_lists.c @@ -72,6 +72,8 @@ void *heap_alloc(size_t size_bytes) { printf("Node size %d is same as requested %d\n", (int)node->size_in_words, (int)size_in_words); node->is_allocated = true; + list.count_allocated++; + list.count_de_allocated--; return node; } @@ -92,11 +94,15 @@ void *heap_alloc(size_t size_bytes) printf("\n"); emptyNode->is_allocated = true; + emptyNode->next = node->next; emptyNode->previous = node; emptyNode->size_in_words = size_in_words; emptyNode->start = node->start + (node->size_in_words - size_in_words); + if(emptyNode->next != NULL) + emptyNode->next->previous = emptyNode; + node->size_in_words = node->size_in_words - size_in_words; node->next = emptyNode; list.count_allocated++; @@ -127,16 +133,28 @@ void heap_free(void *ptr) if(deAllocateNode(node) == false) { + printf("Failed to de-allocate the node\n"); return; } + printf("De-allocating node:\n"); + printNode(node); + printf("Previous: \n"); + printNode(node->previous); + printf("Next node: \n"); + printNode(node->next); + printf("\n"); + //check previous node - if both are free -> can be combined (to prevent de-fragmentation) - bool mergedWithPrevious = tryDeFragment(node->previous, node); + Node* prev = node->previous; + Node* next = node->next; + + bool mergedWithPrevious = tryDeFragment(prev, node); if(mergedWithPrevious) - tryDeFragment(node->previous, node->next); + tryDeFragment(prev, next); else - tryDeFragment(node, node->next); + tryDeFragment(node, next); } void heap_collect() {} //at this stage this will not be implemented, not that necessary. @@ -160,16 +178,25 @@ Node* findNode(SortedLinkedList* list, size_t size_in_words) void printNode(Node* node) { if(node == NULL) + { printf("NULL"); - - Node* node_address = node; - int node_address_offset = (int)(node_address - &node_alloc[0]); + return; + } + int start_offset = (int)(node->start - heap); + + int prevIndex = -1; + int nextIndex = -1; + + if(node->previous != NULL) + prevIndex = node->previous->allocated_index; + + if(node->next != NULL) + nextIndex = node->next->allocated_index; - printf("{start:%p, size_in_words: %d, allocated_index: %d, is_allocated: %d, node_address: %p, node_address_offset: %d, start_offset: %d}", - (void*)node->start, (int)node->size_in_words, node->allocated_index, node->is_allocated, - (void*)node_address, node_address_offset, start_offset); + printf("{start:%d, size_in_words: %d, allocated_index: %d, is_allocated: %d, prevIndex: %d, nextIndex: %d}", + start_offset, (int)node->size_in_words, node->allocated_index, node->is_allocated, prevIndex, nextIndex); } void printLinkedList(SortedLinkedList* list) @@ -303,14 +330,40 @@ void printAllocations(void) bool tryDeFragment(Node* prev, Node* current) { - if(prev == NULL || current == NULL || prev->is_allocated == true - || current->is_allocated == true) + //validations + if(prev == NULL || current == NULL) + { + printf("\nCannot merge NULL nodes...\n"); return false; + } + + if(prev->is_allocated == true || current->is_allocated == true) + { + printf("\nOne of the nodes is allocated - cannot merge. prev allocated = %d, current allocated = %d\n", + prev->is_allocated, current->is_allocated); + return false; + } + + if(prev->allocated_index != current->previous->allocated_index || + current->allocated_index != prev->next->allocated_index) + { + printf("\nNodes are not consequental: "); + printf("\nPrevious: "); + printNode(prev); + printf("\nCurrent: "); + printNode(current); + printf("\n"); + } + + printf("Requested to merge nodes %d and %d", prev->allocated_index, current->allocated_index); int diff = (int)(current->start - prev->start); if(diff != (int)prev->size_in_words) + { + printf("diff is %d, prev size is : %d", diff, (int)prev->size_in_words); return false; + } //we are ready to merge the nodes. @@ -325,8 +378,14 @@ bool tryDeFragment(Node* prev, Node* current) current->start = NULL; mem_alloc[current->allocated_index] = 0; + //3. if next node is not NULL -> need to update the previous flag. + if(prev->next != NULL) + prev->next->previous = prev; + list.count_total--; list.count_de_allocated--; + printf("De fragnment successful"); + return true; } \ No newline at end of file From dfd6b9ef0f8c61a59bd1101498879e695cc3a2fb Mon Sep 17 00:00:00 2001 From: memoz1981 Date: Sat, 6 Apr 2024 08:40:57 +0400 Subject: [PATCH 14/18] Added logger struct and functions - not fully implemented yet --- Makefile | 4 ++-- heap_using_linked_lists.c | 7 +++++-- linked_list.h | 3 ++- logger.c | 37 ++++++++++++++++++++++++++----------- logger.h | 5 ++++- main.c | 10 ++++++---- 6 files changed, 45 insertions(+), 21 deletions(-) diff --git a/Makefile b/Makefile index 846b45c..d4c97b1 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ CFLAGS=-Wall -Wextra -Werror -std=c11 -pedantic -ggdb -heap: main.c heap_using_linked_lists.c heap.h - $(CC) $(CFLAGS) -o heap main.c heap_using_linked_lists.c +heap: main.c heap_using_linked_lists.c heap.h logger.c logger.h + $(CC) $(CFLAGS) -o heap main.c heap_using_linked_lists.c logger.c diff --git a/heap_using_linked_lists.c b/heap_using_linked_lists.c index c782281..5953587 100644 --- a/heap_using_linked_lists.c +++ b/heap_using_linked_lists.c @@ -5,6 +5,7 @@ #include "./linked_list.h" #include #include "logger.h" +#include uintptr_t heap[HEAP_CAP_WORDS] = {0}; Node* initializeHeadNode(void); @@ -41,7 +42,8 @@ void *heap_alloc(size_t size_bytes) //Validation 1 - size should be greater than zero if(size_bytes <= 0) { - printf("\nInvalid request, size should be greater than or equal to zero.\n"); + logToConsole(Information, "Invalid request, size should be greater than or equal to zero.\n"); + return NULL; } @@ -250,7 +252,7 @@ Node node_alloc[MAX_NUMBER_OF_NODES] = } }; -void initialize(void) +void initialize(enum LogLevel minimumLogLevel) { int array_size = sizeof(node_alloc)/sizeof(node_alloc[0]); for(int i = 0; i < array_size; i++) @@ -260,6 +262,7 @@ void initialize(void) list.head = initializeHeadNode(); list.count_total++; list.count_de_allocated++; + setMinimumLogLevel(minimumLogLevel); } Node* initializeHeadNode(void) diff --git a/linked_list.h b/linked_list.h index 7e7b63c..4d4eba4 100644 --- a/linked_list.h +++ b/linked_list.h @@ -12,6 +12,7 @@ a start offset for the memory location and size of the memory (could be in bytes #include #include +#include "logger.h" /*-------------------------LINKED LIST DECLARATION AND FUNCTIONS-------------------------------*/ @@ -43,7 +44,7 @@ Node* findNodeByPointer(SortedLinkedList* list, void* ptr); extern SortedLinkedList list; extern int mem_alloc[MAX_NUMBER_OF_NODES]; extern Node node_alloc[MAX_NUMBER_OF_NODES]; -extern void initialize(void); +void initialize(enum LogLevel minimumLogLevel); extern Node* allocateNode(void); extern bool deAllocateNode(Node* node); extern void printAllocations(void); diff --git a/logger.c b/logger.c index 18a4bd6..fadfc31 100644 --- a/logger.c +++ b/logger.c @@ -1,35 +1,50 @@ #include #include "logger.h" #include +#include -void log_level(char* message, enum LogLevel level) +enum LogLevel minimumLogLevel = Debug; + +void setMinimumLogLevel(enum LogLevel logLevel) { - int length = strlen(message) + 20; - char* output = (char*)malloc(length * sizeof(char)); - memset(output, 0, length); + minimumLogLevel = logLevel; +} +void logToConsole(enum LogLevel level, const char *format, ...) +{ + if((int)level < (int)minimumLogLevel) + return; + + va_list argptr; + va_start(argptr, format); + + int size = strlen(format) + 20; + char formatNew[size]; + memset(formatNew, '\0', size); + strcat(formatNew, "\0"); switch(level) { case Debug: - strcat(output, "Debug: "); + strcat(formatNew, "Debug: "); break; case Information: - strcat(output, "Information: "); + strcat(formatNew, "Information: "); break; case Warning: - strcat(output, "Warning: "); + strcat(formatNew, "Warning: "); break; case Error: - strcat(output, "Error: "); + strcat(formatNew, "Error: "); break; default: break; } + strcat(formatNew, format); + strcat(formatNew, "\0"); - strcat(output, message); - - puts(output); + vfprintf(stdout, formatNew, argptr); + va_end(argptr); } \ No newline at end of file diff --git a/logger.h b/logger.h index d902c1c..602ebd6 100644 --- a/logger.h +++ b/logger.h @@ -1,8 +1,11 @@ #ifndef LOGGER_H_ #define LOGGER_H_ +#include enum LogLevel { Debug, Information, Warning, Error}; -void log_level(char* message, enum LogLevel level); +void setMinimumLogLevel(enum LogLevel logLevel); + +void logToConsole(enum LogLevel level, const char *format, ...); #endif diff --git a/main.c b/main.c index f982514..9106c62 100644 --- a/main.c +++ b/main.c @@ -7,23 +7,25 @@ #include "./heap.h" #include "./linked_list.h" +#include "logger.h" + +#define MIN_LOG_LEVEL Information int run(void); int readInteger(char* command); int main() { - initialize(); + initialize(MIN_LOG_LEVEL); int result = 0; while(result != -1) { result = run(); - printf("Printing linked list: \n"); + logToConsole(Information, "Printing linked list: "); printLinkedList(&list); - printf("Printing allocations: \n"); - printAllocations(); + logToConsole(Information, "Printing allocations: "); } } From fb64a0b4d307d4c70ddd0cd7fc54d205d3b4c20f Mon Sep 17 00:00:00 2001 From: memoz1981 Date: Sat, 6 Apr 2024 08:48:46 +0400 Subject: [PATCH 15/18] Implemented logger in a very ugly way --- heap_using_linked_lists.c | 35 ++++++++++++++++------------------- logger.c | 2 +- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/heap_using_linked_lists.c b/heap_using_linked_lists.c index 5953587..c992cf9 100644 --- a/heap_using_linked_lists.c +++ b/heap_using_linked_lists.c @@ -50,7 +50,7 @@ void *heap_alloc(size_t size_bytes) //Validation 2 - we shouldn't have more than Max if(list.count_allocated >= MAX_CONCURRENT_ALLOCATIONS) { - printf("Currently there are %d allocations - we cannot have more than that\n", list.count_allocated); + logToConsole(Warning, "Currently there are %d allocations - we cannot have more than that\n", list.count_allocated); return NULL; } @@ -61,18 +61,17 @@ void *heap_alloc(size_t size_bytes) //Validation 3 - check if any node could be allocated if(node == NULL) { - printf("Memory with requested size doesn't exit.\n"); + logToConsole(Error, "Memory with requested size doesn't exit.\n"); return NULL; } - printf("Found memory in node below: \n"); + logToConsole(Debug, "Found memory in node below: \n"); printNode(node); - printf("\n"); //check for exast match if(node->size_in_words == size_in_words) { - printf("Node size %d is same as requested %d\n", (int)node->size_in_words, (int)size_in_words); + logToConsole(Debug, "Node size %d is same as requested %d\n", (int)node->size_in_words, (int)size_in_words); node->is_allocated = true; list.count_allocated++; list.count_de_allocated--; @@ -87,13 +86,12 @@ void *heap_alloc(size_t size_bytes) if(emptyNode == NULL) { - printf("Error during memory allocation"); + logToConsole(Error, "Error during memory allocation"); return NULL; } - printf("Will use following node to accommodate new allocation: \n"); + logToConsole(Debug, "Will use following node to accommodate new allocation: \n"); printNode(emptyNode); - printf("\n"); emptyNode->is_allocated = true; @@ -129,23 +127,22 @@ void heap_free(void *ptr) if(node == NULL) { - printf("Provided pointer is not valid. \n"); + logToConsole(Error, "Provided pointer is not valid. \n"); return; } if(deAllocateNode(node) == false) { - printf("Failed to de-allocate the node\n"); + logToConsole(Error, "Failed to de-allocate the node\n"); return; } - printf("De-allocating node:\n"); + logToConsole(Debug, "De-allocating node:\n"); printNode(node); - printf("Previous: \n"); + logToConsole(Debug, "Previous: \n"); printNode(node->previous); - printf("Next node: \n"); + logToConsole(Debug, "Next node: \n"); printNode(node->next); - printf("\n"); //check previous node - if both are free -> can be combined (to prevent de-fragmentation) Node* prev = node->previous; @@ -336,13 +333,13 @@ bool tryDeFragment(Node* prev, Node* current) //validations if(prev == NULL || current == NULL) { - printf("\nCannot merge NULL nodes...\n"); + logToConsole(Information, "\nCannot merge NULL nodes...\n"); return false; } if(prev->is_allocated == true || current->is_allocated == true) { - printf("\nOne of the nodes is allocated - cannot merge. prev allocated = %d, current allocated = %d\n", + logToConsole(Information, "\nOne of the nodes is allocated - cannot merge. prev allocated = %d, current allocated = %d\n", prev->is_allocated, current->is_allocated); return false; } @@ -350,7 +347,7 @@ bool tryDeFragment(Node* prev, Node* current) if(prev->allocated_index != current->previous->allocated_index || current->allocated_index != prev->next->allocated_index) { - printf("\nNodes are not consequental: "); + logToConsole(Warning, "\nNodes are not consequental: "); printf("\nPrevious: "); printNode(prev); printf("\nCurrent: "); @@ -364,7 +361,7 @@ bool tryDeFragment(Node* prev, Node* current) if(diff != (int)prev->size_in_words) { - printf("diff is %d, prev size is : %d", diff, (int)prev->size_in_words); + logToConsole(Warning, "diff is %d, prev size is : %d", diff, (int)prev->size_in_words); return false; } @@ -388,7 +385,7 @@ bool tryDeFragment(Node* prev, Node* current) list.count_total--; list.count_de_allocated--; - printf("De fragnment successful"); + logToConsole(Debug, "De fragnment successful"); return true; } \ No newline at end of file diff --git a/logger.c b/logger.c index fadfc31..53de018 100644 --- a/logger.c +++ b/logger.c @@ -21,7 +21,7 @@ void logToConsole(enum LogLevel level, const char *format, ...) int size = strlen(format) + 20; char formatNew[size]; memset(formatNew, '\0', size); - strcat(formatNew, "\0"); + strcat(formatNew, "\n"); switch(level) { case Debug: strcat(formatNew, "Debug: "); From 3bdfa4a09cdd05c028821f949c9a9106854ac52d Mon Sep 17 00:00:00 2001 From: memoz1981 Date: Sat, 6 Apr 2024 08:59:49 +0400 Subject: [PATCH 16/18] Restored changes to a file --- heap_using_chunk_lists.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/heap_using_chunk_lists.c b/heap_using_chunk_lists.c index 93da7f6..e42c724 100644 --- a/heap_using_chunk_lists.c +++ b/heap_using_chunk_lists.c @@ -1,8 +1,9 @@ + #include #include #include -#include "./heap.h" -#include "./chunk_lists.h" +#include "heap.h" +#include "chunk_lists.h" uintptr_t heap[HEAP_CAP_WORDS] = {0}; const uintptr_t *stack_base = 0; @@ -90,7 +91,6 @@ void chunk_list_remove(Chunk_List *list, size_t index) void *heap_alloc(size_t size_bytes) { - printf("Received request to allocate size in bytes %d", (int)size_bytes); const size_t size_words = (size_bytes + sizeof(uintptr_t) - 1) / sizeof(uintptr_t); if (size_words > 0) { @@ -148,8 +148,9 @@ static void mark_region(const uintptr_t *start, const uintptr_t *end) void heap_collect() { - const uintptr_t *stack_start = (coNode* Get(LinkedList* list, size_t size); -Node* se + 1); + const uintptr_t *stack_start = (const uintptr_t*)__builtin_frame_address(0); + memset(reachable_chunks, 0, sizeof(reachable_chunks)); + mark_region(stack_start, stack_base + 1); to_free_count = 0; for (size_t i = 0; i < alloced_chunks.count; ++i) { From 312e7c4eb21ece32f3c506c54d02828f7068ae25 Mon Sep 17 00:00:00 2001 From: memoz1981 Date: Sat, 6 Apr 2024 09:09:32 +0400 Subject: [PATCH 17/18] Tried to fully de-couple 2 implementations --- heap.h | 1 + heap_using_chunk_lists.c | 83 ++++++++++++++++++++++++++++++++++ heap_using_linked_lists.c | 89 ++++++++++++++++++++++++++++++++++++- main.c | 93 +-------------------------------------- 4 files changed, 174 insertions(+), 92 deletions(-) diff --git a/heap.h b/heap.h index 70ea9d2..daba9fe 100644 --- a/heap.h +++ b/heap.h @@ -17,5 +17,6 @@ extern const uintptr_t *stack_base; void *heap_alloc(size_t size_bytes); void heap_free(void *ptr); void heap_collect(); +void run_tests(void); #endif // HEAP_H_ \ No newline at end of file diff --git a/heap_using_chunk_lists.c b/heap_using_chunk_lists.c index e42c724..32a3812 100644 --- a/heap_using_chunk_lists.c +++ b/heap_using_chunk_lists.c @@ -164,3 +164,86 @@ void heap_collect() heap_free(to_free[i]); } } + +/*-------------------------MAIN FUNCTION IMPLEMENTATION-------------------------------*/ + +#define JIM_IMPLEMENTATION +#include "jim.h" + +typedef struct Node Node; + +struct Node { + char x; + Node *left; + Node *right; +}; + +Node *generate_tree(size_t level_cur, size_t level_max) +{ + if (level_cur < level_max) { + Node *root = heap_alloc(sizeof(*root)); + assert((char) level_cur - 'a' <= 'z'); + root->x = level_cur + 'a'; + root->left = generate_tree(level_cur + 1, level_max); + root->right = generate_tree(level_cur + 1, level_max); + return root; + } else { + return NULL; + } +} + +void print_tree(Node *root, Jim *jim) +{ + if (root != NULL) { + jim_object_begin(jim); + + jim_member_key(jim, "value"); + jim_string_sized(jim, &root->x, 1); + + jim_member_key(jim, "left"); + print_tree(root->left, jim); + + jim_member_key(jim, "right"); + print_tree(root->right, jim); + + jim_object_end(jim); + } else { + jim_null(jim); + } +} + +#define N 10 + +void *ptrs[N] = {0}; + +void run_tests(void) +{ + stack_base = (const uintptr_t*)__builtin_frame_address(0); + + for (size_t i = 0; i < 10; ++i) { + heap_alloc(i); + } + + Node *root = generate_tree(0, 3); + + printf("root: %p\n", (void*)root); + + Jim jim = { + .sink = stdout, + .write = (Jim_Write) fwrite, + }; + + print_tree(root, &jim); + + printf("\n------------------------------\n"); + heap_collect(); + chunk_list_dump(&alloced_chunks, "Alloced"); + chunk_list_dump(&freed_chunks, "Freed"); + printf("------------------------------\n"); + root = NULL; + heap_collect(); + chunk_list_dump(&alloced_chunks, "Alloced"); + chunk_list_dump(&freed_chunks, "Freed"); + + return 0; +} diff --git a/heap_using_linked_lists.c b/heap_using_linked_lists.c index c992cf9..86a9ce3 100644 --- a/heap_using_linked_lists.c +++ b/heap_using_linked_lists.c @@ -388,4 +388,91 @@ bool tryDeFragment(Node* prev, Node* current) logToConsole(Debug, "De fragnment successful"); return true; -} \ No newline at end of file +} + +/*-------------------------MAIN FUNCTION IMPLEMENTATION-------------------------------*/ + +#define MIN_LOG_LEVEL Information + +int run(void); +int readInteger(char* command); + +void run_tests(void) +{ + initialize(MIN_LOG_LEVEL); + + int result = 0; + + while(result != -1) + { + result = run(); + logToConsole(Information, "Printing linked list: "); + printLinkedList(&list); + logToConsole(Information, "Printing allocations: "); + } + +} + +int run(void) +{ + printf("\n\n\nChoose one of the options below: \n"); + printf("[c] to clear the screen\n"); + printf("[a]_[size_in_bytes] to allocate...(a_10 will allocate 10 bytes)\n"); + printf("[d]_[index] to de-allocate...(d_0 will de-allocate 0th index)\n"); + printf("[e] to exit\n\n\n"); + + char command[20]; + memset(command, '\0', 20); + scanf("%s", command); + + if(strcmp("e", command) == 0) + return -1; + else if(strcmp("c", command) == 0) + system("clear"); + else if(command[0] == 'a') + { + system("clear"); + int num = readInteger(command); + + printf("Requested to allocate memory of %d bytes \n", num); + + void * pointer = heap_alloc(num); + if(pointer == NULL) + { + printf("Memory could not be allocated...\n"); + return 0; + } + + return 0; + } + else if(command[0] == 'd') + { + system("clear"); + int num = readInteger(command); + + printf("Requested to free node with allocation index %d \n", num); + + heap_free((void*)node_alloc[num].start); + + return 0; + } + else + { + printf("Entered command %s is invalid", command); + } + + return 0; +} + +int readInteger(char* command) +{ + int result = 0; + + for(int i =0; i<= (int)strlen(command); i++) + { + if(command[i] >=48 && command[i] <= 57) + result = result *10 + command[i] - 48; + } + + return result; +} diff --git a/main.c b/main.c index 9106c62..49052e8 100644 --- a/main.c +++ b/main.c @@ -1,95 +1,6 @@ -#include -#include -#include -#include -#include -#include - #include "./heap.h" -#include "./linked_list.h" -#include "logger.h" - -#define MIN_LOG_LEVEL Information - -int run(void); -int readInteger(char* command); -int main() +int main(void) { - initialize(MIN_LOG_LEVEL); - - int result = 0; - - while(result != -1) - { - result = run(); - logToConsole(Information, "Printing linked list: "); - printLinkedList(&list); - logToConsole(Information, "Printing allocations: "); - } - -} - -int run(void) -{ - printf("\n\n\nChoose one of the options below: \n"); - printf("[c] to clear the screen\n"); - printf("[a]_[size_in_bytes] to allocate...(a_10 will allocate 10 bytes)\n"); - printf("[d]_[index] to de-allocate...(d_0 will de-allocate 0th index)\n"); - printf("[e] to exit\n\n\n"); - - char command[20]; - memset(command, '\0', 20); - scanf("%s", command); - - if(strcmp("e", command) == 0) - return -1; - else if(strcmp("c", command) == 0) - system("clear"); - else if(command[0] == 'a') - { - system("clear"); - int num = readInteger(command); - - printf("Requested to allocate memory of %d bytes \n", num); - - void * pointer = heap_alloc(num); - if(pointer == NULL) - { - printf("Memory could not be allocated...\n"); - return 0; - } - - return 0; - } - else if(command[0] == 'd') - { - system("clear"); - int num = readInteger(command); - - printf("Requested to free node with allocation index %d \n", num); - - heap_free((void*)node_alloc[num].start); - - return 0; - } - else - { - printf("Entered command %s is invalid", command); - } - - return 0; -} - -int readInteger(char* command) -{ - int result = 0; - - for(int i =0; i<= (int)strlen(command); i++) - { - if(command[i] >=48 && command[i] <= 57) - result = result *10 + command[i] - 48; - } - - return result; + run_tests(); } From f14f8a68e77afc6144c65b60042abfab4e836371 Mon Sep 17 00:00:00 2001 From: memoz1981 Date: Sat, 6 Apr 2024 09:18:53 +0400 Subject: [PATCH 18/18] Updated makefile to dynamically run one or other implementation --- Makefile | 16 +++++++++++++++- README.md | 13 ++++++++----- heap_using_chunk_lists.c | 2 -- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index d4c97b1..3ff3568 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,18 @@ CFLAGS=-Wall -Wextra -Werror -std=c11 -pedantic -ggdb -heap: main.c heap_using_linked_lists.c heap.h logger.c logger.h +# Default target +all: clean heap + +# Target for building heap with heap1.c +chunk: main.c heap_using_chunk_lists.c heap.h chunk_lists.h + $(CC) $(CFLAGS) -o heap main.c heap_using_chunk_lists.c logger.c + +# Target for building heap with heap2.c +linkedlist: main.c heap_using_linked_lists.c heap.h logger.c logger.h linked_list.h $(CC) $(CFLAGS) -o heap main.c heap_using_linked_lists.c logger.c + +# Target for cleaning up +clean: + rm -f heap + +.PHONY: all heap1 heap2 clean diff --git a/README.md b/README.md index d7ad6bc..b6f0fda 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,15 @@ ## Quick Start +### To run original implementation ```console -$ make +$ make chunk +$ ./heap +``` + +### Alternative Implementation +```console +$ make linkedlist $ ./heap ``` @@ -16,7 +23,3 @@ $ ./heap - No tricks that obscure the pointers (like XOR Linked Lists). - Probably works only on x86_64 - Probably works only when compiled with GCC - -## Linked List Implementation - -1) diff --git a/heap_using_chunk_lists.c b/heap_using_chunk_lists.c index 32a3812..45c7803 100644 --- a/heap_using_chunk_lists.c +++ b/heap_using_chunk_lists.c @@ -244,6 +244,4 @@ void run_tests(void) heap_collect(); chunk_list_dump(&alloced_chunks, "Alloced"); chunk_list_dump(&freed_chunks, "Freed"); - - return 0; }