callback functionality for dyanmic memory allocation

NavEcos ecos@navosha.com
Sat Nov 2 04:25:00 GMT 2002


The following patches allows a user to track:

1) heap creation
2) heap destruction
3) allocation/freeing of dynamic memory
    and
4) reallocation of dynamic memory (i.e. realloc functionality)

Included is the CDL to control it.  By default it is turned off.  There will 
be a performance penalty to turn on the logging ability even if you do not 
use it since a pointer must be checked (the callback).

Example usage is:

  // varriable sized heaps
  Cyg_Mempool_Variable::set_create_cb     (var_create);
  Cyg_Mempool_Variable::set_destroy_cb    (var_destroy);
  Cyg_Mempool_Variable::set_pre_alloc_cb  (var_pre_alloc);
  Cyg_Mempool_Variable::set_post_alloc_cb (var_post_alloc);
  Cyg_Mempool_Variable::set_pre_free_cb   (var_pre_free);
  Cyg_Mempool_Variable::set_post_free_cb  (var_post_free);

  // dlmalloc heaps
  Cyg_Mempool_dlmalloc::set_create_cb     (var_create);
  Cyg_Mempool_dlmalloc::set_destroy_cb    (var_destroy);
  Cyg_Mempool_dlmalloc::set_pre_alloc_cb  (var_pre_alloc);
  Cyg_Mempool_dlmalloc::set_post_alloc_cb (var_post_alloc);
  Cyg_Mempool_dlmalloc::set_pre_free_cb   (var_pre_free);
  Cyg_Mempool_dlmalloc::set_post_free_cb  (var_post_free);

  // fixed size block allocator heaps
  Cyg_Mempool_Fixed::set_create_cb     (fix_create);
  Cyg_Mempool_Fixed::set_destroy_cb    (fix_destroy);
  Cyg_Mempool_Fixed::set_pre_alloc_cb  (fix_pre_alloc);
  Cyg_Mempool_Fixed::set_post_alloc_cb (fix_post_alloc);
  Cyg_Mempool_Fixed::set_pre_free_cb   (fix_pre_free);
  Cyg_Mempool_Fixed::set_post_free_cb  (fix_post_free);

The additional functionality will allow a user to keep track of every 
allocation in the system, as well as to modify allocated memory to add 
padding to detect array overflows.

Diff files attached.

-Rich

-------------- next part --------------
? cdl/memalloc.cdl_new
Index: cdl/memalloc.cdl
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/cdl/memalloc.cdl,v
retrieving revision 1.11
diff -u -r1.11 memalloc.cdl
--- cdl/memalloc.cdl	23 May 2002 23:08:42 -0000	1.11
+++ cdl/memalloc.cdl	2 Nov 2002 12:16:49 -0000
@@ -86,6 +86,17 @@
                     are made available that allow a thread to wait
                     until memory is available."
             }
+
+            cdl_option CYGSEM_MEMALLOC_ALLOCATOR_FIXED_CALLBACK {
+                display        "Allow registered callbacks"
+                active_if      CYGPKG_KERNEL
+                default_value  0
+                description    "
+                    With this option enabled, this allocator will be
+                    able to make calls to callback functions.  With this
+                    enabled you can track heap creations, destroys,
+                    allocations, reallocations and frees"
+            }
         }
 
         cdl_component CYGPKG_MEMALLOC_ALLOCATOR_VARIABLE {
@@ -121,6 +132,17 @@
                     memory fragmentation problems, but involves extra code and
                     processor cycles."
             }
+
+            cdl_option CYGSEM_MEMALLOC_ALLOCATOR_VARIABLE_CALLBACK {
+                display        "Allow registered callbacks"
+                active_if      CYGPKG_KERNEL
+                default_value  0
+                description    "
+                    With this option enabled, this allocator will be
+                    able to make calls to callback functions.  With this
+                    enabled you can track heap creations, destroys,
+                    allocations, reallocations and frees"
+            }
         }
 
         cdl_component CYGPKG_MEMALLOC_ALLOCATOR_DLMALLOC {
@@ -174,7 +196,7 @@
                     silently enabled."
             }
 
-           cdl_option CYGIMP_MEMALLOC_ALLOCATOR_DLMALLOC_USE_MEMCPY {
+            cdl_option CYGIMP_MEMALLOC_ALLOCATOR_DLMALLOC_USE_MEMCPY {
                 display       "Use system memcpy() and memset()"
                 requires      CYGPKG_ISOINFRA
                 default_value { 0 != CYGPKG_ISOINFRA }
@@ -183,7 +205,19 @@
                     are used within the implementation. The alternative is
                     to use some macro equivalents, which some people report
                     are faster in some circumstances."
-           }
+            }
+
+            cdl_option CYGSEM_MEMALLOC_ALLOCATOR_DLMALLOC_CALLBACK {
+                display        "Allow registered callbacks"
+                active_if      CYGPKG_KERNEL
+                default_value  0
+                description    "
+                    With this option enabled, this allocator will be
+                    able to make calls to callback functions.  With this
+                    enabled you can track heap creations, destroys,
+                    allocations, reallocations and frees"
+            }
+
         }
 
         cdl_component CYGPKG_MEMALLOC_ALLOCATOR_SEPMETA {
Index: include/dlmalloc.hxx
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/include/dlmalloc.hxx,v
retrieving revision 1.3
diff -u -r1.3 dlmalloc.hxx
--- include/dlmalloc.hxx	23 May 2002 23:08:43 -0000	1.3
+++ include/dlmalloc.hxx	2 Nov 2002 12:16:49 -0000
@@ -91,9 +91,42 @@
 
 // TYPE DEFINITIONS
 
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_DLMALLOC_CALLBACK
+// memory callback functionality
+class Cyg_Mempool_dlmalloc;
+typedef void fn_dl_create
+  (Cyg_Mempool_dlmalloc *pool, const cyg_uint8 *base_ptr, cyg_int32 size);
+typedef void fn_dl_destroy
+  (Cyg_Mempool_dlmalloc *pool, const cyg_uint8 *base_ptr, cyg_int32 size);
+typedef void fn_dl_pre_alloc
+  (Cyg_Mempool_dlmalloc *pool, cyg_int32 *size);
+typedef void fn_dl_post_alloc
+  (Cyg_Mempool_dlmalloc *pool, cyg_uint8 **mem_ptr, cyg_int32 size);
+typedef void fn_dl_pre_realloc
+  (Cyg_Mempool_dlmalloc *pool, cyg_uint8 **mem_ptr, cyg_int32 *newsize,
+    cyg_int32 oldsize);
+typedef void fn_dl_post_realloc
+  (Cyg_Mempool_dlmalloc *pool, cyg_uint8 **mem_ptr, cyg_int32 size);
+typedef void fn_dl_pre_free
+  (Cyg_Mempool_dlmalloc *pool, cyg_uint8 **mem_ptr, cyg_int32 *psize);
+typedef void fn_dl_post_free
+  (Cyg_Mempool_dlmalloc *pool, cyg_uint8 *mem_ptr, cyg_int32 size);
+#endif
 
 class Cyg_Mempool_dlmalloc
 {
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_DLMALLOC_CALLBACK
+private:
+    static fn_dl_create       *fn_create_cb;
+    static fn_dl_destroy      *fn_destroy_cb;
+    static fn_dl_pre_alloc    *fn_pre_alloc_cb;
+    static fn_dl_post_alloc   *fn_post_alloc_cb;
+    static fn_dl_pre_realloc  *fn_pre_realloc_cb;
+    static fn_dl_post_realloc *fn_post_realloc_cb;
+    static fn_dl_pre_free     *fn_pre_free_cb;
+    static fn_dl_post_free    *fn_post_free_cb;
+#endif
+
 protected:
 #ifdef CYGIMP_MEMALLOC_ALLOCATOR_DLMALLOC_THREADAWARE
     Cyg_Mempolt2<Cyg_Mempool_dlmalloc_Implementation> mypool;
@@ -108,29 +141,102 @@
     // same arena.
     Cyg_Mempool_dlmalloc( cyg_uint8 *base, cyg_int32 size, 
                           CYG_ADDRWORD argthru=0 )
-        : mypool( base, size, argthru ) {}
+        : mypool( base, size, argthru ) {
+# ifdef CYGSEM_MEMALLOC_ALLOCATOR_DLMALLOC_CALLBACK
+void test_fun (void); test_fun ();
+        if ( fn_create_cb != NULL ) {
+            (*fn_create_cb) (this, base, size);
+	}
+# endif
+    }
 
     // Destructor
-    ~Cyg_Mempool_dlmalloc() {}
+    ~Cyg_Mempool_dlmalloc() {
+# ifdef CYGSEM_MEMALLOC_ALLOCATOR_DLMALLOC_CALLBACK
+        if ( fn_destroy_cb != NULL ) {
+            Cyg_Mempool_Status status;
+                mypool.get_status (
+                CYG_MEMPOOL_STAT_ORIGBASE
+                | CYG_MEMPOOL_STAT_ORIGSIZE,
+                status );
+	    (*fn_destroy_cb) (this,status.origbase, status.origsize);
+        }
+# endif
+    }
 
     // get some memory; wait if none available
     // if we aren't configured to be thread-aware this is irrelevant
 #ifdef CYGIMP_MEMALLOC_ALLOCATOR_DLMALLOC_THREADAWARE
     cyg_uint8 *
-    alloc( cyg_int32 size ) { return mypool.alloc( size ); }
+    alloc( cyg_int32 size ) {
+# ifdef CYGSEM_MEMALLOC_ALLOCATOR_DLMALLOC_CALLBACK
+        cyg_uint8
+            *pRet;
+
+        if ( fn_pre_alloc_cb != NULL ) {
+	    (*fn_pre_alloc_cb) (this, &size);
+        }
+
+        pRet = mypool.alloc( size );
+
+        if ( fn_post_alloc_cb != NULL ) {
+	    (*fn_post_alloc_cb) (this, &pRet, size);
+        }
+
+        return pRet;
+# else
+        return mypool.alloc( size );
+# endif
+    }
     
 # ifdef CYGFUN_KERNEL_THREADS_TIMER
     // get some memory with a timeout
     cyg_uint8 *
     alloc( cyg_int32 size, cyg_tick_count delay_timeout ) {
+# ifdef CYGSEM_MEMALLOC_ALLOCATOR_DLMALLOC_CALLBACK
+        cyg_uint8
+            *pRet;
+
+        if ( fn_pre_alloc_cb != NULL ) {
+	    (*fn_pre_alloc_cb) (this, &size);
+        }
+
+        pRet = mypool.alloc( size, delay_timeout );
+
+        if ( fn_post_alloc_cb != NULL ) {
+	    (*fn_post_alloc_cb) (this, &pRet, size);
+        }
+
+        return pRet;
+# else
         return mypool.alloc( size, delay_timeout );
+# endif
     }
 # endif
 #endif
 
     // get some memory, return NULL if none available
     cyg_uint8 *
-    try_alloc( cyg_int32 size ) { return mypool.try_alloc( size ); }
+    try_alloc( cyg_int32 size ) {
+# ifdef CYGSEM_MEMALLOC_ALLOCATOR_DLMALLOC_CALLBACK
+        cyg_uint8
+            *pRet;
+
+        if ( fn_pre_alloc_cb != NULL ) {
+	    (*fn_pre_alloc_cb) (this, &size);
+        }
+
+        pRet = mypool.try_alloc( size );
+
+        if ( fn_post_alloc_cb != NULL ) {
+	    (*fn_post_alloc_cb) (this, &pRet, size);
+        }
+
+        return pRet;
+# else
+        return mypool.try_alloc( size );
+# endif
+    }
 
     
     // resize existing allocation, if oldsize is non-NULL, previous
@@ -146,13 +252,59 @@
     cyg_uint8 *
     resize_alloc( cyg_uint8 *alloc_ptr, cyg_int32 newsize,
                   cyg_int32 *oldsize ) { 
+# ifdef CYGSEM_MEMALLOC_ALLOCATOR_DLMALLOC_CALLBACK
+        cyg_uint8
+            *pRet;
+        cyg_int32
+            originalsize;
+
+        // get the original size of the block of memory
+        originalsize = mypool.addr2size (alloc_ptr);
+
+        if ( fn_pre_alloc_cb != NULL ) {
+	    (*fn_pre_realloc_cb) (this, &alloc_ptr, &newsize, originalsize);
+        }
+
+        pRet = mypool.resize_alloc( alloc_ptr, newsize, oldsize);
+
+        if ( fn_post_alloc_cb != NULL ) {
+	    (*fn_post_realloc_cb) (this, &pRet, newsize);
+        }
+
+        return pRet;
+# else
         return mypool.resize_alloc( alloc_ptr, newsize, oldsize);
+# endif
     }
 
     // free the memory back to the pool
     // returns true on success
     cyg_bool
-    free( cyg_uint8 *ptr, cyg_int32 size=0 ) { return mypool.free(ptr, size); }
+    free( cyg_uint8 *ptr, cyg_int32 size=0 ) {
+# ifdef CYGSEM_MEMALLOC_ALLOCATOR_DLMALLOC_CALLBACK
+        cyg_bool
+            b_Ret;
+
+        if ( 0 == size ) {
+            // if the size wasn't given specifically get it from the pointer
+            size = mypool.addr2size (ptr);
+	}
+
+        if ( fn_pre_free_cb != NULL ) {
+	    (*fn_pre_free_cb) (this, &ptr, &size);
+        }
+
+        b_Ret = mypool.free(ptr, size);
+
+        if ( fn_post_free_cb != NULL ) {
+	    (*fn_post_free_cb) (this, ptr, size);
+        }
+
+        return b_Ret;
+# else
+        return mypool.free(ptr, size);
+# endif
+    }
 
     // Get memory pool status
     // flags is a bitmask of requested fields to fill in. The flags are
@@ -164,6 +316,19 @@
         status.waiting = 0;
         mypool.get_status( flags, status );
     }
+
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_DLMALLOC_CALLBACK
+    static void set_create_cb     (fn_dl_create *cb)    {fn_create_cb    =cb;}
+    static void set_destroy_cb    (fn_dl_destroy *cb)   {fn_destroy_cb   =cb;}
+    static void set_pre_alloc_cb  (fn_dl_pre_alloc *cb) {fn_pre_alloc_cb =cb;}
+    static void set_post_alloc_cb (fn_dl_post_alloc *cb){fn_post_alloc_cb=cb;}
+    static void set_pre_realloc_cb  (fn_dl_pre_realloc *cb)
+      {fn_pre_realloc_cb  = cb;}
+    static void set_post_realloc_cb (fn_dl_post_realloc *cb)
+      {fn_post_realloc_cb = cb;}
+    static void set_pre_free_cb   (fn_dl_pre_free *cb)  {fn_pre_free_cb  =cb;}
+    static void set_post_free_cb  (fn_dl_post_free *cb) {fn_post_free_cb =cb;}
+#endif
 };
 
 #endif // ifndef __MALLOC_IMPL_WANTED
Index: include/dlmallocimpl.hxx
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/include/dlmallocimpl.hxx,v
retrieving revision 1.3
diff -u -r1.3 dlmallocimpl.hxx
--- include/dlmallocimpl.hxx	23 May 2002 23:08:43 -0000	1.3
+++ include/dlmallocimpl.hxx	2 Nov 2002 12:16:49 -0000
@@ -148,6 +148,10 @@
     // Destructor
     ~Cyg_Mempool_dlmalloc_Implementation() {}
 
+    // given a block of allocated memory, returns the size of the block
+    cyg_int32
+    addr2size( cyg_uint8 *addr );
+
     // get some memory, return NULL if none available
     cyg_uint8 *
     try_alloc( cyg_int32 /* size */ );
Index: include/memfixed.hxx
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/include/memfixed.hxx,v
retrieving revision 1.4
diff -u -r1.4 memfixed.hxx
--- include/memfixed.hxx	23 May 2002 23:08:43 -0000	1.4
+++ include/memfixed.hxx	2 Nov 2002 12:16:50 -0000
@@ -85,8 +85,36 @@
 
 // TYPE DEFINITIONS
 
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_FIXED_CALLBACK
+// memory callback functionality
+class Cyg_Mempool_Fixed;
+typedef void fn_fix_create
+  (Cyg_Mempool_Fixed *pool, cyg_uint8 const *base_ptr, cyg_int32 size,
+    cyg_int32 unitsize);
+typedef void fn_fix_destroy
+  (Cyg_Mempool_Fixed *pool, cyg_uint8 const *base_ptr, cyg_int32 size);
+typedef void fn_fix_pre_alloc
+  (Cyg_Mempool_Fixed *pool);
+typedef void fn_fix_post_alloc
+  (Cyg_Mempool_Fixed *pool, cyg_uint8 **mem_ptr);
+typedef void fn_fix_pre_free
+  (Cyg_Mempool_Fixed *pool, cyg_uint8 **mem_ptr);
+typedef void fn_fix_post_free
+  (Cyg_Mempool_Fixed *pool, cyg_uint8 *mem_ptr, cyg_int32 size);
+#endif
+
 class Cyg_Mempool_Fixed
 {
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_FIXED_CALLBACK
+private:
+    static fn_fix_create     *fn_create_cb;
+    static fn_fix_destroy    *fn_destroy_cb;
+    static fn_fix_pre_alloc  *fn_pre_alloc_cb;
+    static fn_fix_post_alloc *fn_post_alloc_cb;
+    static fn_fix_pre_free   *fn_pre_free_cb;
+    static fn_fix_post_free  *fn_post_free_cb;
+#endif
+
 protected:
 #ifdef CYGSEM_MEMALLOC_ALLOCATOR_FIXED_THREADAWARE
     Cyg_Mempolt2<Cyg_Mempool_Fixed_Implementation> mypool;
@@ -138,6 +166,15 @@
     // defined in common.hxx
     void get_status( cyg_mempool_status_flag_t /* flags */,
                      Cyg_Mempool_Status & /* status */ );
+
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_FIXED_CALLBACK
+    static void set_create_cb     (fn_fix_create *cb)    {fn_create_cb    =cb;}
+    static void set_destroy_cb    (fn_fix_destroy *cb)   {fn_destroy_cb   =cb;}
+    static void set_pre_alloc_cb  (fn_fix_pre_alloc *cb) {fn_pre_alloc_cb =cb;}
+    static void set_post_alloc_cb (fn_fix_post_alloc *cb){fn_post_alloc_cb=cb;}
+    static void set_pre_free_cb   (fn_fix_pre_free *cb)  {fn_pre_free_cb  =cb;}
+    static void set_post_free_cb  (fn_fix_post_free *cb) {fn_post_free_cb =cb;}
+#endif
 
     CYGDBG_DEFINE_CHECK_THIS
 };
Index: include/mempolt2.hxx
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/include/mempolt2.hxx,v
retrieving revision 1.3
diff -u -r1.3 mempolt2.hxx
--- include/mempolt2.hxx	23 May 2002 23:08:43 -0000	1.3
+++ include/mempolt2.hxx	2 Nov 2002 12:16:50 -0000
@@ -90,6 +90,9 @@
         cyg_int32 size,
         CYG_ADDRWORD arg_thru );        // Constructor
     ~Cyg_Mempolt2();                    // Destructor
+
+    // get the size of a previously allocated block (does not include overhead)
+    cyg_int32 addr2size( cyg_uint8 *addr );
         
     // get some memory; wait if none available; return NULL if failed
     // due to interrupt
Index: 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
--- include/mempolt2.inl	23 May 2002 23:08:43 -0000	1.3
+++ include/mempolt2.inl	2 Nov 2002 12:16:50 -0000
@@ -90,7 +90,19 @@
     // Unlock the scheduler and maybe switch threads
     Cyg_Scheduler::unlock();    
 }
-        
+
+// -------------------------------------------------------------------------
+// get the size of a previously allocated block of memory - overhead
+template <class T>
+inline cyg_int32
+Cyg_Mempolt2<T>::addr2size( cyg_uint8 *addr )
+{
+    CYG_REPORT_FUNCTION();
+    CYG_ASSERTCLASS( this, "Bad this pointer");
+
+    return pool.addr2size ( addr );
+}
+
 // -------------------------------------------------------------------------
 // get some memory; wait if none available
 template <class T>
Index: include/memvar.hxx
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/include/memvar.hxx,v
retrieving revision 1.4
diff -u -r1.4 memvar.hxx
--- include/memvar.hxx	23 May 2002 23:08:43 -0000	1.4
+++ include/memvar.hxx	2 Nov 2002 12:16:50 -0000
@@ -90,8 +90,42 @@
 
 // TYPE DEFINITIONS
 
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_VARIABLE_CALLBACK
+// memory callback functionality
+class Cyg_Mempool_Variable;
+typedef void fn_var_create
+  (Cyg_Mempool_Variable *pool, const cyg_uint8 *base_ptr, cyg_int32 size);
+typedef void fn_var_destroy
+  (Cyg_Mempool_Variable *pool, const cyg_uint8 *base_ptr, cyg_int32 size);
+typedef void fn_var_pre_alloc
+  (Cyg_Mempool_Variable *pool, cyg_int32 *size);
+typedef void fn_var_post_alloc
+  (Cyg_Mempool_Variable *pool, cyg_uint8 **mem_ptr, cyg_int32 size);
+typedef void fn_var_pre_realloc
+  (Cyg_Mempool_Variable *pool, cyg_uint8 **mem_ptr, cyg_int32 *newsize,
+    cyg_int32 oldsize);
+typedef void fn_var_post_realloc
+  (Cyg_Mempool_Variable *pool, cyg_uint8 **mem_ptr, cyg_int32 size);
+typedef void fn_var_pre_free
+  (Cyg_Mempool_Variable *pool, cyg_uint8 **mem_ptr, cyg_int32 *psize);
+typedef void fn_var_post_free
+  (Cyg_Mempool_Variable *pool, cyg_uint8 *mem_ptr, cyg_int32 size);
+#endif
+
 class Cyg_Mempool_Variable
 {
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_VARIABLE_CALLBACK
+private:
+    static fn_var_create       *fn_create_cb;
+    static fn_var_destroy      *fn_destroy_cb;
+    static fn_var_pre_alloc    *fn_pre_alloc_cb;
+    static fn_var_post_alloc   *fn_post_alloc_cb;
+    static fn_var_pre_realloc  *fn_pre_realloc_cb;
+    static fn_var_post_realloc *fn_post_realloc_cb;
+    static fn_var_pre_free     *fn_pre_free_cb;
+    static fn_var_post_free    *fn_post_free_cb;
+#endif
+
 protected:
 #ifdef CYGSEM_MEMALLOC_ALLOCATOR_VARIABLE_THREADAWARE
     Cyg_Mempolt2<Cyg_Mempool_Variable_Implementation> mypool;
@@ -154,6 +188,19 @@
     void
     get_status( cyg_mempool_status_flag_t /* flags */,
                 Cyg_Mempool_Status & /* status */ );
+
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_VARIABLE_CALLBACK
+    static void set_create_cb     (fn_var_create *cb)    {fn_create_cb    =cb;}
+    static void set_destroy_cb    (fn_var_destroy *cb)   {fn_destroy_cb   =cb;}
+    static void set_pre_alloc_cb  (fn_var_pre_alloc *cb) {fn_pre_alloc_cb =cb;}
+    static void set_post_alloc_cb (fn_var_post_alloc *cb){fn_post_alloc_cb=cb;}
+    static void set_pre_realloc_cb  (fn_var_pre_realloc *cb)
+      {fn_pre_realloc_cb  = cb;}
+    static void set_post_realloc_cb (fn_var_post_realloc *cb)
+      {fn_post_realloc_cb = cb;}
+    static void set_pre_free_cb   (fn_var_pre_free *cb)  {fn_pre_free_cb  =cb;}
+    static void set_post_free_cb  (fn_var_post_free *cb) {fn_post_free_cb =cb;}
+#endif
 
     CYGDBG_DEFINE_CHECK_THIS
 };
Index: include/mvarimpl.hxx
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/include/mvarimpl.hxx,v
retrieving revision 1.3
diff -u -r1.3 mvarimpl.hxx
--- include/mvarimpl.hxx	23 May 2002 23:08:44 -0000	1.3
+++ include/mvarimpl.hxx	2 Nov 2002 12:16:51 -0000
@@ -114,6 +114,10 @@
     // Destructor
     ~Cyg_Mempool_Variable_Implementation();
 
+    // get the size in bytes of a previously allocated block of memory
+    cyg_int32
+    addr2size( cyg_uint8 *addr );
+
     // get size bytes of memory
     cyg_uint8 *
     try_alloc( cyg_int32 /* size */ );
Index: 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
--- include/mvarimpl.inl	23 May 2002 23:08:44 -0000	1.5
+++ include/mvarimpl.inl	2 Nov 2002 12:16:51 -0000
@@ -99,6 +99,12 @@
     return ((cyg_uint8 *)dq + sizeof(struct memdq));
 }
 
+inline cyg_int32
+Cyg_Mempool_Variable_Implementation::addr2size( cyg_uint8 *addr )
+{
+    return addr2memdq (addr)->size - sizeof(struct memdq);
+}
+
 // -------------------------------------------------------------------------
 
 inline void
Index: src/dlmalloc.cxx
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/src/dlmalloc.cxx,v
retrieving revision 1.6
diff -u -r1.6 dlmalloc.cxx
--- src/dlmalloc.cxx	23 May 2002 23:08:44 -0000	1.6
+++ src/dlmalloc.cxx	2 Nov 2002 12:16:53 -0000
@@ -1032,6 +1032,25 @@
 
 */
 
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_DLMALLOC_CALLBACK
+// callbacks used for debugging memory leaks
+fn_dl_create       *Cyg_Mempool_dlmalloc::fn_create_cb       = NULL;
+fn_dl_destroy      *Cyg_Mempool_dlmalloc::fn_destroy_cb      = NULL;
+fn_dl_pre_alloc    *Cyg_Mempool_dlmalloc::fn_pre_alloc_cb    = NULL;
+fn_dl_post_alloc   *Cyg_Mempool_dlmalloc::fn_post_alloc_cb   = NULL;
+fn_dl_pre_realloc  *Cyg_Mempool_dlmalloc::fn_pre_realloc_cb  = NULL;
+fn_dl_post_realloc *Cyg_Mempool_dlmalloc::fn_post_realloc_cb = NULL;
+fn_dl_pre_free     *Cyg_Mempool_dlmalloc::fn_pre_free_cb     = NULL;
+fn_dl_post_free    *Cyg_Mempool_dlmalloc::fn_post_free_cb    = NULL;
+#endif
+
+cyg_int32
+Cyg_Mempool_dlmalloc_Implementation::addr2size( cyg_uint8 *addr )
+{
+    return chunksize(mem2chunk(addr)) - SIZE_SZ;
+}
+
+
 cyg_uint8 *
 Cyg_Mempool_dlmalloc_Implementation::try_alloc( cyg_int32 bytes )
 {
Index: src/memfixed.cxx
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/src/memfixed.cxx,v
retrieving revision 1.3
diff -u -r1.3 memfixed.cxx
--- src/memfixed.cxx	23 May 2002 23:08:45 -0000	1.3
+++ src/memfixed.cxx	2 Nov 2002 12:16:53 -0000
@@ -99,6 +99,16 @@
 }
 #endif
 
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_FIXED_CALLBACK
+// callbacks used for debugging memory leaks
+fn_fix_create     *Cyg_Mempool_Fixed::fn_create_cb     = NULL;
+fn_fix_destroy    *Cyg_Mempool_Fixed::fn_destroy_cb    = NULL;
+fn_fix_pre_alloc  *Cyg_Mempool_Fixed::fn_pre_alloc_cb  = NULL;
+fn_fix_post_alloc *Cyg_Mempool_Fixed::fn_post_alloc_cb = NULL;
+fn_fix_pre_free   *Cyg_Mempool_Fixed::fn_pre_free_cb   = NULL;
+fn_fix_post_free  *Cyg_Mempool_Fixed::fn_post_free_cb  = NULL;
+#endif
+
 // -------------------------------------------------------------------------
 // Constructor: gives the base and size of the arena in which memory is
 // to be carved out, note that management structures are taken from the
@@ -109,11 +119,26 @@
     CYG_ADDRWORD alloc_unit )
     : mypool( base, size, alloc_unit )
 {
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_FIXED_CALLBACK
+    if ( fn_create_cb != NULL ) {
+       (*fn_create_cb) (this, base, size, alloc_unit);
+    }
+#endif
 }
 
 // Destructor
 Cyg_Mempool_Fixed::~Cyg_Mempool_Fixed()
 {
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_FIXED_CALLBACK
+    if ( fn_destroy_cb != NULL ) {
+       Cyg_Mempool_Status status;
+       mypool.get_status (
+         CYG_MEMPOOL_STAT_ORIGBASE
+         | CYG_MEMPOOL_STAT_ORIGSIZE,
+         status );
+       (*fn_destroy_cb) (this, status.origbase, status.origsize);
+    }
+#endif
 }
 
 // -------------------------------------------------------------------------
@@ -122,7 +147,24 @@
 cyg_uint8 *
 Cyg_Mempool_Fixed::alloc()
 {
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_FIXED_CALLBACK
+    cyg_uint8
+      *pRet;
+
+    if ( fn_pre_alloc_cb != NULL ) {
+       (*fn_pre_alloc_cb) (this);
+    }
+
+    pRet = mypool.alloc ( 0 );
+
+    if ( fn_post_alloc_cb != NULL ) {
+       (*fn_post_alloc_cb) (this, &pRet);
+    }
+
+    return pRet;
+#else
     return mypool.alloc( 0 );
+#endif
 }
     
 # ifdef CYGFUN_KERNEL_THREADS_TIMER
@@ -130,7 +172,24 @@
 cyg_uint8 *
 Cyg_Mempool_Fixed::alloc(cyg_tick_count delay_timeout )
 {
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_FIXED_CALLBACK
+    cyg_uint8
+      *pRet;
+
+    if ( fn_pre_alloc_cb != NULL ) {
+       (*fn_pre_alloc_cb) (this);
+    }
+
+    pRet = mypool.alloc( 0, delay_timeout );
+
+    if ( fn_post_alloc_cb != NULL ) {
+       (*fn_post_alloc_cb) (this, &pRet);
+    }
+
+    return pRet;
+#else
     return mypool.alloc( 0, delay_timeout );
+#endif
 }
 # endif
 #endif
@@ -139,14 +198,48 @@
 cyg_uint8 *
 Cyg_Mempool_Fixed::try_alloc()
 {
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_FIXED_CALLBACK
+    cyg_uint8
+      *pRet;
+
+    if ( fn_pre_alloc_cb != NULL ) {
+       (*fn_pre_alloc_cb) (this);
+    }
+
+    pRet = mypool.try_alloc( 0 );
+
+    if ( fn_post_alloc_cb != NULL ) {
+       (*fn_post_alloc_cb) (this, &pRet);
+    }
+
+    return pRet;
+#else
     return mypool.try_alloc( 0 );
+#endif
 }
     
 // free the memory back to the pool
 cyg_bool 
 Cyg_Mempool_Fixed::free( cyg_uint8 *p )
 {
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_FIXED_CALLBACK
+    bool
+      bRet;
+
+    if ( fn_pre_free_cb != NULL ) {
+       (*fn_pre_free_cb) (this, &p);
+    }
+
+    bRet = mypool.free( p, 0 );
+
+    if ( fn_post_free_cb != NULL ) {
+      (*fn_post_free_cb) (this, p, 0);
+    }
+
+    return bRet;
+#else
     return mypool.free( p, 0 );
+#endif
 }
 
 // supposedly resize existing allocation. This is defined in the
Index: src/memvar.cxx
===================================================================
RCS file: /cvs/ecos/ecos/packages/services/memalloc/common/current/src/memvar.cxx,v
retrieving revision 1.3
diff -u -r1.3 memvar.cxx
--- src/memvar.cxx	23 May 2002 23:08:45 -0000	1.3
+++ src/memvar.cxx	2 Nov 2002 12:16:54 -0000
@@ -98,6 +98,18 @@
 }
 #endif
 
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_VARIABLE_CALLBACK
+// callbacks used for debugging memory leaks
+fn_var_create       *Cyg_Mempool_Variable::fn_create_cb       = NULL;
+fn_var_destroy      *Cyg_Mempool_Variable::fn_destroy_cb      = NULL;
+fn_var_pre_alloc    *Cyg_Mempool_Variable::fn_pre_alloc_cb    = NULL;
+fn_var_post_alloc   *Cyg_Mempool_Variable::fn_post_alloc_cb   = NULL;
+fn_var_pre_realloc  *Cyg_Mempool_Variable::fn_pre_realloc_cb  = NULL;
+fn_var_post_realloc *Cyg_Mempool_Variable::fn_post_realloc_cb = NULL;
+fn_var_pre_free     *Cyg_Mempool_Variable::fn_pre_free_cb     = NULL;
+fn_var_post_free    *Cyg_Mempool_Variable::fn_post_free_cb    = NULL;
+#endif
+
 // -------------------------------------------------------------------------
 // Constructor: gives the base and size of the arena in which memory is
 // to be carved out
@@ -107,11 +119,26 @@
     cyg_int32 alignment)
     : mypool( base, size, (CYG_ADDRWORD)alignment )
 {
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_VARIABLE_CALLBACK
+    if ( fn_create_cb != NULL ) {
+      (*fn_create_cb) (this, base, size);
+    }
+#endif
 }
 
 // Destructor
 Cyg_Mempool_Variable::~Cyg_Mempool_Variable()
 {
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_VARIABLE_CALLBACK
+    if ( fn_destroy_cb != NULL ) {
+      Cyg_Mempool_Status status;
+      mypool.get_status (
+        CYG_MEMPOOL_STAT_ORIGBASE
+        | CYG_MEMPOOL_STAT_ORIGSIZE,
+        status );
+      (*fn_destroy_cb) (this, status.origbase, status.origsize);
+    }
+#endif
 }
 
 // -------------------------------------------------------------------------
@@ -120,7 +147,23 @@
 cyg_uint8 *
 Cyg_Mempool_Variable::alloc(cyg_int32 size)
 {
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_VARIABLE_CALLBACK
+    cyg_uint8
+      *pRet;
+
+    if ( fn_pre_alloc_cb != NULL ) {
+        (*fn_pre_alloc_cb) (this, &size);
+    }
+    pRet = mypool.alloc( size );
+
+    if ( fn_post_alloc_cb != NULL) {
+        (*fn_post_alloc_cb) (this, &pRet, size);
+    }
+
+    return pRet;
+#else
     return mypool.alloc( size );
+#endif
 }
     
 # ifdef CYGFUN_KERNEL_THREADS_TIMER
@@ -128,7 +171,24 @@
 cyg_uint8 *
 Cyg_Mempool_Variable::alloc(cyg_int32 size, cyg_tick_count delay_timeout)
 {
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_VARIABLE_CALLBACK
+    cyg_uint8
+      *pRet;
+
+    if ( fn_pre_alloc_cb != NULL ) {
+        (*fn_pre_alloc_cb) (this, &size);
+    }
+
+    pRet = mypool.alloc( size , delay_timeout );
+
+    if ( fn_post_alloc_cb != NULL ) {
+        (*fn_post_alloc_cb) (this, &pRet, size);
+    }
+
+    return pRet;
+#else
     return mypool.alloc( size , delay_timeout );
+#endif
 }
 # endif
 #endif
@@ -137,7 +197,24 @@
 cyg_uint8 *
 Cyg_Mempool_Variable::try_alloc(cyg_int32 size)
 {
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_VARIABLE_CALLBACK
+    cyg_uint8
+      *pRet;
+
+    if ( fn_pre_alloc_cb != NULL ) {
+        (*fn_pre_alloc_cb) (this, &size);
+    }
+
+    pRet = mypool.try_alloc( size );
+
+    if ( fn_post_alloc_cb != NULL ) {
+        (*fn_post_alloc_cb) (this, &pRet, size);
+    }
+
+    return pRet;
+#else
     return mypool.try_alloc( size );
+#endif
 }
 
 // resize existing allocation, if oldsize is non-NULL, previous
@@ -154,14 +231,58 @@
 Cyg_Mempool_Variable::resize_alloc( cyg_uint8 *alloc_ptr, cyg_int32 newsize,
                                     cyg_int32 *oldsize )
 {
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_VARIABLE_CALLBACK
+    cyg_uint8
+        *pRet;
+    cyg_int32
+        originalsize;
+
+    // get the original size of the block of memory
+    originalsize = mypool.addr2size (alloc_ptr);
+
+    if ( fn_pre_realloc_cb != NULL ) {
+        (*fn_pre_realloc_cb) (this, &alloc_ptr, &newsize, originalsize);
+    }
+
+    pRet = mypool.resize_alloc( alloc_ptr, newsize, oldsize );
+
+    if ( fn_post_realloc_cb != NULL ) {
+        (*fn_post_realloc_cb) (this, &pRet, newsize);
+    }
+
+    return pRet;
+#else
     return mypool.resize_alloc( alloc_ptr, newsize, oldsize );
+#endif
 }
 
 // free the memory back to the pool
 cyg_bool 
 Cyg_Mempool_Variable::free( cyg_uint8 *p, cyg_int32 size )
 {
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_VARIABLE_CALLBACK
+    cyg_bool
+      bRet;
+
+    if (0 == size) {
+        // if the size wasn't given specifically get it from the pointer
+        size = mypool.addr2size (p);
+    }
+
+    if ( fn_pre_free_cb != NULL ) {
+        (*fn_pre_free_cb) (this, &p, &size);
+    }
+
+    bRet = mypool.free( p, size );
+
+    if ( fn_post_free_cb != NULL ) {
+        (*fn_post_free_cb) (this, p, size);
+    }
+
+    return bRet;
+#else
     return mypool.free( p, size );
+#endif
 }
 
 // Get memory pool status


More information about the Ecos-patches mailing list