propagate the result of atomically properly (fixes #3049)
authorSimon Marlow <marlowsd@gmail.com>
Wed, 24 Jun 2009 14:15:30 +0000 (14:15 +0000)
committerSimon Marlow <marlowsd@gmail.com>
Wed, 24 Jun 2009 14:15:30 +0000 (14:15 +0000)
includes/Closures.h
includes/mkDerivedConstants.c
rts/PrimOps.cmm

index ef5fa4e..eb5d1ed 100644 (file)
@@ -398,6 +398,7 @@ typedef struct {
   StgHeader   header;
   StgClosure *code;
   StgTVarWatchQueue *next_invariant_to_check;
   StgHeader   header;
   StgClosure *code;
   StgTVarWatchQueue *next_invariant_to_check;
+  StgClosure *result;
 } StgAtomicallyFrame;
 
 typedef struct {
 } StgAtomicallyFrame;
 
 typedef struct {
index 89b9b1f..f1289f6 100644 (file)
@@ -335,6 +335,7 @@ main(int argc, char *argv[])
     closure_size(StgAtomicallyFrame);
     closure_field(StgAtomicallyFrame, code);
     closure_field(StgAtomicallyFrame, next_invariant_to_check);
     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);
 
     closure_field(StgInvariantCheckQueue, invariant);
     closure_field(StgInvariantCheckQueue, my_execution);
index 84567fe..9efc9f1 100644 (file)
@@ -678,18 +678,20 @@ INFO_TABLE_RET(stg_atomically_frame, ATOMICALLY_FRAME,
 #if defined(PROFILING)
   W_ unused1, W_ unused2,
 #endif
 #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;
 
 {
   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;
   ("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
 
   } 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;
     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 {
       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
 #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;
 
 {
   W_ frame, trec, valid;
 
@@ -825,6 +828,7 @@ atomicallyzh_fast
 
   SET_HDR(frame,stg_atomically_frame_info, W_[CCCS]);
   StgAtomicallyFrame_code(frame) = R1;
 
   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 */
   StgAtomicallyFrame_next_invariant_to_check(frame) = END_INVARIANT_CHECK_QUEUE;
 
   /* Start the memory transcation */