From 78c491b13bd3afea76a8bb3f30d13e417c768941 Mon Sep 17 00:00:00 2001 From: Simon Marlow Date: Tue, 6 Mar 2007 14:31:12 +0000 Subject: [PATCH] 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). --- compiler/prelude/primops.txt.pp | 5 +++++ rts/PrimOps.cmm | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/compiler/prelude/primops.txt.pp b/compiler/prelude/primops.txt.pp index 10bcf37..7b006e1 100644 --- a/compiler/prelude/primops.txt.pp +++ b/compiler/prelude/primops.txt.pp @@ -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" ------------------------------------------------------------------------ diff --git a/rts/PrimOps.cmm b/rts/PrimOps.cmm index b58baa0..437ce55 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)); + } +} -- 1.7.10.4