[commit: ghc] master: Add LOCK_CLOSURE macro for use in C--, which inlines the capability check. (3a8c501)

Edward Z. Yang ezyang at MIT.EDU
Thu Jul 11 02:07:46 CEST 2013


Repository : http://darcs.haskell.org/ghc.git/

On branch  : master

https://github.com/ghc/ghc/commit/3a8c50111d5a92594f5c2f1b2b96a7c1cfab82eb

>---------------------------------------------------------------

commit 3a8c50111d5a92594f5c2f1b2b96a7c1cfab82eb
Author: Edward Z. Yang <ezyang at mit.edu>
Date:   Wed Jul 10 13:10:32 2013 -0700

    Add LOCK_CLOSURE macro for use in C--, which inlines the capability check.
    
    This patch also tweaks lockClosure to be INLINE_HEADER, so C-- clients
    don't accidentally use them and updates some other code which locks closures
    to do the capability check.
    
    Signed-off-by: Edward Z. Yang <ezyang at mit.edu>

>---------------------------------------------------------------

 includes/rts/storage/SMPClosureOps.h | 35 ++++++++++++++++------
 rts/PrimOps.cmm                      | 56 ++++++------------------------------
 2 files changed, 34 insertions(+), 57 deletions(-)

diff --git a/includes/rts/storage/SMPClosureOps.h b/includes/rts/storage/SMPClosureOps.h
index 2b058fe..a8ebb5d 100644
--- a/includes/rts/storage/SMPClosureOps.h
+++ b/includes/rts/storage/SMPClosureOps.h
@@ -11,13 +11,26 @@
 
 #ifdef CMINUSMINUS
 
+/* Lock closure, equivalent to ccall lockClosure but the condition is inlined.
+ * Arguments are swapped for uniformity with unlockClosure. */
+#if defined(THREADED_RTS)
+#define LOCK_CLOSURE(closure, info)                             \
+    if (CInt[n_capabilities] == 1 :: CInt) {                    \
+        info = GET_INFO(closure);                               \
+    } else {                                                    \
+        ("ptr" info) = ccall reallyLockClosure(closure "ptr");  \
+    }
+#else
+#define LOCK_CLOSURE(closure, info) info = GET_INFO(closure)
+#endif
+
 #define unlockClosure(ptr,info)                 \
     prim_write_barrier;                         \
     StgHeader_info(ptr) = info;
 
 #else
 
-EXTERN_INLINE StgInfoTable *lockClosure(StgClosure *p);
+INLINE_HEADER StgInfoTable *lockClosure(StgClosure *p);
 EXTERN_INLINE StgInfoTable *reallyLockClosure(StgClosure *p);
 EXTERN_INLINE StgInfoTable *tryLockClosure(StgClosure *p);
 EXTERN_INLINE void unlockClosure(StgClosure *p, const StgInfoTable *info);
@@ -30,8 +43,10 @@ EXTERN_INLINE void unlockClosure(StgClosure *p, const StgInfoTable *info);
  * This is used primarily in the implementation of MVars.
  * -------------------------------------------------------------------------- */
 
-// We want a callable copy of lockClosure() so that we can refer to it
-// from .cmm files compiled using the native codegen.
+// We want a callable copy of reallyLockClosure() so that we can refer to it
+// from .cmm files compiled using the native codegen, so these are given
+// EXTERN_INLINE.  C-- should use LOCK_CLOSURE not lockClosure, so we've
+// kept it INLINE_HEADER.
 EXTERN_INLINE StgInfoTable *reallyLockClosure(StgClosure *p)
 {
     StgWord info;
@@ -45,7 +60,7 @@ EXTERN_INLINE StgInfoTable *reallyLockClosure(StgClosure *p)
     } while (1);
 }
 
-EXTERN_INLINE StgInfoTable *lockClosure(StgClosure *p)
+INLINE_HEADER StgInfoTable *lockClosure(StgClosure *p)
 {
     if (n_capabilities == 1) {
         return (StgInfoTable *)p->header.info;
@@ -55,6 +70,8 @@ EXTERN_INLINE StgInfoTable *lockClosure(StgClosure *p)
     }
 }
 
+// ToDo: consider splitting tryLockClosure into reallyTryLockClosure,
+// same as lockClosure
 EXTERN_INLINE StgInfoTable *tryLockClosure(StgClosure *p)
 {
     StgWord info;
@@ -77,7 +94,7 @@ EXTERN_INLINE StgInfoTable *
 reallyLockClosure(StgClosure *p)
 { return (StgInfoTable *)p->header.info; }
 
-EXTERN_INLINE StgInfoTable *
+INLINE_HEADER StgInfoTable *
 lockClosure(StgClosure *p)
 { return (StgInfoTable *)p->header.info; }
 
@@ -95,12 +112,12 @@ EXTERN_INLINE void unlockClosure(StgClosure *p, const StgInfoTable *info)
 }
 
 // Handy specialised versions of lockClosure()/unlockClosure()
-EXTERN_INLINE void lockTSO(StgTSO *tso);
-EXTERN_INLINE void lockTSO(StgTSO *tso)
+INLINE_HEADER void lockTSO(StgTSO *tso);
+INLINE_HEADER void lockTSO(StgTSO *tso)
 { lockClosure((StgClosure *)tso); }
 
-EXTERN_INLINE void unlockTSO(StgTSO *tso);
-EXTERN_INLINE void unlockTSO(StgTSO *tso)
+INLINE_HEADER void unlockTSO(StgTSO *tso);
+INLINE_HEADER void unlockTSO(StgTSO *tso)
 { unlockClosure((StgClosure*)tso, (const StgInfoTable *)&stg_TSO_info); }
 
 #endif /* CMINUSMINUS */
diff --git a/rts/PrimOps.cmm b/rts/PrimOps.cmm
index 63babd0..4f7dffb 100644
--- a/rts/PrimOps.cmm
+++ b/rts/PrimOps.cmm
@@ -404,7 +404,7 @@ stg_addCFinalizzerToWeakzh ( W_ fptr,   // finalizer
 {
   W_ c, info;
 
-  ("ptr" info) = ccall lockClosure(w "ptr");
+  LOCK_CLOSURE(w, info);
 
   if (info == stg_DEAD_WEAK_info) {
     // Already dead.
@@ -439,7 +439,7 @@ stg_finalizzeWeakzh ( gcptr w )
   gcptr f, list;
   W_ info;
 
-  ("ptr" info) = ccall lockClosure(w "ptr");
+  LOCK_CLOSURE(w, info);
 
   // already dead?
   if (info == stg_DEAD_WEAK_info) {
@@ -494,7 +494,7 @@ stg_deRefWeakzh ( gcptr w )
     // alive or not. We use lockClosure to wait for the info pointer to become
     // something other than stg_WHITEHOLE_info.
 
-    ("ptr" info) = ccall lockClosure(w "ptr");
+    LOCK_CLOSURE(w, info);
     unlockClosure(w, info);
   }
 
@@ -1192,16 +1192,7 @@ stg_takeMVarzh ( P_ mvar /* :: MVar a */ )
 {
     W_ val, info, tso, q;
 
-#if defined(THREADED_RTS)
-    if (CInt[n_capabilities] == 1 :: CInt) {
-        info = GET_INFO(mvar);
-    }
-    else {
-        ("ptr" info) = ccall reallyLockClosure(mvar "ptr");
-    }
-#else
-    info = GET_INFO(mvar);
-#endif
+    LOCK_CLOSURE(mvar, info);
 
     /* If the MVar is empty, put ourselves on its blocking queue,
      * and wait until we're woken up.
@@ -1294,16 +1285,7 @@ stg_tryTakeMVarzh ( P_ mvar /* :: MVar a */ )
 {
     W_ val, info, tso, q;
 
-#if defined(THREADED_RTS)
-    if (CInt[n_capabilities] == 1 :: CInt) {
-        info = GET_INFO(mvar);
-    }
-    else {
-        ("ptr" info) = ccall reallyLockClosure(mvar "ptr");
-    }
-#else
-    info = GET_INFO(mvar);
-#endif
+    LOCK_CLOSURE(mvar, info);
 
     /* If the MVar is empty, return 0. */
     if (StgMVar_value(mvar) == stg_END_TSO_QUEUE_closure) {
@@ -1370,16 +1352,7 @@ stg_putMVarzh ( P_ mvar, /* :: MVar a */
 {
     W_ info, tso, q;
 
-#if defined(THREADED_RTS)
-    if (CInt[n_capabilities] == 1 :: CInt) {
-        info = GET_INFO(mvar);
-    }
-    else {
-        ("ptr" info) = ccall reallyLockClosure(mvar "ptr");
-    }
-#else
-    info = GET_INFO(mvar);
-#endif
+    LOCK_CLOSURE(mvar, info);
 
     if (StgMVar_value(mvar) != stg_END_TSO_QUEUE_closure) {
 
@@ -1480,16 +1453,7 @@ stg_tryPutMVarzh ( P_ mvar, /* :: MVar a */
 {
     W_ info, tso, q;
 
-#if defined(THREADED_RTS)
-    if (CInt[n_capabilities] == 1 :: CInt) {
-        info = GET_INFO(mvar);
-    }
-    else {
-        ("ptr" info) = ccall reallyLockClosure(mvar "ptr");
-    }
-#else
-    info = GET_INFO(mvar);
-#endif
+    LOCK_CLOSURE(mvar, info);
 
     if (StgMVar_value(mvar) != stg_END_TSO_QUEUE_closure) {
 #if defined(THREADED_RTS)
@@ -1561,11 +1525,7 @@ stg_atomicReadMVarzh ( P_ mvar, /* :: MVar a */ )
 {
     W_ val, info, tso, q;
 
-#if defined(THREADED_RTS)
-    ("ptr" info) = ccall lockClosure(mvar "ptr");
-#else
-    info = GET_INFO(mvar);
-#endif
+    LOCK_CLOSURE(mvar, info);
 
     if (info == stg_MVAR_CLEAN_info) {
         ccall dirty_MVAR(BaseReg "ptr", mvar "ptr");





More information about the ghc-commits mailing list