LibC: Make malloc thread safe with pthread_spinlock
This commit is contained in:
parent
cf59f89bfb
commit
cc2b4967ea
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <pthread.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
@ -72,6 +73,8 @@ struct malloc_info_t
|
||||||
static malloc_info_t s_malloc_info;
|
static malloc_info_t s_malloc_info;
|
||||||
static auto& s_malloc_pools = s_malloc_info.pools;
|
static auto& s_malloc_pools = s_malloc_info.pools;
|
||||||
|
|
||||||
|
static pthread_spinlock_t s_malloc_lock;
|
||||||
|
|
||||||
static bool allocate_pool(size_t pool_index)
|
static bool allocate_pool(size_t pool_index)
|
||||||
{
|
{
|
||||||
auto& pool = s_malloc_pools[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
|
// 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++)
|
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))
|
if (s_malloc_pools[i].start == nullptr)
|
||||||
return ret;
|
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
|
// allocate new pool
|
||||||
for (size_t i = first_usable_pool; i < s_malloc_pool_count; i++)
|
for (size_t i = first_usable_pool; i < s_malloc_pool_count; i++)
|
||||||
{
|
{
|
||||||
if (s_malloc_pools[i].start != nullptr)
|
if (s_malloc_pools[i].start != nullptr)
|
||||||
continue;
|
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;
|
break;
|
||||||
// NOTE: always works since we just created the pool
|
return ret;
|
||||||
return allocate_from_pool(i, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
|
@ -258,6 +273,8 @@ void free(void* ptr)
|
||||||
if (ptr == nullptr)
|
if (ptr == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
pthread_spin_lock(&s_malloc_lock);
|
||||||
|
|
||||||
auto* node = node_from_data_pointer(ptr);
|
auto* node = node_from_data_pointer(ptr);
|
||||||
|
|
||||||
node->allocated = false;
|
node->allocated = false;
|
||||||
|
@ -279,6 +296,8 @@ void free(void* ptr)
|
||||||
node->prev_free = nullptr;
|
node->prev_free = nullptr;
|
||||||
node->next_free = pool.free_list;
|
node->next_free = pool.free_list;
|
||||||
pool.free_list = node;
|
pool.free_list = node;
|
||||||
|
|
||||||
|
pthread_spin_unlock(&s_malloc_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* calloc(size_t nmemb, size_t size)
|
void* calloc(size_t nmemb, size_t size)
|
||||||
|
|
Loading…
Reference in New Issue