summaryrefslogtreecommitdiff
path: root/rts/HeapStackCheck.cmm
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2010-03-29 14:44:56 +0000
committerSimon Marlow <marlowsd@gmail.com>2010-03-29 14:44:56 +0000
commit5d52d9b64c21dcf77849866584744722f8121389 (patch)
tree25aeafc9b761e73714c24ae414c0b1c41765c99f /rts/HeapStackCheck.cmm
parent79957d77c1bff767f1041d3fabdeb94d92a52878 (diff)
downloadhaskell-5d52d9b64c21dcf77849866584744722f8121389.tar.gz
New implementation of BLACKHOLEs
This replaces the global blackhole_queue with a clever scheme that enables us to queue up blocked threads on the closure that they are blocked on, while still avoiding atomic instructions in the common case. Advantages: - gets rid of a locked global data structure and some tricky GC code (replacing it with some per-thread data structures and different tricky GC code :) - wakeups are more prompt: parallel/concurrent performance should benefit. I haven't seen anything dramatic in the parallel benchmarks so far, but a couple of threading benchmarks do improve a bit. - waking up a thread blocked on a blackhole is now O(1) (e.g. if it is the target of throwTo). - less sharing and better separation of Capabilities: communication is done with messages, the data structures are strictly owned by a Capability and cannot be modified except by sending messages. - this change will utlimately enable us to do more intelligent scheduling when threads block on each other. This is what started off the whole thing, but it isn't done yet (#3838). I'll be documenting all this on the wiki in due course.
Diffstat (limited to 'rts/HeapStackCheck.cmm')
-rw-r--r--rts/HeapStackCheck.cmm36
1 files changed, 19 insertions, 17 deletions
diff --git a/rts/HeapStackCheck.cmm b/rts/HeapStackCheck.cmm
index 5bdf600a1c..f8bccc091d 100644
--- a/rts/HeapStackCheck.cmm
+++ b/rts/HeapStackCheck.cmm
@@ -159,6 +159,24 @@ __stg_gc_enter_1
}
/* -----------------------------------------------------------------------------
+ stg_enter_checkbh is just like stg_enter, except that we also call
+ checkBlockingQueues(). The point of this is that the GC can
+ replace an stg_marked_upd_frame with an stg_enter_checkbh if it
+ finds that the BLACKHOLE has already been updated by another
+ thread. It would be unsafe to use stg_enter, because there might
+ be an orphaned BLOCKING_QUEUE now.
+ -------------------------------------------------------------------------- */
+
+INFO_TABLE_RET( stg_enter_checkbh, RET_SMALL, P_ unused)
+{
+ R1 = Sp(1);
+ Sp_adj(2);
+ foreign "C" checkBlockingQueues(MyCapability() "ptr",
+ CurrentTSO) [R1];
+ ENTER();
+}
+
+/* -----------------------------------------------------------------------------
Heap checks in Primitive case alternatives
A primitive case alternative is entered with a value either in
@@ -593,11 +611,7 @@ INFO_TABLE_RET( stg_block_putmvar, RET_SMALL, P_ unused1, P_ unused2 )
// code fragment executed just before we return to the scheduler
stg_block_putmvar_finally
{
-#ifdef THREADED_RTS
unlockClosure(R3, stg_MVAR_DIRTY_info);
-#else
- SET_INFO(R3, stg_MVAR_DIRTY_info);
-#endif
jump StgReturn;
}
@@ -611,24 +625,12 @@ stg_block_putmvar
BLOCK_BUT_FIRST(stg_block_putmvar_finally);
}
-// code fragment executed just before we return to the scheduler
-stg_block_blackhole_finally
-{
-#if defined(THREADED_RTS)
- // The last thing we do is release sched_lock, which is
- // preventing other threads from accessing blackhole_queue and
- // picking up this thread before we are finished with it.
- RELEASE_LOCK(sched_mutex "ptr");
-#endif
- jump StgReturn;
-}
-
stg_block_blackhole
{
Sp_adj(-2);
Sp(1) = R1;
Sp(0) = stg_enter_info;
- BLOCK_BUT_FIRST(stg_block_blackhole_finally);
+ BLOCK_GENERIC;
}
INFO_TABLE_RET( stg_block_throwto, RET_SMALL, P_ unused, P_ unused )