From cc2b4967eaaf86d0a9995b22bbac24a1c1ab01a3 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Tue, 15 Apr 2025 22:31:54 +0300 Subject: [PATCH] LibC: Make malloc thread safe with pthread_spinlock --- userspace/libraries/LibC/malloc.cpp | 31 +++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/userspace/libraries/LibC/malloc.cpp b/userspace/libraries/LibC/malloc.cpp index 0627529c..58e4c079 100644 --- a/userspace/libraries/LibC/malloc.cpp +++ b/userspace/libraries/LibC/malloc.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -72,6 +73,8 @@ struct malloc_info_t static malloc_info_t s_malloc_info; static auto& s_malloc_pools = s_malloc_info.pools; +static pthread_spinlock_t s_malloc_lock; + static bool allocate_pool(size_t pool_index) { auto& pool = s_malloc_pools[pool_index]; @@ -200,19 +203,31 @@ void* malloc(size_t size) // try to find any already existing pools that we can allocate in for (size_t i = first_usable_pool; i < s_malloc_pool_count; i++) - if (s_malloc_pools[i].start != nullptr) - if (void* ret = allocate_from_pool(i, size)) - return ret; + { + if (s_malloc_pools[i].start == nullptr) + continue; + pthread_spin_lock(&s_malloc_lock); + void* ret = allocate_from_pool(i, size); + pthread_spin_unlock(&s_malloc_lock); + if (ret != nullptr) + return ret; + } // allocate new pool for (size_t i = first_usable_pool; i < s_malloc_pool_count; i++) { if (s_malloc_pools[i].start != nullptr) continue; - if (!allocate_pool(i)) + + pthread_spin_lock(&s_malloc_lock); + void* ret = nullptr; + if (allocate_pool(i)) + ret = allocate_from_pool(i, size); + pthread_spin_unlock(&s_malloc_lock); + + if (ret == nullptr) break; - // NOTE: always works since we just created the pool - return allocate_from_pool(i, size); + return ret; } errno = ENOMEM; @@ -258,6 +273,8 @@ void free(void* ptr) if (ptr == nullptr) return; + pthread_spin_lock(&s_malloc_lock); + auto* node = node_from_data_pointer(ptr); node->allocated = false; @@ -279,6 +296,8 @@ void free(void* ptr) node->prev_free = nullptr; node->next_free = pool.free_list; pool.free_list = node; + + pthread_spin_unlock(&s_malloc_lock); } void* calloc(size_t nmemb, size_t size)