From faf4f29cc0b45416f48f2839a9a0b8363e9428c1 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 30 Jun 2014 22:34:20 +0600 Subject: Guardedalloc: Implement atomic peak memory update Updating maximum requires a bit of a cycle which usually does 1 iteration only, sometimes needs a bit more but seems there's no speed regressions. For now the code is commented out. This way it's easier for others to verify there's no speed regressions. Reviewers: campbellbarton Differential Revision: https://developer.blender.org/D626 --- intern/guardedalloc/intern/mallocn_intern.h | 7 +++++ intern/guardedalloc/intern/mallocn_lockfree_impl.c | 34 ++++++++++++++-------- 2 files changed, 29 insertions(+), 12 deletions(-) (limited to 'intern/guardedalloc') diff --git a/intern/guardedalloc/intern/mallocn_intern.h b/intern/guardedalloc/intern/mallocn_intern.h index 523d1786b97..7da74f7cc4c 100644 --- a/intern/guardedalloc/intern/mallocn_intern.h +++ b/intern/guardedalloc/intern/mallocn_intern.h @@ -103,6 +103,13 @@ # include #endif +/* visual studio 2012 does not define inline for C */ +#ifdef _MSC_VER +# define MEM_INLINE static __inline +#else +# define MEM_INLINE static inline +#endif + #define IS_POW2(a) (((a) & ((a) - 1)) == 0) /* Extra padding which needs to be applied on MemHead to make it aligned. */ diff --git a/intern/guardedalloc/intern/mallocn_lockfree_impl.c b/intern/guardedalloc/intern/mallocn_lockfree_impl.c index ffb23702601..c0f6aeeaa9d 100644 --- a/intern/guardedalloc/intern/mallocn_lockfree_impl.c +++ b/intern/guardedalloc/intern/mallocn_lockfree_impl.c @@ -70,6 +70,23 @@ enum { #define MEMHEAD_IS_MMAP(memhead) ((memhead)->len & (size_t) MEMHEAD_MMAP_FLAG) #define MEMHEAD_IS_ALIGNED(memhead) ((memhead)->len & (size_t) MEMHEAD_ALIGN_FLAG) +/* Uncomment this to have proper peak counter. */ +//#define USE_ATOMIC_MAX + +MEM_INLINE void update_maximum(size_t *maximum_value, size_t value) +{ +#ifdef USE_ATOMIC_MAX + size_t prev_value = *maximum_value; + while (prev_value < value) { + if (atomic_cas_z(maximum_value, prev_value, value) != prev_value) { + break; + } + } +#else + *maximum_value = value > *maximum_value ? value : *maximum_value; +#endif +} + #ifdef __GNUC__ __attribute__ ((format(printf, 1, 2))) #endif @@ -264,9 +281,7 @@ void *MEM_lockfree_callocN(size_t len, const char *str) memh->len = len; atomic_add_u(&totblock, 1); atomic_add_z(&mem_in_use, len); - - /* TODO(sergey): Not strictly speaking thread-safe. */ - peak_mem = mem_in_use > peak_mem ? mem_in_use : peak_mem; + update_maximum(&peak_mem, mem_in_use); return PTR_FROM_MEMHEAD(memh); } @@ -291,9 +306,7 @@ void *MEM_lockfree_mallocN(size_t len, const char *str) memh->len = len; atomic_add_u(&totblock, 1); atomic_add_z(&mem_in_use, len); - - /* TODO(sergey): Not strictly speaking thread-safe. */ - peak_mem = mem_in_use > peak_mem ? mem_in_use : peak_mem; + update_maximum(&peak_mem, mem_in_use); return PTR_FROM_MEMHEAD(memh); } @@ -342,9 +355,7 @@ void *MEM_lockfree_mallocN_aligned(size_t len, size_t alignment, const char *str memh->alignment = (short) alignment; atomic_add_u(&totblock, 1); atomic_add_z(&mem_in_use, len); - - /* TODO(sergey): Not strictly speaking thread-safe. */ - peak_mem = mem_in_use > peak_mem ? mem_in_use : peak_mem; + update_maximum(&peak_mem, mem_in_use); return PTR_FROM_MEMHEAD(memh); } @@ -381,9 +392,8 @@ void *MEM_lockfree_mapallocN(size_t len, const char *str) atomic_add_z(&mem_in_use, len); atomic_add_z(&mmap_in_use, len); - /* TODO(sergey): Not strictly speaking thread-safe. */ - peak_mem = mem_in_use > peak_mem ? mem_in_use : peak_mem; - peak_mem = mmap_in_use > peak_mem ? mmap_in_use : peak_mem; + update_maximum(&peak_mem, mem_in_use); + update_maximum(&peak_mem, mmap_in_use); return PTR_FROM_MEMHEAD(memh); } -- cgit v1.2.3