Browse Source

USE_DELETED_CHAIN, memory alignment

David Rose 16 years ago
parent
commit
f68fa1909a

+ 23 - 0
dtool/Config.pp

@@ -395,6 +395,13 @@
 //#defer ALTERNATIVE_MALLOC $[or $[WINDOWS_PLATFORM],$[DO_MEMORY_USAGE],$[not $[HAVE_THREADS]]]
 //#defer ALTERNATIVE_MALLOC $[or $[WINDOWS_PLATFORM],$[DO_MEMORY_USAGE],$[not $[HAVE_THREADS]]]
 #define ALTERNATIVE_MALLOC
 #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
 // Define this true to build the low-level native network
 // implementation.  Normally this should be set true.
 // implementation.  Normally this should be set true.
 #define WANT_NATIVE_NET 1
 #define WANT_NATIVE_NET 1
@@ -407,6 +414,11 @@
 // Normally, if you build NATIVE_NET, you will also build NET.
 // Normally, if you build NATIVE_NET, you will also build NET.
 #defer HAVE_NET $[WANT_NATIVE_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
 // Is a third-party STL library installed, and where?  This is only
 // necessary if the default include and link lines that come with the
 // necessary if the default include and link lines that come with the
 // compiler don't provide adequate STL support.  At least some form of
 // compiler don't provide adequate STL support.  At least some form of
@@ -460,6 +472,17 @@
 #define TIFF_LIBS tiff z
 #define TIFF_LIBS tiff z
 #defer HAVE_TIFF $[libtest $[TIFF_LPATH],$[TIFF_LIBS]]
 #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
 // Is libtar installed, and where?  This is used to optimize patch
 // generation against tar files.
 // generation against tar files.
 #define TAR_IPATH
 #define TAR_IPATH

+ 14 - 0
dtool/LocalSetup.pp

@@ -244,6 +244,14 @@ $[cdefine HAVE_PNG]
 /* Define if we have libtiff installed.  */
 /* Define if we have libtiff installed.  */
 $[cdefine HAVE_TIFF]
 $[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.  */
 /* Define if we have libtar installed.  */
 $[cdefine HAVE_TAR]
 $[cdefine HAVE_TAR]
 
 
@@ -344,6 +352,9 @@ $[cdefine USE_PANDAFILESTREAM]
 /* Define if we want to compile the net code.  */
 /* Define if we want to compile the net code.  */
 $[cdefine HAVE_NET]
 $[cdefine HAVE_NET]
 
 
+/* Define if we want to compile the egg code.  */
+$[cdefine HAVE_EGG]
+
 /* Define if we want to compile the audio code.  */
 /* Define if we want to compile the audio code.  */
 $[cdefine HAVE_AUDIO]
 $[cdefine HAVE_AUDIO]
 
 
@@ -584,6 +595,9 @@ $[cdefine USE_MEMORY_PTMALLOC2]
 $[cdefine USE_MEMORY_MALLOC]
 $[cdefine USE_MEMORY_MALLOC]
 $[cdefine USE_MEMORY_NOWRAPPERS]
 $[cdefine USE_MEMORY_NOWRAPPERS]
 
 
+// To activate the DELETED_CHAIN macros.
+$[cdefine USE_DELETED_CHAIN]
+
 // If we are to build the native net interfaces.
 // If we are to build the native net interfaces.
 $[cdefine WANT_NATIVE_NET]
 $[cdefine WANT_NATIVE_NET]
 
 

+ 5 - 4
dtool/pptempl/PostConfig.pp

@@ -8,12 +8,13 @@
   #define IPH_VERSION 2.0
   #define IPH_VERSION 2.0
   
   
   #if $[eq $[IPH_PLATFORM], iPhoneOS]
   #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]
   #elif $[eq $[IPH_PLATFORM], iPhoneSimulator]
     #define ARCH_FLAGS -arch i386
     #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
     #define DEBUGFLAGS -gdwarf-2
   #else
   #else
     #error Inappropriate value for BUILD_IPHONE.
     #error Inappropriate value for BUILD_IPHONE.

+ 3 - 3
dtool/src/dtoolbase/deletedBufferChain.I

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

+ 10 - 0
dtool/src/dtoolbase/deletedBufferChain.cxx

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

+ 15 - 0
dtool/src/dtoolbase/deletedChain.h

@@ -87,6 +87,7 @@ public:
   static DeletedChain<Type> _chain;
   static DeletedChain<Type> _chain;
 };
 };
 
 
+#ifdef USE_DELETED_CHAIN
 // Place this macro within a class definition to define appropriate
 // Place this macro within a class definition to define appropriate
 // operator new and delete methods that take advantage of
 // operator new and delete methods that take advantage of
 // DeletedChain.
 // DeletedChain.
@@ -131,6 +132,20 @@ public:
 #define ALLOC_DELETED_CHAIN_DEF(Type)                        \
 #define ALLOC_DELETED_CHAIN_DEF(Type)                        \
   DeletedChain< Type > Type::_deleted_chain;
   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"
 #include "deletedChain.T"
 
 
 #endif
 #endif

+ 54 - 9
dtool/src/dtoolbase/memoryHook.cxx

@@ -189,9 +189,15 @@ heap_alloc_single(size_t size) {
   void *alloc = call_malloc(inflate_size(size));
   void *alloc = call_malloc(inflate_size(size));
 #endif
 #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
 #ifdef DO_MEMORY_USAGE
@@ -255,9 +261,15 @@ heap_alloc_array(size_t size) {
   void *alloc = call_malloc(inflate_size(size));
   void *alloc = call_malloc(inflate_size(size));
 #endif
 #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
 #ifdef DO_MEMORY_USAGE
@@ -298,9 +310,19 @@ heap_realloc_array(void *ptr, size_t size) {
   alloc = call_realloc(alloc, inflate_size(size));
   alloc = call_realloc(alloc, inflate_size(size));
 #endif
 #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);
   return alloc_to_ptr(alloc, size);
@@ -499,6 +521,29 @@ get_deleted_chain(size_t buffer_size) {
   return chain;
   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
 #ifdef DO_MEMORY_USAGE
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: MemoryHook::overflow_heap_size
 //     Function: MemoryHook::overflow_heap_size

+ 2 - 0
dtool/src/dtoolbase/memoryHook.h

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

+ 7 - 0
dtool/src/dtoolbase/neverFreeMemory.cxx

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