summaryrefslogtreecommitdiff
path: root/rts/ThreadPaused.c
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2011-05-31 09:39:09 +0100
committerSimon Marlow <marlowsd@gmail.com>2011-05-31 10:52:54 +0100
commitd77cec05ebc9abe62b8af990b519fc9f36684239 (patch)
tree30e95727f7f13dbd898dcb84c640ada715df12d7 /rts/ThreadPaused.c
parent79f275092de54ba5f7e7336c13231ad5198befdf (diff)
downloadhaskell-d77cec05ebc9abe62b8af990b519fc9f36684239.tar.gz
Fix a cause of very occasional <<loop>> with parallel programs and
-feager-blackholing (#5226). See comments for details.
Diffstat (limited to 'rts/ThreadPaused.c')
-rw-r--r--rts/ThreadPaused.c34
1 files changed, 32 insertions, 2 deletions
diff --git a/rts/ThreadPaused.c b/rts/ThreadPaused.c
index aeae1d4128..02b4f58eab 100644
--- a/rts/ThreadPaused.c
+++ b/rts/ThreadPaused.c
@@ -230,8 +230,38 @@ threadPaused(Capability *cap, StgTSO *tso)
#ifdef THREADED_RTS
retry:
#endif
- if (bh_info == &stg_BLACKHOLE_info ||
- bh_info == &stg_WHITEHOLE_info)
+ // If the info table is a WHITEHOLE or a BLACKHOLE, then
+ // another thread has claimed it (via the SET_INFO()
+ // below), or is in the process of doing so. In that case
+ // we want to suspend the work that the current thread has
+ // done on this thunk and wait until the other thread has
+ // finished.
+ //
+ // If eager blackholing is taking place, it could be the
+ // case that the blackhole points to the current
+ // TSO. e.g.:
+ //
+ // this thread other thread
+ // --------------------------------------------------------
+ // c->indirectee = other_tso;
+ // c->header.info = EAGER_BH
+ // threadPaused()
+ // c->indirectee = other_tso;
+ // c->header.info = EAGER_BH
+ // c->header.info = BLACKHOLE
+ // threadPaused()
+ // *** c->header.info is now BLACKHOLE,
+ // c->indirectee points to this TSO
+ //
+ // So in this case do *not* suspend the work of the
+ // current thread, because the current thread will become
+ // deadlocked on itself. See #5226 for an instance of
+ // this bug.
+ //
+ if ((bh_info == &stg_WHITEHOLE_info ||
+ bh_info == &stg_BLACKHOLE_info)
+ &&
+ ((StgInd*)bh)->indirectee != (StgClosure*)tso)
{
debugTrace(DEBUG_squeeze,
"suspending duplicate work: %ld words of stack",