From 3ed8136c8096cc69a3607d32106e9c4be10d619a Mon Sep 17 00:00:00 2001 From: Przemyslaw Czerpak Date: Wed, 15 Oct 2008 15:51:02 +0000 Subject: [PATCH] 2008-10-15 17:50 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/include/hbstack.h * harbour/source/vm/estack.c * harbour/source/vm/hvm.c * harbour/source/debug/dbgentry.c * harbour/source/debug/debugger.prg * moved debugRequest flag and debugger internal structure pointer to HVM stack * allocate debugger internal structure dynamically in thread thread local area when PCODE with debug information is executed * changed STATIC s_oDebugger to THREAD STATIC * send HB_DBG_VMQUIT after each thread termination when debugger is activated Now debugger can be used in MT programs and each thread can be debugged separately (each has its own debuger). Please only remember that thread sharing console window can overwrite other threads debugger screen. There is also one limitation which I'll try to remove later: only main thread debugger keeps information about file wide STATIC names and line numbers with possible break point places. This data should be shared between debuggers. --- harbour/ChangeLog | 21 +++++++++++++++ harbour/include/hbstack.h | 12 +++++---- harbour/source/debug/dbgentry.c | 29 ++++++++++++++++----- harbour/source/debug/debugger.prg | 2 +- harbour/source/vm/estack.c | 20 ++++++++++++++ harbour/source/vm/hvm.c | 43 +++++++++++++++++++------------ 6 files changed, 98 insertions(+), 29 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 538fb01031..938a14b1c8 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,27 @@ 2008-12-31 13:59 UTC+0100 Foo Bar (foo.bar foobar.org) */ +2008-10-15 17:50 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/include/hbstack.h + * harbour/source/vm/estack.c + * harbour/source/vm/hvm.c + * harbour/source/debug/dbgentry.c + * harbour/source/debug/debugger.prg + * moved debugRequest flag and debugger internal structure + pointer to HVM stack + * allocate debugger internal structure dynamically in thread + thread local area when PCODE with debug information is executed + * changed STATIC s_oDebugger to THREAD STATIC + * send HB_DBG_VMQUIT after each thread termination when + debugger is activated + Now debugger can be used in MT programs and each thread can be + debugged separately (each has its own debuger). Please only + remember that thread sharing console window can overwrite other + threads debugger screen. There is also one limitation which I'll + try to remove later: only main thread debugger keeps information + about file wide STATIC names and line numbers with possible break + point places. This data should be shared between debuggers. + 2008-10-15 13:32 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/include/hbapi.h * harbour/source/vm/hvm.c diff --git a/harbour/include/hbstack.h b/harbour/include/hbstack.h index 701ba02c0b..531e6c3550 100644 --- a/harbour/include/hbstack.h +++ b/harbour/include/hbstack.h @@ -168,16 +168,13 @@ typedef struct char szDate[ 9 ]; /* last returned date from _pards() yyyymmdd format */ void * pCDP; /* current codepage module */ void * pLang; /* current language module */ - const char * szDefaultRDD; /* default RDD */ - int iArea; /* current workarea number */ - int iAreaCount; /* number of allocated workareas number */ - void ** pWorkAreas; /* workareas pool */ - BOOL fNetErr; /* current NETERR() flag */ int iTSD; /* number of allocated TSD holders */ PHB_TSD_HOLDER pTSD; /* thread specific data holder */ HB_PRIVATE_STACK privates; /* private variables stack */ HB_SET_STRUCT set; int iKeyPoll; /* counter for GT/keyboard polling */ + int fDebugRequest; /* request debugger activation */ + void * pDebugInfo; /* internal debugger structure */ #if defined( HB_MT_VM ) int iUnlocked; /* counter for nested hb_vmUnlock() calls */ PHB_DYN_HANDLES pDynH; /* dynamic symbol handles */ @@ -288,6 +285,8 @@ extern BYTE * hb_stackDirBuffer( void ); extern PHB_IOERRORS hb_stackIOErrors( void ); extern PHB_STACKRDD hb_stackRDD( void ); +extern void ** hb_stackDebugInfo( void ); + #ifdef _HB_API_INTERNAL_ extern void hb_stackDecrease( ULONG ulItems ); extern HB_ITEM_PTR hb_stackNewFrame( PHB_STACK_STATE pFrame, USHORT uiParams ); @@ -310,6 +309,7 @@ extern LONG hb_stackWithObjectOffset( void ); extern void hb_stackWithObjectSetOffset( LONG ); extern int * hb_stackKeyPolls( void ); +extern BOOL * hb_stackDebugRequest( void ); extern void hb_stackDestroyTSD( void ); @@ -446,6 +446,8 @@ extern void hb_stackIsStackRef( void *, PHB_TSD_FUNC ); #define hb_stackGetPrivateStack( ) ( &hb_stack.privates ) #define hb_stackSetStruct( ) ( &hb_stack.set ) #define hb_stackKeyPolls( ) ( &hb_stack.iKeyPoll ) +#define hb_stackDebugRequest( ) ( &hb_stack.fDebugRequest ) +#define hb_stackDebugInfo( ) ( &hb_stack.pDebugInfo ) #endif diff --git a/harbour/source/debug/dbgentry.c b/harbour/source/debug/dbgentry.c index 3197016fa2..dcbc71d3a0 100644 --- a/harbour/source/debug/dbgentry.c +++ b/harbour/source/debug/dbgentry.c @@ -64,6 +64,8 @@ /* dummy function declaration */ static BOOL hb_clsSetScope( BOOL fScope ) { return fScope; } +#define HB_DBGINFO_DISABLE ( ( HB_DEBUGINFO * ) ( HB_PTRDIFF ) 0x01 ) + #if defined( HB_OS_UNIX_COMPATIBLE ) #define FILENAME_EQUAL(s1, s2) ( !strcmp( (s1), (s2) ) ) #else @@ -173,10 +175,6 @@ typedef struct } HB_DEBUGINFO; -static HB_DEBUGINFO s_Info = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* bCBTrace */ TRUE, 0, 0, 0, 0, 0 }; -static HB_DEBUGINFO *s_pInfo = &s_Info; - - static PHB_ITEM hb_dbgActivateBreakArray( HB_DEBUGINFO *info ); static PHB_ITEM @@ -364,10 +362,22 @@ hb_dbgEntry( int nMode, int nLine, char *szName, int nIndex, int nFrame ) int i; ULONG nProcLevel; char szProcName[ HB_SYMBOL_NAME_LEN + HB_SYMBOL_NAME_LEN + 5 ]; - HB_DEBUGINFO *info = s_pInfo; + HB_DEBUGINFO ** infoPtr = ( HB_DEBUGINFO ** ) hb_stackDebugInfo(); + HB_DEBUGINFO *info = *infoPtr; - if ( ( info->bInside || info->bQuit ) && nMode != HB_DBG_VMQUIT ) + if( info == HB_DBGINFO_DISABLE ) return; + else if ( nMode != HB_DBG_VMQUIT ) + { + if( !info ) + { + info = *infoPtr = ( HB_DEBUGINFO * ) ALLOC( sizeof( HB_DEBUGINFO ) ); + memset( info, 0, sizeof( HB_DEBUGINFO ) ); + info->bCBTrace = TRUE; + } + else if ( info->bInside || info->bQuit ) + return; + } switch ( nMode ) { @@ -536,7 +546,12 @@ hb_dbgEntry( int nMode, int nLine, char *szName, int nIndex, int nFrame ) return; case HB_DBG_VMQUIT: - hb_dbgQuit( info ); + if( info ) + { + hb_dbgQuit( info ); + FREE( info ); + *infoPtr = HB_DBGINFO_DISABLE; + } return; } } diff --git a/harbour/source/debug/debugger.prg b/harbour/source/debug/debugger.prg index 6c1955fc9b..9e478a1b41 100644 --- a/harbour/source/debug/debugger.prg +++ b/harbour/source/debug/debugger.prg @@ -108,7 +108,7 @@ #define DEBUGGER_MAXROW 22 #define DEBUGGER_MAXCOL 77 -STATIC s_oDebugger +THREAD STATIC s_oDebugger PROCEDURE __dbgAltDEntry() diff --git a/harbour/source/vm/estack.c b/harbour/source/vm/estack.c index 5a06f13afd..c5f64f00b3 100644 --- a/harbour/source/vm/estack.c +++ b/harbour/source/vm/estack.c @@ -432,6 +432,26 @@ int * hb_stackKeyPolls( void ) return &hb_stack.iKeyPoll; } +#undef hb_stackDebugRequest +BOOL * hb_stackDebugRequest( void ) +{ + HB_STACK_TLS_PRELOAD + + HB_TRACE(HB_TR_DEBUG, ("hb_stackDebugRequest()")); + + return &hb_stack.fDebugRequest; +} + +#undef hb_stackDebugInfo +void ** hb_stackDebugInfo( void ) +{ + HB_STACK_TLS_PRELOAD + + HB_TRACE(HB_TR_DEBUG, ("hb_stackDebugInfo()")); + + return &hb_stack.pDebugInfo; +} + #undef hb_stackGetPrivateStack PHB_PRIVATE_STACK hb_stackGetPrivateStack( void ) { diff --git a/harbour/source/vm/hvm.c b/harbour/source/vm/hvm.c index ca977ee81c..223f79112a 100644 --- a/harbour/source/vm/hvm.c +++ b/harbour/source/vm/hvm.c @@ -216,11 +216,10 @@ static void hb_vmStaticName( BYTE bIsGlobal, USHORT uiStatic, char * szStatic static void hb_vmModuleName( char * szModuleName ); /* PRG and function name information for the debugger */ static void hb_vmDebugEntry( int nMode, int nLine, char *szName, int nIndex, int nFrame ); -static void hb_vmDebuggerExit( void ); /* shuts down the debugger */ +static void hb_vmDebuggerExit( BOOL fRemove ); /* shuts down the debugger */ static void hb_vmDebuggerShowLine( USHORT uiLine ); /* makes the debugger shows a specific source code line */ static void hb_vmDebuggerEndProc( void ); /* notifies the debugger for an endproc */ -static BOOL s_bDebugRequest = FALSE; /* debugger invoked via the VM */ static PHB_DYNS s_pDynsDbgEntry = NULL; /* Cached __DBGENTRY symbol */ static HB_DBGENTRY_FUNC s_pFunDbgEntry; /* C level debugger entry */ #endif @@ -808,9 +807,13 @@ HB_EXPORT void hb_vmThreadQuit( void ) } hb_itemClear( hb_stackReturnItem() ); + hb_stackSetActionRequest( 0 ); hb_rddCloseAll(); /* close all workareas */ hb_stackRemove( 1 ); /* clear stack items, leave only initial symbol item */ hb_memvarsClear(); /* clear all PUBLIC (and PRIVATE if any) variables */ +#ifndef HB_NO_DEBUG + hb_vmDebuggerExit( FALSE ); /* deactivate debugger */ +#endif hb_vmStackRelease(); /* release HVM stack and remove it from linked HVM stacks list */ } @@ -1010,11 +1013,6 @@ HB_EXPORT int hb_vmQuit( void ) hb_vmDoModuleExitFunctions(); hb_vmCleanModuleFunctions(); -#ifndef HB_NO_DEBUG - /* deactivate debugger */ - hb_vmDebuggerExit(); -#endif - /* release all known items stored in subsystems */ hb_itemClear( hb_stackReturnItem() ); hb_stackRemove( 1 ); /* clear stack items, leave only initial symbol item */ @@ -1033,6 +1031,11 @@ HB_EXPORT int hb_vmQuit( void ) hb_rddCloseAll(); /* close all workareas */ hb_rddShutDown(); /* remove all registered RDD drivers */ +#ifndef HB_NO_DEBUG + /* deactivate debugger */ + hb_vmDebuggerExit( TRUE ); +#endif + /* release thread specific data */ hb_stackDestroyTSD(); @@ -5717,9 +5720,9 @@ static void hb_vmDummyDebugEntry( int nMode, int nLine, char *szName, int nIndex HB_SYMBOL_UNUSED( nFrame ); } -static void hb_vmDebuggerExit( void ) +static void hb_vmDebuggerExit( BOOL fRemove ) { - HB_TRACE(HB_TR_DEBUG, ("hb_vmDebuggerExit")); + HB_TRACE(HB_TR_DEBUG, ("hb_vmDebuggerExit(%d)", fRemove)); /* is debugger linked ? */ if( s_pFunDbgEntry ) @@ -5728,7 +5731,8 @@ static void hb_vmDebuggerExit( void ) s_pFunDbgEntry( HB_DBG_VMQUIT, 0, NULL, 0, 0 ); /* set dummy debugger function to avoid debugger activation in .prg * destructors if any */ - s_pFunDbgEntry = hb_vmDummyDebugEntry; + if( fRemove ) + s_pFunDbgEntry = hb_vmDummyDebugEntry; } } @@ -10561,17 +10565,22 @@ HB_EXPORT void hb_vmFlagClear( ULONG flags ) void hb_vmRequestDebug( void ) { - HB_TRACE(HB_TR_DEBUG, ("hb_vmRequestDebug()")); #ifndef HB_NO_DEBUG - s_bDebugRequest = TRUE; + HB_STACK_TLS_PRELOAD + + HB_TRACE(HB_TR_DEBUG, ("hb_vmRequestDebug()")); + + *( hb_stackDebugRequest() ) = TRUE; #endif } HB_EXPORT BOOL hb_dbg_InvokeDebug( BOOL bInvoke ) { #ifndef HB_NO_DEBUG - BOOL bRequest = s_bDebugRequest; - s_bDebugRequest = bInvoke; + HB_STACK_TLS_PRELOAD + BOOL * pfRequest = hb_stackDebugRequest(); + BOOL bRequest = *pfRequest; + *pfRequest = bInvoke; return bRequest; #else HB_SYMBOL_UNUSED( bInvoke ); @@ -10615,8 +10624,10 @@ HB_FUNC( __DBGINVOKEDEBUG ) HB_STACK_TLS_PRELOAD #ifndef HB_NO_DEBUG - hb_retl( s_bDebugRequest ); - s_bDebugRequest = hb_parl( 1 ); + BOOL * pfRequest = hb_stackDebugRequest(); + + hb_retl( *pfRequest ); + *pfRequest = hb_parl( 1 ); #else hb_retl( FALSE ); #endif