Merge pull request #76755 from RandomShaper/fix_allocator_thsafe

Add missing thread safety to PagedAllocator
This commit is contained in:
Rémi Verschelde 2023-05-09 17:44:45 +02:00
commit 58ea42e4ab
No known key found for this signature in database
GPG key ID: C3336907360768E1
2 changed files with 44 additions and 11 deletions

View file

@ -36,15 +36,15 @@
#include <atomic> #include <atomic>
class SpinLock { class SpinLock {
std::atomic_flag locked = ATOMIC_FLAG_INIT; mutable std::atomic_flag locked = ATOMIC_FLAG_INIT;
public: public:
_ALWAYS_INLINE_ void lock() { _ALWAYS_INLINE_ void lock() const {
while (locked.test_and_set(std::memory_order_acquire)) { while (locked.test_and_set(std::memory_order_acquire)) {
// Continue. // Continue.
} }
} }
_ALWAYS_INLINE_ void unlock() { _ALWAYS_INLINE_ void unlock() const {
locked.clear(std::memory_order_release); 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) { if (!p_allow_unfreed || !std::is_trivially_destructible<T>::value) {
ERR_FAIL_COND(allocs_available < pages_allocated * page_size); ERR_FAIL_COND(allocs_available < pages_allocated * page_size);
} }
@ -116,16 +117,41 @@ public:
allocs_available = 0; 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 { 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) { void configure(uint32_t p_page_size) {
if (thread_safe) {
spin_lock.lock();
}
ERR_FAIL_COND(page_pool != nullptr); //sanity check ERR_FAIL_COND(page_pool != nullptr); //sanity check
ERR_FAIL_COND(p_page_size == 0); ERR_FAIL_COND(p_page_size == 0);
page_size = nearest_power_of_2_templated(p_page_size); page_size = nearest_power_of_2_templated(p_page_size);
page_mask = page_size - 1; page_mask = page_size - 1;
page_shift = get_shift_from_power_of_2(page_size); 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. // Power of 2 recommended because of alignment with OS page sizes.
@ -135,13 +161,20 @@ public:
} }
~PagedAllocator() { ~PagedAllocator() {
if (allocs_available < pages_allocated * page_size) { if (thread_safe) {
spin_lock.lock();
}
bool leaked = allocs_available < pages_allocated * page_size;
if (leaked) {
if (CoreGlobals::leak_reporting_enabled) { 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())); ERR_PRINT(String("Pages in use exist at exit in PagedAllocator: ") + String(typeid(T).name()));
} }
return; } else {
_reset(false);
}
if (thread_safe) {
spin_lock.unlock();
} }
reset();
} }
}; };