From 55d2c9a9a63ae3dcdfe24ad33dc50ef8db5c011b Mon Sep 17 00:00:00 2001 From: Jean-Francois Lefebvre Date: Tue, 18 Dec 2001 06:20:04 +0000 Subject: [PATCH] 2001-12-18 07:21 UTC+0100 JFL (Mafact) --- harbour/ChangeLog | 10 ++++++ harbour/include/hbapi.h | 1 + harbour/source/vm/garbage.c | 64 ++++++++++++++++++++++++++++++++++--- 3 files changed, 71 insertions(+), 4 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 57cacb2c99..9d8722c4b3 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,16 @@ 2002-12-01 23:12 UTC+0100 Foo Bar */ +2001-12-18 07:21 UTC+0100 JFL (Mafact) + * source/vm/garbage.c + ! RON Further Fix for forever loop when GC try to free first item in the + arrayclone cloned list. + + RON Added hb_gcReleaseAll() + it will increase cleanup speed (on app termination), and will + result in a more complete cleanup in certain situations + * include/hbapi.h + + RON Added hb_gcReleaseAll() + 2001-12-18 06:44 UTC+0100 Antonio Linares * source/vm/maindll.c * source/vm/maindllh.c diff --git a/harbour/include/hbapi.h b/harbour/include/hbapi.h index 4f447bd32f..c8aad8634e 100644 --- a/harbour/include/hbapi.h +++ b/harbour/include/hbapi.h @@ -558,6 +558,7 @@ extern void * hb_gcLock( void *pAlloc ); /* do not release passed memory block * extern void * hb_gcUnlock( void *pAlloc ); /* passed block is allowed to be released */ extern void hb_gcCollect( void ); /* checks if a single memory block can be released */ extern void hb_gcCollectAll( void ); /* checks if all memory blocks can be released */ +extern void hb_gcReleaseAll( void ); /* release all memory blocks unconditionally */ extern void hb_gcItemRef( HB_ITEM_PTR pItem ); /* checks if passed item refers passed memory block pointer */ extern void hb_vmIsLocalRef( void ); /* hvm.c - mark all local variables as used */ extern void hb_vmIsStaticRef( void ); /* hvm.c - mark all static variables as used */ diff --git a/harbour/source/vm/garbage.c b/harbour/source/vm/garbage.c index 8f5d43e905..7fef6a125c 100644 --- a/harbour/source/vm/garbage.c +++ b/harbour/source/vm/garbage.c @@ -372,32 +372,53 @@ void hb_gcCollectAll( void ) ( s_pCurrBlock->pFunc )( ( void *)( s_pCurrBlock + 1 ) ); } } + s_pCurrBlock = s_pCurrBlock->pNext; + } while ( s_pCurrBlock && (pAlloc != s_pCurrBlock) ); pAlloc = s_pCurrBlock; do { + NewTopBlock: + if( s_pCurrBlock->used & HB_GC_DELETE ) { pDelete = s_pCurrBlock; hb_gcUnlink( &s_pCurrBlock, s_pCurrBlock ); + /* + Releasing the top block in the list, so we must mark the new top into pAlloc + but we still need to process this new top. Without this goto, the while + condition will immediatly fail. Using extra flags, and new conditions + will adversly effect performance. + */ if( pDelete == pAlloc ) { - pAlloc = s_pCurrBlock; - } + pAlloc = s_pCurrBlock; + HB_GARBAGE_FREE( pDelete ); - HB_GARBAGE_FREE( pDelete ); + if( s_pCurrBlock ) + { + goto NewTopBlock; + } + } + else + { + HB_GARBAGE_FREE( pDelete ); + } } else { s_pCurrBlock = s_pCurrBlock->pNext; } - } while ( s_pCurrBlock && (pAlloc != s_pCurrBlock) ); + + } while ( s_pCurrBlock && ( pAlloc != s_pCurrBlock ) ); s_bCollecting = FALSE; + s_pCurrBlock = pAlloc; + /* Step 4 - flip flag */ /* Reverse used/unused flag so we don't have to mark all blocks * during next collecting @@ -406,6 +427,41 @@ void hb_gcCollectAll( void ) } } +void hb_gcReleaseAll( void ) +{ + if( s_pCurrBlock ) + { + HB_GARBAGE_PTR pAlloc, pDelete; + + s_bCollecting = TRUE; + + pAlloc = s_pCurrBlock; + do + { + /* call a cleanup function */ + if( s_pCurrBlock->pFunc ) + { + HB_TRACE( HB_TR_INFO, ( "Cleanup, %p", s_pCurrBlock ) ); + ( s_pCurrBlock->pFunc )( ( void *)( s_pCurrBlock + 1 ) ); + } + + s_pCurrBlock = s_pCurrBlock->pNext; + + } while ( s_pCurrBlock && pAlloc != s_pCurrBlock ); + + do + { + HB_TRACE( HB_TR_INFO, ( "Release %p", s_pCurrBlock ) ); + pDelete = s_pCurrBlock; + hb_gcUnlink( &s_pCurrBlock, s_pCurrBlock ); + HB_GARBAGE_FREE( pDelete ); + + } while ( s_pCurrBlock ); + } + + s_bCollecting = FALSE; +} + /* service a single garbage collector step * Check a single memory block if it can be released */