summaryrefslogtreecommitdiff
path: root/rts/Threads.c
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2010-03-11 09:57:44 +0000
committerSimon Marlow <marlowsd@gmail.com>2010-03-11 09:57:44 +0000
commit7408b39235bccdcde48df2a73337ff976fbc09b7 (patch)
treecf20c372fdc5787170d53df36fc24ecf8113c89e /rts/Threads.c
parent12cfec943127f0c81e1ffa1ca5ce46e888e3027c (diff)
downloadhaskell-7408b39235bccdcde48df2a73337ff976fbc09b7.tar.gz
Use message-passing to implement throwTo in the RTS
This replaces some complicated locking schemes with message-passing in the implementation of throwTo. The benefits are - previously it was impossible to guarantee that a throwTo from a thread running on one CPU to a thread running on another CPU would be noticed, and we had to rely on the GC to pick up these forgotten exceptions. This no longer happens. - the locking regime is simpler (though the code is about the same size) - threads can be unblocked from a blocked_exceptions queue without having to traverse the whole queue now. It's a rare case, but replaces an O(n) operation with an O(1). - generally we move in the direction of sharing less between Capabilities (aka HECs), which will become important with other changes we have planned. Also in this patch I replaced several STM-specific closure types with a generic MUT_PRIM closure type, which allowed a lot of code in the GC and other places to go away, hence the line-count reduction. The message-passing changes resulted in about a net zero line-count difference.
Diffstat (limited to 'rts/Threads.c')
-rw-r--r--rts/Threads.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/rts/Threads.c b/rts/Threads.c
index 08b7aab66e..f824d021d4 100644
--- a/rts/Threads.c
+++ b/rts/Threads.c
@@ -74,7 +74,7 @@ createThread(Capability *cap, nat size)
tso->what_next = ThreadRunGHC;
tso->why_blocked = NotBlocked;
- tso->blocked_exceptions = END_TSO_QUEUE;
+ tso->blocked_exceptions = END_BLOCKED_EXCEPTIONS_QUEUE;
tso->flags = 0;
tso->dirty = 1;
@@ -218,8 +218,9 @@ unblockOne_ (Capability *cap, StgTSO *tso,
// NO, might be a WHITEHOLE: ASSERT(get_itbl(tso)->type == TSO);
ASSERT(tso->why_blocked != NotBlocked);
+ ASSERT(tso->why_blocked != BlockedOnMsgWakeup ||
+ tso->block_info.closure->header.info == &stg_IND_info);
- tso->why_blocked = NotBlocked;
next = tso->_link;
tso->_link = END_TSO_QUEUE;
@@ -235,6 +236,8 @@ unblockOne_ (Capability *cap, StgTSO *tso,
}
tso->cap = cap;
+ write_barrier();
+ tso->why_blocked = NotBlocked;
appendToRunQueue(cap,tso);
// context-switch soonish so we can migrate the new thread if
@@ -246,6 +249,7 @@ unblockOne_ (Capability *cap, StgTSO *tso,
wakeupThreadOnCapability(cap, tso->cap, tso);
}
#else
+ tso->why_blocked = NotBlocked;
appendToRunQueue(cap,tso);
// context-switch soonish so we can migrate the new thread if
@@ -327,13 +331,15 @@ printThreadBlockage(StgTSO *tso)
case BlockedOnMVar:
debugBelch("is blocked on an MVar @ %p", tso->block_info.closure);
break;
- case BlockedOnException:
- debugBelch("is blocked on delivering an exception to thread %lu",
- (unsigned long)tso->block_info.tso->id);
- break;
case BlockedOnBlackHole:
debugBelch("is blocked on a black hole");
break;
+ case BlockedOnMsgWakeup:
+ debugBelch("is blocked on a wakeup message");
+ break;
+ case BlockedOnMsgThrowTo:
+ debugBelch("is blocked on a throwto message");
+ break;
case NotBlocked:
debugBelch("is not blocked");
break;