changeset 1687:eb235374a7ae

2004-06-24 Oyvind Harboe <oyvind.harboe@zylin.com> * Added cyg_memalloc_alloc_fail() fn which is invoked before return NULL from failed allocations. Useful breakpoint site. Andrew Lunn wrote some of the code and pointed out various wrinkles to be ironed out.
author asl
date Mon, 05 Jul 2004 11:07:04 +0000
parents 961151dc048e
children 30d12b1c7bb0
files packages/services/memalloc/common/current/ChangeLog packages/services/memalloc/common/current/cdl/memalloc.cdl packages/services/memalloc/common/current/include/common.hxx packages/services/memalloc/common/current/include/kapi.h packages/services/memalloc/common/current/include/memjoin.inl packages/services/memalloc/common/current/include/mempolt2.inl packages/services/memalloc/common/current/include/mempoolt.inl packages/services/memalloc/common/current/include/mfiximpl.inl packages/services/memalloc/common/current/include/mvarimpl.inl packages/services/memalloc/common/current/include/sepmetaimpl.inl packages/services/memalloc/common/current/src/dlmalloc.cxx
diffstat 11 files changed, 108 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/packages/services/memalloc/common/current/ChangeLog
+++ b/packages/services/memalloc/common/current/ChangeLog
@@ -1,3 +1,10 @@
+2004-06-24  Oyvind Harboe  <oyvind.harboe@zylin.com>
+
+	* Added cyg_memalloc_alloc_fail() fn which is invoked before 
+	return NULL from failed allocations. Useful breakpoint site.
+	Andrew Lunn wrote some of the code and pointed out various
+	wrinkles to be ironed out.
+
 2004-02-15  Jonathan Larmour  <jifl@eCosCentric.com>
 
 	* include/kapi.h: Add throw specifications throughout.
--- a/packages/services/memalloc/common/current/cdl/memalloc.cdl
+++ b/packages/services/memalloc/common/current/cdl/memalloc.cdl
@@ -56,7 +56,7 @@ cdl_package CYGPKG_MEMALLOC {
         interface. It also contains some sample implementations."
     include_dir   cyg/memalloc
     compile       dlmalloc.cxx memfixed.cxx memvar.cxx \
-                  sepmeta.cxx
+                  sepmeta.cxx debug.c
 
 # ====================================================================
 
@@ -239,6 +239,15 @@ cdl_package CYGPKG_MEMALLOC {
             forces a NULL pointer to be returned."
     }       
 
+    cdl_option CYGSEM_MEMALLOC_INVOKE_OUT_OF_MEMORY {
+        display       "Breakpoint site when running out of memory"
+        default_value 0
+        description   "
+            Whenever the system runs out of memory, it invokes this function
+            before either going to sleep waiting for memory to become 
+            available or returning failure."
+    }       
+
     cdl_component CYGPKG_MEMALLOC_MALLOC_ALLOCATORS {
         display      "malloc() and supporting allocators"
         flavor        bool
--- a/packages/services/memalloc/common/current/include/common.hxx
+++ b/packages/services/memalloc/common/current/include/common.hxx
@@ -130,6 +130,23 @@ public:
 // And an opaque type for any arguments with these flags
 typedef cyg_uint16 cyg_mempool_status_flag_t;
 
+// breakpoint site for out of memory conditions
+#ifdef CYGSEM_MEMALLOC_INVOKE_OUT_OF_MEMORY
+#include <cyg/memalloc/kapi.h> // protoype for cyg_memalloc_alloc_fail
+#define CYG_MEMALLOC_FAIL_TEST( test, size )                \
+   CYG_MACRO_START                                          \
+   if ( test) {                                             \
+        cyg_memalloc_alloc_fail(__FILE__, __LINE__, size ); \
+   }                                                        \
+   CYG_MACRO_END
+#define CYG_MEMALLOC_FAIL( size)                            \
+   CYG_MACRO_START                                          \
+   cyg_memalloc_alloc_fail(__FILE__, __LINE__, size );      \
+   CYG_MACRO_END
+#else
+#define CYG_MEMALLOC_FAIL_TEST( test, size )  CYG_EMPTY_STATEMENT
+#define CYG_MEMALLOC_FAIL( size )             CYG_EMPTY_STATEMENT
+#endif        
 
 #endif /* ifndef CYGONCE_MEMALLOC_COMMON_HXX */
 /* EOF common.hxx */
--- a/packages/services/memalloc/common/current/include/kapi.h
+++ b/packages/services/memalloc/common/current/include/kapi.h
@@ -58,11 +58,23 @@
 //========================================================================*/
 
 /* CONFIGURATION */
-
+#include <pkgconf/system.h>
 #include <pkgconf/memalloc.h>
 
 /* TYPE DEFINITIONS */
+#ifdef CYGPKG_KERNEL
+#include <cyg/kernel/kapi.h>
+#else
+typedef cyg_uint32 cyg_handle_t;
+#endif
 
+/*---------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*---------------------------------------------------------------------------*/
 struct cyg_mempool_var;
 typedef struct cyg_mempool_var cyg_mempool_var;
 
@@ -176,6 +188,16 @@ cyg_bool_t cyg_mempool_fix_waiting(cyg_h
    provided. */
 void cyg_mempool_fix_get_info(cyg_handle_t fixpool, cyg_mempool_info *info) __THROW;
 
+/* user overrideable function invoked before running out of memory. */
+__externC void cyg_memalloc_alloc_fail(char * file, int line, cyg_int32 size) 
+     __THROW;
+
+/*---------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*---------------------------------------------------------------------------*/
 
 
 #endif /* ifndef CYGONCE_MEMALLOC_KAPI_H */
--- a/packages/services/memalloc/common/current/include/memjoin.inl
+++ b/packages/services/memalloc/common/current/include/memjoin.inl
@@ -178,6 +178,9 @@ Cyg_Mempool_Joined<T>::try_alloc( cyg_in
     }
 
     CYG_REPORT_RETVAL( ptr );
+
+    CYG_MEMALLOC_FAIL_TEST(ptr==NULL, size);
+
     return ptr;
 } // Cyg_Mempool_Joined<T>::try_alloc()
 
@@ -214,6 +217,7 @@ Cyg_Mempool_Joined<T>::resize_alloc( cyg
     ret = pool->resize_alloc( alloc_ptr, newsize, oldsize );
 
     CYG_REPORT_RETVAL( ret );
+
     return ret;    
 } // Cyg_Mempool_Joined<T>::resize_alloc()
 
--- a/packages/services/memalloc/common/current/include/mempolt2.inl
+++ b/packages/services/memalloc/common/current/include/mempolt2.inl
@@ -116,6 +116,8 @@ Cyg_Mempolt2<T>::alloc( cyg_int32 size )
 
     Mempolt2WaitInfo waitinfo( size );
 
+    CYG_MEMALLOC_FAIL(size);
+
     self->set_wait_info( (CYG_ADDRWORD)&waitinfo );
     self->set_sleep_reason( Cyg_Thread::WAIT );
     self->sleep();
@@ -187,6 +189,9 @@ Cyg_Mempolt2<T>::alloc( cyg_int32 size, 
     // straight to unlock.
     
     if( Cyg_Thread::NONE == self->get_wake_reason() ) {
+
+	CYG_MEMALLOC_FAIL(size);
+
         self->set_wait_info( (CYG_ADDRWORD)&waitinfo );
         self->sleep();
         queue.enqueue( self );
@@ -251,6 +256,9 @@ Cyg_Mempolt2<T>::try_alloc( cyg_int32 si
 
     // Unlock the scheduler and maybe switch threads
     Cyg_Scheduler::unlock();
+
+    CYG_MEMALLOC_FAIL_TEST(ret==NULL, size);
+
     return ret;
 }
     
@@ -283,6 +291,9 @@ Cyg_Mempolt2<T>::resize_alloc( cyg_uint8
 
     // Unlock the scheduler and maybe switch threads
     Cyg_Scheduler::unlock();
+
+    CYG_MEMALLOC_FAIL_TEST(ret==NULL, newsize);
+
     return ret;
 }
     
--- a/packages/services/memalloc/common/current/include/mempoolt.inl
+++ b/packages/services/memalloc/common/current/include/mempoolt.inl
@@ -111,6 +111,9 @@ Cyg_Mempoolt<T>::alloc( cyg_int32 size )
     cyg_uint8 *ret;
     cyg_bool result = true;
     while( result && (NULL == (ret = pool.alloc( size ))) ) {
+
+	CYG_MEMALLOC_FAIL(size);
+
         self->set_sleep_reason( Cyg_Thread::WAIT );
         self->sleep();
         queue.enqueue( self );
@@ -182,6 +185,8 @@ Cyg_Mempoolt<T>::alloc( cyg_int32 size, 
         result = false;
             
     while( result && (NULL == (ret = pool.alloc( size ))) ) {
+	CYG_MEMALLOC_FAIL(size);
+
         self->set_sleep_reason( Cyg_Thread::TIMEOUT );
         self->sleep();
         queue.enqueue( self );
@@ -248,6 +253,9 @@ Cyg_Mempoolt<T>::try_alloc( cyg_int32 si
     // Unlock the scheduler and maybe switch threads
     Cyg_Scheduler::unlock();
     CYG_REPORT_RETVAL( ret );
+
+    CYG_MEMALLOC_FAIL_TEST(ret==NULL, size);
+
     return ret;
 }
     
--- a/packages/services/memalloc/common/current/include/mfiximpl.inl
+++ b/packages/services/memalloc/common/current/include/mfiximpl.inl
@@ -59,6 +59,7 @@
 #include <cyg/hal/hal_arch.h>          // HAL_LSBIT_INDEX magic asm code
 #include <cyg/memalloc/mfiximpl.hxx>
 
+
 // -------------------------------------------------------------------------
 
 inline
@@ -122,8 +123,10 @@ Cyg_Mempool_Fixed_Implementation::try_al
 {
     // size parameter is not used
     CYG_UNUSED_PARAM( cyg_int32, size );
-    if ( 0 >= freeblocks )
+    if ( 0 >= freeblocks ) {
+	CYG_MEMALLOC_FAIL(size);
         return NULL;
+    }
     cyg_int32 i = firstfree;
     cyg_uint8 *p = NULL;
     do {
@@ -172,8 +175,10 @@ Cyg_Mempool_Fixed_Implementation::resize
 
     if (newsize == blocksize)
         return alloc_ptr;
-    else
+    else {
+	CYG_MEMALLOC_FAIL(newsize);
         return NULL;
+    }
 } // resize_alloc()
 
 
--- a/packages/services/memalloc/common/current/include/mvarimpl.inl
+++ b/packages/services/memalloc/common/current/include/mvarimpl.inl
@@ -275,6 +275,8 @@ Cyg_Mempool_Variable_Implementation::try
     cyg_uint8 *ptr = memdq2alloc( dq );
     CYG_ASSERT( ((CYG_ADDRESS)ptr & (alignment-1)) == 0,
                 "returned memory not aligned" );
+    CYG_MEMALLOC_FAIL_TEST(ptr==NULL, size);
+
     return ptr;
 }
 
@@ -358,6 +360,8 @@ Cyg_Mempool_Variable_Implementation::res
         ret = alloc_ptr;
     }
         
+    CYG_MEMALLOC_FAIL_TEST(ret==NULL, newsize);
+
     return ret;
 
 } // resize_alloc()
--- a/packages/services/memalloc/common/current/include/sepmetaimpl.inl
+++ b/packages/services/memalloc/common/current/include/sepmetaimpl.inl
@@ -374,8 +374,12 @@ Cyg_Mempool_Sepmeta_Implementation::try_
     size = (size + alignment - 1) & -alignment;
 
     struct memdq *dq = find_free_dq( size );
-    if (NULL == dq)
+   
+
+    if (NULL == dq) {	
+	CYG_MEMALLOC_FAIL(size);
         return NULL;
+    }
 
     cyg_int32 dqsize = dq->memnext->mem - dq->mem;
 
@@ -399,8 +403,11 @@ Cyg_Mempool_Sepmeta_Implementation::try_
 
         // first get a memdq
 
-        if ( NULL == freemetahead ) // out of metadata. 
+        if ( NULL == freemetahead ) {
+ 	    // out of metadata. 
+	    CYG_MEMALLOC_FAIL(size);
             return NULL;
+	}
 
         // FIXME: since we don't search all the way for an exact fit
         // first we may be able to find an exact fit later and therefore
@@ -496,7 +503,10 @@ Cyg_Mempool_Sepmeta_Implementation::resi
             prevmemsize = dq->mem - dq->memprev->mem;
         }
         if (nextmemsize + prevmemsize + currsize < newsize)
+	{
+    	    CYG_MEMALLOC_FAIL_TEST(true, newsize);
             return NULL; // can't fit it
+	}
 
         // expand forwards
         if ( nextmemsize != 0 ) {
@@ -560,8 +570,10 @@ Cyg_Mempool_Sepmeta_Implementation::resi
         } else {
             // if its already allocated we need to create a new free list
             // entry
-            if (NULL == freemetahead)
+            if (NULL == freemetahead) {
+		CYG_MEMALLOC_FAIL(newsize);
                 return NULL;  // can't do it
+	    }
 
             struct memdq *fdq = freemetahead;
             freemetahead = fdq->next;
--- a/packages/services/memalloc/common/current/src/dlmalloc.cxx
+++ b/packages/services/memalloc/common/current/src/dlmalloc.cxx
@@ -215,7 +215,6 @@
 #include <cyg/infra/cyg_ass.h>         // assertions
 #include <stddef.h>                    // for size_t
 #include <cyg/memalloc/dlmalloc.hxx>
-//#include <cyg/infra/diag.h>
 
 /*
     Debugging:
@@ -1273,6 +1272,7 @@ Cyg_Mempool_dlmalloc_Implementation::try
       //diag_printf("chunksize(top)=%ld, nb=%d, remainder=%ld\n", chunksize(top),
       //            nb, remainder_size);
       MALLOC_UNLOCK;
+      CYG_MEMALLOC_FAIL(bytes);
       return NULL; /* propagate failure */
   }
 
@@ -1558,6 +1558,7 @@ Cyg_Mempool_dlmalloc_Implementation::res
 
     // couldn't resize the allocation any direction, so return failure
     MALLOC_UNLOCK;
+    CYG_MEMALLOC_FAIL(bytes);
     return NULL;
   }