From e1ba8c6f231f2d7c51be5ff28497ac41bd4dc65d Mon Sep 17 00:00:00 2001 From: Przemyslaw Czerpak Date: Thu, 26 Nov 2009 02:46:11 +0000 Subject: [PATCH] 2009-11-26 03:45 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/include/hbapi.h * harbour/include/hbvm.h * harbour/include/hbvmpub.h * harbour/include/hbstack.h * harbour/src/vm/hvm.c * harbour/src/vm/estack.c * harbour/src/vm/fm.c * harbour/src/vm/garbage.c + added new function hb_xclean() executed by GC just before resuming suspended threads - it can be used by memory manager to clean internal structures and release unused memory to OS. % release unused memory to OS in hb_xclean() when DLMALLOC is used % release unused memory in all mspaces to OS in hb_xclean() when HB_FM_DLMT_ALLOC is used % release unused memory in mspace when last thread detach it % balance used mspaces between threads in hb_xclean() when HB_FM_DLMT_ALLOC is used --- harbour/ChangeLog | 19 ++++++++ harbour/include/hbapi.h | 1 + harbour/include/hbstack.h | 1 + harbour/include/hbvm.h | 3 ++ harbour/include/hbvmpub.h | 2 + harbour/src/vm/estack.c | 18 ++++++++ harbour/src/vm/fm.c | 96 ++++++++++++++++++++++++++++++--------- harbour/src/vm/garbage.c | 5 ++ harbour/src/vm/hvm.c | 21 +++++++++ 9 files changed, 144 insertions(+), 22 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 2ee1bca8c9..83765b4a04 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -17,6 +17,25 @@ past entries belonging to author(s): Viktor Szakats. */ +2009-11-26 03:45 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/include/hbapi.h + * harbour/include/hbvm.h + * harbour/include/hbvmpub.h + * harbour/include/hbstack.h + * harbour/src/vm/hvm.c + * harbour/src/vm/estack.c + * harbour/src/vm/fm.c + * harbour/src/vm/garbage.c + + added new function hb_xclean() executed by GC just before resuming + suspended threads - it can be used by memory manager to clean + internal structures and release unused memory to OS. + % release unused memory to OS in hb_xclean() when DLMALLOC is used + % release unused memory in all mspaces to OS in hb_xclean() when + HB_FM_DLMT_ALLOC is used + % release unused memory in mspace when last thread detach it + % balance used mspaces between threads in hb_xclean() when + HB_FM_DLMT_ALLOC is used + 2009-11-26 02:25 UTC+0200 Mindaugas Kavaliauskas (dbtopas/at/dbtopas.lt) * harbour/contrib/hbwin/axcore.c * harbour/contrib/hbwin/olecore.c diff --git a/harbour/include/hbapi.h b/harbour/include/hbapi.h index 1c4a4a738b..a25daa24a5 100644 --- a/harbour/include/hbapi.h +++ b/harbour/include/hbapi.h @@ -497,6 +497,7 @@ extern HB_EXPORT void hb_xsetinfo( const char * szValue ); #ifdef _HB_API_INTERNAL_ extern void hb_xinit_thread( void ); extern void hb_xexit_thread( void ); +extern void hb_xclean( void ); #endif #ifdef _HB_API_INTERNAL_ diff --git a/harbour/include/hbstack.h b/harbour/include/hbstack.h index 7a969070e0..a0d268036c 100644 --- a/harbour/include/hbstack.h +++ b/harbour/include/hbstack.h @@ -345,6 +345,7 @@ extern void * hb_stackGetI18N( void ); extern void hb_stackSetI18N( void * ); extern void hb_stackIsStackRef( void *, PHB_TSD_FUNC ); +extern void hb_stackUpdateAllocator( void *, PHB_ALLOCUPDT_FUNC, int ); #if defined( HB_MT_VM ) extern void * hb_stackList( void ); diff --git a/harbour/include/hbvm.h b/harbour/include/hbvm.h index 7d7c911775..6a03404f14 100644 --- a/harbour/include/hbvm.h +++ b/harbour/include/hbvm.h @@ -108,6 +108,9 @@ extern HB_EXPORT PHB_SYMB hb_vmProcessDynLibSymbols( PHB_SYMB pSymbols, USHORT u extern void hb_vmEnumRelease( PHB_ITEM pBase, PHB_ITEM pValue ); extern BOOL hb_vmMsgReference( PHB_ITEM pObject, PHB_DYNS pMessage, PHB_DYNS pAccMsg ); /* create extended message reference */ + + extern void hb_vmUpdateAllocator( PHB_ALLOCUPDT_FUNC pFunc, int iCount ); + #endif extern void hb_vmSetExceptionHandler( void ); diff --git a/harbour/include/hbvmpub.h b/harbour/include/hbvmpub.h index 76c022b692..37f16c9ebd 100644 --- a/harbour/include/hbvmpub.h +++ b/harbour/include/hbvmpub.h @@ -225,6 +225,8 @@ typedef struct _HB_SYMB #define HB_DYNS_FUNC( hbfunc ) BOOL hbfunc( PHB_DYNS pDynSymbol, void * Cargo ) typedef HB_DYNS_FUNC( PHB_DYNS_FUNC ); +typedef void * ( * PHB_ALLOCUPDT_FUNC )( void *, int ); + typedef void (*HB_INIT_FUNC)(void *); /* List of functions used by hb_vmAtInit()/hb_vmAtExit() */ typedef struct _HB_FUNC_LIST diff --git a/harbour/src/vm/estack.c b/harbour/src/vm/estack.c index 73f96b0558..667a221915 100644 --- a/harbour/src/vm/estack.c +++ b/harbour/src/vm/estack.c @@ -1312,3 +1312,21 @@ void hb_stackIsStackRef( void * pStackId, PHB_TSD_FUNC pCleanFunc ) hb_gtIsGtRef( pStack->hGT ); } + +void hb_stackUpdateAllocator( void * pStackId, PHB_ALLOCUPDT_FUNC pFunc, int iCount ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_stackUpdateAllocator(%p, %p, %d)", pStackId, pFunc, iCount)); + +#if defined( HB_MT_VM ) + { + PHB_STACK pStack = ( PHB_STACK ) pStackId; + + if( pStack->allocator ) + pStack->allocator = pFunc( pStack->allocator, iCount ); + } +#else + HB_SYMBOL_UNUSED( pStackId ); + HB_SYMBOL_UNUSED( pFunc ); + HB_SYMBOL_UNUSED( iCount ); +#endif +} diff --git a/harbour/src/vm/fm.c b/harbour/src/vm/fm.c index ebabc124b5..c56ebc73af 100644 --- a/harbour/src/vm/fm.c +++ b/harbour/src/vm/fm.c @@ -107,6 +107,7 @@ #include "hbmemory.ch" #include "hbdate.h" #include "hbset.h" +#include "hbvm.h" #if defined( HB_MT_VM ) # include "hbthread.h" # include "hbatomic.h" @@ -393,6 +394,42 @@ static mspace hb_mspace( void ) return s_gm; } +static PHB_MSPACE hb_mspace_alloc( void ) +{ + if( s_mspool[ 0 ].ms == NULL && s_gm ) + { + s_mspool[ 0 ].count = 1; + s_mspool[ 0 ].ms = s_gm; + return &s_mspool[ 0 ]; + } + else + { + int i, imin = 0; + for( i = 1; i < HB_MSPACE_COUNT; ++i ) + { + if( s_mspool[ i ].count < s_mspool[ imin ].count ) + imin = i; + } + if( s_mspool[ imin ].ms == NULL ) + s_mspool[ imin ].ms = create_mspace( 0, 1 ); + s_mspool[ imin ].count++; + return &s_mspool[ imin ]; + } +} + +static void * hb_mspace_update( void * pAlloc, int iCount ) +{ + PHB_MSPACE pm = ( PHB_MSPACE ) pAlloc; + + if( pm->count > iCount ) + { + pAlloc = ( void * ) hb_mspace_alloc(); + pm->count--; + } + + return pAlloc; +} + static void hb_mspace_cleanup( void ) { int i; @@ -446,25 +483,7 @@ void hb_xinit_thread( void ) if( hb_stack.allocator == NULL ) { HB_FM_LOCK - if( s_mspool[ 0 ].ms == NULL && s_gm ) - { - s_mspool[ 0 ].count = 1; - s_mspool[ 0 ].ms = s_gm; - hb_stack.allocator = ( void * ) &s_mspool[ 0 ]; - } - else - { - int i, imin = 0; - for( i = 1; i < HB_MSPACE_COUNT; ++i ) - { - if( s_mspool[ i ].count < s_mspool[ imin ].count ) - imin = i; - } - if( s_mspool[ imin ].ms == NULL ) - s_mspool[ imin ].ms = create_mspace( 0, 1 ); - s_mspool[ imin ].count++; - hb_stack.allocator = ( void * ) &s_mspool[ imin ]; - } + hb_stack.allocator = ( void * ) hb_mspace_alloc(); HB_FM_UNLOCK } #endif @@ -474,16 +493,49 @@ void hb_xexit_thread( void ) { #if defined( HB_FM_DLMT_ALLOC ) HB_STACK_TLS_PRELOAD - if( hb_stack.allocator != NULL ) + PHB_MSPACE pm = ( PHB_MSPACE ) hb_stack.allocator; + + if( pm ) { - HB_FM_LOCK - ( ( PHB_MSPACE ) hb_stack.allocator )->count--; hb_stack.allocator = NULL; + HB_FM_LOCK + if( --pm->count == 0 ) + mspace_trim( pm->ms, 0 ); HB_FM_UNLOCK } #endif } +void hb_xclean( void ) +{ +#if defined( HB_FM_DLMT_ALLOC ) + HB_FM_LOCK + { + int i, imax, icount; + + if( s_gm ) + mspace_trim( s_gm, 0 ); + + for( i = imax = icount = 0; i < HB_MSPACE_COUNT; ++i ) + { + icount += s_mspool[ i ].count; + if( imax < s_mspool[ i ].count ) + imax = s_mspool[ i ].count; + mspace_trim( s_mspool[ i ].ms, 0 ); + } + icount = ( icount + HB_MSPACE_COUNT - 1 ) / HB_MSPACE_COUNT; + if( imax > icount ) + { + /* balance mspaces between running threads */ + hb_vmUpdateAllocator( hb_mspace_update, icount ); + } + } + HB_FM_UNLOCK +#elif defined( HB_FM_DL_ALLOC ) + dlmalloc_trim( 0 ); +#endif +} + void hb_xsetfilename( const char * szValue ) { #ifdef HB_FM_STATISTICS diff --git a/harbour/src/vm/garbage.c b/harbour/src/vm/garbage.c index 7a3381a4e1..0ee2abfe35 100644 --- a/harbour/src/vm/garbage.c +++ b/harbour/src/vm/garbage.c @@ -705,6 +705,11 @@ void hb_gcCollectAll( BOOL fForce ) s_ulBlocksMarked = s_ulBlocks; #endif + + /* call memory manager cleanup function */ + hb_xclean(); + + /* resume suspended threads */ hb_vmResumeThreads(); /* do we have any deleted blocks? */ diff --git a/harbour/src/vm/hvm.c b/harbour/src/vm/hvm.c index 71d30b7d7b..5acb5474e4 100644 --- a/harbour/src/vm/hvm.c +++ b/harbour/src/vm/hvm.c @@ -11399,6 +11399,27 @@ void hb_vmIsStackRef( void ) #endif /* HB_MT_VM */ } +void hb_vmUpdateAllocator( PHB_ALLOCUPDT_FUNC pFunc, int iCount ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_vmUpdateAllocator(%p, %d)", pFunc, int iCount)); + +#if defined( HB_MT_VM ) + if( s_vmStackLst ) + { + PHB_THREADSTATE pStack = s_vmStackLst; + do + { + if( pStack->pStackId ) + hb_stackUpdateAllocator( pStack->pStackId, pFunc, iCount ); + pStack = pStack->pNext; + } + while( pStack != s_vmStackLst ); + } +#else + hb_stackUpdateAllocator( hb_stackId(), pFunc, iCount ); +#endif /* HB_MT_VM */ +} + /* ------------------------------------------------------------------------ */ /* $Doc$