From 0ee6cfbe62211121fc84a9d2e500f414f9e397f7 Mon Sep 17 00:00:00 2001 From: Simon Marlow Date: Tue, 29 Sep 2009 13:07:22 +0000 Subject: [PATCH] Use "rep; nop" inside a spin-lock loop on x86/x86-64 This helps on a hyperthreaded CPU by yielding to the other thread in a spinlock loop. --- includes/rts/SpinLock.h | 2 ++ includes/stg/SMP.h | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/includes/rts/SpinLock.h b/includes/rts/SpinLock.h index 9bfb35b..3d0b56c 100644 --- a/includes/rts/SpinLock.h +++ b/includes/rts/SpinLock.h @@ -49,6 +49,7 @@ spin: r = cas((StgVolatilePtr)&(p->lock), 1, 0); if (r == 0) { p->spin++; + busy_wait_nop(); goto spin; } } @@ -76,6 +77,7 @@ INLINE_HEADER void ACQUIRE_SPIN_LOCK(SpinLock * p) StgWord32 r = 0; do { r = cas((StgVolatilePtr)p, 1, 0); + busy_wait_nop(); } while(r == 0); } diff --git a/includes/stg/SMP.h b/includes/stg/SMP.h index 8297f57..b302f48 100644 --- a/includes/stg/SMP.h +++ b/includes/stg/SMP.h @@ -64,6 +64,13 @@ EXTERN_INLINE StgWord atomic_inc(StgVolatilePtr p); */ EXTERN_INLINE StgWord atomic_dec(StgVolatilePtr p); +/* + * Busy-wait nop: this is a hint to the CPU that we are currently in a + * busy-wait loop waiting for another CPU to change something. On a + * hypertreaded CPU it should yield to another thread, for example. + */ +EXTERN_INLINE void busy_wait_nop(void); + #endif // !IN_STG_CODE /* @@ -216,6 +223,17 @@ atomic_dec(StgVolatilePtr p) #endif } +EXTERN_INLINE void +busy_wait_nop(void) +{ +#if defined(i386_HOST_ARCH) || defined(x86_64_HOST_ARCH) + __asm__ __volatile__ ("rep; nop"); + // +#else + // nothing +#endif +} + #endif // !IN_STG_CODE /* -- 1.7.10.4