[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [59942] branches/soc-2013-depsgraph_mt: Lock-free memory allocator

Sergey Sharybin sergey.vfx at gmail.com
Mon Sep 9 11:27:26 CEST 2013


Revision: 59942
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=59942
Author:   nazgul
Date:     2013-09-09 09:27:25 +0000 (Mon, 09 Sep 2013)
Log Message:
-----------
Lock-free memory allocator

Release builds will now use lock-free allocator by
default without any internal locks happening.

MemHead is also reduces to as minimum as it's possible.
It still need to be size_t stored in a MemHead in order
to make us keep track on memory we're requesting from
the system, not memory which system is allocating. This
is probably also faster than using a malloc's usable
size function.

Lock-free guarded allocator will say you whether all
the blocks were freed, but wouldn't give you a list
of unfreed blocks list. To have such a list use a
--debug or --debug-memory command line arguments.

Debug builds does have the same behavior as release
builds. This is so tools like valgrind are not
screwed up by guarded allocator as they're currently
are.

Modified Paths:
--------------
    branches/soc-2013-depsgraph_mt/CMakeLists.txt
    branches/soc-2013-depsgraph_mt/intern/guardedalloc/CMakeLists.txt
    branches/soc-2013-depsgraph_mt/intern/guardedalloc/MEM_guardedalloc.h
    branches/soc-2013-depsgraph_mt/intern/guardedalloc/SConscript
    branches/soc-2013-depsgraph_mt/intern/guardedalloc/intern/mallocn.c
    branches/soc-2013-depsgraph_mt/source/blender/makesdna/intern/CMakeLists.txt
    branches/soc-2013-depsgraph_mt/source/blender/makesdna/intern/SConscript
    branches/soc-2013-depsgraph_mt/source/blender/makesrna/intern/CMakeLists.txt
    branches/soc-2013-depsgraph_mt/source/blender/makesrna/intern/SConscript
    branches/soc-2013-depsgraph_mt/source/creator/creator.c

Added Paths:
-----------
    branches/soc-2013-depsgraph_mt/intern/guardedalloc/intern/mallocn_guarded_impl.c
    branches/soc-2013-depsgraph_mt/intern/guardedalloc/intern/mallocn_intern.h
    branches/soc-2013-depsgraph_mt/intern/guardedalloc/intern/mallocn_lockfree_impl.c

Modified: branches/soc-2013-depsgraph_mt/CMakeLists.txt
===================================================================
--- branches/soc-2013-depsgraph_mt/CMakeLists.txt	2013-09-09 09:14:49 UTC (rev 59941)
+++ branches/soc-2013-depsgraph_mt/CMakeLists.txt	2013-09-09 09:27:25 UTC (rev 59942)
@@ -282,9 +282,6 @@
 option(WITH_CXX_GUARDEDALLOC "Enable GuardedAlloc for C++ memory allocation tracking (only enable for development)" OFF)
 mark_as_advanced(WITH_CXX_GUARDEDALLOC)
 
-option(WITH_GUARDEDALLOC "Enable GuardedAlloc (DISABLE AT OWN RISK!)" ON)
-mark_as_advanced(WITH_GUARDEDALLOC)
-
 option(WITH_ASSERT_ABORT "Call abort() when raising an assertion through BLI_assert()" OFF)
 mark_as_advanced(WITH_ASSERT_ABORT)
 

Modified: branches/soc-2013-depsgraph_mt/intern/guardedalloc/CMakeLists.txt
===================================================================
--- branches/soc-2013-depsgraph_mt/intern/guardedalloc/CMakeLists.txt	2013-09-09 09:14:49 UTC (rev 59941)
+++ branches/soc-2013-depsgraph_mt/intern/guardedalloc/CMakeLists.txt	2013-09-09 09:27:25 UTC (rev 59942)
@@ -34,11 +34,11 @@
 
 set(SRC
 	./intern/mallocn.c
+	./intern/mallocn_guarded_impl.c
+	./intern/mallocn_lockfree_impl.c
 
 	MEM_guardedalloc.h
-
-	# include here since its a header-only
-	../atomic/atomic_ops.h
+	./intern/mallocn_intern.h
 )
 
 if(WIN32 AND NOT UNIX)
@@ -49,12 +49,6 @@
 	)
 endif()
 
-if (WITH_GUARDEDALLOC)
-	add_definitions(-DWITH_GUARDEDALLOC)
-else()
-	message(WARNING "Disabling GuardedAlloc is experemental, use at own risk!")
-endif()
-
 blender_add_lib(bf_intern_guardedalloc "${SRC}" "${INC}" "${INC_SYS}")
 
 # Override C++ alloc, optional.

Modified: branches/soc-2013-depsgraph_mt/intern/guardedalloc/MEM_guardedalloc.h
===================================================================
--- branches/soc-2013-depsgraph_mt/intern/guardedalloc/MEM_guardedalloc.h	2013-09-09 09:14:49 UTC (rev 59941)
+++ branches/soc-2013-depsgraph_mt/intern/guardedalloc/MEM_guardedalloc.h	2013-09-09 09:27:25 UTC (rev 59942)
@@ -62,12 +62,10 @@
 
 #include <stdio.h>          /* needed for FILE* */
 
-/* needed for uintptr_t, exception, dont use BLI anywhere else in MEM_* */
+/* needed for uintptr_t and attributes, exception, dont use BLI anywhere else in MEM_* */
 #include "../../source/blender/blenlib/BLI_sys_types.h"
+#include "../../source/blender/blenlib/BLI_compiler_attrs.h"
 
-/* some GNU attributes are only available from GCC 4.3 */
-#define MEM_GNU_ATTRIBUTES (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 403))
-
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -75,57 +73,36 @@
 	/** Returns the length of the allocated memory segment pointed at
 	 * by vmemh. If the pointer was not previously allocated by this
 	 * module, the result is undefined.*/
-	size_t MEM_allocN_len(const void *vmemh)
-#if MEM_GNU_ATTRIBUTES
-	__attribute__((warn_unused_result))
-#endif
-	;
+	extern size_t (*MEM_allocN_len)(const void *vmemh) ATTR_WARN_UNUSED_RESULT;
 
 	/**
 	 * Release memory previously allocatred by this module. 
 	 */
-	void MEM_freeN(void *vmemh);
+	extern void (*MEM_freeN)(void *vmemh);
 
 #if 0  /* UNUSED */
 	/**
 	 * Return zero if memory is not in allocated list
 	 */
-	short MEM_testN(void *vmemh);
+	extern short (*MEM_testN)(void *vmemh);
 #endif
 
 	/**
 	 * Duplicates a block of memory, and returns a pointer to the
 	 * newly allocated block.  */
-	void *MEM_dupallocN(const void *vmemh)
-#if MEM_GNU_ATTRIBUTES
-	__attribute__((malloc))
-	__attribute__((warn_unused_result))
-#endif
-	;
+	extern void *(*MEM_dupallocN)(const void *vmemh) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT;
 
 	/**
 	 * Reallocates a block of memory, and returns pointer to the newly
 	 * allocated block, the old one is freed. this is not as optimized
 	 * as a system realloc but just makes a new allocation and copies
 	 * over from existing memory. */
-	void *MEM_reallocN_id(void *vmemh, size_t len, const char *str)
-#if MEM_GNU_ATTRIBUTES
-	__attribute__((malloc))
-	__attribute__((warn_unused_result))
-	__attribute__((alloc_size(2)))
-#endif
-	;
+	extern void *(*MEM_reallocN_id)(void *vmemh, size_t len, const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(2);
 
 	/**
 	 * A variant of realloc which zeros new bytes
 	 */
-	void *MEM_recallocN_id(void *vmemh, size_t len, const char *str)
-#if MEM_GNU_ATTRIBUTES
-	__attribute__((malloc))
-	__attribute__((warn_unused_result))
-	__attribute__((alloc_size(2)))
-#endif
-	;
+	extern void *(*MEM_recallocN_id)(void *vmemh, size_t len, const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(2);
 
 #define MEM_reallocN(vmemh, len) MEM_reallocN_id(vmemh, len, __func__)
 #define MEM_recallocN(vmemh, len) MEM_recallocN_id(vmemh, len, __func__)
@@ -134,97 +111,75 @@
 	 * Allocate a block of memory of size len, with tag name str. The
 	 * memory is cleared. The name must be static, because only a
 	 * pointer to it is stored ! */
-	void *MEM_callocN(size_t len, const char *str)
-#if MEM_GNU_ATTRIBUTES
-	__attribute__((malloc))
-	__attribute__((warn_unused_result))
-	__attribute__((nonnull(2)))
-	__attribute__((alloc_size(1)))
-#endif
-	;
+	extern void *(*MEM_callocN)(size_t len, const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(1) ATTR_NONNULL(2);
 
 	/**
 	 * Allocate a block of memory of size len, with tag name str. The
 	 * name must be a static, because only a pointer to it is stored !
 	 * */
-	void *MEM_mallocN(size_t len, const char *str)
-#if MEM_GNU_ATTRIBUTES
-	__attribute__((malloc))
-	__attribute__((warn_unused_result))
-	__attribute__((nonnull(2)))
-	__attribute__((alloc_size(1)))
-#endif
-	;
+	extern void *(*MEM_mallocN)(size_t len, const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(1) ATTR_NONNULL(2);
 
 	/**
 	 * Same as callocN, clears memory and uses mmap (disk cached) if supported.
 	 * Can be free'd with MEM_freeN as usual.
 	 * */
-	void *MEM_mapallocN(size_t len, const char *str)
-#if MEM_GNU_ATTRIBUTES
-	__attribute__((malloc))
-	__attribute__((warn_unused_result))
-	__attribute__((nonnull(2)))
-	__attribute__((alloc_size(1)))
-#endif
-	;
+	extern void *(*MEM_mapallocN)(size_t len, const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(1) ATTR_NONNULL(2);
 
 	/** Print a list of the names and sizes of all allocated memory
 	 * blocks. as a python dict for easy investigation */ 
-	void MEM_printmemlist_pydict(void);
+	extern void (*MEM_printmemlist_pydict)(void);
 
 	/** Print a list of the names and sizes of all allocated memory
 	 * blocks. */ 
-	void MEM_printmemlist(void);
+	extern void (*MEM_printmemlist)(void);
 
 	/** calls the function on all allocated memory blocks. */
-	void MEM_callbackmemlist(void (*func)(void *));
+	extern void (*MEM_callbackmemlist)(void (*func)(void *));
 
 	/** Print statistics about memory usage */
-	void MEM_printmemlist_stats(void);
+	extern void (*MEM_printmemlist_stats)(void);
 	
 	/** Set the callback function for error output. */
-	void MEM_set_error_callback(void (*func)(const char *));
+	extern void (*MEM_set_error_callback)(void (*func)(const char *));
 
 	/**
 	 * Are the start/end block markers still correct ?
 	 *
 	 * @retval 0 for correct memory, 1 for corrupted memory. */
-	bool MEM_check_memory_integrity(void);
+	extern bool (*MEM_check_memory_integrity)(void);
 
 	/** Set thread locking functions for safe memory allocation from multiple
 	 * threads, pass NULL pointers to disable thread locking again. */
-	void MEM_set_lock_callback(void (*lock)(void), void (*unlock)(void));
+	extern void (*MEM_set_lock_callback)(void (*lock)(void), void (*unlock)(void));
 	
 	/** Attempt to enforce OSX (or other OS's) to have malloc and stack nonzero */
-	void MEM_set_memory_debug(void);
+	extern void (*MEM_set_memory_debug)(void);
 
 	/**
 	 * Memory usage stats
 	 * - MEM_get_memory_in_use is all memory
 	 * - MEM_get_mapped_memory_in_use is a subset of all memory */
-	uintptr_t MEM_get_memory_in_use(void);
+	extern uintptr_t (*MEM_get_memory_in_use)(void);
 	/** Get mapped memory usage. */
-	uintptr_t MEM_get_mapped_memory_in_use(void);
+	extern uintptr_t (*MEM_get_mapped_memory_in_use)(void);
 	/** Get amount of memory blocks in use. */
-	unsigned int MEM_get_memory_blocks_in_use(void);
+	extern unsigned int (*MEM_get_memory_blocks_in_use)(void);
 
 	/** Reset the peak memory statistic to zero. */
-	void MEM_reset_peak_memory(void);
+	extern void (*MEM_reset_peak_memory)(void);
 
 	/** Get the peak memory usage in bytes, including mmap allocations. */
-	size_t MEM_get_peak_memory(void)
-#if MEM_GNU_ATTRIBUTES
-	__attribute__((warn_unused_result))
-#endif
-	;
+	extern size_t (*MEM_get_peak_memory)(void) ATTR_WARN_UNUSED_RESULT;
 
 #define MEM_SAFE_FREE(v) if (v) { MEM_freeN(v); v = NULL; } (void)0
 
 #ifndef NDEBUG
-const char *MEM_name_ptr(void *vmemh);
+extern const char *(*MEM_name_ptr)(void *vmemh);
 #endif
 
+/* Switch allocator to slower but fully guarded mode. */
+void MEM_use_guarded_allocator(void);
+
 #ifdef __cplusplus
 /* alloc funcs for C++ only */
 #define MEM_CXX_CLASS_ALLOC_FUNCS(_id)                                        \

Modified: branches/soc-2013-depsgraph_mt/intern/guardedalloc/SConscript
===================================================================
--- branches/soc-2013-depsgraph_mt/intern/guardedalloc/SConscript	2013-09-09 09:14:49 UTC (rev 59941)
+++ branches/soc-2013-depsgraph_mt/intern/guardedalloc/SConscript	2013-09-09 09:27:25 UTC (rev 59942)
@@ -31,9 +31,6 @@
 
 sources = ['intern/mallocn.c', 'intern/mmap_win.c']
 
-# could make this optional
-defs.append('WITH_GUARDEDALLOC')
-
 if env['WITH_BF_CXX_GUARDEDALLOC']:
     sources.append('cpp/mallocn.cpp')
     defs.append('WITH_CXX_GUARDEDALLOC')

Modified: branches/soc-2013-depsgraph_mt/intern/guardedalloc/intern/mallocn.c
===================================================================
--- branches/soc-2013-depsgraph_mt/intern/guardedalloc/intern/mallocn.c	2013-09-09 09:14:49 UTC (rev 59941)
+++ branches/soc-2013-depsgraph_mt/intern/guardedalloc/intern/mallocn.c	2013-09-09 09:27:25 UTC (rev 59942)
@@ -32,1262 +32,64 @@
  * Guarded memory allocation, and boundary-write detection.
  */
 
-#include <stdlib.h>
-#include <string.h> /* memcpy */
-#include <stdarg.h>
-#include <sys/types.h>
-
-/* mmap exception */
-#if defined(WIN32)
-#  include "mmap_win.h"
-#else
-#  include <sys/mman.h>
-#endif
-
-#if defined(_MSC_VER)
-#  define __func__ __FUNCTION__
-#endif
-

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list