USE_DELETED_CHAIN, memory alignment

This commit is contained in:
David Rose 2009-04-24 22:52:23 +00:00
parent 926059131b
commit f68fa1909a
9 changed files with 133 additions and 16 deletions

View File

@ -395,6 +395,13 @@
//#defer ALTERNATIVE_MALLOC $[or $[WINDOWS_PLATFORM],$[DO_MEMORY_USAGE],$[not $[HAVE_THREADS]]]
#define ALTERNATIVE_MALLOC
// Define this true to use the DELETED_CHAIN macros, which support
// fast re-use of existing allocated blocks, minimizing the low-level
// calls to malloc() and free() for frequently-created and -deleted
// objects. There's usually no reason to set this false, unless you
// suspect a bug in Panda's memory management code.
#define USE_DELETED_CHAIN 1
// Define this true to build the low-level native network
// implementation. Normally this should be set true.
#define WANT_NATIVE_NET 1
@ -407,6 +414,11 @@
// Normally, if you build NATIVE_NET, you will also build NET.
#defer HAVE_NET $[WANT_NATIVE_NET]
// Do you want to build the egg loader? Usually there's no reason to
// avoid building this, unless you really want to make a low-footprint
// build (such as, for instance, for the iPhone).
#define HAVE_EGG 1
// Is a third-party STL library installed, and where? This is only
// necessary if the default include and link lines that come with the
// compiler don't provide adequate STL support. At least some form of
@ -460,6 +472,17 @@
#define TIFF_LIBS tiff z
#defer HAVE_TIFF $[libtest $[TIFF_LPATH],$[TIFF_LIBS]]
// These image file formats don't require the assistance of a
// third-party library to read and write, so there's normally no
// reason to disable them in the build, unless you are looking to
// reduce the memory footprint.
#define HAVE_SGI_RGB 1
#define HAVE_TGA 1
#define HAVE_IMG 1
#define HAVE_SOFTIMAGE_PIC 1
#define HAVE_BMP 1
#define HAVE_PNM 1
// Is libtar installed, and where? This is used to optimize patch
// generation against tar files.
#define TAR_IPATH

View File

@ -244,6 +244,14 @@ $[cdefine HAVE_PNG]
/* Define if we have libtiff installed. */
$[cdefine HAVE_TIFF]
/* Define if we want to build these other image file formats. */
$[cdefine HAVE_SGI_RGB]
$[cdefine HAVE_TGA]
$[cdefine HAVE_IMG]
$[cdefine HAVE_SOFTIMAGE_PIC]
$[cdefine HAVE_BMP]
$[cdefine HAVE_PNM]
/* Define if we have libtar installed. */
$[cdefine HAVE_TAR]
@ -344,6 +352,9 @@ $[cdefine USE_PANDAFILESTREAM]
/* Define if we want to compile the net code. */
$[cdefine HAVE_NET]
/* Define if we want to compile the egg code. */
$[cdefine HAVE_EGG]
/* Define if we want to compile the audio code. */
$[cdefine HAVE_AUDIO]
@ -584,6 +595,9 @@ $[cdefine USE_MEMORY_PTMALLOC2]
$[cdefine USE_MEMORY_MALLOC]
$[cdefine USE_MEMORY_NOWRAPPERS]
// To activate the DELETED_CHAIN macros.
$[cdefine USE_DELETED_CHAIN]
// If we are to build the native net interfaces.
$[cdefine WANT_NATIVE_NET]

View File

@ -8,12 +8,13 @@
#define IPH_VERSION 2.0
#if $[eq $[IPH_PLATFORM], iPhoneOS]
#define ARCH_FLAGS -arch armv6
#define osflags -miphoneos-version-min=2.0
#define DEBUGFLAGS
#define ARCH_FLAGS -arch armv6 -mcpu=arm1176jzf-s
#define osflags -fpascal-strings -fasm-blocks -fvisibility=hidden -fvisibility-inlines-hidden -miphoneos-version-min=2.0
#define DEBUGFLAGS -gdwarf-2
//#define DEBUGFLAGS
#elif $[eq $[IPH_PLATFORM], iPhoneSimulator]
#define ARCH_FLAGS -arch i386
#define osflags -mmacosx-version-min=10.5
#define osflags -fpascal-strings -fasm-blocks -fvisibility=hidden -fvisibility-inlines-hidden -mmacosx-version-min=10.5
#define DEBUGFLAGS -gdwarf-2
#else
#error Inappropriate value for BUILD_IPHONE.

View File

@ -30,7 +30,7 @@ validate(void *ptr) {
return false;
}
#ifdef USE_DELETEDCHAINFLAG
#if defined(USE_DELETEDCHAINFLAG) && defined(USE_DELETED_CHAIN)
const ObjectNode *obj = buffer_to_node(ptr);
return AtomicAdjust::get(obj->_flag) == DCF_alive;
#else
@ -56,7 +56,7 @@ get_buffer_size() const {
////////////////////////////////////////////////////////////////////
INLINE void *DeletedBufferChain::
node_to_buffer(DeletedBufferChain::ObjectNode *node) {
#ifdef USE_DELETEDCHAINFLAG
#if defined(USE_DELETEDCHAINFLAG) && defined(USE_DELETED_CHAIN)
// In development mode, we increment the pointer so that the
// returned data does not overlap our _flag member.
return (void *)(((AtomicAdjust::Integer *)node) + 1);
@ -72,7 +72,7 @@ node_to_buffer(DeletedBufferChain::ObjectNode *node) {
////////////////////////////////////////////////////////////////////
INLINE DeletedBufferChain::ObjectNode *DeletedBufferChain::
buffer_to_node(void *ptr) {
#ifdef USE_DELETEDCHAINFLAG
#if defined(USE_DELETEDCHAINFLAG) && defined(USE_DELETED_CHAIN)
// In development mode, we decrement the pointer to undo the
// increment we did above.
return (ObjectNode *)(((AtomicAdjust::Integer *)ptr) - 1);

View File

@ -46,6 +46,7 @@ DeletedBufferChain(size_t buffer_size) {
////////////////////////////////////////////////////////////////////
void *DeletedBufferChain::
allocate(size_t size, TypeHandle type_handle) {
#ifdef USE_DELETED_CHAIN
TAU_PROFILE("void *DeletedBufferChain::allocate(size_t, TypeHandle)", " ", TAU_USER);
assert(size <= _buffer_size);
@ -89,6 +90,10 @@ allocate(size_t size, TypeHandle type_handle) {
#endif // DO_MEMORY_USAGE
return ptr;
#else // USE_DELETED_CHAIN
return PANDA_MALLOC_SINGLE(_buffer_size);
#endif // USE_DELETED_CHAIN
}
////////////////////////////////////////////////////////////////////
@ -99,6 +104,7 @@ allocate(size_t size, TypeHandle type_handle) {
////////////////////////////////////////////////////////////////////
void DeletedBufferChain::
deallocate(void *ptr, TypeHandle type_handle) {
#ifdef USE_DELETED_CHAIN
TAU_PROFILE("void DeletedBufferChain::deallocate(void *, TypeHandle)", " ", TAU_USER);
assert(ptr != (void *)NULL);
@ -127,4 +133,8 @@ deallocate(void *ptr, TypeHandle type_handle) {
_deleted_chain = obj;
_lock.release();
#else // USE_DELETED_CHAIN
PANDA_FREE_SINGLE(ptr);
#endif // USE_DELETED_CHAIN
}

View File

@ -87,6 +87,7 @@ public:
static DeletedChain<Type> _chain;
};
#ifdef USE_DELETED_CHAIN
// Place this macro within a class definition to define appropriate
// operator new and delete methods that take advantage of
// DeletedChain.
@ -131,6 +132,20 @@ public:
#define ALLOC_DELETED_CHAIN_DEF(Type) \
DeletedChain< Type > Type::_deleted_chain;
#else // USE_DELETED_CHAIN
#define ALLOC_DELETED_CHAIN(Type) \
inline static bool validate_ptr(const void *ptr) { \
return (ptr != NULL); \
}
#define ALLOC_DELETED_CHAIN_DECL(Type) \
inline static bool validate_ptr(const void *ptr) { \
return (ptr != NULL); \
}
#define ALLOC_DELETED_CHAIN_DEF(Type)
#endif // USE_DELETED_CHAIN
#include "deletedChain.T"
#endif

View File

@ -189,9 +189,15 @@ heap_alloc_single(size_t size) {
void *alloc = call_malloc(inflate_size(size));
#endif
if (alloc == (void *)NULL) {
cerr << "Out of memory!\n";
abort();
while (alloc == (void *)NULL) {
alloc_fail();
#ifdef MEMORY_HOOK_MALLOC_LOCK
_lock.acquire();
alloc = call_malloc(inflate_size(size));
_lock.release();
#else
alloc = call_malloc(inflate_size(size));
#endif
}
#ifdef DO_MEMORY_USAGE
@ -255,9 +261,15 @@ heap_alloc_array(size_t size) {
void *alloc = call_malloc(inflate_size(size));
#endif
if (alloc == (void *)NULL) {
cerr << "Out of memory!\n";
abort();
while (alloc == (void *)NULL) {
alloc_fail();
#ifdef MEMORY_HOOK_MALLOC_LOCK
_lock.acquire();
alloc = call_malloc(inflate_size(size));
_lock.release();
#else
alloc = call_malloc(inflate_size(size));
#endif
}
#ifdef DO_MEMORY_USAGE
@ -298,9 +310,19 @@ heap_realloc_array(void *ptr, size_t size) {
alloc = call_realloc(alloc, inflate_size(size));
#endif
if (alloc == (void *)NULL) {
cerr << "Out of memory!\n";
abort();
while (alloc == (void *)NULL) {
alloc_fail();
// Recover the original pointer.
alloc = ptr_to_alloc(ptr, orig_size);
#ifdef MEMORY_HOOK_MALLOC_LOCK
_lock.acquire();
alloc = call_realloc(alloc, inflate_size(size));
_lock.release();
#else
alloc = call_realloc(alloc, inflate_size(size));
#endif
}
return alloc_to_ptr(alloc, size);
@ -499,6 +521,29 @@ get_deleted_chain(size_t buffer_size) {
return chain;
}
////////////////////////////////////////////////////////////////////
// Function: MemoryHook::alloc_fail
// Access: Protected, Virtual
// Description: This callback method is called whenever a low-level
// call to call_malloc() has returned NULL, indicating
// failure.
//
// Since this method is called very low-level, and may
// be in the middle of any number of critical sections,
// it will be difficult for this callback initiate any
// emergency high-level operation to make more memory
// available. However, this module is set up to assume
// that that's what this method does, and will make
// another alloc attempt after it returns. Probably the
// only sensible thing this method can do, however, is
// just to display a message and abort.
////////////////////////////////////////////////////////////////////
void MemoryHook::
alloc_fail() {
cerr << "Out of memory!\n";
abort();
}
#ifdef DO_MEMORY_USAGE
////////////////////////////////////////////////////////////////////
// Function: MemoryHook::overflow_heap_size

View File

@ -67,6 +67,8 @@ public:
DeletedBufferChain *get_deleted_chain(size_t buffer_size);
virtual void alloc_fail();
private:
INLINE static size_t inflate_size(size_t size);
INLINE static void *alloc_to_ptr(void *alloc, size_t size);

View File

@ -25,6 +25,10 @@ static const size_t min_page_remaining_size = 16;
// We always allocate at least this many bytes at a time.
static const size_t min_page_size = 128 * 1024; // 128K
// We always allocate integer multiples of this many bytes, to
// guarantee this minimum alignment.
static const size_t alignment_size = sizeof(long);
////////////////////////////////////////////////////////////////////
// Function: NeverFreeMemory::Constructor
// Access: Private
@ -45,6 +49,9 @@ void *NeverFreeMemory::
ns_alloc(size_t size) {
_lock.acquire();
// Round up to the next alignment_size.
size = ((size + alignment_size - 1) / alignment_size) * alignment_size;
_total_used += size;
// Look for a page that has sufficient space remaining.