diff options
author | Simon Marlow <marlowsd@gmail.com> | 2010-03-11 09:57:44 +0000 |
---|---|---|
committer | Simon Marlow <marlowsd@gmail.com> | 2010-03-11 09:57:44 +0000 |
commit | 7408b39235bccdcde48df2a73337ff976fbc09b7 (patch) | |
tree | cf20c372fdc5787170d53df36fc24ecf8113c89e /rts/sm/MarkWeak.c | |
parent | 12cfec943127f0c81e1ffa1ca5ce46e888e3027c (diff) | |
download | haskell-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/sm/MarkWeak.c')
-rw-r--r-- | rts/sm/MarkWeak.c | 39 |
1 files changed, 6 insertions, 33 deletions
diff --git a/rts/sm/MarkWeak.c b/rts/sm/MarkWeak.c index 7b7187c94d..9df39b9a08 100644 --- a/rts/sm/MarkWeak.c +++ b/rts/sm/MarkWeak.c @@ -22,6 +22,7 @@ #include "Schedule.h" #include "Weak.h" #include "Storage.h" +#include "Threads.h" /* ----------------------------------------------------------------------------- Weak Pointers @@ -80,9 +81,6 @@ StgWeak *old_weak_ptr_list; // also pending finaliser list // List of threads found to be unreachable StgTSO *resurrected_threads; -// List of blocked threads found to have pending throwTos -StgTSO *exception_threads; - static void resurrectUnreachableThreads (generation *gen); static rtsBool tidyThreadList (generation *gen); @@ -93,7 +91,6 @@ initWeakForGC(void) weak_ptr_list = NULL; weak_stage = WeakPtrs; resurrected_threads = END_TSO_QUEUE; - exception_threads = END_TSO_QUEUE; } rtsBool @@ -286,35 +283,11 @@ static rtsBool tidyThreadList (generation *gen) next = t->global_link; - // This is a good place to check for blocked - // exceptions. It might be the case that a thread is - // blocked on delivering an exception to a thread that - // is also blocked - we try to ensure that this - // doesn't happen in throwTo(), but it's too hard (or - // impossible) to close all the race holes, so we - // accept that some might get through and deal with - // them here. A GC will always happen at some point, - // even if the system is otherwise deadlocked. - // - // If an unreachable thread has blocked - // exceptions, we really want to perform the - // blocked exceptions rather than throwing - // BlockedIndefinitely exceptions. This is the - // only place we can discover such threads. - // The target thread might even be - // ThreadFinished or ThreadKilled. Bugs here - // will only be seen when running on a - // multiprocessor. - if (t->blocked_exceptions != END_TSO_QUEUE) { - if (tmp == NULL) { - evacuate((StgClosure **)&t); - flag = rtsTrue; - } - t->global_link = exception_threads; - exception_threads = t; - *prev = next; - continue; - } + // if the thread is not masking exceptions but there are + // pending exceptions on its queue, then something has gone + // wrong: + ASSERT(t->blocked_exceptions == END_BLOCKED_EXCEPTIONS_QUEUE + || (t->flags & TSO_BLOCKEX)); if (tmp == NULL) { // not alive (yet): leave this thread on the |