Add missing thread safety to PagedAllocator

This commit is contained in:
Pedro J. Estébanez 2023-05-05 19:55:29 +02:00
parent cf8ad12b56
commit 341b95871c
2 changed files with 44 additions and 11 deletions

View file

@ -36,15 +36,15 @@
#include <atomic>
class SpinLock {
std::atomic_flag locked = ATOMIC_FLAG_INIT;
mutable std::atomic_flag locked = ATOMIC_FLAG_INIT;
public:
_ALWAYS_INLINE_ void lock() {
_ALWAYS_INLINE_ void lock() const {
while (locked.test_and_set(std::memory_order_acquire)) {
// Continue.
}
}
_ALWAYS_INLINE_ void unlock() {
_ALWAYS_INLINE_ void unlock() const {
locked.clear(std::memory_order_release);
}
};

View file

@ -99,7 +99,8 @@ public:
}
}
void reset(bool p_allow_unfreed = false) {
private:
void _reset(bool p_allow_unfreed) {
if (!p_allow_unfreed || !std::is_trivially_destructible<T>::value) {
ERR_FAIL_COND(allocs_available < pages_allocated * page_size);
}
@ -116,16 +117,41 @@ public:
allocs_available = 0;
}
}
public:
void reset(bool p_allow_unfreed = false) {
if (thread_safe) {
spin_lock.lock();
}
_reset(p_allow_unfreed);
if (thread_safe) {
spin_lock.unlock();
}
}
bool is_configured() const {
return page_size > 0;
if (thread_safe) {
spin_lock.lock();
}
bool result = page_size > 0;
if (thread_safe) {
spin_lock.unlock();
}
return result;
}
void configure(uint32_t p_page_size) {
if (thread_safe) {
spin_lock.lock();
}
ERR_FAIL_COND(page_pool != nullptr); //sanity check
ERR_FAIL_COND(p_page_size == 0);
page_size = nearest_power_of_2_templated(p_page_size);
page_mask = page_size - 1;
page_shift = get_shift_from_power_of_2(page_size);
if (thread_safe) {
spin_lock.unlock();
}
}
// Power of 2 recommended because of alignment with OS page sizes.
@ -135,13 +161,20 @@ public:
}
~PagedAllocator() {
if (allocs_available < pages_allocated * page_size) {
if (CoreGlobals::leak_reporting_enabled) {
ERR_FAIL_COND_MSG(allocs_available < pages_allocated * page_size, String("Pages in use exist at exit in PagedAllocator: ") + String(typeid(T).name()));
}
return;
if (thread_safe) {
spin_lock.lock();
}
bool leaked = allocs_available < pages_allocated * page_size;
if (leaked) {
if (CoreGlobals::leak_reporting_enabled) {
ERR_PRINT(String("Pages in use exist at exit in PagedAllocator: ") + String(typeid(T).name()));
}
} else {
_reset(false);
}
if (thread_safe) {
spin_lock.unlock();
}
reset();
}
};