Use "rep; nop" inside a spin-lock loop on x86/x86-64
authorSimon Marlow <marlowsd@gmail.com>
Tue, 29 Sep 2009 13:07:22 +0000 (13:07 +0000)
committerSimon Marlow <marlowsd@gmail.com>
Tue, 29 Sep 2009 13:07:22 +0000 (13:07 +0000)
This helps on a hyperthreaded CPU by yielding to the other thread in a
spinlock loop.

includes/rts/SpinLock.h
includes/stg/SMP.h

index 9bfb35b..3d0b56c 100644 (file)
@@ -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);
 }
 
index 8297f57..b302f48 100644 (file)
@@ -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
 
 /*