summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2009-06-24 14:15:30 +0000
committerSimon Marlow <marlowsd@gmail.com>2009-06-24 14:15:30 +0000
commitdce2394f7d2a695c1020643eda12465a280468f5 (patch)
treed65e883ef03b8e2b19b7a7f82591bad61bcab17d
parentbabf070d4c20a1a3438918fcd6b1cc5d20f0dbe1 (diff)
downloadhaskell-dce2394f7d2a695c1020643eda12465a280468f5.tar.gz
propagate the result of atomically properly (fixes #3049)
-rw-r--r--includes/Closures.h1
-rw-r--r--includes/mkDerivedConstants.c1
-rw-r--r--rts/PrimOps.cmm12
3 files changed, 10 insertions, 4 deletions
diff --git a/includes/Closures.h b/includes/Closures.h
index ef5fa4e807..eb5d1ed89d 100644
--- a/includes/Closures.h
+++ b/includes/Closures.h
@@ -398,6 +398,7 @@ typedef struct {
StgHeader header;
StgClosure *code;
StgTVarWatchQueue *next_invariant_to_check;
+ StgClosure *result;
} StgAtomicallyFrame;
typedef struct {
diff --git a/includes/mkDerivedConstants.c b/includes/mkDerivedConstants.c
index 89b9b1fbe5..f1289f61f3 100644
--- a/includes/mkDerivedConstants.c
+++ b/includes/mkDerivedConstants.c
@@ -335,6 +335,7 @@ main(int argc, char *argv[])
closure_size(StgAtomicallyFrame);
closure_field(StgAtomicallyFrame, code);
closure_field(StgAtomicallyFrame, next_invariant_to_check);
+ closure_field(StgAtomicallyFrame, result);
closure_field(StgInvariantCheckQueue, invariant);
closure_field(StgInvariantCheckQueue, my_execution);
diff --git a/rts/PrimOps.cmm b/rts/PrimOps.cmm
index 84567fee8f..9efc9f1ed8 100644
--- a/rts/PrimOps.cmm
+++ b/rts/PrimOps.cmm
@@ -678,18 +678,20 @@ INFO_TABLE_RET(stg_atomically_frame, ATOMICALLY_FRAME,
#if defined(PROFILING)
W_ unused1, W_ unused2,
#endif
- P_ unused3, P_ unused4)
+ P_ code, P_ next_invariant_to_check, P_ result)
{
W_ frame, trec, valid, next_invariant, q, outer;
- frame = Sp;
- trec = StgTSO_trec(CurrentTSO);
+ frame = Sp;
+ trec = StgTSO_trec(CurrentTSO);
+ result = R1;
("ptr" outer) = foreign "C" stmGetEnclosingTRec(trec "ptr") [];
if (outer == NO_TREC) {
/* First time back at the atomically frame -- pick up invariants */
("ptr" q) = foreign "C" stmGetInvariantsToCheck(MyCapability() "ptr", trec "ptr") [];
StgAtomicallyFrame_next_invariant_to_check(frame) = q;
+ StgAtomicallyFrame_result(frame) = result;
} else {
/* Second/subsequent time back at the atomically frame -- abort the
@@ -723,6 +725,7 @@ INFO_TABLE_RET(stg_atomically_frame, ATOMICALLY_FRAME,
if (valid != 0) {
/* Transaction was valid: commit succeeded */
StgTSO_trec(CurrentTSO) = NO_TREC;
+ R1 = StgAtomicallyFrame_result(frame);
Sp = Sp + SIZEOF_StgAtomicallyFrame;
jump %ENTRY_CODE(Sp(SP_OFF));
} else {
@@ -740,7 +743,7 @@ INFO_TABLE_RET(stg_atomically_waiting_frame, ATOMICALLY_FRAME,
#if defined(PROFILING)
W_ unused1, W_ unused2,
#endif
- P_ unused3, P_ unused4)
+ P_ code, P_ next_invariant_to_check, P_ result)
{
W_ frame, trec, valid;
@@ -825,6 +828,7 @@ atomicallyzh_fast
SET_HDR(frame,stg_atomically_frame_info, W_[CCCS]);
StgAtomicallyFrame_code(frame) = R1;
+ StgAtomicallyFrame_result(frame) = NO_TREC;
StgAtomicallyFrame_next_invariant_to_check(frame) = END_INVARIANT_CHECK_QUEUE;
/* Start the memory transcation */