From 1517046258dccfe5c37596388d097e6d44efcf81 Mon Sep 17 00:00:00 2001 From: karutoh Date: Thu, 8 Feb 2024 01:44:09 -0800 Subject: [PATCH 01/10] Implemented malloc and free. Needs reverse chunking, and fragmenting implemented. --- main.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 98 insertions(+), 3 deletions(-) diff --git a/main.c b/main.c index eaddc08..b15c67f 100644 --- a/main.c +++ b/main.c @@ -1,15 +1,110 @@ #include +#include +#include -void* malloc(unsigned long size) +#define ALIGN4(s) (((((s)-1)>>2)<<2)+4) +#define BLOCK_SIZE sizeof(struct block) + +struct block { - return NULL; + size_t size; + struct block* next; + int free; +}; + +struct block* freeList = NULL; + +struct block* extend_heap(struct block* last, size_t s) +{ + struct block* b = sbrk(0); + + if (sbrk(BLOCK_SIZE + s) == (void*)-1) + return NULL; + + b->size = s; + b->next = NULL; + b->free = 0; + + if (last) + last->next = b; + + return b; +} + +struct block* find_first(size_t s) +{ + struct block* current = freeList; + while (current && (!current->free || current->size < s)) + current = current->next; + + return current; +} + +struct block* find_last() +{ + struct block* current = freeList; + while (current && current->next) + current = freeList->next; + + return current; +} + +void* malloc(size_t size) +{ + struct block* b; + + size_t alignedSize = ALIGN4(size); + + if (freeList) + { + b = find_first(alignedSize); + if (!b) + b = extend_heap(find_last(), alignedSize); + } + else + { + b = extend_heap(NULL, alignedSize); + if (!b) + return NULL; + + freeList = b; + } + + return (char*)b + BLOCK_SIZE; } void free(void* ptr) { + if (!ptr) + return; + + struct block* b = (struct block*)((char*)ptr - BLOCK_SIZE); + b->free = 1; + + struct block* link = b->next; + while (b->next && b->next->free) + { + b->size += BLOCK_SIZE + b->next->size; + b->next = link->next; + } + + if (!b->next) + brk(b); } -int main(void) +int main() { + int* a = (int*)malloc(sizeof(int)); + int* b = (int*)malloc(sizeof(int)); + + *a = 5; + *b = 12; + + printf("Test 1: %i\n", *a); + printf("Test 2: %i", *b); + + free(b); + free(a); + return 0; } \ No newline at end of file From a9fcd9102fba973e4df84b0943e5a564cb31d682 Mon Sep 17 00:00:00 2001 From: karutoh Date: Thu, 8 Feb 2024 02:00:57 -0800 Subject: [PATCH 02/10] Added documentation. --- main.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/main.c b/main.c index b15c67f..8951147 100644 --- a/main.c +++ b/main.c @@ -5,6 +5,7 @@ #define ALIGN4(s) (((((s)-1)>>2)<<2)+4) #define BLOCK_SIZE sizeof(struct block) +/// The memory's block header. struct block { size_t size; @@ -14,6 +15,10 @@ struct block struct block* freeList = NULL; +/// Extends heap memory upwards, towards zero. +/// @param [in] last The last block that the newly created block will link to. +/// @param [in] s The size of the memory needed aligned by 4 bytes. +/// @returns The new memory block. struct block* extend_heap(struct block* last, size_t s) { struct block* b = sbrk(0); @@ -31,6 +36,9 @@ struct block* extend_heap(struct block* last, size_t s) return b; } +/// Finds the first block that will fit the given size. +/// @param [in] s The 4 byte aligned size to look for. +/// @returns The matching available memory block. struct block* find_first(size_t s) { struct block* current = freeList; @@ -40,6 +48,8 @@ struct block* find_first(size_t s) return current; } +/// Finds the last memory block in the linked list to attach a new block to. +/// @returns The last memory block. struct block* find_last() { struct block* current = freeList; @@ -49,6 +59,10 @@ struct block* find_last() return current; } +/// Will find or allocate a memory block. +/// @param [in] size The size of the memory block to request. +/// @returns The requested memory on the heap. +/// @todo Fragmenting functionality. void* malloc(size_t size) { struct block* b; @@ -60,6 +74,10 @@ void* malloc(size_t size) b = find_first(alignedSize); if (!b) b = extend_heap(find_last(), alignedSize); + /* + else + Fragment here if possible. + */ } else { @@ -73,6 +91,10 @@ void* malloc(size_t size) return (char*)b + BLOCK_SIZE; } +/// Will flag the provided memory as free and will defragment other blocks adjacent to it. +/// @param [in] ptr The memory to flag as free. +/// @note If all data after the provided memory is free, it will reduce the heap size. +/// @todo Reverse defragmenting. void free(void* ptr) { if (!ptr) @@ -88,6 +110,8 @@ void free(void* ptr) b->next = link->next; } + // Reverse defragment here. + if (!b->next) brk(b); } From eaa93effafdd8b927b5ad3b8d7732cb0a7e52528 Mon Sep 17 00:00:00 2001 From: karutoh Date: Thu, 8 Feb 2024 02:05:06 -0800 Subject: [PATCH 03/10] Fixed grammatical error. --- main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.c b/main.c index 8951147..c3eddcc 100644 --- a/main.c +++ b/main.c @@ -5,7 +5,7 @@ #define ALIGN4(s) (((((s)-1)>>2)<<2)+4) #define BLOCK_SIZE sizeof(struct block) -/// The memory's block header. +/// The memory block's header. struct block { size_t size; From f49256d7e7ff5b9393a156ee5e9ec340181bd4ef Mon Sep 17 00:00:00 2001 From: karutoh Date: Thu, 8 Feb 2024 02:07:49 -0800 Subject: [PATCH 04/10] Code optimization. --- main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main.c b/main.c index c3eddcc..65af95b 100644 --- a/main.c +++ b/main.c @@ -88,7 +88,7 @@ void* malloc(size_t size) freeList = b; } - return (char*)b + BLOCK_SIZE; + return (struct block*)b + 1; } /// Will flag the provided memory as free and will defragment other blocks adjacent to it. @@ -100,7 +100,7 @@ void free(void* ptr) if (!ptr) return; - struct block* b = (struct block*)((char*)ptr - BLOCK_SIZE); + struct block* b = (struct block*)ptr - 1; b->free = 1; struct block* link = b->next; From dd07283ffc300a4d5f42c03845ba761b7c3c6aa2 Mon Sep 17 00:00:00 2001 From: karutoh Date: Thu, 8 Feb 2024 02:08:38 -0800 Subject: [PATCH 05/10] Removed unnecessary casts. --- main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main.c b/main.c index 65af95b..60be449 100644 --- a/main.c +++ b/main.c @@ -88,7 +88,7 @@ void* malloc(size_t size) freeList = b; } - return (struct block*)b + 1; + return b + 1; } /// Will flag the provided memory as free and will defragment other blocks adjacent to it. @@ -100,7 +100,7 @@ void free(void* ptr) if (!ptr) return; - struct block* b = (struct block*)ptr - 1; + struct block* b = ptr - 1; b->free = 1; struct block* link = b->next; From 6525d5f2b9fb51bb2650e5af7222c8918e0ee5fc Mon Sep 17 00:00:00 2001 From: karutoh Date: Thu, 8 Feb 2024 02:09:58 -0800 Subject: [PATCH 06/10] Reinstated a necessary cast. --- main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.c b/main.c index 60be449..3821143 100644 --- a/main.c +++ b/main.c @@ -100,7 +100,7 @@ void free(void* ptr) if (!ptr) return; - struct block* b = ptr - 1; + struct block* b = (struct block*)ptr - 1; b->free = 1; struct block* link = b->next; From 3b38eddf5deaceb8948824ddda0b804052533b4e Mon Sep 17 00:00:00 2001 From: karutoh Date: Thu, 8 Feb 2024 16:44:26 -0800 Subject: [PATCH 07/10] Optimized code by adding last block global variable. --- main.c | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/main.c b/main.c index 3821143..c10d2f3 100644 --- a/main.c +++ b/main.c @@ -13,13 +13,13 @@ struct block int free; }; -struct block* freeList = NULL; +struct block* first = NULL; +struct block* last = NULL; /// Extends heap memory upwards, towards zero. -/// @param [in] last The last block that the newly created block will link to. /// @param [in] s The size of the memory needed aligned by 4 bytes. /// @returns The new memory block. -struct block* extend_heap(struct block* last, size_t s) +struct block* extend_heap(size_t s) { struct block* b = sbrk(0); @@ -33,6 +33,8 @@ struct block* extend_heap(struct block* last, size_t s) if (last) last->next = b; + last = b; + return b; } @@ -41,24 +43,13 @@ struct block* extend_heap(struct block* last, size_t s) /// @returns The matching available memory block. struct block* find_first(size_t s) { - struct block* current = freeList; + struct block* current = first; while (current && (!current->free || current->size < s)) current = current->next; return current; } -/// Finds the last memory block in the linked list to attach a new block to. -/// @returns The last memory block. -struct block* find_last() -{ - struct block* current = freeList; - while (current && current->next) - current = freeList->next; - - return current; -} - /// Will find or allocate a memory block. /// @param [in] size The size of the memory block to request. /// @returns The requested memory on the heap. @@ -69,11 +60,13 @@ void* malloc(size_t size) size_t alignedSize = ALIGN4(size); - if (freeList) + if (first) { b = find_first(alignedSize); if (!b) - b = extend_heap(find_last(), alignedSize); + { + b = extend_heap(alignedSize); + } /* else Fragment here if possible. @@ -81,11 +74,11 @@ void* malloc(size_t size) } else { - b = extend_heap(NULL, alignedSize); + b = extend_heap(alignedSize); if (!b) return NULL; - freeList = b; + first = b; } return b + 1; From 14d4e0ee674e0f2df74b7aee311e041f13efb8e3 Mon Sep 17 00:00:00 2001 From: karutoh Date: Thu, 8 Feb 2024 17:04:41 -0800 Subject: [PATCH 08/10] Fixed forward defragmenting, added reverse defragmenting, and added a line break on second printf. --- main.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/main.c b/main.c index c10d2f3..dad4fdb 100644 --- a/main.c +++ b/main.c @@ -9,6 +9,7 @@ struct block { size_t size; + struct block* prev; struct block* next; int free; }; @@ -27,6 +28,7 @@ struct block* extend_heap(size_t s) return NULL; b->size = s; + b->prev = last; b->next = NULL; b->free = 0; @@ -87,7 +89,6 @@ void* malloc(size_t size) /// Will flag the provided memory as free and will defragment other blocks adjacent to it. /// @param [in] ptr The memory to flag as free. /// @note If all data after the provided memory is free, it will reduce the heap size. -/// @todo Reverse defragmenting. void free(void* ptr) { if (!ptr) @@ -96,15 +97,15 @@ void free(void* ptr) struct block* b = (struct block*)ptr - 1; b->free = 1; - struct block* link = b->next; + while (b->prev && b->prev->free) + b = b->prev; + while (b->next && b->next->free) { b->size += BLOCK_SIZE + b->next->size; - b->next = link->next; + b->next = b->next->next; } - // Reverse defragment here. - if (!b->next) brk(b); } @@ -118,10 +119,10 @@ int main() *b = 12; printf("Test 1: %i\n", *a); - printf("Test 2: %i", *b); + printf("Test 2: %i\n", *b); - free(b); free(a); + free(b); return 0; } \ No newline at end of file From 0b25fa434f3b0bd54430345501f409f47b06f59f Mon Sep 17 00:00:00 2001 From: karutoh Date: Thu, 8 Feb 2024 17:24:49 -0800 Subject: [PATCH 09/10] Added memory block fragmenting. --- main.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/main.c b/main.c index dad4fdb..753b5bc 100644 --- a/main.c +++ b/main.c @@ -52,6 +52,21 @@ struct block* find_first(size_t s) return current; } +struct block* fragment_block(struct block* in, size_t s) +{ + size_t totalSize = BLOCK_SIZE + s; + struct block* b = (struct block*)((char*)(in + 1) + (in->size - totalSize)); + b->size = s; + b->prev = in; + b->next = in->next; + b->free = 0; + + in->size -= totalSize; + in->next = b; + + return b; +} + /// Will find or allocate a memory block. /// @param [in] size The size of the memory block to request. /// @returns The requested memory on the heap. @@ -66,13 +81,9 @@ void* malloc(size_t size) { b = find_first(alignedSize); if (!b) - { b = extend_heap(alignedSize); - } - /* - else - Fragment here if possible. - */ + else if (b->size > BLOCK_SIZE + alignedSize) + b = fragment_block(b, alignedSize); } else { @@ -95,6 +106,9 @@ void free(void* ptr) return; struct block* b = (struct block*)ptr - 1; + if (b->free) + return; + b->free = 1; while (b->prev && b->prev->free) @@ -124,5 +138,7 @@ int main() free(a); free(b); + int* c = (int*)malloc(sizeof(int)); + return 0; } \ No newline at end of file From 8b520b4bedda6060a7c1b1a1bd14659241a4d4c3 Mon Sep 17 00:00:00 2001 From: Greg Bowne Date: Thu, 8 Feb 2024 17:34:20 -0800 Subject: [PATCH 10/10] updated malloc and extended heap --- main.c | 70 ++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 29 deletions(-) diff --git a/main.c b/main.c index 753b5bc..adecd3a 100644 --- a/main.c +++ b/main.c @@ -4,6 +4,7 @@ #define ALIGN4(s) (((((s)-1)>>2)<<2)+4) #define BLOCK_SIZE sizeof(struct block) +#define MINIMUM_BLOCK_SIZE 16 /// The memory block's header. struct block @@ -22,22 +23,27 @@ struct block* last = NULL; /// @returns The new memory block. struct block* extend_heap(size_t s) { - struct block* b = sbrk(0); + struct block* b = sbrk(0); - if (sbrk(BLOCK_SIZE + s) == (void*)-1) - return NULL; + // Ensure the allocated size is at least the minimum block size + if (s < MINIMUM_BLOCK_SIZE) { + s = MINIMUM_BLOCK_SIZE; + } - b->size = s; - b->prev = last; - b->next = NULL; - b->free = 0; + if (sbrk(BLOCK_SIZE + s) == (void*)-1) + return NULL; - if (last) - last->next = b; + b->size = s; + b->prev = last; + b->next = NULL; + b->free = 0; - last = b; + if (last) + last->next = b; - return b; + last = b; + + return b; } /// Finds the first block that will fit the given size. @@ -73,30 +79,36 @@ struct block* fragment_block(struct block* in, size_t s) /// @todo Fragmenting functionality. void* malloc(size_t size) { - struct block* b; + struct block* b; - size_t alignedSize = ALIGN4(size); + size_t alignedSize = ALIGN4(size); - if (first) - { - b = find_first(alignedSize); - if (!b) - b = extend_heap(alignedSize); - else if (b->size > BLOCK_SIZE + alignedSize) - b = fragment_block(b, alignedSize); - } - else - { - b = extend_heap(alignedSize); - if (!b) - return NULL; + // Enforce the minimum block size + if (alignedSize < MINIMUM_BLOCK_SIZE) { + alignedSize = MINIMUM_BLOCK_SIZE; + } - first = b; - } + if (first) + { + b = find_first(alignedSize); + if (!b) + b = extend_heap(alignedSize); + else if (b->size > BLOCK_SIZE + alignedSize) + b = fragment_block(b, alignedSize); + } + else + { + b = extend_heap(alignedSize); + if (!b) + return NULL; - return b + 1; + first = b; + } + + return b + 1; } + /// Will flag the provided memory as free and will defragment other blocks adjacent to it. /// @param [in] ptr The memory to flag as free. /// @note If all data after the provided memory is free, it will reduce the heap size.