diff options
Diffstat (limited to 'core')
| -rw-r--r-- | core/os/memory.cpp | 40 | ||||
| -rw-r--r-- | core/os/memory.h | 12 | ||||
| -rw-r--r-- | core/safe_refcount.cpp | 56 | ||||
| -rw-r--r-- | core/safe_refcount.h | 2 |
4 files changed, 77 insertions, 33 deletions
diff --git a/core/os/memory.cpp b/core/os/memory.cpp index 069ee48fa..acc960acd 100644 --- a/core/os/memory.cpp +++ b/core/os/memory.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "memory.h" #include "copymem.h" +#include "core/safe_refcount.h" #include "error_macros.h" #include <stdio.h> #include <stdlib.h> @@ -43,14 +44,12 @@ void *operator new(size_t p_size, void *(*p_allocfunc)(size_t p_size)) { return p_allocfunc(p_size); } -#include <stdio.h> - #ifdef DEBUG_ENABLED -size_t Memory::mem_usage = 0; -size_t Memory::max_usage = 0; +uint64_t Memory::mem_usage = 0; +uint64_t Memory::max_usage = 0; #endif -size_t Memory::alloc_count = 0; +uint64_t Memory::alloc_count = 0; void *Memory::alloc_static(size_t p_bytes, bool p_pad_align) { @@ -62,10 +61,10 @@ void *Memory::alloc_static(size_t p_bytes, bool p_pad_align) { void *mem = malloc(p_bytes + (prepad ? PAD_ALIGN : 0)); - alloc_count++; - ERR_FAIL_COND_V(!mem, NULL); + atomic_increment(&alloc_count); + if (prepad) { uint64_t *s = (uint64_t *)mem; *s = p_bytes; @@ -73,10 +72,8 @@ void *Memory::alloc_static(size_t p_bytes, bool p_pad_align) { uint8_t *s8 = (uint8_t *)mem; #ifdef DEBUG_ENABLED - mem_usage += p_bytes; - if (mem_usage > max_usage) { - max_usage = mem_usage; - } + atomic_add(&mem_usage, p_bytes); + atomic_exchange_if_greater(&max_usage, mem_usage); #endif return s8 + PAD_ALIGN; } else { @@ -103,8 +100,12 @@ void *Memory::realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align) { uint64_t *s = (uint64_t *)mem; #ifdef DEBUG_ENABLED - mem_usage -= *s; - mem_usage += p_bytes; + if (p_bytes > *s) { + atomic_add(&mem_usage, p_bytes - *s); + atomic_exchange_if_greater(&max_usage, mem_usage); + } else { + atomic_sub(&mem_usage, *s - p_bytes); + } #endif if (p_bytes == 0) { @@ -144,14 +145,14 @@ void Memory::free_static(void *p_ptr, bool p_pad_align) { bool prepad = p_pad_align; #endif - alloc_count--; + atomic_decrement(&alloc_count); if (prepad) { mem -= PAD_ALIGN; uint64_t *s = (uint64_t *)mem; #ifdef DEBUG_ENABLED - mem_usage -= *s; + atomic_sub(&mem_usage, *s); #endif free(mem); @@ -161,19 +162,20 @@ void Memory::free_static(void *p_ptr, bool p_pad_align) { } } -size_t Memory::get_mem_available() { +uint64_t Memory::get_mem_available() { - return 0xFFFFFFFFFFFFF; + return -1; // 0xFFFF... } -size_t Memory::get_mem_usage() { +uint64_t Memory::get_mem_usage() { #ifdef DEBUG_ENABLED return mem_usage; #else return 0; #endif } -size_t Memory::get_mem_max_usage() { + +uint64_t Memory::get_mem_max_usage() { #ifdef DEBUG_ENABLED return max_usage; #else diff --git a/core/os/memory.h b/core/os/memory.h index b3eb59995..e1d7138ad 100644 --- a/core/os/memory.h +++ b/core/os/memory.h @@ -45,20 +45,20 @@ class Memory { Memory(); #ifdef DEBUG_ENABLED - static size_t mem_usage; - static size_t max_usage; + static uint64_t mem_usage; + static uint64_t max_usage; #endif - static size_t alloc_count; + static uint64_t alloc_count; public: static void *alloc_static(size_t p_bytes, bool p_pad_align = false); static void *realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align = false); static void free_static(void *p_ptr, bool p_pad_align = false); - static size_t get_mem_available(); - static size_t get_mem_usage(); - static size_t get_mem_max_usage(); + static uint64_t get_mem_available(); + static uint64_t get_mem_usage(); + static uint64_t get_mem_max_usage(); }; class DefaultAllocator { diff --git a/core/safe_refcount.cpp b/core/safe_refcount.cpp index d7e529732..971e9ad1d 100644 --- a/core/safe_refcount.cpp +++ b/core/safe_refcount.cpp @@ -78,6 +78,15 @@ static _ALWAYS_INLINE_ T _atomic_add_impl(register T *pw, register T val) { return *pw; } +template <class T> +static _ALWAYS_INLINE_ T _atomic_exchange_if_greater_impl(register T *pw, register T val) { + + if (val > *pw) + *pw = val; + + return *pw; +} + #elif defined(__GNUC__) /* Implementation for GCC & Clang */ @@ -121,6 +130,18 @@ static _ALWAYS_INLINE_ T _atomic_add_impl(register T *pw, register T val) { return __sync_add_and_fetch(pw, val); } +template <class T> +static _ALWAYS_INLINE_ T _atomic_exchange_if_greater_impl(register T *pw, register T val) { + + while (true) { + T tmp = static_cast<T const volatile &>(*pw); + if (tmp >= val) + return tmp; // already greater, or equal + if (__sync_val_compare_and_swap(pw, tmp, val) == tmp) + return val; + } +} + #elif defined(_MSC_VER) /* Implementation for MSVC-Windows */ @@ -139,6 +160,15 @@ static _ALWAYS_INLINE_ T _atomic_add_impl(register T *pw, register T val) { return tmp + 1; \ } +#define ATOMIC_EXCHANGE_IF_GREATER_BODY(m_pw, m_val, m_win_type, m_win_cmpxchg, m_cpp_type) \ + while (true) { \ + m_cpp_type tmp = static_cast<m_cpp_type const volatile &>(*(m_pw)); \ + if (tmp >= m_val) \ + return tmp; /* already greater, or equal */ \ + if (m_win_cmpxchg((m_win_type volatile *)(m_pw), m_val, tmp) == tmp) \ + return m_val; \ + } + static _ALWAYS_INLINE_ uint32_t _atomic_conditional_increment_impl(register uint32_t *pw) { ATOMIC_CONDITIONAL_INCREMENT_BODY(pw, LONG, InterlockedCompareExchange, uint32_t) @@ -156,11 +186,7 @@ static _ALWAYS_INLINE_ uint32_t _atomic_increment_impl(register uint32_t *pw) { static _ALWAYS_INLINE_ uint32_t _atomic_sub_impl(register uint32_t *pw, register uint32_t val) { -#if _WIN32_WINNT >= 0x0601 // Windows 7+ - return InterlockedExchangeSubtract(pw, val) - val; -#else return InterlockedExchangeAdd((LONG volatile *)pw, -(int32_t)val) - val; -#endif } static _ALWAYS_INLINE_ uint32_t _atomic_add_impl(register uint32_t *pw, register uint32_t val) { @@ -168,6 +194,11 @@ static _ALWAYS_INLINE_ uint32_t _atomic_add_impl(register uint32_t *pw, register return InterlockedAdd((LONG volatile *)pw, val); } +static _ALWAYS_INLINE_ uint32_t _atomic_exchange_if_greater_impl(register uint32_t *pw, register uint32_t val) { + + ATOMIC_EXCHANGE_IF_GREATER_BODY(pw, val, LONG, InterlockedCompareExchange, uint32_t) +} + static _ALWAYS_INLINE_ uint64_t _atomic_conditional_increment_impl(register uint64_t *pw) { ATOMIC_CONDITIONAL_INCREMENT_BODY(pw, LONGLONG, InterlockedCompareExchange64, uint64_t) @@ -185,11 +216,7 @@ static _ALWAYS_INLINE_ uint64_t _atomic_increment_impl(register uint64_t *pw) { static _ALWAYS_INLINE_ uint64_t _atomic_sub_impl(register uint64_t *pw, register uint64_t val) { -#if _WIN32_WINNT >= 0x0601 && !defined(UWP_ENABLED) // Windows 7+ except UWP - return InterlockedExchangeSubtract64(pw, val) - val; -#else return InterlockedExchangeAdd64((LONGLONG volatile *)pw, -(int64_t)val) - val; -#endif } static _ALWAYS_INLINE_ uint64_t _atomic_add_impl(register uint64_t *pw, register uint64_t val) { @@ -197,6 +224,11 @@ static _ALWAYS_INLINE_ uint64_t _atomic_add_impl(register uint64_t *pw, register return InterlockedAdd64((LONGLONG volatile *)pw, val); } +static _ALWAYS_INLINE_ uint64_t _atomic_exchange_if_greater_impl(register uint64_t *pw, register uint64_t val) { + + ATOMIC_EXCHANGE_IF_GREATER_BODY(pw, val, LONGLONG, InterlockedCompareExchange64, uint64_t) +} + #else //no threads supported? @@ -226,6 +258,10 @@ uint32_t atomic_add(register uint32_t *pw, register uint32_t val) { return _atomic_add_impl(pw, val); } +uint32_t atomic_exchange_if_greater(register uint32_t *pw, register uint32_t val) { + return _atomic_exchange_if_greater_impl(pw, val); +} + uint64_t atomic_conditional_increment(register uint64_t *counter) { return _atomic_conditional_increment_impl(counter); } @@ -245,3 +281,7 @@ uint64_t atomic_sub(register uint64_t *pw, register uint64_t val) { uint64_t atomic_add(register uint64_t *pw, register uint64_t val) { return _atomic_add_impl(pw, val); } + +uint64_t atomic_exchange_if_greater(register uint64_t *pw, register uint64_t val) { + return _atomic_exchange_if_greater_impl(pw, val); +} diff --git a/core/safe_refcount.h b/core/safe_refcount.h index a2d2b5e12..ed0620c77 100644 --- a/core/safe_refcount.h +++ b/core/safe_refcount.h @@ -41,12 +41,14 @@ uint32_t atomic_decrement(register uint32_t *pw); uint32_t atomic_increment(register uint32_t *pw); uint32_t atomic_sub(register uint32_t *pw, register uint32_t val); uint32_t atomic_add(register uint32_t *pw, register uint32_t val); +uint32_t atomic_exchange_if_greater(register uint32_t *pw, register uint32_t val); uint64_t atomic_conditional_increment(register uint64_t *counter); uint64_t atomic_decrement(register uint64_t *pw); uint64_t atomic_increment(register uint64_t *pw); uint64_t atomic_sub(register uint64_t *pw, register uint64_t val); uint64_t atomic_add(register uint64_t *pw, register uint64_t val); +uint64_t atomic_exchange_if_greater(register uint64_t *pw, register uint64_t val); struct SafeRefCount { |
