summaryrefslogtreecommitdiff
path: root/rts/PrimOps.cmm
diff options
context:
space:
mode:
authorSimon Marlow <simonmar@microsoft.com>2007-03-06 14:31:12 +0000
committerSimon Marlow <simonmar@microsoft.com>2007-03-06 14:31:12 +0000
commit78c491b13bd3afea76a8bb3f30d13e417c768941 (patch)
treee14ad4e8ab5774dbef717aa9515728b641aeda17 /rts/PrimOps.cmm
parenta1e3066e066f0f75da361f881b2f3198e0aada5f (diff)
downloadhaskell-78c491b13bd3afea76a8bb3f30d13e417c768941.tar.gz
add noDuplicate#
This primop ensures that the current computation is not being duplicated, by calling threadPaused(). The idea is to use it inside unsafePerformIO/unsafeInterleaveIO (see #986).
Diffstat (limited to 'rts/PrimOps.cmm')
-rw-r--r--rts/PrimOps.cmm20
1 files changed, 20 insertions, 0 deletions
diff --git a/rts/PrimOps.cmm b/rts/PrimOps.cmm
index b58baa0995..437ce55ac5 100644
--- a/rts/PrimOps.cmm
+++ b/rts/PrimOps.cmm
@@ -2130,3 +2130,23 @@ asyncDoProczh_fast
#endif
}
#endif
+
+// noDuplicate# tries to ensure that none of the thunks under
+// evaluation by the current thread are also under evaluation by
+// another thread. It relies on *both* threads doing noDuplicate#;
+// the second one will get blocked if they are duplicating some work.
+noDuplicatezh_fast
+{
+ SAVE_THREAD_STATE();
+ ASSERT(StgTSO_what_next(CurrentTSO) == ThreadRunGHC::I16);
+ foreign "C" threadPaused (MyCapability() "ptr", CurrentTSO "ptr") [];
+
+ if (StgTSO_what_next(CurrentTSO) == ThreadKilled::I16) {
+ R1 = ThreadFinished;
+ jump StgReturn;
+ } else {
+ LOAD_THREAD_STATE();
+ ASSERT(StgTSO_what_next(CurrentTSO) == ThreadRunGHC::I16);
+ jump %ENTRY_CODE(Sp(0));
+ }
+}