From c48200cd526704bffbc6888bcf86bb81b2df669d Mon Sep 17 00:00:00 2001 From: Mineplay Date: Fri, 11 Apr 2025 16:03:11 -0500 Subject: [PATCH 1/8] feat(allocator): implemented basic malloc functionality --- Include/Hallocy/Allocator.h | 30 +++++++++++++++++++++++++++ Src/Hallocy/Allocator.c | 41 +++++++++++++++++++++++++++++++++++++ Src/Main.c | 8 +++++++- 3 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 Include/Hallocy/Allocator.h create mode 100644 Src/Hallocy/Allocator.c diff --git a/Include/Hallocy/Allocator.h b/Include/Hallocy/Allocator.h new file mode 100644 index 0000000..80d6249 --- /dev/null +++ b/Include/Hallocy/Allocator.h @@ -0,0 +1,30 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ----------------------------------------------------------------------------- + * File: Allocator.h + * Description: + * This file contains the functions for allocating, freeing and managing memory. + * It includes functions to allocate, reallocate, free, copy, move and set memory. + * + * Author: Mineplay + * ----------------------------------------------------------------------------- + */ +#ifndef HALLOCY_ALLOCATOR +#define HALLOCY_ALLOCATOR + +#include + +void *hallocy_malloc(size_t size); + +#endif \ No newline at end of file diff --git a/Src/Hallocy/Allocator.c b/Src/Hallocy/Allocator.c new file mode 100644 index 0000000..17bbc6a --- /dev/null +++ b/Src/Hallocy/Allocator.c @@ -0,0 +1,41 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ----------------------------------------------------------------------------- + * File: Allocator.h + * Description: + * This file implements the functions for allocating, freeing and managing memory. + * It includes functions to allocate, reallocate, free, copy, move and set memory. + * + * Author: Mineplay + * ----------------------------------------------------------------------------- + */ +#include "../../Include/Hallocy/Allocator.h" + +#if defined(_WIN32) +#include +#elif defined(__linux__) +#include +#include +#endif + +void *hallocy_malloc(size_t size) { + void *memory_pointer = NULL; + #if defined(_WIN32) + memory_pointer = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + #elif defined(__linux__) + memory_pointer = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + #endif + + return memory_pointer; +} \ No newline at end of file diff --git a/Src/Main.c b/Src/Main.c index 8321e25..e78593e 100644 --- a/Src/Main.c +++ b/Src/Main.c @@ -1,6 +1,12 @@ #include +#include int main() { - printf("Hello, World!\n"); + char *memory = (char *)hallocy_malloc(3); + memory[0] = 'H'; + memory[1] = 'i'; + memory[2] = '\0'; + + printf("%s\n", memory); return 0; } \ No newline at end of file From 776bee499d5ee14527b231b8cde3ecc186692711 Mon Sep 17 00:00:00 2001 From: Mineplay Date: Fri, 11 Apr 2025 16:16:46 -0500 Subject: [PATCH 2/8] perf(allocator): made allocation size align with page size of system --- Src/Hallocy/Allocator.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/Src/Hallocy/Allocator.c b/Src/Hallocy/Allocator.c index 17bbc6a..be9569d 100644 --- a/Src/Hallocy/Allocator.c +++ b/Src/Hallocy/Allocator.c @@ -29,12 +29,26 @@ #include #endif +static size_t page_size = 0; + void *hallocy_malloc(size_t size) { + if (page_size == 0) { + #if defined(_WIN32) + SYSTEM_INFO system_info; + GetSystemInfo(&system_info); + + page_size = system_info.dwPageSize; + #elif defined(__linux__) + page_size = sysconf(_SC_PAGESIZE); + #endif + } + + size_t aligned_size = page_size * ((size / page_size) + 1); void *memory_pointer = NULL; #if defined(_WIN32) - memory_pointer = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + memory_pointer = VirtualAlloc(NULL, aligned_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); #elif defined(__linux__) - memory_pointer = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + memory_pointer = mmap(NULL, aligned_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); #endif return memory_pointer; From 1e653f67c707340e498d34aa6add052748e83913 Mon Sep 17 00:00:00 2001 From: Mineplay Date: Fri, 11 Apr 2025 17:26:35 -0500 Subject: [PATCH 3/8] refactor(allocator): added header to memory blocks --- Src/Hallocy/Allocator.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/Src/Hallocy/Allocator.c b/Src/Hallocy/Allocator.c index be9569d..6d56c05 100644 --- a/Src/Hallocy/Allocator.c +++ b/Src/Hallocy/Allocator.c @@ -29,6 +29,11 @@ #include #endif +typedef struct HallocyMemoryHeader { + size_t size; + struct HallocyMemoryHeader *next; +} HallocyMemoryHeader; + static size_t page_size = 0; void *hallocy_malloc(size_t size) { @@ -43,13 +48,16 @@ void *hallocy_malloc(size_t size) { #endif } - size_t aligned_size = page_size * ((size / page_size) + 1); - void *memory_pointer = NULL; + size_t aligned_size = page_size * (((size + sizeof(HallocyMemoryHeader)) / page_size) + 1); + HallocyMemoryHeader *memory_pointer = NULL; #if defined(_WIN32) - memory_pointer = VirtualAlloc(NULL, aligned_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + memory_pointer = (HallocyMemoryHeader*)VirtualAlloc(NULL, aligned_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); #elif defined(__linux__) - memory_pointer = mmap(NULL, aligned_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + memory_pointer = (HallocyMemoryHeader*)mmap(NULL, aligned_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); #endif - return memory_pointer; + memory_pointer->size = aligned_size; + memory_pointer->next = NULL; + + return (void*)(memory_pointer + 1); } \ No newline at end of file From 3aabf00607c9651905f7c4feb22317997239d417 Mon Sep 17 00:00:00 2001 From: Mineplay Date: Fri, 11 Apr 2025 17:31:15 -0500 Subject: [PATCH 4/8] fix(allocator): added error check to malloc function --- Src/Hallocy/Allocator.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Src/Hallocy/Allocator.c b/Src/Hallocy/Allocator.c index 6d56c05..1f96cb9 100644 --- a/Src/Hallocy/Allocator.c +++ b/Src/Hallocy/Allocator.c @@ -56,6 +56,10 @@ void *hallocy_malloc(size_t size) { memory_pointer = (HallocyMemoryHeader*)mmap(NULL, aligned_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); #endif + if (memory_pointer == NULL) { + return NULL; + } + memory_pointer->size = aligned_size; memory_pointer->next = NULL; From dd10dfd376fd268a0f22ecf8d288ca8c59e2c5c0 Mon Sep 17 00:00:00 2001 From: Mineplay Date: Fri, 11 Apr 2025 18:21:20 -0500 Subject: [PATCH 5/8] feat(allocator): implemented basic free function to free allocated memory --- Include/Hallocy/Allocator.h | 4 +++ Include/Hallocy/Error.h | 34 +++++++++++++++++++++++++ Src/Hallocy/Allocator.c | 50 +++++++++++++++++++++++++++++++++++++ Src/Main.c | 13 +++++++++- 4 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 Include/Hallocy/Error.h diff --git a/Include/Hallocy/Allocator.h b/Include/Hallocy/Allocator.h index 80d6249..a8f0805 100644 --- a/Include/Hallocy/Allocator.h +++ b/Include/Hallocy/Allocator.h @@ -24,7 +24,11 @@ #define HALLOCY_ALLOCATOR #include +#include + +#include "Error.h" void *hallocy_malloc(size_t size); +HallocyError hallocy_free(void *pointer); #endif \ No newline at end of file diff --git a/Include/Hallocy/Error.h b/Include/Hallocy/Error.h new file mode 100644 index 0000000..3e65784 --- /dev/null +++ b/Include/Hallocy/Error.h @@ -0,0 +1,34 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ----------------------------------------------------------------------------- + * File: Error.h + * Description: + * This file contains the ErrorCode enum that defines the error codes for the + * library. + * + * Author: Mineplay + * ----------------------------------------------------------------------------- + */ +#ifndef HALLOCY_ERROR +#define HALLOCY_ERROR + +typedef enum { + HALLOCY_ERROR_NONE = 0, + HALLOCY_ERROR_INVALID_POINTER = 1, + HALLOCY_ERROR_OUT_OF_MEMORY = 2, + HALLOCY_ERROR_UNKNOWN = 3, + HALLOCY_ERROR_INVALID_PARAM = 4 +} HallocyError; + +#endif \ No newline at end of file diff --git a/Src/Hallocy/Allocator.c b/Src/Hallocy/Allocator.c index 1f96cb9..79151e5 100644 --- a/Src/Hallocy/Allocator.c +++ b/Src/Hallocy/Allocator.c @@ -27,6 +27,7 @@ #elif defined(__linux__) #include #include +#include #endif typedef struct HallocyMemoryHeader { @@ -64,4 +65,53 @@ void *hallocy_malloc(size_t size) { memory_pointer->next = NULL; return (void*)(memory_pointer + 1); +} + +HallocyError hallocy_free(void *pointer) { + if (pointer == NULL) { + return HALLOCY_ERROR_INVALID_POINTER; + } + + HallocyMemoryHeader *memory_header = ((HallocyMemoryHeader*)pointer) - 1; + #if defined(_WIN32) + bool result = VirtualFree(memory_header, 0, MEM_RELEASE); + if (result == false) { + DWORD error = GetLastError(); + switch (error) { + case ERROR_INVALID_PARAMETER: + return HALLOCY_ERROR_INVALID_PARAM; + + case ERROR_NOT_ENOUGH_MEMORY: + return HALLOCY_ERROR_OUT_OF_MEMORY; + + case ERROR_INVALID_HANDLE: + return HALLOCY_ERROR_INVALID_POINTER; + + case ERROR_INVALID_ADDRESS: + return HALLOCY_ERROR_INVALID_POINTER; + + default: + return HALLOCY_ERROR_UNKNOWN; + } + } + #elif defined(__linux__) + int result = munmap(memory_header, memory_header->size); + if (result == -1) { + switch (errno) { + case EINVAL: + return HALLOCY_ERROR_INVALID_PARAM; + + case ENOMEM: + return HALLOCY_ERROR_OUT_OF_MEMORY; + + case EFAULT: + return HALLOCY_ERROR_INVALID_POINTER; + + default: + return HALLOCY_ERROR_UNKNOWN; + } + } + #endif + + return HALLOCY_ERROR_NONE; } \ No newline at end of file diff --git a/Src/Main.c b/Src/Main.c index e78593e..3b99def 100644 --- a/Src/Main.c +++ b/Src/Main.c @@ -3,10 +3,21 @@ int main() { char *memory = (char *)hallocy_malloc(3); + if (memory == NULL) { + printf("Failed it allocate memory!"); + return -1; + } + memory[0] = 'H'; memory[1] = 'i'; memory[2] = '\0'; - + printf("%s\n", memory); + int code = hallocy_free(memory); + if (code != HALLOCY_ERROR_NONE) { + printf("Failed to free memory error code (%d)!", code); + return -1; + } + return 0; } \ No newline at end of file From 120ddaed027c733d989c66e5ab43510ccbd2ae99 Mon Sep 17 00:00:00 2001 From: Mineplay Date: Fri, 11 Apr 2025 19:01:08 -0500 Subject: [PATCH 6/8] perf(allocator): made small allocations reusable by adding a memory bin --- Src/Hallocy/Allocator.c | 187 +++++++++++++++++++++++++++++++--------- 1 file changed, 148 insertions(+), 39 deletions(-) diff --git a/Src/Hallocy/Allocator.c b/Src/Hallocy/Allocator.c index 79151e5..ba86aa7 100644 --- a/Src/Hallocy/Allocator.c +++ b/Src/Hallocy/Allocator.c @@ -24,6 +24,8 @@ #if defined(_WIN32) #include + +static HANDLE hallocy_heap = NULL; #elif defined(__linux__) #include #include @@ -35,7 +37,12 @@ typedef struct HallocyMemoryHeader { struct HallocyMemoryHeader *next; } HallocyMemoryHeader; +static _Thread_local size_t hallocy_small_memory_freed = 0; +static _Thread_local size_t hallocy_small_memory_allocated = 0; +static _Thread_local HallocyMemoryHeader *hallocy_small_memory_bin = NULL; + static size_t page_size = 0; +static size_t hallocy_small_allocation_size = 0; void *hallocy_malloc(size_t size) { if (page_size == 0) { @@ -45,20 +52,65 @@ void *hallocy_malloc(size_t size) { page_size = system_info.dwPageSize; #elif defined(__linux__) - page_size = sysconf(_SC_PAGESIZE); + page_size = sysconf(_SC_PAGE_SIZE); #endif + + hallocy_small_allocation_size = page_size; } size_t aligned_size = page_size * (((size + sizeof(HallocyMemoryHeader)) / page_size) + 1); HallocyMemoryHeader *memory_pointer = NULL; - #if defined(_WIN32) - memory_pointer = (HallocyMemoryHeader*)VirtualAlloc(NULL, aligned_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - #elif defined(__linux__) - memory_pointer = (HallocyMemoryHeader*)mmap(NULL, aligned_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - #endif + if (aligned_size <= hallocy_small_allocation_size) { + HallocyMemoryHeader *previous_header = NULL; + memory_pointer = hallocy_small_memory_bin; + while (memory_pointer != NULL) { + if (memory_pointer->size >= aligned_size) { + hallocy_small_memory_allocated += memory_pointer->size; + hallocy_small_memory_freed -= memory_pointer->size; - if (memory_pointer == NULL) { - return NULL; + if (previous_header == NULL) { + hallocy_small_memory_bin = hallocy_small_memory_bin->next; + } else { + previous_header->next = memory_pointer->next; + } + + memory_pointer->next = NULL; + return (void*)(memory_pointer + 1); + } + + previous_header = memory_pointer; + memory_pointer = memory_pointer->next; + } + + #if defined(_WIN32) + if (hallocy_heap == NULL) { + hallocy_heap = GetProcessHeap(); + } + + memory_pointer = HeapAlloc(hallocy_heap, 0, aligned_size); + if (memory_pointer == NULL) { + return NULL; + } + #elif defined(__linux__) + memory_pointer = mmap(NULL, aligned_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (memory_pointer == MAP_FAILED) { + return NULL; + } + #endif + + hallocy_small_memory_allocated += aligned_size; + } else { + #if defined(_WIN32) + memory_pointer = (HallocyMemoryHeader*)VirtualAlloc(NULL, aligned_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + if (memory_pointer == NULL) { + return NULL; + } + #elif defined(__linux__) + memory_pointer = (HallocyMemoryHeader*)mmap(NULL, aligned_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (memory_pointer == MAP_FAILED) { + return NULL; + } + #endif } memory_pointer->size = aligned_size; @@ -73,45 +125,102 @@ HallocyError hallocy_free(void *pointer) { } HallocyMemoryHeader *memory_header = ((HallocyMemoryHeader*)pointer) - 1; - #if defined(_WIN32) - bool result = VirtualFree(memory_header, 0, MEM_RELEASE); - if (result == false) { - DWORD error = GetLastError(); - switch (error) { - case ERROR_INVALID_PARAMETER: - return HALLOCY_ERROR_INVALID_PARAM; + if (memory_header->size <= hallocy_small_allocation_size) { + memory_header->next = hallocy_small_memory_bin; + hallocy_small_memory_bin = memory_header; + + hallocy_small_memory_allocated -= memory_header->size; + hallocy_small_memory_freed += memory_header->size; + if (hallocy_small_memory_allocated == 0 && hallocy_small_memory_freed > hallocy_small_allocation_size * 10) { + HallocyMemoryHeader *previous_header = NULL; + HallocyMemoryHeader *current_header = hallocy_small_memory_bin; + while (current_header != NULL) { + previous_header = current_header; + current_header = current_header->next; - case ERROR_NOT_ENOUGH_MEMORY: - return HALLOCY_ERROR_OUT_OF_MEMORY; + #if defined(_WIN32) + bool result = HeapFree(hallocy_heap, 0, previous_header); + if (result == false) { + DWORD error = GetLastError(); + switch (error) { + case ERROR_INVALID_PARAMETER: + return HALLOCY_ERROR_INVALID_PARAM; + + case ERROR_NOT_ENOUGH_MEMORY: + return HALLOCY_ERROR_OUT_OF_MEMORY; + + case ERROR_INVALID_HANDLE: + return HALLOCY_ERROR_INVALID_POINTER; + + default: + return HALLOCY_ERROR_UNKNOWN; + } + } + #elif defined(__linux__) + int result = munmap(previous_header, previous_header->size); + if (result == -1) { + switch (errno) { + case EINVAL: + return HALLOCY_ERROR_INVALID_PARAM; + + case ENOMEM: + return HALLOCY_ERROR_OUT_OF_MEMORY; + + case EFAULT: + return HALLOCY_ERROR_INVALID_POINTER; + + default: + return HALLOCY_ERROR_UNKNOWN; + } + } + #endif + } - case ERROR_INVALID_HANDLE: - return HALLOCY_ERROR_INVALID_POINTER; - - case ERROR_INVALID_ADDRESS: - return HALLOCY_ERROR_INVALID_POINTER; - - default: - return HALLOCY_ERROR_UNKNOWN; + hallocy_small_memory_bin = NULL; + hallocy_small_memory_allocated = 0; + hallocy_small_memory_freed = 0; } - } - #elif defined(__linux__) - int result = munmap(memory_header, memory_header->size); - if (result == -1) { - switch (errno) { - case EINVAL: - return HALLOCY_ERROR_INVALID_PARAM; + } else { + #if defined(_WIN32) + bool result = VirtualFree(memory_header, 0, MEM_RELEASE); + if (result == false) { + DWORD error = GetLastError(); + switch (error) { + case ERROR_INVALID_PARAMETER: + return HALLOCY_ERROR_INVALID_PARAM; - case ENOMEM: - return HALLOCY_ERROR_OUT_OF_MEMORY; + case ERROR_NOT_ENOUGH_MEMORY: + return HALLOCY_ERROR_OUT_OF_MEMORY; - case EFAULT: - return HALLOCY_ERROR_INVALID_POINTER; + case ERROR_INVALID_HANDLE: + return HALLOCY_ERROR_INVALID_POINTER; - default: - return HALLOCY_ERROR_UNKNOWN; + case ERROR_INVALID_ADDRESS: + return HALLOCY_ERROR_INVALID_POINTER; + + default: + return HALLOCY_ERROR_UNKNOWN; + } } + #elif defined(__linux__) + int result = munmap(memory_header, memory_header->size); + if (result == -1) { + switch (errno) { + case EINVAL: + return HALLOCY_ERROR_INVALID_PARAM; + + case ENOMEM: + return HALLOCY_ERROR_OUT_OF_MEMORY; + + case EFAULT: + return HALLOCY_ERROR_INVALID_POINTER; + + default: + return HALLOCY_ERROR_UNKNOWN; + } + } + #endif } - #endif return HALLOCY_ERROR_NONE; } \ No newline at end of file From 21e79b8af4fdfe755eec5aa339b169a720d9f4b9 Mon Sep 17 00:00:00 2001 From: Mineplay Date: Sat, 12 Apr 2025 13:29:10 -0500 Subject: [PATCH 7/8] perf(allocator): made medium allocations reusable by adding memory bin --- Src/Hallocy/Allocator.c | 169 +++++++++++++++++++++++++++++++++++++++- Src/Main.c | 2 +- 2 files changed, 169 insertions(+), 2 deletions(-) diff --git a/Src/Hallocy/Allocator.c b/Src/Hallocy/Allocator.c index ba86aa7..6ecf751 100644 --- a/Src/Hallocy/Allocator.c +++ b/Src/Hallocy/Allocator.c @@ -25,11 +25,20 @@ #if defined(_WIN32) #include +static const INIT_ONCE HALLOCY_INIT_ONCE = INIT_ONCE_STATIC_INIT; + static HANDLE hallocy_heap = NULL; +static CRITICAL_SECTION hallocy_critical_section; #elif defined(__linux__) #include #include #include +#include + +static const int HALLOCY_FUTEX_WAKE = 0; +static const int HALLOCY_FUTEX_WAIT = 1; + +static int hallocy_futex_address = 0; #endif typedef struct HallocyMemoryHeader { @@ -37,12 +46,27 @@ typedef struct HallocyMemoryHeader { struct HallocyMemoryHeader *next; } HallocyMemoryHeader; +static size_t hallocy_medium_memory_freed = 0; +static size_t hallocy_medium_memory_allocated = 0; +static HallocyMemoryHeader *hallocy_medium_memory_bin = NULL; + static _Thread_local size_t hallocy_small_memory_freed = 0; static _Thread_local size_t hallocy_small_memory_allocated = 0; static _Thread_local HallocyMemoryHeader *hallocy_small_memory_bin = NULL; static size_t page_size = 0; static size_t hallocy_small_allocation_size = 0; +static size_t hallocy_medium_allocation_size = 0; + +#if defined(_WIN32) +static BOOL CALLBACK hallocy_initialize_mutex(PINIT_ONCE init_once, PVOID parameter, PVOID *context) { + (void)init_once; + (void)parameter; + (void)context; + + return InitializeCriticalSectionEx(&hallocy_critical_section, 0x00000400, 0); +} +#endif void *hallocy_malloc(size_t size) { if (page_size == 0) { @@ -56,6 +80,7 @@ void *hallocy_malloc(size_t size) { #endif hallocy_small_allocation_size = page_size; + hallocy_medium_allocation_size = page_size * 10; } size_t aligned_size = page_size * (((size + sizeof(HallocyMemoryHeader)) / page_size) + 1); @@ -99,6 +124,72 @@ void *hallocy_malloc(size_t size) { #endif hallocy_small_memory_allocated += aligned_size; + } else if (aligned_size <= hallocy_medium_allocation_size) { + #if defined(_WIN32) + InitOnceExecuteOnce(&HALLOCY_INIT_ONCE, hallocy_initialize_mutex, NULL, NULL); + EnterCriticalSection(&hallocy_critical_section); + #elif defined(__linux__) + bool locked = false; + while (!locked) { + if (__sync_bool_compare_and_swap(&hallocy_futex_address, 0, 1)) { + locked = true; + } else { + syscall(SYS_futex, &hallocy_futex_address, HALLOCY_FUTEX_WAIT, 1, NULL, NULL, 0); + } + } + #endif + + HallocyMemoryHeader *previous_header = NULL; + memory_pointer = hallocy_medium_memory_bin; + while (memory_pointer != NULL) { + if (memory_pointer->size >= aligned_size) { + hallocy_medium_memory_allocated += memory_pointer->size; + hallocy_medium_memory_freed -= memory_pointer->size; + + if (previous_header == NULL) { + hallocy_medium_memory_bin = hallocy_medium_memory_bin->next; + } else { + previous_header->next = memory_pointer->next; + } + + #if defined(_WIN32) + LeaveCriticalSection(&hallocy_critical_section); + #elif defined(__linux__) + hallocy_futex_address = 0; + syscall(SYS_futex, &hallocy_futex_address, HALLOCY_FUTEX_WAKE, 1, NULL, NULL, 0); + #endif + + memory_pointer->next = NULL; + return (void*)(memory_pointer + 1); + } + + previous_header = memory_pointer; + memory_pointer = memory_pointer->next; + } + + #if defined(_WIN32) + if (hallocy_heap == NULL) { + hallocy_heap = GetProcessHeap(); + } + + memory_pointer = HeapAlloc(hallocy_heap, 0, aligned_size); + if (memory_pointer == NULL) { + return NULL; + } + + hallocy_medium_allocation_size += aligned_size; + LeaveCriticalSection(&hallocy_critical_section); + #elif defined(__linux__) + memory_pointer = mmap(NULL, aligned_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (memory_pointer == MAP_FAILED) { + return NULL; + } + + hallocy_medium_allocation_size += aligned_size; + + hallocy_futex_address = 0; + syscall(SYS_futex, &hallocy_futex_address, HALLOCY_FUTEX_WAKE, 1, NULL, NULL, 0); + #endif } else { #if defined(_WIN32) memory_pointer = (HallocyMemoryHeader*)VirtualAlloc(NULL, aligned_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); @@ -131,7 +222,7 @@ HallocyError hallocy_free(void *pointer) { hallocy_small_memory_allocated -= memory_header->size; hallocy_small_memory_freed += memory_header->size; - if (hallocy_small_memory_allocated == 0 && hallocy_small_memory_freed > hallocy_small_allocation_size * 10) { + if (hallocy_small_memory_allocated == 0 && hallocy_small_memory_freed > hallocy_medium_allocation_size) { HallocyMemoryHeader *previous_header = NULL; HallocyMemoryHeader *current_header = hallocy_small_memory_bin; while (current_header != NULL) { @@ -180,6 +271,82 @@ HallocyError hallocy_free(void *pointer) { hallocy_small_memory_allocated = 0; hallocy_small_memory_freed = 0; } + } else if (memory_header->size <= hallocy_medium_allocation_size) { + #if defined(_WIN32) + InitOnceExecuteOnce(&HALLOCY_INIT_ONCE, hallocy_initialize_mutex, NULL, NULL); + EnterCriticalSection(&hallocy_critical_section); + #elif defined(__linux__) + bool locked = false; + while (!locked) { + if (__sync_bool_compare_and_swap(&hallocy_futex_address, 0, 1)) { + locked = true; + } else { + syscall(SYS_futex, &hallocy_futex_address, HALLOCY_FUTEX_WAIT, 1, NULL, NULL, 0); + } + } + #endif + + memory_header->next = hallocy_medium_memory_bin; + hallocy_medium_memory_bin = memory_header; + + hallocy_medium_memory_allocated -= memory_header->size; + hallocy_medium_memory_freed += memory_header->size; + if (hallocy_medium_memory_allocated == 0 && hallocy_medium_memory_freed > hallocy_medium_allocation_size) { + HallocyMemoryHeader *previous_header = NULL; + HallocyMemoryHeader *current_header = hallocy_medium_memory_bin; + while (current_header != NULL) { + previous_header = current_header; + current_header = current_header->next; + + #if defined(_WIN32) + bool result = HeapFree(hallocy_heap, 0, previous_header); + if (result == false) { + DWORD error = GetLastError(); + switch (error) { + case ERROR_INVALID_PARAMETER: + return HALLOCY_ERROR_INVALID_PARAM; + + case ERROR_NOT_ENOUGH_MEMORY: + return HALLOCY_ERROR_OUT_OF_MEMORY; + + case ERROR_INVALID_HANDLE: + return HALLOCY_ERROR_INVALID_POINTER; + + default: + return HALLOCY_ERROR_UNKNOWN; + } + } + #elif defined(__linux__) + int result = munmap(previous_header, previous_header->size); + if (result == -1) { + switch (errno) { + case EINVAL: + return HALLOCY_ERROR_INVALID_PARAM; + + case ENOMEM: + return HALLOCY_ERROR_OUT_OF_MEMORY; + + case EFAULT: + return HALLOCY_ERROR_INVALID_POINTER; + + default: + return HALLOCY_ERROR_UNKNOWN; + } + } + #endif + } + + hallocy_medium_memory_bin = NULL; + hallocy_medium_memory_allocated = 0; + hallocy_medium_memory_freed = 0; + } + + #if defined(_WIN32) + LeaveCriticalSection(&hallocy_critical_section); + #elif defined(__linux__) + hallocy_futex_address = 0; + syscall(SYS_futex, &hallocy_futex_address, HALLOCY_FUTEX_WAKE, 1, NULL, NULL, 0); + #endif } else { #if defined(_WIN32) bool result = VirtualFree(memory_header, 0, MEM_RELEASE); diff --git a/Src/Main.c b/Src/Main.c index 3b99def..8fc9e75 100644 --- a/Src/Main.c +++ b/Src/Main.c @@ -2,7 +2,7 @@ #include int main() { - char *memory = (char *)hallocy_malloc(3); + char *memory = (char *)hallocy_malloc(12288); if (memory == NULL) { printf("Failed it allocate memory!"); return -1; From b954870e45eba557ab460fc0efac8cc76a9fa3d0 Mon Sep 17 00:00:00 2001 From: Mineplay Date: Sat, 12 Apr 2025 15:10:26 -0500 Subject: [PATCH 8/8] refactor(tests): moved main.c to seperate tests folder --- CMakeLists.txt | 11 +++++---- Src/{Hallocy => }/Allocator.c | 2 +- Src/Main.c | 23 ------------------ Tests/Main.c | 44 +++++++++++++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 29 deletions(-) rename Src/{Hallocy => }/Allocator.c (99%) delete mode 100644 Src/Main.c create mode 100644 Tests/Main.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 321f2de..499bee9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,21 +5,22 @@ set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) include_directories(${PROJECT_SOURCE_DIR}/Include) -file(GLOB_RECURSE SRC_FILES "${PROJECT_SOURCE_DIR}/Src/Hallocy/*.c") +file(GLOB_RECURSE SRC_FILES "${PROJECT_SOURCE_DIR}/Src/*.c") add_library(Hallocy STATIC ${SRC_FILES}) -add_executable(HallocyApp ${PROJECT_SOURCE_DIR}/Src/Main.c) +add_executable(HallocyTest ${PROJECT_SOURCE_DIR}/Tests/Main.c) -target_link_libraries(HallocyApp Hallocy) +target_include_directories(HallocyTest PRIVATE ${PROJECT_SOURCE_DIR}/Tests) +target_link_libraries(HallocyTest Hallocy) if (MSVC) target_compile_options(Hallocy PRIVATE /W4 /Zl) else() target_compile_options(Hallocy PRIVATE -mavx512f -mavx512vl) - target_compile_options(HallocyApp PRIVATE -mavx512f -mavx512vl) + target_compile_options(HallocyTest PRIVATE -mavx512f -mavx512vl) target_compile_options(Hallocy PRIVATE -march=native) - target_compile_options(HallocyApp PRIVATE -march=native) + target_compile_options(HallocyTest PRIVATE -march=native) target_compile_options(Hallocy PRIVATE -Wall -Wextra -pedantic) endif() \ No newline at end of file diff --git a/Src/Hallocy/Allocator.c b/Src/Allocator.c similarity index 99% rename from Src/Hallocy/Allocator.c rename to Src/Allocator.c index 6ecf751..5471122 100644 --- a/Src/Hallocy/Allocator.c +++ b/Src/Allocator.c @@ -20,7 +20,7 @@ * Author: Mineplay * ----------------------------------------------------------------------------- */ -#include "../../Include/Hallocy/Allocator.h" +#include "../Include/Hallocy/Allocator.h" #if defined(_WIN32) #include diff --git a/Src/Main.c b/Src/Main.c deleted file mode 100644 index 8fc9e75..0000000 --- a/Src/Main.c +++ /dev/null @@ -1,23 +0,0 @@ -#include -#include - -int main() { - char *memory = (char *)hallocy_malloc(12288); - if (memory == NULL) { - printf("Failed it allocate memory!"); - return -1; - } - - memory[0] = 'H'; - memory[1] = 'i'; - memory[2] = '\0'; - - printf("%s\n", memory); - int code = hallocy_free(memory); - if (code != HALLOCY_ERROR_NONE) { - printf("Failed to free memory error code (%d)!", code); - return -1; - } - - return 0; -} \ No newline at end of file diff --git a/Tests/Main.c b/Tests/Main.c new file mode 100644 index 0000000..3b13990 --- /dev/null +++ b/Tests/Main.c @@ -0,0 +1,44 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ----------------------------------------------------------------------------- + * File: Main.c + * Description: + * Executes all tests. + * + * Author: Mineplay + * ----------------------------------------------------------------------------- + */ + #include + #include + + int main() { + char *memory = (char *)hallocy_malloc(12288); + if (memory == NULL) { + printf("Failed it allocate memory!"); + return -1; + } + + memory[0] = 'H'; + memory[1] = 'i'; + memory[2] = '\0'; + + printf("%s\n", memory); + int code = hallocy_free(memory); + if (code != HALLOCY_ERROR_NONE) { + printf("Failed to free memory error code (%d)!", code); + return -1; + } + + return 0; + } \ No newline at end of file