# HG changeset patch # User asl # Date 1089025624 0 # Node ID eb235374a7aeaf5e99f9dbc704ae9a25b9bfc9c3 # Parent 961151dc048ef90b7f4de118eddabf6f01c9c4c7 2004-06-24 Oyvind Harboe * 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. diff --git a/packages/services/memalloc/common/current/ChangeLog b/packages/services/memalloc/common/current/ChangeLog --- a/packages/services/memalloc/common/current/ChangeLog +++ b/packages/services/memalloc/common/current/ChangeLog @@ -1,3 +1,10 @@ +2004-06-24 Oyvind Harboe + + * 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 * include/kapi.h: Add throw specifications throughout. diff --git a/packages/services/memalloc/common/current/cdl/memalloc.cdl b/packages/services/memalloc/common/current/cdl/memalloc.cdl --- 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 diff --git a/packages/services/memalloc/common/current/include/common.hxx b/packages/services/memalloc/common/current/include/common.hxx --- 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 // 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 */ diff --git a/packages/services/memalloc/common/current/include/kapi.h b/packages/services/memalloc/common/current/include/kapi.h --- a/packages/services/memalloc/common/current/include/kapi.h +++ b/packages/services/memalloc/common/current/include/kapi.h @@ -58,11 +58,23 @@ //========================================================================*/ /* CONFIGURATION */ - +#include #include /* TYPE DEFINITIONS */ +#ifdef CYGPKG_KERNEL +#include +#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 */ diff --git a/packages/services/memalloc/common/current/include/memjoin.inl b/packages/services/memalloc/common/current/include/memjoin.inl --- 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::try_alloc( cyg_in } CYG_REPORT_RETVAL( ptr ); + + CYG_MEMALLOC_FAIL_TEST(ptr==NULL, size); + return ptr; } // Cyg_Mempool_Joined::try_alloc() @@ -214,6 +217,7 @@ Cyg_Mempool_Joined::resize_alloc( cyg ret = pool->resize_alloc( alloc_ptr, newsize, oldsize ); CYG_REPORT_RETVAL( ret ); + return ret; } // Cyg_Mempool_Joined::resize_alloc() diff --git a/packages/services/memalloc/common/current/include/mempolt2.inl b/packages/services/memalloc/common/current/include/mempolt2.inl --- a/packages/services/memalloc/common/current/include/mempolt2.inl +++ b/packages/services/memalloc/common/current/include/mempolt2.inl @@ -116,6 +116,8 @@ Cyg_Mempolt2::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::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::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::resize_alloc( cyg_uint8 // Unlock the scheduler and maybe switch threads Cyg_Scheduler::unlock(); + + CYG_MEMALLOC_FAIL_TEST(ret==NULL, newsize); + return ret; } diff --git a/packages/services/memalloc/common/current/include/mempoolt.inl b/packages/services/memalloc/common/current/include/mempoolt.inl --- a/packages/services/memalloc/common/current/include/mempoolt.inl +++ b/packages/services/memalloc/common/current/include/mempoolt.inl @@ -111,6 +111,9 @@ Cyg_Mempoolt::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::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::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; } diff --git a/packages/services/memalloc/common/current/include/mfiximpl.inl b/packages/services/memalloc/common/current/include/mfiximpl.inl --- a/packages/services/memalloc/common/current/include/mfiximpl.inl +++ b/packages/services/memalloc/common/current/include/mfiximpl.inl @@ -59,6 +59,7 @@ #include // HAL_LSBIT_INDEX magic asm code #include + // ------------------------------------------------------------------------- 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() diff --git a/packages/services/memalloc/common/current/include/mvarimpl.inl b/packages/services/memalloc/common/current/include/mvarimpl.inl --- 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() diff --git a/packages/services/memalloc/common/current/include/sepmetaimpl.inl b/packages/services/memalloc/common/current/include/sepmetaimpl.inl --- 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; diff --git a/packages/services/memalloc/common/current/src/dlmalloc.cxx b/packages/services/memalloc/common/current/src/dlmalloc.cxx --- a/packages/services/memalloc/common/current/src/dlmalloc.cxx +++ b/packages/services/memalloc/common/current/src/dlmalloc.cxx @@ -215,7 +215,6 @@ #include // assertions #include // for size_t #include -//#include /* 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; }