Commit 3a8c5011 authored by Edward Z. Yang's avatar Edward Z. Yang

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's avatarEdward Z. Yang <ezyang@mit.edu>
parent 70e20631
......@@ -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 */
......
......@@ -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");
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment