add noDuplicate#
authorSimon Marlow <simonmar@microsoft.com>
Tue, 6 Mar 2007 14:31:12 +0000 (14:31 +0000)
committerSimon Marlow <simonmar@microsoft.com>
Tue, 6 Mar 2007 14:31:12 +0000 (14:31 +0000)
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).

compiler/prelude/primops.txt.pp
rts/PrimOps.cmm

index 10bcf37..7b006e1 100644 (file)
@@ -1532,6 +1532,11 @@ primop  IsCurrentThreadBoundOp "isCurrentThreadBound#" GenPrimOp
    with
    out_of_line = True
 
+primop  NoDuplicateOp "noDuplicate#" GenPrimOp
+   State# RealWorld -> State# RealWorld
+   with
+   out_of_line = True
+
 ------------------------------------------------------------------------
 section "Weak pointers"
 ------------------------------------------------------------------------
index b58baa0..437ce55 100644 (file)
@@ -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));
+    }
+}