From 9ee34a0cb977be8917fd3183470e636f160ff36b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Czerpak?= Date: Fri, 10 Jan 2014 11:07:11 +0100 Subject: [PATCH] 2014-01-10 11:07 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) * include/hbatomic.h * for GCC >= 4.1 (except MinGW) use build-in GCC __sync_*() atomic functions instead of our x86 assembler macros. This can be disabled by HB_USE_GCCATOMIC_OFF macro. Please make tests on different platforms. If you find some platforms on which compile or link errors bound with __sync_*() functions are reported then please send information about used platform and GCC version. GCC 4.1 or higher should support it during compilation but not all runtime libraries have implementation for __sync_*() functions. Low level implementations were added later for different platforms. In such case adding -DHB_USE_GCCATOMIC_OFF to HB_USER_CFLAGS should be sufficient workaround but I want to document such cases so please send information about it to devel list. ; This modification fixes problem with x86_64 CentOS and RH builds were default GCC does not respect volatile in our ASM macros and "optimize" them breaking our memory barriers. --- ChangeLog.txt | 18 ++++++++++++++ include/hbatomic.h | 58 +++++++++++++++++++++++----------------------- 2 files changed, 47 insertions(+), 29 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index 7019f87044..d31ed6f5fb 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -10,6 +10,24 @@ * Change, ! Fix, % Optimization, + Addition, - Removal, ; Comment */ +2014-01-10 11:07 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) + * include/hbatomic.h + * for GCC >= 4.1 (except MinGW) use build-in GCC __sync_*() atomic + functions instead of our x86 assembler macros. This can be disabled + by HB_USE_GCCATOMIC_OFF macro. Please make tests on different + platforms. If you find some platforms on which compile or link + errors bound with __sync_*() functions are reported then please + send information about used platform and GCC version. GCC 4.1 or + higher should support it during compilation but not all runtime + libraries have implementation for __sync_*() functions. Low level + implementations were added later for different platforms. In such + case adding -DHB_USE_GCCATOMIC_OFF to HB_USER_CFLAGS should be + sufficient workaround but I want to document such cases so please + send information about it to devel list. + ; This modification fixes problem with x86_64 CentOS and RH builds + were default GCC does not respect volatile in our ASM macros and + "optimize" them breaking our memory barriers. + 2014-01-09 22:51 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) * src/rtl/tgetint.prg ! force linking HB_PValue diff --git a/include/hbatomic.h b/include/hbatomic.h index 39e5578fc6..503de15752 100644 --- a/include/hbatomic.h +++ b/include/hbatomic.h @@ -94,7 +94,35 @@ HB_EXTERN_BEGIN # define HB_USE_GCCATOMIC # endif -# if defined( HB_CPU_X86 ) || defined( HB_CPU_X86_64 ) +# if defined( HB_USE_GCCATOMIC ) + +# define HB_ATOM_INC( p ) __sync_add_and_fetch( (p), 1 ) +# define HB_ATOM_DEC( p ) __sync_sub_and_fetch( (p), 1 ) +# define HB_ATOM_GET( p ) ( *(p) ) +# define HB_ATOM_SET( p, n ) do { *(p) = (n); } while(0) + + static __inline__ void hb_spinlock_acquire( int * l ) + { + for( ;; ) + { + if( ! __sync_lock_test_and_set( l, 1 ) ) + return; + + #ifdef HB_SPINLOCK_REPEAT + if( ! __sync_lock_test_and_set( l, 1 ) ) + return; + #endif + HB_SCHED_YIELD(); + } + } + +# define HB_SPINLOCK_T int +# define HB_SPINLOCK_INIT 0 +# 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_X86 ) || defined( HB_CPU_X86_64 ) # if HB_COUNTER_SIZE == 4 @@ -187,34 +215,6 @@ HB_EXTERN_BEGIN # define HB_SPINLOCK_RELEASE(l) hb_spinlock_release(l) # define HB_SPINLOCK_ACQUIRE(l) hb_spinlock_acquire(l) -# elif defined( HB_USE_GCCATOMIC ) - -# define HB_ATOM_INC( p ) __sync_add_and_fetch( (p), 1 ) -# define HB_ATOM_DEC( p ) __sync_sub_and_fetch( (p), 1 ) -# define HB_ATOM_GET( p ) ( *(p) ) -# define HB_ATOM_SET( p, n ) do { *(p) = (n); } while(0) - - static __inline__ void hb_spinlock_acquire( int * l ) - { - for( ;; ) - { - if( ! __sync_lock_test_and_set( l, 1 ) ) - return; - - #ifdef HB_SPINLOCK_REPEAT - if( ! __sync_lock_test_and_set( l, 1 ) ) - return; - #endif - HB_SCHED_YIELD(); - } - } - -# define HB_SPINLOCK_T int -# define HB_SPINLOCK_INIT 0 -# 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 ) # if HB_COUNTER_SIZE == 4