summaryrefslogtreecommitdiff
path: root/rts/sm
diff options
context:
space:
mode:
authorSimon Marlow <simonmarhaskell@gmail.com>2008-04-16 23:44:46 +0000
committerSimon Marlow <simonmarhaskell@gmail.com>2008-04-16 23:44:46 +0000
commite7987f16175f88daa11f06f25d10161a95f84bc4 (patch)
treeef37f54793292bbfffe0a14969f298470217682b /rts/sm
parent200c73fdfea734765c48309cc8dcbcf44b69c8c5 (diff)
downloadhaskell-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.c1
-rw-r--r--rts/sm/MarkWeak.c34
-rw-r--r--rts/sm/MarkWeak.h1
-rw-r--r--rts/sm/Storage.c4
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;
}
/*