From 766cd74186c8a210f9010a8da1704dc79b79933d Mon Sep 17 00:00:00 2001 From: Przemyslaw Czerpak Date: Tue, 23 Mar 2010 14:20:25 +0000 Subject: [PATCH] 2010-03-23 15:19 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/include/hbxvm.h * harbour/src/vm/hvm.c + added hb_xvmPushAliasedFieldExt() and hb_xvmPopAliasedFieldExt() * harbour/src/compiler/gencc.c % use hb_xvmPushAliasedFieldExt() and hb_xvmPopAliasedFieldExt() to optimize code generated for -> expressions in -gc3 mode * harbour/include/hbsetup.h + added _HB_INLINE_ macro * harbour/include/hbatomic.h + added HB_SPINLOCK_TRY(l) + added support for recursive spin locks * harbour/src/vm/fm.c * use _HB_INLINE_ --- harbour/ChangeLog | 20 ++++ harbour/include/hbatomic.h | 186 +++++++++++++++++++++++++++-------- harbour/include/hbsetup.h | 11 +++ harbour/include/hbxvm.h | 2 + harbour/src/compiler/gencc.c | 74 ++++++++++++-- harbour/src/vm/fm.c | 11 +-- harbour/src/vm/hvm.c | 33 +++++++ 7 files changed, 277 insertions(+), 60 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index c7037c3e9f..a60e48231c 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -17,6 +17,26 @@ past entries belonging to author(s): Viktor Szakats. */ +2010-03-23 15:19 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/include/hbxvm.h + * harbour/src/vm/hvm.c + + added hb_xvmPushAliasedFieldExt() and hb_xvmPopAliasedFieldExt() + + * harbour/src/compiler/gencc.c + % use hb_xvmPushAliasedFieldExt() and hb_xvmPopAliasedFieldExt() + to optimize code generated for -> expressions + in -gc3 mode + + * harbour/include/hbsetup.h + + added _HB_INLINE_ macro + + * harbour/include/hbatomic.h + + added HB_SPINLOCK_TRY(l) + + added support for recursive spin locks + + * harbour/src/vm/fm.c + * use _HB_INLINE_ + 2010-03-23 12:55 UTC+0200 Mindaugas Kavaliauskas (dbtopas/at/dbtopas.lt) * harbour/contrib/rddsql/hbrddsql.h * harbour/contrib/rddsql/sqlbase.c diff --git a/harbour/include/hbatomic.h b/harbour/include/hbatomic.h index a3f5db1493..084ad7c78e 100644 --- a/harbour/include/hbatomic.h +++ b/harbour/include/hbatomic.h @@ -79,7 +79,7 @@ HB_EXTERN_BEGIN # define HB_SCHED_YIELD() Sleep( 0 ) #elif defined( HB_OS_OS2 ) # define HB_SCHED_YIELD() DosSleep( 0 ) -#elif defined( __SVR4 ) +#elif defined( HB_OS_SUNOS ) || defined( __SVR4 ) # define HB_SCHED_YIELD() thr_yield() #elif defined( HB_OS_UNIX ) # define HB_SCHED_YIELD() sched_yield() @@ -165,7 +165,6 @@ HB_EXTERN_BEGIN { if( !hb_spinlock_trylock( l ) ) return; - #ifdef HB_SPINLOCK_REPEAT if( !hb_spinlock_trylock( l ) ) return; @@ -181,8 +180,10 @@ HB_EXTERN_BEGIN # define HB_SPINLOCK_T volatile int # define HB_SPINLOCK_INIT 0 -# define HB_SPINLOCK_ACQUIRE(l) hb_spinlock_acquire(l) +# define HB_SPINLOCK_TRY(l) (hb_spinlock_trylock(l)==0) # define HB_SPINLOCK_RELEASE(l) hb_spinlock_release(l) +# define HB_SPINLOCK_ACQUIRE(l) hb_spinlock_acquire(l) + # elif ( ( __GNUC__ > 4 ) || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 1) ) && \ !defined( __MINGW32CE__ ) @@ -209,8 +210,9 @@ HB_EXTERN_BEGIN # define HB_SPINLOCK_T int # define HB_SPINLOCK_INIT 0 -# define HB_SPINLOCK_ACQUIRE(l) hb_spinlock_acquire(l) +# define HB_SPINLOCK_TRY(l) (__sync_lock_test_and_set(l. 1)==0) # define HB_SPINLOCK_RELEASE(l) __sync_lock_release(l) +# define HB_SPINLOCK_ACQUIRE(l) hb_spinlock_acquire(l) # elif defined( HB_CPU_PPC ) @@ -327,7 +329,7 @@ HB_EXTERN_BEGIN "xchg eax, dword ptr [edx]" \ parm [ edx ] value [ eax ] modify exact [ eax ] ; - static inline void hb_spinlock_acquire( volatile int * l ) + static __inline void hb_spinlock_acquire( volatile int * l ) { for( ;; ) { @@ -342,15 +344,16 @@ HB_EXTERN_BEGIN } } - static inline void hb_spinlock_release( volatile int * l ) + static __inline void hb_spinlock_release( volatile int * l ) { *l = 0; } # define HB_SPINLOCK_T volatile int # define HB_SPINLOCK_INIT 0 -# define HB_SPINLOCK_ACQUIRE(l) hb_spinlock_acquire(l) +# define HB_SPINLOCK_TRY(l) (hb_spinlock_trylock(l)==0) # define HB_SPINLOCK_RELEASE(l) hb_spinlock_release(l) +# define HB_SPINLOCK_ACQUIRE(l) hb_spinlock_acquire(l) # endif /* x86 */ @@ -382,22 +385,8 @@ HB_EXTERN_BEGIN # if !defined( HB_SPINLOCK_T ) # define HB_SPINLOCK_T volatile LONG # define HB_SPINLOCK_INIT 0 -# ifdef HB_SPINLOCK_REPEAT -# define HB_SPINLOCK_ACQUIRE(l) do { \ - if( !InterlockedExchange( (LONG*)(l), 1 ) ) \ - break; \ - if( !InterlockedExchange( (LONG*)(l), 1 ) ) \ - break; \ - Sleep( 0 ); \ - } while(1) -# else -# define HB_SPINLOCK_ACQUIRE(l) do { \ - if( !InterlockedExchange( (LONG*)(l), 1 ) ) \ - break; \ - Sleep( 0 ); \ - } while(1) -# endif -# define HB_SPINLOCK_RELEASE(l) do { *(l) = 0; } while(0) +# define HB_SPINLOCK_TRY(l) (!InterlockedExchange( (LONG*)(l), 1 )) +# define HB_SPINLOCK_RELEASE(l) ( *(l) = 0 ) # endif #elif defined( HB_OS_DARWIN ) @@ -425,12 +414,14 @@ HB_EXTERN_BEGIN # if !defined( HB_SPINLOCK_T ) || 1 /* <= force using OSSpinLock */ # undef HB_SPINLOCK_T # undef HB_SPINLOCK_INIT -# undef HB_SPINLOCK_ACQUIRE +# undef HB_SPINLOCK_TRY # undef HB_SPINLOCK_RELEASE +# undef HB_SPINLOCK_ACQUIRE # define HB_SPINLOCK_T OSSpinLock # define HB_SPINLOCK_INIT OS_SPINLOCK_INIT -# define HB_SPINLOCK_ACQUIRE(l) OSSpinLockLock(l) +# define HB_SPINLOCK_TRY(l) OSSpinLockTry(l) # define HB_SPINLOCK_RELEASE(l) OSSpinLockUnlock(l) +# define HB_SPINLOCK_ACQUIRE(l) OSSpinLockLock(l) # endif #elif defined( HB_OS_SUNOS ) @@ -451,26 +442,139 @@ HB_EXTERN_BEGIN # if !defined( HB_SPINLOCK_T ) # define HB_SPINLOCK_T volatile uint_t # define HB_SPINLOCK_INIT 0 -# ifdef HB_SPINLOCK_REPEAT -# define HB_SPINLOCK_ACQUIRE(l) do { \ - if( !atomic_swap_uint( (l), 1 ) ) \ - break; \ - if( !atomic_swap_uint( (l), 1 ) ) \ - break; \ - thr_yield(); \ - } while(1) -# else -# define HB_SPINLOCK_ACQUIRE(l) do { \ - if( !atomic_swap_uint( (l), 1 ) ) \ - break; \ - thr_yield(); \ - } while(1) -# endif -# define HB_SPINLOCK_RELEASE(l) do { *(l) = 0; } while(0) +# define HB_SPINLOCK_TRY(l) ( ! atomic_swap_uint( (l), 1 ) ) +# define HB_SPINLOCK_RELEASE(l) ( *(l) = 0 ) # endif #endif /* HB_OS_??? */ +#if defined( HB_SPINLOCK_T ) +# if !defined( HB_SPINLOCK_ACQUIRE ) +# ifdef HB_SPINLOCK_REPEAT +# define HB_SPINLOCK_ACQUIRE(l) do { \ + if( HB_SPINLOCK_TRY( l ) ) \ + break; \ + if( HB_SPINLOCK_TRY( l ) ) \ + break; \ + HB_SCHED_YIELD(); \ + } while(1) +# else +# define HB_SPINLOCK_ACQUIRE(l) do { \ + if( HB_SPINLOCK_TRY( l ) ) \ + break; \ + HB_SCHED_YIELD(); \ + } while(1) +# endif +# endif +# if !defined( HB_SPINLOCK_R ) + struct hb_spinlock_r + { + HB_SPINLOCK_T lock; + unsigned int count; + HB_THREAD_ID thid; + }; + + static _HB_INLINE_ void hb_spinlock_release_r( struct hb_spinlock_r * sl ) + { + if( --sl->count == 0 ) + { + sl->thid = 0; + HB_SPINLOCK_RELEASE( &sl->lock ); + } + } + + static _HB_INLINE_ int hb_spinlock_try_r( struct hb_spinlock_r * sl ) + { + HB_SPINLOCK_T * l = &(sl)->lock; + int r = 0; + if( *l != HB_SPINLOCK_INIT ) + { + if( (sl)->thid == HB_THREAD_SELF() ) + { + (sl)->count++; + r = 1; + } + } + else if( HB_SPINLOCK_TRY( l ) ) + { + (sl)->thid = HB_THREAD_SELF(); + (sl)->count = 1; + r = 1; + } + return r; + } + +# ifndef HB_SPINLOCK_REPEAT +# define HB_SPINLOCK_REPEAT 63 +# endif + +/* workaround for borland C/C++ compiler limitation */ +#if defined( __BORLANDC__ ) +# define hb_spinlock_acquire_r( sl ) \ + do { \ + HB_SPINLOCK_T * l = &(sl)->lock; \ + int count = HB_SPINLOCK_REPEAT; \ + for( ;; ) \ + { \ + if( *l != HB_SPINLOCK_INIT ) \ + { \ + if( (sl)->thid == HB_THREAD_SELF() ) \ + { \ + (sl)->count++; \ + break; \ + } \ + } \ + else if( HB_SPINLOCK_TRY( l ) ) \ + { \ + (sl)->thid = HB_THREAD_SELF(); \ + (sl)->count = 1; \ + break; \ + } \ + if( --count == 0 ) \ + { \ + HB_SCHED_YIELD(); \ + count = HB_SPINLOCK_REPEAT; \ + } \ + } \ + } while( 0 ) +#else + static _HB_INLINE_ void hb_spinlock_acquire_r( struct hb_spinlock_r * sl ) + { + HB_SPINLOCK_T * l = &(sl)->lock; + int count = HB_SPINLOCK_REPEAT; + for( ;; ) + { + if( *l != HB_SPINLOCK_INIT ) + { + if( (sl)->thid == HB_THREAD_SELF() ) + { + (sl)->count++; + break; + } + } + else if( HB_SPINLOCK_TRY( l ) ) + { + (sl)->thid = HB_THREAD_SELF(); + (sl)->count = 1; + break; + } + if( --count == 0 ) + { + HB_SCHED_YIELD(); + count = HB_SPINLOCK_REPEAT; + } + } + } +#endif + +# define HB_SPINLOCK_R struct hb_spinlock_r +# define HB_SPINLOCK_INIT_R { 0, 0, 0 } +# define HB_SPINLOCK_TRY_R(l) hb_spinlock_try_r(l) +# define HB_SPINLOCK_RELEASE_R(l) hb_spinlock_release_r(l) +# define HB_SPINLOCK_ACQUIRE_R(l) hb_spinlock_acquire_r(l) +# endif /* !HB_SPINLOCK_R */ +#endif /* HB_SPINLOCK_T */ + HB_EXTERN_END #endif /* HB_ATOMIC_H_ */ diff --git a/harbour/include/hbsetup.h b/harbour/include/hbsetup.h index 0e0ed6bd07..c10d82dbb7 100644 --- a/harbour/include/hbsetup.h +++ b/harbour/include/hbsetup.h @@ -515,4 +515,15 @@ #define HB_RESTRICT #endif +#if defined( __GNUC__ ) || defined( __SUNPRO_C ) || defined( __SUNPRO_CC ) + #define _HB_INLINE_ __inline__ +#elif defined( __BORLANDC__ ) || defined( _MSC_VER ) || \ + defined( __WATCOMC__ ) || defined( __POCC__ ) || defined( __XCC__ ) || \ + defined( __LCC__ ) || defined( __DMC__ ) + #define _HB_INLINE_ __inline +#else /* __cplusplus */ + #define _HB_INLINE_ inline +#endif + + #endif /* HB_SETUP_H_ */ diff --git a/harbour/include/hbxvm.h b/harbour/include/hbxvm.h index 5e502ad635..be9d53a7a6 100644 --- a/harbour/include/hbxvm.h +++ b/harbour/include/hbxvm.h @@ -131,6 +131,8 @@ extern HB_EXPORT HB_BOOL hb_xvmPushMemvarByRef( PHB_SYMB pSymbol ); extern HB_EXPORT HB_BOOL hb_xvmPopMemvar( PHB_SYMB pSymbol ); extern HB_EXPORT HB_BOOL hb_xvmPushAliasedField( PHB_SYMB pSymbol ); extern HB_EXPORT HB_BOOL hb_xvmPopAliasedField( PHB_SYMB pSymbol ); +extern HB_EXPORT HB_BOOL hb_xvmPushAliasedFieldExt( PHB_SYMB pAlias, PHB_SYMB pField ); +extern HB_EXPORT HB_BOOL hb_xvmPopAliasedFieldExt( PHB_SYMB pAlias, PHB_SYMB pField ); extern HB_EXPORT HB_BOOL hb_xvmPushAliasedVar( PHB_SYMB pSymbol ); extern HB_EXPORT HB_BOOL hb_xvmPopAliasedVar( PHB_SYMB pSymbol ); extern HB_EXPORT HB_BOOL hb_xvmPushAlias( void ); diff --git a/harbour/src/compiler/gencc.c b/harbour/src/compiler/gencc.c index cadcb66658..ac20f1cddf 100644 --- a/harbour/src/compiler/gencc.c +++ b/harbour/src/compiler/gencc.c @@ -1401,12 +1401,39 @@ static HB_GENC_FUNC( hb_p_pushsym ) { HB_GENC_LABEL(); - if( pFunc->pCode[ lPCodePos + 3 ] == HB_P_PUSHNIL && - HB_GENC_GETLABEL( lPCodePos + 3 ) == 0 ) + if( HB_GENC_GETLABEL( lPCodePos + 3 ) == 0 ) { - fprintf( cargo->yyc, "\thb_xvmPushFuncSymbol( symbols + %hu );\n", - HB_PCODE_MKUSHORT( &pFunc->pCode[ lPCodePos + 1 ] ) ); - return 4; + switch( pFunc->pCode[ lPCodePos + 3 ] ) + { + case HB_P_PUSHNIL: + fprintf( cargo->yyc, "\thb_xvmPushFuncSymbol( symbols + %hu );\n", + HB_PCODE_MKUSHORT( &pFunc->pCode[ lPCodePos + 1 ] ) ); + return 4; + case HB_P_PUSHALIASEDFIELDNEAR: + fprintf( cargo->yyc, + "\thb_xvmPushAliasedFieldExt( symbols + %u, symbols + %u );\n", + HB_PCODE_MKUSHORT( &pFunc->pCode[ lPCodePos + 1 ] ), + pFunc->pCode[ lPCodePos + 4 ] ); + return 5; + case HB_P_PUSHALIASEDFIELD: + fprintf( cargo->yyc, + "\thb_xvmPushAliasedFieldExt( symbols + %u, symbols + %u );\n", + HB_PCODE_MKUSHORT( &pFunc->pCode[ lPCodePos + 1 ] ), + HB_PCODE_MKUSHORT( &pFunc->pCode[ lPCodePos + 4 ] ) ); + return 6; + case HB_P_POPALIASEDFIELDNEAR: + fprintf( cargo->yyc, + "\thb_xvmPopAliasedFieldExt( symbols + %u, symbols + %u );\n", + HB_PCODE_MKUSHORT( &pFunc->pCode[ lPCodePos + 1 ] ), + pFunc->pCode[ lPCodePos + 4 ] ); + return 5; + case HB_P_POPALIASEDFIELD: + fprintf( cargo->yyc, + "\thb_xvmPopAliasedFieldExt( symbols + %u, symbols + %u );\n", + HB_PCODE_MKUSHORT( &pFunc->pCode[ lPCodePos + 1 ] ), + HB_PCODE_MKUSHORT( &pFunc->pCode[ lPCodePos + 4 ] ) ); + return 6; + } } fprintf( cargo->yyc, "\thb_xvmPushSymbol( symbols + %hu );\n", @@ -1418,12 +1445,39 @@ static HB_GENC_FUNC( hb_p_pushsymnear ) { HB_GENC_LABEL(); - if( pFunc->pCode[ lPCodePos + 2 ] == HB_P_PUSHNIL && - HB_GENC_GETLABEL( lPCodePos + 2 ) == 0 ) + if( HB_GENC_GETLABEL( lPCodePos + 2 ) == 0 ) { - fprintf( cargo->yyc, "\thb_xvmPushFuncSymbol( symbols + %hu );\n", - pFunc->pCode[ lPCodePos + 1 ] ); - return 3; + switch( pFunc->pCode[ lPCodePos + 2 ] ) + { + case HB_P_PUSHNIL: + fprintf( cargo->yyc, "\thb_xvmPushFuncSymbol( symbols + %u );\n", + pFunc->pCode[ lPCodePos + 1 ] ); + return 3; + case HB_P_PUSHALIASEDFIELDNEAR: + fprintf( cargo->yyc, + "\thb_xvmPushAliasedFieldExt( symbols + %u, symbols + %u );\n", + pFunc->pCode[ lPCodePos + 1 ], + pFunc->pCode[ lPCodePos + 3 ] ); + return 4; + case HB_P_PUSHALIASEDFIELD: + fprintf( cargo->yyc, + "\thb_xvmPushAliasedFieldExt( symbols + %u, symbols + %u );\n", + pFunc->pCode[ lPCodePos + 1 ], + HB_PCODE_MKUSHORT( &pFunc->pCode[ lPCodePos + 3 ] ) ); + return 5; + case HB_P_POPALIASEDFIELDNEAR: + fprintf( cargo->yyc, + "\thb_xvmPopAliasedFieldExt( symbols + %u, symbols + %u );\n", + pFunc->pCode[ lPCodePos + 1 ], + pFunc->pCode[ lPCodePos + 3 ] ); + return 4; + case HB_P_POPALIASEDFIELD: + fprintf( cargo->yyc, + "\thb_xvmPopAliasedFieldExt( symbols + %u, symbols + %u );\n", + pFunc->pCode[ lPCodePos + 1 ], + HB_PCODE_MKUSHORT( &pFunc->pCode[ lPCodePos + 3 ] ) ); + return 5; + } } fprintf( cargo->yyc, "\thb_xvmPushSymbol( symbols + %d );\n", diff --git a/harbour/src/vm/fm.c b/harbour/src/vm/fm.c index 0b30c74003..ad33a5e83c 100644 --- a/harbour/src/vm/fm.c +++ b/harbour/src/vm/fm.c @@ -74,13 +74,6 @@ # define _GNU_SOURCE #endif -/* For Sun C, a more generic solution would be nice */ -#if defined( __SUNPRO_C ) || defined( __SUNPRO_CC ) -# ifndef __inline -# define __inline __inline__ -# endif -#endif - /* NOTE: Need to have these before Harbour headers, because in MT mode, they will automatically #include . */ #define INCL_BASE @@ -345,14 +338,14 @@ typedef void * PHB_MEMINFO; # undef HB_ATOM_INC # undef HB_ATOM_GET # undef HB_ATOM_SET - static __inline void hb_counterIncrement( volatile HB_COUNTER * p ) + static _HB_INLINE_ void hb_counterIncrement( volatile HB_COUNTER * p ) { HB_FM_LOCK ++(*p); HB_FM_UNLOCK } # define HB_ATOM_INC( p ) hb_counterIncrement( p ) - static __inline int hb_counterDecrement( volatile HB_COUNTER * p ) + static _HB_INLINE_ int hb_counterDecrement( volatile HB_COUNTER * p ) { int iResult; HB_FM_LOCK diff --git a/harbour/src/vm/hvm.c b/harbour/src/vm/hvm.c index db0b14d376..215d66d72d 100644 --- a/harbour/src/vm/hvm.c +++ b/harbour/src/vm/hvm.c @@ -9317,6 +9317,21 @@ HB_BOOL hb_xvmPushAliasedField( PHB_SYMB pSymbol ) HB_XVM_RETURN } +HB_BOOL hb_xvmPushAliasedFieldExt( PHB_SYMB pAlias, PHB_SYMB pField ) +{ + HB_STACK_TLS_PRELOAD + int iCurrArea; + + HB_TRACE(HB_TR_INFO, ("hb_xvmPushAliasedFieldExt(%p,%p)", pAlias, pField)); + + iCurrArea = hb_rddGetCurrentWorkAreaNumber(); + if( hb_rddSelectWorkAreaSymbol( pAlias ) == HB_SUCCESS ) + hb_rddGetFieldValue( hb_stackAllocItem(), pField ); + hb_rddSelectWorkAreaNumber( iCurrArea ); + + HB_XVM_RETURN +} + HB_BOOL hb_xvmPushAliasedVar( PHB_SYMB pSymbol ) { HB_STACK_TLS_PRELOAD @@ -9385,6 +9400,24 @@ HB_BOOL hb_xvmPopAliasedField( PHB_SYMB pSymbol ) HB_XVM_RETURN } +HB_BOOL hb_xvmPopAliasedFieldExt( PHB_SYMB pAlias, PHB_SYMB pField ) +{ + HB_STACK_TLS_PRELOAD + int iCurrArea; + + HB_TRACE(HB_TR_INFO, ("hb_xvmPopAliasedFieldExt(%p,%p)", pAlias, pField)); + + iCurrArea = hb_rddGetCurrentWorkAreaNumber(); + if( hb_rddSelectWorkAreaSymbol( pAlias ) == HB_SUCCESS ) + { + hb_rddPutFieldValue( hb_stackItemFromTop( -1 ), pField ); + hb_stackPop(); + } + hb_rddSelectWorkAreaNumber( iCurrArea ); + + HB_XVM_RETURN +} + HB_BOOL hb_xvmPopAliasedVar( PHB_SYMB pSymbol ) { HB_STACK_TLS_PRELOAD