summaryrefslogtreecommitdiff
path: root/includes
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2009-09-29 13:07:22 +0000
committerSimon Marlow <marlowsd@gmail.com>2009-09-29 13:07:22 +0000
commit0ee6cfbe62211121fc84a9d2e500f414f9e397f7 (patch)
tree21e8c6ac9b4bd138bb847290b1d9233d11f65f38 /includes
parenteab91b9df6cd3eab7ba1b2ed0f0e649b314611bc (diff)
downloadhaskell-0ee6cfbe62211121fc84a9d2e500f414f9e397f7.tar.gz
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.
Diffstat (limited to 'includes')
-rw-r--r--includes/rts/SpinLock.h2
-rw-r--r--includes/stg/SMP.h18
2 files changed, 20 insertions, 0 deletions
diff --git a/includes/rts/SpinLock.h b/includes/rts/SpinLock.h
index 9bfb35bbac..3d0b56cfcb 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 8297f5711c..b302f4886b 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
/*