This is the mail archive of the ecos-patches@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

new memory debug feature


-- 
Øyvind Harboe
http://www.zylin.com

Index: ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/ChangeLog,v
retrieving revision 1.30
diff -u -5 -p -w -r1.30 ChangeLog
--- ChangeLog	15 Mar 2004 15:42:04 -0000	1.30
+++ ChangeLog	24 Jun 2004 11:23:28 -0000
@@ -1,5 +1,13 @@
+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.
 	* src/kapi.cxx: Ditto.
 
Index: cdl/memalloc.cdl
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/cdl/memalloc.cdl,v
retrieving revision 1.12
diff -u -5 -p -w -r1.12 memalloc.cdl
--- cdl/memalloc.cdl	6 Oct 2003 16:41:07 -0000	1.12
+++ cdl/memalloc.cdl	24 Jun 2004 11:23:28 -0000
@@ -54,11 +54,11 @@ cdl_package CYGPKG_MEMALLOC {
         This package provides memory allocator infrastructure required for
         dynamic memory allocators, including the ISO standard malloc
         interface. It also contains some sample implementations."
     include_dir   cyg/memalloc
     compile       dlmalloc.cxx memfixed.cxx memvar.cxx \
-                  sepmeta.cxx
+                  sepmeta.cxx debug.c
 
 # ====================================================================
 
     cdl_component CYGPKG_MEMALLOC_ALLOCATORS {
         display       "Memory allocator implementations"
@@ -237,10 +237,19 @@ cdl_package CYGPKG_MEMALLOC {
             either argument 0 ). It is permitted by the standard to return
             either a NULL pointer or a unique pointer. Enabling this option
             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
         active_if     CYGPKG_ISOINFRA
         implements    CYGINT_ISO_MALLOC
Index: include/common.hxx
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/include/common.hxx,v
retrieving revision 1.3
diff -u -5 -p -w -r1.3 common.hxx
--- include/common.hxx	23 May 2002 23:08:43 -0000	1.3
+++ include/common.hxx	24 Jun 2004 11:23:36 -0000
@@ -55,10 +55,12 @@
 //
 //========================================================================*/
 
 /* CONFIGURATION */
 
+#include <cyg/kernel/kapi.h>
+#include <cyg/memalloc/kapi.h>
 #include <pkgconf/memalloc.h>
 
 /* TYPE DEFINITIONS */
 
 // struct Cyg_Mempool_Status is returned by the get_status() method of
@@ -129,7 +131,20 @@ 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
+#define CYG_MEMALLOC_FAIL_TEST( test, size)          \
+   CYG_MACRO_START                                \
+   if ( test) {                              \
+        cyg_memalloc_alloc_fail(__FILE__, __LINE__, size ); \
+   }                                                \
+   CYG_MACRO_END
+#else
+#define CYG_MEMALLOC_FAIL_TEST( test, size)  CYG_EMPTY_STATEMENT
+#endif        
+
 #endif /* ifndef CYGONCE_MEMALLOC_COMMON_HXX */
 /* EOF common.hxx */
Index: include/kapi.h
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/include/kapi.h,v
retrieving revision 1.4
diff -u -5 -p -w -r1.4 kapi.h
--- include/kapi.h	15 Mar 2004 15:42:04 -0000	1.4
+++ include/kapi.h	24 Jun 2004 11:23:36 -0000
@@ -174,9 +174,10 @@ cyg_bool_t cyg_mempool_fix_waiting(cyg_h
 
 /* Puts information about a variable memory pool into the structure
    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;
 
 #endif /* ifndef CYGONCE_MEMALLOC_KAPI_H */
 /* EOF kapi.h */
Index: include/memjoin.inl
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/include/memjoin.inl,v
retrieving revision 1.6
diff -u -5 -p -w -r1.6 memjoin.inl
--- include/memjoin.inl	5 Feb 2003 01:10:12 -0000	1.6
+++ include/memjoin.inl	24 Jun 2004 11:23:37 -0000
@@ -176,10 +176,13 @@ Cyg_Mempool_Joined<T>::try_alloc( cyg_in
         if ( NULL != ptr )
             break;
     }
 
     CYG_REPORT_RETVAL( ptr );
+
+    CYG_MEMALLOC_FAIL_TEST(ptr==NULL, size);
+
     return ptr;
 } // Cyg_Mempool_Joined<T>::try_alloc()
 
 
 // -------------------------------------------------------------------------
@@ -212,10 +215,11 @@ Cyg_Mempool_Joined<T>::resize_alloc( cyg
     CYG_ASSERT( NULL != pool, "Couldn't find pool for pointer!" );
 
     ret = pool->resize_alloc( alloc_ptr, newsize, oldsize );
 
     CYG_REPORT_RETVAL( ret );
+
     return ret;    
 } // Cyg_Mempool_Joined<T>::resize_alloc()
 
 
 // -------------------------------------------------------------------------
Index: include/mempolt2.inl
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/include/mempolt2.inl,v
retrieving revision 1.3
diff -u -5 -p -w -r1.3 mempolt2.inl
--- include/mempolt2.inl	23 May 2002 23:08:43 -0000	1.3
+++ include/mempolt2.inl	24 Jun 2004 11:23:37 -0000
@@ -114,10 +114,12 @@ Cyg_Mempolt2<T>::alloc( cyg_int32 size )
 
     Cyg_Thread *self = Cyg_Thread::self();
 
     Mempolt2WaitInfo waitinfo( size );
 
+    CYG_MEMALLOC_FAIL_TEST(true, size);
+
     self->set_wait_info( (CYG_ADDRWORD)&waitinfo );
     self->set_sleep_reason( Cyg_Thread::WAIT );
     self->sleep();
     queue.enqueue( self );
 
@@ -185,10 +187,13 @@ Cyg_Mempolt2<T>::alloc( cyg_int32 size, 
     // If the timeout is in the past, the wake reason will have been set to
     // something other than NONE already. If so, skip the wait and go
     // straight to unlock.
     
     if( Cyg_Thread::NONE == self->get_wake_reason() ) {
+
+	CYG_MEMALLOC_FAIL_TEST(true, size);
+
         self->set_wait_info( (CYG_ADDRWORD)&waitinfo );
         self->sleep();
         queue.enqueue( self );
     }
 
@@ -249,10 +254,13 @@ Cyg_Mempolt2<T>::try_alloc( cyg_int32 si
 
     CYG_ASSERTCLASS( this, "Bad this pointer");
 
     // Unlock the scheduler and maybe switch threads
     Cyg_Scheduler::unlock();
+
+    CYG_MEMALLOC_FAIL_TEST(ret==NULL, size);
+
     return ret;
 }
     
     
 // -------------------------------------------------------------------------
@@ -281,10 +289,13 @@ Cyg_Mempolt2<T>::resize_alloc( cyg_uint8
 
     CYG_ASSERTCLASS( this, "Bad this pointer");
 
     // Unlock the scheduler and maybe switch threads
     Cyg_Scheduler::unlock();
+
+    CYG_MEMALLOC_FAIL_TEST(ret==NULL, newsize);
+
     return ret;
 }
     
     
 // -------------------------------------------------------------------------
Index: include/mempoolt.inl
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/include/mempoolt.inl,v
retrieving revision 1.3
diff -u -5 -p -w -r1.3 mempoolt.inl
--- include/mempoolt.inl	23 May 2002 23:08:43 -0000	1.3
+++ include/mempoolt.inl	24 Jun 2004 11:23:38 -0000
@@ -109,10 +109,13 @@ Cyg_Mempoolt<T>::alloc( cyg_int32 size )
     // grabbing the freed storage between the wakeup in free() and this
     // thread actually starting.
     cyg_uint8 *ret;
     cyg_bool result = true;
     while( result && (NULL == (ret = pool.alloc( size ))) ) {
+
+	CYG_MEMALLOC_FAIL_TEST(true, size);
+
         self->set_sleep_reason( Cyg_Thread::WAIT );
         self->sleep();
         queue.enqueue( self );
 
         CYG_ASSERT( 1 == Cyg_Scheduler::get_sched_lock(),
@@ -180,10 +183,12 @@ Cyg_Mempoolt<T>::alloc( cyg_int32 size, 
     
     if( self->get_wake_reason() != Cyg_Thread::NONE )
         result = false;
             
     while( result && (NULL == (ret = pool.alloc( size ))) ) {
+	CYG_MEMALLOC_FAIL_TEST(true, size);
+
         self->set_sleep_reason( Cyg_Thread::TIMEOUT );
         self->sleep();
         queue.enqueue( self );
 
         CYG_ASSERT( 1 == Cyg_Scheduler::get_sched_lock(),
@@ -246,10 +251,13 @@ Cyg_Mempoolt<T>::try_alloc( cyg_int32 si
     CYG_ASSERTCLASS( this, "Bad this pointer");
 
     // Unlock the scheduler and maybe switch threads
     Cyg_Scheduler::unlock();
     CYG_REPORT_RETVAL( ret );
+
+    CYG_MEMALLOC_FAIL_TEST(ret==NULL, size);
+
     return ret;
 }
     
     
 // -------------------------------------------------------------------------
Index: include/mfiximpl.inl
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/include/mfiximpl.inl,v
retrieving revision 1.3
diff -u -5 -p -w -r1.3 mfiximpl.inl
--- include/mfiximpl.inl	23 May 2002 23:08:44 -0000	1.3
+++ include/mfiximpl.inl	24 Jun 2004 11:23:38 -0000
@@ -57,10 +57,11 @@
 
 #include <pkgconf/memalloc.h>
 #include <cyg/hal/hal_arch.h>          // HAL_LSBIT_INDEX magic asm code
 #include <cyg/memalloc/mfiximpl.hxx>
 
+
 // -------------------------------------------------------------------------
 
 inline
 Cyg_Mempool_Fixed_Implementation::Cyg_Mempool_Fixed_Implementation(
         cyg_uint8 *base,
@@ -120,12 +121,14 @@ Cyg_Mempool_Fixed_Implementation::~Cyg_M
 inline cyg_uint8 *
 Cyg_Mempool_Fixed_Implementation::try_alloc( cyg_int32 size )
 {
     // size parameter is not used
     CYG_UNUSED_PARAM( cyg_int32, size );
-    if ( 0 >= freeblocks )
+    if ( 0 >= freeblocks ) {
+	CYG_MEMALLOC_FAIL_TEST(true, size);
         return NULL;
+    }
     cyg_int32 i = firstfree;
     cyg_uint8 *p = NULL;
     do {
         if ( 0xffffffff != bitmap[ i ] ) {
             // then there is a free block in this bucket
@@ -170,12 +173,14 @@ Cyg_Mempool_Fixed_Implementation::resize
     if ( NULL != oldsize )
         *oldsize = blocksize;
 
     if (newsize == blocksize)
         return alloc_ptr;
-    else
+    else {
+	CYG_MEMALLOC_FAIL_TEST(true, newsize);
         return NULL;
+    }
 } // resize_alloc()
 
 
 // -------------------------------------------------------------------------
 
Index: include/mvarimpl.inl
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/include/mvarimpl.inl,v
retrieving revision 1.5
diff -u -5 -p -w -r1.5 mvarimpl.inl
--- include/mvarimpl.inl	23 May 2002 23:08:44 -0000	1.5
+++ include/mvarimpl.inl	24 Jun 2004 11:23:38 -0000
@@ -273,10 +273,12 @@ Cyg_Mempool_Variable_Implementation::try
     freemem -=size;
 
     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;
 }
 
 // -------------------------------------------------------------------------
 // resize existing allocation, if oldsize is non-NULL, previous
@@ -356,10 +358,12 @@ Cyg_Mempool_Variable_Implementation::res
     } // if
     else if ( newsize == dq->size ) {
         ret = alloc_ptr;
     }
         
+    CYG_MEMALLOC_FAIL_TEST(ret==NULL, newsize);
+
     return ret;
 
 } // resize_alloc()
 
 
Index: include/sepmetaimpl.inl
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/include/sepmetaimpl.inl,v
retrieving revision 1.4
diff -u -5 -p -w -r1.4 sepmetaimpl.inl
--- include/sepmetaimpl.inl	23 May 2002 23:08:44 -0000	1.4
+++ include/sepmetaimpl.inl	24 Jun 2004 11:23:39 -0000
@@ -372,12 +372,16 @@ Cyg_Mempool_Sepmeta_Implementation::try_
         return NULL;
 
     size = (size + alignment - 1) & -alignment;
 
     struct memdq *dq = find_free_dq( size );
-    if (NULL == dq)
+   
+
+    if (NULL == dq) {	
+	CYG_MEMALLOC_FAIL_TEST(true, size);
         return NULL;
+    }
 
     cyg_int32 dqsize = dq->memnext->mem - dq->mem;
 
     if( size == dqsize ) {
         // exact fit -- unlink from free list
@@ -397,12 +401,15 @@ Cyg_Mempool_Sepmeta_Implementation::try_
 
         // Split into two memdq's, returning the second one
 
         // first get a memdq
 
-        if ( NULL == freemetahead ) // out of metadata. 
+        if ( NULL == freemetahead ) {
+ 	    // out of metadata. 
+	    CYG_MEMALLOC_FAIL_TEST(true, 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
         // not need more metadata. We don't do this yet though.
 
@@ -494,11 +501,14 @@ Cyg_Mempool_Sepmeta_Implementation::resi
         }
         if ( dq->prev != dq->memprev) { // ditto
             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 ) {
             if (nextmemsize <= (newsize - currsize)) { // taking all of it
                 struct memdq *fblk = dq->memnext;
@@ -558,12 +568,14 @@ Cyg_Mempool_Sepmeta_Implementation::resi
             CYG_ASSERT( dq->memnext->mem > dq->mem,
                         "moving next block back corruption" );
         } else {
             // if its already allocated we need to create a new free list
             // entry
-            if (NULL == freemetahead)
+            if (NULL == freemetahead) {
+		CYG_MEMALLOC_FAIL_TEST(true, newsize);
                 return NULL;  // can't do it
+	    }
 
             struct memdq *fdq = freemetahead;
             freemetahead = fdq->next;
 
             fdq->memprev = dq;
Index: src/dlmalloc.cxx
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/src/dlmalloc.cxx,v
retrieving revision 1.8
diff -u -5 -p -w -r1.8 dlmalloc.cxx
--- src/dlmalloc.cxx	6 Oct 2003 18:25:57 -0000	1.8
+++ src/dlmalloc.cxx	24 Jun 2004 11:23:40 -0000
@@ -207,18 +207,24 @@
 //----------------------------------------------------------------------------
 
 
 /* Preliminaries */
 
+#include <cyg/kernel/kapi.h>
 #include <pkgconf/memalloc.h>          // configuration header
 #include <pkgconf/infra.h>             // CYGDBG_USE_ASSERTS
 #include <cyg/infra/cyg_type.h>        // types
 #include <cyg/infra/cyg_ass.h>         // assertions
 #include <stddef.h>                    // for size_t
 #include <cyg/memalloc/dlmalloc.hxx>
+
+#include <cyg/memalloc/kapi.h>
+
 //#include <cyg/infra/diag.h>
 
+
+
 /*
     Debugging:
 
     Because freed chunks may be overwritten with link fields, this
     malloc will often die when freed memory is overwritten by user
@@ -1271,10 +1277,11 @@ Cyg_Mempool_dlmalloc_Implementation::try
   if (chunksize(top) < nb || remainder_size < (long)MINSIZE)
   {
       //diag_printf("chunksize(top)=%ld, nb=%d, remainder=%ld\n", chunksize(top),
       //            nb, remainder_size);
       MALLOC_UNLOCK;
+      CYG_MEMALLOC_FAIL_TEST(true, bytes);
       return NULL; /* propagate failure */
   }
 
   victim = top;
   set_head(victim, nb | PREV_INUSE);
@@ -1556,10 +1563,11 @@ Cyg_Mempool_dlmalloc_Implementation::res
       }
     }
 
     // couldn't resize the allocation any direction, so return failure
     MALLOC_UNLOCK;
+    CYG_MEMALLOC_FAIL_TEST(true, bytes);
     return NULL;
   }
 
 
  split:  /* split off extra room in old or expanded chunk */
Index: src/malloc.cxx
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/src/malloc.cxx,v
retrieving revision 1.5
diff -u -5 -p -w -r1.5 malloc.cxx
--- src/malloc.cxx	23 May 2002 23:08:45 -0000	1.5
+++ src/malloc.cxx	24 Jun 2004 11:23:41 -0000
@@ -280,8 +280,11 @@ mallinfo( void )
 
     CYG_REPORT_RETURN();
     return ret;
 } // mallinfo()
 
+
 #endif // ifdef CYGPKG_MEMALLOC_MALLOC_ALLOCATORS
 
+
+
 // EOF malloc.cxx
--- /dev/null	2004-06-24 13:23:53.455000000 +0200
+++ src/debug.c	2004-06-24 13:00:03.179331200 +0200
@@ -0,0 +1,71 @@
+//========================================================================
+//
+//      debug.c
+//
+//      default implementation of out of memory debug breakpoint site
+//
+//========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):     oyvind
+// Contributors:  
+// Date:          2000-06-17
+// Purpose:       
+// Description:   Memory usage debugging
+// Usage:       
+//
+//####DESCRIPTIONEND####
+//
+//========================================================================
+
+// CONFIGURATION
+
+#include <pkgconf/memalloc.h>   // Configuration header
+
+#include <cyg/infra/cyg_type.h>    // Common type definitions and support
+#include <cyg/infra/cyg_trac.h>    // Common tracing support
+#include <cyg/infra/cyg_ass.h>     // Common assertion support
+#include <string.h>                // For memset() and memmove()
+#include <stdlib.h>                // header for this file
+
+#if CYGSEM_MEMALLOC_INVOKE_OUT_OF_MEMORY
+void cyg_memalloc_alloc_fail(char * file, int line, cyg_int32 size) __THROW
+{
+  // handy breakpoint site.
+}
+#endif
+
+// EOF debug.c

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]