diff options
author | Simon Marlow <simonmarhaskell@gmail.com> | 2008-04-16 23:44:46 +0000 |
---|---|---|
committer | Simon Marlow <simonmarhaskell@gmail.com> | 2008-04-16 23:44:46 +0000 |
commit | e7987f16175f88daa11f06f25d10161a95f84bc4 (patch) | |
tree | ef37f54793292bbfffe0a14969f298470217682b /rts/sm | |
parent | 200c73fdfea734765c48309cc8dcbcf44b69c8c5 (diff) | |
download | haskell-e7987f16175f88daa11f06f25d10161a95f84bc4.tar.gz |
Don't look at all the threads before each GC.
We were looking at all the threads for 2 reasons:
1. to catch transactions that might be looping as a
result of seeing an inconsistent view of memory.
2. to catch threads with blocked exceptions that are
themselves blocked.
For (1) we now check for this case whenever a thread yields, and for
(2) we catch these threads in the GC itself and send the exceptions
after GC (see performPendingThrowTos).
Diffstat (limited to 'rts/sm')
-rw-r--r-- | rts/sm/GC.c | 1 | ||||
-rw-r--r-- | rts/sm/MarkWeak.c | 34 | ||||
-rw-r--r-- | rts/sm/MarkWeak.h | 1 | ||||
-rw-r--r-- | rts/sm/Storage.c | 4 |
4 files changed, 30 insertions, 10 deletions
diff --git a/rts/sm/GC.c b/rts/sm/GC.c index 3cb71fa7f8..1d6469947c 100644 --- a/rts/sm/GC.c +++ b/rts/sm/GC.c @@ -692,6 +692,7 @@ GarbageCollect ( rtsBool force_major_gc ) // send exceptions to any threads which were about to die RELEASE_SM_LOCK; resurrectThreads(resurrected_threads); + performPendingThrowTos(exception_threads); ACQUIRE_SM_LOCK; // Update the stable pointer hash table. diff --git a/rts/sm/MarkWeak.c b/rts/sm/MarkWeak.c index 078919dae7..5f71a30627 100644 --- a/rts/sm/MarkWeak.c +++ b/rts/sm/MarkWeak.c @@ -74,10 +74,12 @@ static WeakStage weak_stage; */ StgWeak *old_weak_ptr_list; // also pending finaliser list -/* List of all threads during GC - */ +// List of threads found to be unreachable StgTSO *resurrected_threads; +// List of blocked threads found to have pending throwTos +StgTSO *exception_threads; + void initWeakForGC(void) { @@ -85,6 +87,7 @@ initWeakForGC(void) weak_ptr_list = NULL; weak_stage = WeakPtrs; resurrected_threads = END_TSO_QUEUE; + exception_threads = END_TSO_QUEUE; } rtsBool @@ -225,14 +228,29 @@ traverseWeakPtrList(void) next = t->global_link; } else { - step *new_step; - // alive: move this thread onto the correct - // threads list. + // alive next = t->global_link; - new_step = Bdescr((P_)t)->step; - t->global_link = new_step->threads; - new_step->threads = t; *prev = next; + + // 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 (t->blocked_exceptions != END_TSO_QUEUE) { + t->global_link = exception_threads; + exception_threads = t; + } else { + // move this thread onto the correct threads list. + step *new_step; + new_step = Bdescr((P_)t)->step; + t->global_link = new_step->threads; + new_step->threads = t; + } } } } diff --git a/rts/sm/MarkWeak.h b/rts/sm/MarkWeak.h index c586ba1cc2..7b3a806857 100644 --- a/rts/sm/MarkWeak.h +++ b/rts/sm/MarkWeak.h @@ -13,6 +13,7 @@ extern StgWeak *old_weak_ptr_list; extern StgTSO *resurrected_threads; +extern StgTSO *exception_threads; void initWeakForGC ( void ); rtsBool traverseWeakPtrList ( void ); diff --git a/rts/sm/Storage.c b/rts/sm/Storage.c index db0299c503..702c246717 100644 --- a/rts/sm/Storage.c +++ b/rts/sm/Storage.c @@ -846,11 +846,11 @@ void dirty_TSO (Capability *cap, StgTSO *tso) { bdescr *bd; - if ((tso->flags & TSO_DIRTY) == 0) { - tso->flags |= TSO_DIRTY; + if ((tso->flags & (TSO_DIRTY|TSO_LINK_DIRTY)) == 0) { bd = Bdescr((StgPtr)tso); if (bd->gen_no > 0) recordMutableCap((StgClosure*)tso,cap,bd->gen_no); } + tso->flags |= TSO_DIRTY; } /* |