summaryrefslogtreecommitdiff
path: root/includes/rts/storage/SMPClosureOps.h
diff options
context:
space:
mode:
Diffstat (limited to 'includes/rts/storage/SMPClosureOps.h')
-rw-r--r--includes/rts/storage/SMPClosureOps.h77
1 files changed, 57 insertions, 20 deletions
diff --git a/includes/rts/storage/SMPClosureOps.h b/includes/rts/storage/SMPClosureOps.h
index 39349874f7..a8ebb5d0ed 100644
--- a/includes/rts/storage/SMPClosureOps.h
+++ b/includes/rts/storage/SMPClosureOps.h
@@ -11,13 +11,27 @@
#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;
+ 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);
@@ -29,35 +43,58 @@ 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.
-EXTERN_INLINE StgInfoTable *lockClosure(StgClosure *p)
+// 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;
do {
- nat i = 0;
- do {
- info = xchg((P_)(void *)&p->header.info, (W_)&stg_WHITEHOLE_info);
- if (info != (W_)&stg_WHITEHOLE_info) return (StgInfoTable *)info;
- } while (++i < SPIN_COUNT);
- yieldThread();
+ nat i = 0;
+ do {
+ info = xchg((P_)(void *)&p->header.info, (W_)&stg_WHITEHOLE_info);
+ if (info != (W_)&stg_WHITEHOLE_info) return (StgInfoTable *)info;
+ } while (++i < SPIN_COUNT);
+ yieldThread();
} while (1);
}
+INLINE_HEADER StgInfoTable *lockClosure(StgClosure *p)
+{
+ if (n_capabilities == 1) {
+ return (StgInfoTable *)p->header.info;
+ }
+ else {
+ return reallyLockClosure(p);
+ }
+}
+
+// ToDo: consider splitting tryLockClosure into reallyTryLockClosure,
+// same as lockClosure
EXTERN_INLINE StgInfoTable *tryLockClosure(StgClosure *p)
{
StgWord info;
- info = xchg((P_)(void *)&p->header.info, (W_)&stg_WHITEHOLE_info);
- if (info != (W_)&stg_WHITEHOLE_info) {
- return (StgInfoTable *)info;
- } else {
- return NULL;
+ if (n_capabilities == 1) {
+ return (StgInfoTable *)p->header.info;
+ }
+ else {
+ info = xchg((P_)(void *)&p->header.info, (W_)&stg_WHITEHOLE_info);
+ if (info != (W_)&stg_WHITEHOLE_info) {
+ return (StgInfoTable *)info;
+ } else {
+ return NULL;
+ }
}
}
#else /* !THREADED_RTS */
EXTERN_INLINE StgInfoTable *
+reallyLockClosure(StgClosure *p)
+{ return (StgInfoTable *)p->header.info; }
+
+INLINE_HEADER StgInfoTable *
lockClosure(StgClosure *p)
{ return (StgInfoTable *)p->header.info; }
@@ -75,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 */