From d3d69395401d3e7be7a8794e0b6850e608a30a24 Mon Sep 17 00:00:00 2001 From: simonmar Date: Mon, 28 Nov 2005 14:39:47 +0000 Subject: [PATCH] [project @ 2005-11-28 14:39:47 by simonmar] Small performance improvement to STM: reduce the size of an atomically frame from 3 words to 2 words by combining the "waiting" boolean field with the info pointer, i.e. having two separate info tables/return addresses for an atomically frame, one for the normal case and one for the waiitng case. --- ghc/includes/Closures.h | 1 - ghc/includes/StgMiscClosures.h | 2 + ghc/includes/mkDerivedConstants.c | 1 - ghc/rts/PrimOps.cmm | 103 +++++++++++++++++++++---------------- 4 files changed, 61 insertions(+), 46 deletions(-) diff --git a/ghc/includes/Closures.h b/ghc/includes/Closures.h index e8966d0..8487893 100644 --- a/ghc/includes/Closures.h +++ b/ghc/includes/Closures.h @@ -399,7 +399,6 @@ typedef struct StgTRecHeader_ { typedef struct { StgHeader header; - StgBool waiting; StgClosure *code; } StgAtomicallyFrame; diff --git a/ghc/includes/StgMiscClosures.h b/ghc/includes/StgMiscClosures.h index a9938aa..cc75d5b 100644 --- a/ghc/includes/StgMiscClosures.h +++ b/ghc/includes/StgMiscClosures.h @@ -43,6 +43,7 @@ RTS_RET_INFO(stg_seq_frame_info); RTS_RET_INFO(stg_catch_frame_info); RTS_RET_INFO(stg_catch_retry_frame_info); RTS_RET_INFO(stg_atomically_frame_info); +RTS_RET_INFO(stg_atomically_waiting_frame_info); RTS_RET_INFO(stg_catch_stm_frame_info); RTS_ENTRY(stg_upd_frame_ret); @@ -206,6 +207,7 @@ RTS_ENTRY(stg_blockAsyncExceptionszh_ret_ret); RTS_ENTRY(stg_catch_frame_ret); RTS_ENTRY(stg_catch_retry_frame_ret); RTS_ENTRY(stg_atomically_frame_ret); +RTS_ENTRY(stg_atomically_waiting_frame_ret); RTS_ENTRY(stg_catch_stm_frame_ret); RTS_ENTRY(stg_catch_frame_ret); RTS_ENTRY(stg_catch_entry); diff --git a/ghc/includes/mkDerivedConstants.c b/ghc/includes/mkDerivedConstants.c index e94cbbf..01e5b5d 100644 --- a/ghc/includes/mkDerivedConstants.c +++ b/ghc/includes/mkDerivedConstants.c @@ -348,7 +348,6 @@ main(int argc, char *argv[]) closure_field(StgMutVar, var); closure_size(StgAtomicallyFrame); - closure_field(StgAtomicallyFrame, waiting); closure_field(StgAtomicallyFrame, code); closure_size(StgCatchSTMFrame); diff --git a/ghc/rts/PrimOps.cmm b/ghc/rts/PrimOps.cmm index b25a1e5..84b81dc 100644 --- a/ghc/rts/PrimOps.cmm +++ b/ghc/rts/PrimOps.cmm @@ -1021,11 +1021,11 @@ ATOMICALLY_FRAME_ERROR(stg_atomically_frame_7_ret) #endif #if defined(PROFILING) -#define ATOMICALLY_FRAME_BITMAP 7 -#define ATOMICALLY_FRAME_WORDS 4 +#define ATOMICALLY_FRAME_BITMAP 3 +#define ATOMICALLY_FRAME_WORDS 3 #else -#define ATOMICALLY_FRAME_BITMAP 1 -#define ATOMICALLY_FRAME_WORDS 2 +#define ATOMICALLY_FRAME_BITMAP 0 +#define ATOMICALLY_FRAME_WORDS 1 #endif @@ -1041,50 +1041,66 @@ INFO_TABLE_RET(stg_atomically_frame, stg_atomically_frame_6_ret, stg_atomically_frame_7_ret) { - W_ frame, trec, valid; - IF_NOT_REG_R1(W_ rval; rval = Sp(0); Sp_adj(1); ) + W_ frame, trec, valid; + IF_NOT_REG_R1(W_ rval; rval = Sp(0); Sp_adj(1); ) - frame = Sp; - trec = StgTSO_trec(CurrentTSO); - if (StgAtomicallyFrame_waiting(frame)) { - /* The TSO is currently waiting: should we stop waiting? */ - valid = foreign "C" stmReWait(MyCapability() "ptr", CurrentTSO "ptr"); - if (valid) { - /* Previous attempt is still valid: no point trying again yet */ + frame = Sp; + trec = StgTSO_trec(CurrentTSO); + + /* The TSO is not currently waiting: try to commit the transaction */ + valid = foreign "C" stmCommitTransaction(MyCapability() "ptr", trec "ptr"); + if (valid) { + /* Transaction was valid: commit succeeded */ + StgTSO_trec(CurrentTSO) = NO_TREC; + Sp = Sp + SIZEOF_StgAtomicallyFrame; + IF_NOT_REG_R1(Sp_adj(-1); Sp(0) = rval;) + jump %ENTRY_CODE(Sp(SP_OFF)); + } else { + /* Transaction was not valid: try again */ + "ptr" trec = foreign "C" stmStartTransaction(MyCapability() "ptr", NO_TREC "ptr"); + StgTSO_trec(CurrentTSO) = trec; + R1 = StgAtomicallyFrame_code(frame); + Sp_adj(-1); + jump RET_LBL(stg_ap_v); + } +} + +INFO_TABLE_RET(stg_atomically_waiting_frame, + ATOMICALLY_FRAME_WORDS, ATOMICALLY_FRAME_BITMAP, + ATOMICALLY_FRAME, + stg_atomically_frame_0_ret, + stg_atomically_frame_1_ret, + stg_atomically_frame_2_ret, + stg_atomically_frame_3_ret, + stg_atomically_frame_4_ret, + stg_atomically_frame_5_ret, + stg_atomically_frame_6_ret, + stg_atomically_frame_7_ret) +{ + W_ frame, trec, valid; + IF_NOT_REG_R1(W_ rval; rval = Sp(0); Sp_adj(1); ) + + frame = Sp; + + /* The TSO is currently waiting: should we stop waiting? */ + valid = foreign "C" stmReWait(MyCapability() "ptr", CurrentTSO "ptr"); + if (valid) { + /* Previous attempt is still valid: no point trying again yet */ IF_NOT_REG_R1(Sp_adj(-2); Sp(1) = stg_NO_FINALIZER_closure; Sp(0) = stg_ut_1_0_unreg_info;) - jump stg_block_noregs; - } else { - /* Previous attempt is no longer valid: try again */ - "ptr" trec = foreign "C" stmStartTransaction(MyCapability() "ptr", NO_TREC "ptr"); - StgTSO_trec(CurrentTSO) = trec; - StgAtomicallyFrame_waiting(frame) = 0 :: CInt; /* false; */ - R1 = StgAtomicallyFrame_code(frame); - Sp_adj(-1); - jump RET_LBL(stg_ap_v); - } - } else { - /* The TSO is not currently waiting: try to commit the transaction */ - valid = foreign "C" stmCommitTransaction(MyCapability() "ptr", trec "ptr"); - if (valid) { - /* Transaction was valid: commit succeeded */ - StgTSO_trec(CurrentTSO) = NO_TREC; - Sp = Sp + SIZEOF_StgAtomicallyFrame; - IF_NOT_REG_R1(Sp_adj(-1); Sp(0) = rval;) - jump %ENTRY_CODE(Sp(SP_OFF)); - } else { - /* Transaction was not valid: try again */ - "ptr" trec = foreign "C" stmStartTransaction(MyCapability() "ptr", NO_TREC "ptr"); - StgTSO_trec(CurrentTSO) = trec; - R1 = StgAtomicallyFrame_code(frame); - Sp_adj(-1); - jump RET_LBL(stg_ap_v); - } - } + jump stg_block_noregs; + } else { + /* Previous attempt is no longer valid: try again */ + "ptr" trec = foreign "C" stmStartTransaction(MyCapability() "ptr", NO_TREC "ptr"); + StgTSO_trec(CurrentTSO) = trec; + StgHeader_info(frame) = stg_atomically_frame_info; + R1 = StgAtomicallyFrame_code(frame); + Sp_adj(-1); + jump RET_LBL(stg_ap_v); + } } - // STM catch frame -------------------------------------------------------------- #define CATCH_STM_FRAME_ENTRY_TEMPLATE(label,ret) \ @@ -1161,7 +1177,6 @@ atomicallyzh_fast frame = Sp; SET_HDR(frame,stg_atomically_frame_info, W_[CCCS]); - StgAtomicallyFrame_waiting(frame) = 0 :: CInt; // False StgAtomicallyFrame_code(frame) = R1; /* Start the memory transcation */ @@ -1296,7 +1311,7 @@ retry_pop_stack: r = foreign "C" stmWait(MyCapability() "ptr", CurrentTSO "ptr", trec "ptr"); if (r) { // Transaction was valid: stmWait put us on the TVars' queues, we now block - StgAtomicallyFrame_waiting(frame) = 1 :: CInt; // true + StgHeader_info(frame) = stg_atomically_waiting_frame_info; Sp = frame; // Fix up the stack in the unregisterised case: the return convention is different. IF_NOT_REG_R1(Sp_adj(-2); -- 1.7.10.4