Fix trac #3001: Biographical profiling segfaults
[ghc-hetmet.git] / includes / SMP.h
index eaac770..49bc336 100644 (file)
  *      Unregisterised builds are ok, but only 1 CPU supported.
  */
 
-#ifdef CMINUSMINUS
-
-#define unlockClosure(ptr,info)                 \
-    prim %write_barrier() [];                   \
-    StgHeader_info(ptr) = info;    
-
-#else
-
 #if defined(THREADED_RTS)
 
 #if  defined(TICKY_TICKY)
    Atomic operations
    ------------------------------------------------------------------------- */
    
+#if !IN_STG_CODE
+// We only want write_barrier() declared in .hc files.  Defining the
+// other inline functions here causes type mismatch errors from gcc,
+// because the generated C code is assuming that there are no
+// prototypes in scope.
+
 /* 
  * The atomic exchange operation: xchg(p,w) exchanges the value
  * pointed to by p with the value w, returning the old value.
@@ -54,15 +52,25 @@ EXTERN_INLINE StgWord xchg(StgPtr p, StgWord w);
  */
 EXTERN_INLINE StgWord cas(StgVolatilePtr p, StgWord o, StgWord n);
 
+#endif // !IN_STG_CODE
+
 /*
  * Prevents write operations from moving across this call in either
  * direction.
  */ 
 EXTERN_INLINE void write_barrier(void);
 
+/*
+ * Prevents loads from moving before earlier stores.
+ */
+EXTERN_INLINE void store_load_barrier(void);
+
 /* ----------------------------------------------------------------------------
    Implementations
    ------------------------------------------------------------------------- */
+
+#if !IN_STG_CODE
+
 /* 
  * NB: the xchg instruction is implicitly locked, so we do not need
  * a lock prefix here. 
@@ -149,6 +157,8 @@ cas(StgVolatilePtr p, StgWord o, StgWord n)
 #endif
 }
 
+#endif // !IN_STG_CODE
+
 /*
  * Write barrier - ensure that all preceding writes have happened
  * before all following writes.  
@@ -175,11 +185,31 @@ write_barrier(void) {
 #endif
 }
 
+EXTERN_INLINE void
+store_load_barrier(void) {
+#if i386_HOST_ARCH
+    __asm__ __volatile__ ("lock; addl $0,0(%%esp)" : : : "memory");
+#elif x86_64_HOST_ARCH
+    __asm__ __volatile__ ("lock; addq $0,0(%%rsp)" : : : "memory");
+#elif powerpc_HOST_ARCH
+    __asm__ __volatile__ ("msync" : : : "memory");
+#elif sparc_HOST_ARCH
+    /* Sparc in TSO mode does not require write/write barriers. */
+    __asm__ __volatile__ ("membar" : : : "memory");
+#elif !defined(WITHSMP)
+    return;
+#else
+#error memory barriers unimplemented on this architecture
+#endif
+}
+
 /* ---------------------------------------------------------------------- */
 #else /* !THREADED_RTS */
 
 #define write_barrier() /* nothing */
 
+#define store_load_barrier() /* nothing */
+
 INLINE_HEADER StgWord
 xchg(StgPtr p, StgWord w)
 {
@@ -188,8 +218,17 @@ xchg(StgPtr p, StgWord w)
     return old;
 }
 
-#endif /* !THREADED_RTS */
+STATIC_INLINE StgWord
+cas(StgVolatilePtr p, StgWord o, StgWord n)
+{
+    StgWord result;
+    result = *p;
+    if (result == o) {
+        *p = n;
+    }
+    return result;
+}
 
-#endif /* CMINUSMINUS */
+#endif /* !THREADED_RTS */
 
 #endif /* SMP_H */