new memory debug feature

Andrew Lunn andrew@lunn.ch
Thu Jul 1 14:51:00 GMT 2004


> There are quite a lot of functions with weak attributes scattered
> around the sources. Take a look, for example, at hal_spurious_IRQ() in
> the ARM architecture HAL. There certainly shouldn't be any compiler
> problems in this area, it's platform independent and has been working
> for years.

I had the syntax wrong :-(

Anyway, here i what i think is the final version. I've compiled it for
synth and run the memalloc tests and compiled both default and redboot
template for the edb7xxx without problems.

        Andrew

-------------- next part --------------
? services/memalloc/common/current/src/debug.c
Index: services/memalloc/common/current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/ChangeLog,v
retrieving revision 1.30
diff -u -r1.30 ChangeLog
--- services/memalloc/common/current/ChangeLog	15 Mar 2004 15:42:04 -0000	1.30
+++ services/memalloc/common/current/ChangeLog	1 Jul 2004 14:49:10 -0000
@@ -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.
Index: services/memalloc/common/current/cdl/memalloc.cdl
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/cdl/memalloc.cdl,v
retrieving revision 1.12
diff -u -r1.12 memalloc.cdl
--- services/memalloc/common/current/cdl/memalloc.cdl	6 Oct 2003 16:41:07 -0000	1.12
+++ services/memalloc/common/current/cdl/memalloc.cdl	1 Jul 2004 14:49:11 -0000
@@ -56,7 +56,7 @@
         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 @@
             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
Index: services/memalloc/common/current/include/common.hxx
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/include/common.hxx,v
retrieving revision 1.3
diff -u -r1.3 common.hxx
--- services/memalloc/common/current/include/common.hxx	23 May 2002 23:08:43 -0000	1.3
+++ services/memalloc/common/current/include/common.hxx	1 Jul 2004 14:49:12 -0000
@@ -130,6 +130,23 @@
 // 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 */
Index: services/memalloc/common/current/include/kapi.h
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/include/kapi.h,v
retrieving revision 1.4
diff -u -r1.4 kapi.h
--- services/memalloc/common/current/include/kapi.h	15 Mar 2004 15:42:04 -0000	1.4
+++ services/memalloc/common/current/include/kapi.h	1 Jul 2004 14:49:12 -0000
@@ -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 @@
    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 */
Index: services/memalloc/common/current/include/memjoin.inl
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/include/memjoin.inl,v
retrieving revision 1.6
diff -u -r1.6 memjoin.inl
--- services/memalloc/common/current/include/memjoin.inl	5 Feb 2003 01:10:12 -0000	1.6
+++ services/memalloc/common/current/include/memjoin.inl	1 Jul 2004 14:49:12 -0000
@@ -178,6 +178,9 @@
     }
 
     CYG_REPORT_RETVAL( ptr );
+
+    CYG_MEMALLOC_FAIL_TEST(ptr==NULL, size);
+
     return ptr;
 } // Cyg_Mempool_Joined<T>::try_alloc()
 
@@ -214,6 +217,7 @@
     ret = pool->resize_alloc( alloc_ptr, newsize, oldsize );
 
     CYG_REPORT_RETVAL( ret );
+
     return ret;    
 } // Cyg_Mempool_Joined<T>::resize_alloc()
 
Index: services/memalloc/common/current/include/mempolt2.inl
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/include/mempolt2.inl,v
retrieving revision 1.3
diff -u -r1.3 mempolt2.inl
--- services/memalloc/common/current/include/mempolt2.inl	23 May 2002 23:08:43 -0000	1.3
+++ services/memalloc/common/current/include/mempolt2.inl	1 Jul 2004 14:49:13 -0000
@@ -116,6 +116,8 @@
 
     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 @@
     // 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 @@
 
     // Unlock the scheduler and maybe switch threads
     Cyg_Scheduler::unlock();
+
+    CYG_MEMALLOC_FAIL_TEST(ret==NULL, size);
+
     return ret;
 }
     
@@ -283,6 +291,9 @@
 
     // Unlock the scheduler and maybe switch threads
     Cyg_Scheduler::unlock();
+
+    CYG_MEMALLOC_FAIL_TEST(ret==NULL, newsize);
+
     return ret;
 }
     
Index: services/memalloc/common/current/include/mempoolt.inl
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/include/mempoolt.inl,v
retrieving revision 1.3
diff -u -r1.3 mempoolt.inl
--- services/memalloc/common/current/include/mempoolt.inl	23 May 2002 23:08:43 -0000	1.3
+++ services/memalloc/common/current/include/mempoolt.inl	1 Jul 2004 14:49:14 -0000
@@ -111,6 +111,9 @@
     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 @@
         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 @@
     // Unlock the scheduler and maybe switch threads
     Cyg_Scheduler::unlock();
     CYG_REPORT_RETVAL( ret );
+
+    CYG_MEMALLOC_FAIL_TEST(ret==NULL, size);
+
     return ret;
 }
     
Index: services/memalloc/common/current/include/mfiximpl.inl
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/include/mfiximpl.inl,v
retrieving revision 1.3
diff -u -r1.3 mfiximpl.inl
--- services/memalloc/common/current/include/mfiximpl.inl	23 May 2002 23:08:44 -0000	1.3
+++ services/memalloc/common/current/include/mfiximpl.inl	1 Jul 2004 14:49:14 -0000
@@ -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 @@
 {
     // 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 @@
 
     if (newsize == blocksize)
         return alloc_ptr;
-    else
+    else {
+	CYG_MEMALLOC_FAIL(newsize);
         return NULL;
+    }
 } // resize_alloc()
 
 
Index: services/memalloc/common/current/include/mvarimpl.inl
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/include/mvarimpl.inl,v
retrieving revision 1.5
diff -u -r1.5 mvarimpl.inl
--- services/memalloc/common/current/include/mvarimpl.inl	23 May 2002 23:08:44 -0000	1.5
+++ services/memalloc/common/current/include/mvarimpl.inl	1 Jul 2004 14:49:15 -0000
@@ -275,6 +275,8 @@
     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 @@
         ret = alloc_ptr;
     }
         
+    CYG_MEMALLOC_FAIL_TEST(ret==NULL, newsize);
+
     return ret;
 
 } // resize_alloc()
Index: services/memalloc/common/current/include/sepmetaimpl.inl
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/include/sepmetaimpl.inl,v
retrieving revision 1.4
diff -u -r1.4 sepmetaimpl.inl
--- services/memalloc/common/current/include/sepmetaimpl.inl	23 May 2002 23:08:44 -0000	1.4
+++ services/memalloc/common/current/include/sepmetaimpl.inl	1 Jul 2004 14:49:16 -0000
@@ -374,8 +374,12 @@
     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 @@
 
         // 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 @@
             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 @@
         } 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;
Index: services/memalloc/common/current/src/dlmalloc.cxx
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/src/dlmalloc.cxx,v
retrieving revision 1.8
diff -u -r1.8 dlmalloc.cxx
--- services/memalloc/common/current/src/dlmalloc.cxx	6 Oct 2003 18:25:57 -0000	1.8
+++ services/memalloc/common/current/src/dlmalloc.cxx	1 Jul 2004 14:49:19 -0000
@@ -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 @@
       //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 @@
 
     // couldn't resize the allocation any direction, so return failure
     MALLOC_UNLOCK;
+    CYG_MEMALLOC_FAIL(bytes);
     return NULL;
   }
 


More information about the Ecos-patches mailing list