MAYBE_GC(R2_PTR,newArrayzh_fast);
words = BYTES_TO_WDS(SIZEOF_StgMutArrPtrs) + n;
- "ptr" arr = foreign "C" allocateLocal(MyCapability() "ptr",words) [];
+ "ptr" arr = foreign "C" allocateLocal(MyCapability() "ptr",words) [R2];
TICK_ALLOC_PRIM(SIZEOF_StgMutArrPtrs, WDS(n), 0);
- SET_HDR(arr, stg_MUT_ARR_PTRS_info, W_[CCCS]);
+ SET_HDR(arr, stg_MUT_ARR_PTRS_DIRTY_info, W_[CCCS]);
StgMutArrPtrs_ptrs(arr) = n;
// Initialise all elements of the the array with the value in R2
// multiple times during GC, which would be unnecessarily slow.
//
if (StgHeader_info(R1) != stg_MUT_ARR_PTRS_FROZEN0_info) {
- SET_INFO(R1,stg_MUT_ARR_PTRS_info);
+ SET_INFO(R1,stg_MUT_ARR_PTRS_DIRTY_info);
foreign "C" recordMutableLock(R1 "ptr") [R1];
// must be done after SET_INFO, because it ASSERTs closure_MUTABLE()
RET_P(R1);
} else {
- SET_INFO(R1,stg_MUT_ARR_PTRS_info);
+ SET_INFO(R1,stg_MUT_ARR_PTRS_DIRTY_info);
RET_P(R1);
}
}
ALLOC_PRIM( SIZEOF_StgMutVar, R1_PTR, newMutVarzh_fast);
mv = Hp - SIZEOF_StgMutVar + WDS(1);
- SET_HDR(mv,stg_MUT_VAR_info,W_[CCCS]);
+ SET_HDR(mv,stg_MUT_VAR_DIRTY_info,W_[CCCS]);
StgMutVar_var(mv) = R1;
RET_P(mv);
HP_CHK_GEN_TICKY(SIZE, R1_PTR & R2_PTR, atomicModifyMutVarzh_fast);
-#if defined(SMP)
- foreign "C" ACQUIRE_LOCK(sm_mutex "ptr");
+#if defined(THREADED_RTS)
+ foreign "C" ACQUIRE_LOCK(atomic_modify_mutvar_mutex "ptr") [R1,R2];
#endif
x = StgMutVar_var(R1);
StgThunk_payload(y,0) = z;
StgMutVar_var(R1) = y;
+ foreign "C" dirty_MUT_VAR(BaseReg "ptr", R1 "ptr") [R1];
TICK_ALLOC_THUNK_1();
CCCS_ALLOC(THUNK_1_SIZE);
LDV_RECORD_CREATE(r);
StgThunk_payload(r,0) = z;
-#if defined(SMP)
- foreign "C" RELEASE_LOCK(sm_mutex "ptr") [];
+#if defined(THREADED_RTS)
+ foreign "C" RELEASE_LOCK(atomic_modify_mutvar_mutex "ptr") [];
#endif
RET_P(r);
/* ToDo: this is shockingly inefficient */
-#ifndef SMP
+#ifndef THREADED_RTS
section "bss" {
mp_tmp1:
bits8 [SIZEOF_MP_INT];
}
#endif
-#ifdef SMP
+#ifdef THREADED_RTS
#define FETCH_MP_TEMP(X) \
W_ X; \
X = BaseReg + (OFFSET_StgRegTable_r ## X);
GMP_TAKE2_RET2(quotRemIntegerzh_fast, mpz_tdiv_qr)
GMP_TAKE2_RET2(divModIntegerzh_fast, mpz_fdiv_qr)
-#ifndef SMP
+#ifndef THREADED_RTS
section "bss" {
mp_tmp_w: W_; // NB. mp_tmp_w is really an here mp_limb_t
}
// create it right now, return ThreadID in R1
"ptr" R1 = foreign "C" createIOThread( MyCapability() "ptr",
RtsFlags_GcFlags_initialStkSize(RtsFlags),
- R1 "ptr");
- foreign "C" scheduleThread(MyCapability() "ptr", R1 "ptr");
+ R1 "ptr") [R1];
+ foreign "C" scheduleThread(MyCapability() "ptr", R1 "ptr") [R1];
// switch at the earliest opportunity
CInt[context_switch] = 1 :: CInt;
R1 = ThreadId#
R2 = Addr# */
#ifdef DEBUG
- foreign "C" labelThread(R1 "ptr", R2 "ptr");
+ foreign "C" labelThread(R1 "ptr", R2 "ptr") [];
#endif
jump %ENTRY_CODE(Sp(0));
}
R1 = StgCatchRetryFrame_first_code(frame);
StgCatchRetryFrame_first_code_trec(frame) = new_trec;
}
- Sp_adj(-1);
- jump RET_LBL(stg_ap_v);
+ jump stg_ap_v_fast;
}
}
trec = StgTSO_trec(CurrentTSO);
/* The TSO is not currently waiting: try to commit the transaction */
- valid = foreign "C" stmCommitTransaction(MyCapability() "ptr", trec "ptr");
+ valid = foreign "C" stmCommitTransaction(MyCapability() "ptr", trec "ptr") [];
if (valid) {
/* Transaction was valid: commit succeeded */
StgTSO_trec(CurrentTSO) = NO_TREC;
jump %ENTRY_CODE(Sp(SP_OFF));
} else {
/* Transaction was not valid: try again */
- "ptr" trec = foreign "C" stmStartTransaction(MyCapability() "ptr", NO_TREC "ptr");
+ "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_ap_v_fast;
}
}
frame = Sp;
/* The TSO is currently waiting: should we stop waiting? */
- valid = foreign "C" stmReWait(MyCapability() "ptr", CurrentTSO "ptr");
+ 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);
jump stg_block_noregs;
} else {
/* Previous attempt is no longer valid: try again */
- "ptr" trec = foreign "C" stmStartTransaction(MyCapability() "ptr", NO_TREC "ptr");
+ "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);
+ jump stg_ap_v_fast;
}
}
/* Args: R1 = m :: STM a */
STK_CHK_GEN(SIZEOF_StgAtomicallyFrame + WDS(1), R1_PTR, atomicallyzh_fast);
+ old_trec = StgTSO_trec(CurrentTSO);
+
+ /* Nested transactions are not allowed; raise an exception */
+ if (old_trec != NO_TREC) {
+ R1 = GHCziIOBase_NestedAtomically_closure;
+ jump raisezh_fast;
+ }
+
/* Set up the atomically frame */
Sp = Sp - SIZEOF_StgAtomicallyFrame;
frame = Sp;
StgAtomicallyFrame_code(frame) = R1;
/* Start the memory transcation */
- old_trec = StgTSO_trec(CurrentTSO);
- ASSERT(old_trec == NO_TREC);
- "ptr" new_trec = foreign "C" stmStartTransaction(MyCapability() "ptr", old_trec "ptr");
+ "ptr" new_trec = foreign "C" stmStartTransaction(MyCapability() "ptr", old_trec "ptr") [R1];
StgTSO_trec(CurrentTSO) = new_trec;
/* Apply R1 to the realworld token */
- Sp_adj(-1);
- jump RET_LBL(stg_ap_v);
+ jump stg_ap_v_fast;
}
StgCatchSTMFrame_handler(frame) = R2;
/* Apply R1 to the realworld token */
- Sp_adj(-1);
- jump RET_LBL(stg_ap_v);
+ jump stg_ap_v_fast;
}
/* Start a nested transaction within which to run the first code */
trec = StgTSO_trec(CurrentTSO);
- "ptr" new_trec = foreign "C" stmStartTransaction(MyCapability() "ptr", trec "ptr");
+ "ptr" new_trec = foreign "C" stmStartTransaction(MyCapability() "ptr", trec "ptr") [R1,R2];
StgTSO_trec(CurrentTSO) = new_trec;
/* Set up the catch-retry frame */
StgCatchRetryFrame_first_code_trec(frame) = new_trec;
/* Apply R1 to the realworld token */
- Sp_adj(-1);
- jump RET_LBL(stg_ap_v);
+ jump stg_ap_v_fast;
}
// Find the enclosing ATOMICALLY_FRAME or CATCH_RETRY_FRAME
retry_pop_stack:
trec = StgTSO_trec(CurrentTSO);
- "ptr" outer = foreign "C" stmGetEnclosingTRec(trec "ptr");
+ "ptr" outer = foreign "C" stmGetEnclosingTRec(trec "ptr") [];
StgTSO_sp(CurrentTSO) = Sp;
- frame_type = foreign "C" findRetryFrameHelper(CurrentTSO "ptr");
+ frame_type = foreign "C" findRetryFrameHelper(CurrentTSO "ptr") [];
Sp = StgTSO_sp(CurrentTSO);
frame = Sp;
ASSERT(outer != NO_TREC);
if (!StgCatchRetryFrame_running_alt_code(frame)) {
// Retry in the first code: try the alternative
- "ptr" trec = foreign "C" stmStartTransaction(MyCapability() "ptr", outer "ptr");
+ "ptr" trec = foreign "C" stmStartTransaction(MyCapability() "ptr", outer "ptr") [];
StgTSO_trec(CurrentTSO) = trec;
StgCatchRetryFrame_running_alt_code(frame) = 1 :: CInt; // true;
R1 = StgCatchRetryFrame_alt_code(frame);
- Sp_adj(-1);
- jump RET_LBL(stg_ap_v);
+ jump stg_ap_v_fast;
} else {
// Retry in the alternative code: propagate
W_ other_trec;
other_trec = StgCatchRetryFrame_first_code_trec(frame);
- r = foreign "C" stmCommitNestedTransaction(MyCapability() "ptr", other_trec "ptr");
+ r = foreign "C" stmCommitNestedTransaction(MyCapability() "ptr", other_trec "ptr") [];
if (r) {
- r = foreign "C" stmCommitNestedTransaction(MyCapability() "ptr", trec "ptr");
+ r = foreign "C" stmCommitNestedTransaction(MyCapability() "ptr", trec "ptr") [];
} else {
- foreign "C" stmAbortTransaction(MyCapability() "ptr", trec "ptr");
+ foreign "C" stmAbortTransaction(MyCapability() "ptr", trec "ptr") [];
}
if (r) {
// Merge between siblings succeeded: commit it back to enclosing transaction
goto retry_pop_stack;
} else {
// Merge failed: we musn't propagate the retry. Try both paths again.
- "ptr" trec = foreign "C" stmStartTransaction(MyCapability() "ptr", outer "ptr");
+ "ptr" trec = foreign "C" stmStartTransaction(MyCapability() "ptr", outer "ptr") [];
StgCatchRetryFrame_first_code_trec(frame) = trec;
StgCatchRetryFrame_running_alt_code(frame) = 0 :: CInt; // false;
StgTSO_trec(CurrentTSO) = trec;
R1 = StgCatchRetryFrame_first_code(frame);
- Sp_adj(-1);
- jump RET_LBL(stg_ap_v);
+ jump stg_ap_v_fast;
}
}
}
// We've reached the ATOMICALLY_FRAME: attempt to wait
ASSERT(frame_type == ATOMICALLY_FRAME);
ASSERT(outer == NO_TREC);
- r = foreign "C" stmWait(MyCapability() "ptr", CurrentTSO "ptr", trec "ptr");
+ 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
StgHeader_info(frame) = stg_atomically_waiting_frame_info;
jump stg_block_stmwait;
} else {
// Transaction was not valid: retry immediately
- "ptr" trec = foreign "C" stmStartTransaction(MyCapability() "ptr", outer "ptr");
+ "ptr" trec = foreign "C" stmStartTransaction(MyCapability() "ptr", outer "ptr") [];
StgTSO_trec(CurrentTSO) = trec;
R1 = StgAtomicallyFrame_code(frame);
Sp = frame;
- Sp_adj(-1);
- jump RET_LBL(stg_ap_v);
+ jump stg_ap_v_fast;
}
}
MAYBE_GC (R1_PTR, newTVarzh_fast);
new_value = R1;
- "ptr" tv = foreign "C" stmNewTVar(MyCapability() "ptr", new_value "ptr");
+ "ptr" tv = foreign "C" stmNewTVar(MyCapability() "ptr", new_value "ptr") [];
RET_P(tv);
}
/* args: R1 = MVar closure */
mvar = R1;
-#if defined(SMP)
- "ptr" info = foreign "C" lockClosure(mvar "ptr");
+#if defined(THREADED_RTS)
+ "ptr" info = foreign "C" lockClosure(mvar "ptr") [];
#else
info = GET_INFO(mvar);
#endif
/* actually perform the putMVar for the thread that we just woke up */
tso = StgMVar_head(mvar);
PerformPut(tso,StgMVar_value(mvar));
+ foreign "C" dirtyTSO(tso "ptr") [];
#if defined(GRAN) || defined(PAR)
/* ToDo: check 2nd arg (mvar) is right */
StgMVar_tail(mvar) = stg_END_TSO_QUEUE_closure;
}
-#if defined(SMP)
- foreign "C" unlockClosure(mvar "ptr", stg_FULL_MVAR_info);
+#if defined(THREADED_RTS)
+ foreign "C" unlockClosure(mvar "ptr", stg_FULL_MVAR_info) [];
#endif
RET_P(val);
}
/* No further putMVars, MVar is now empty */
StgMVar_value(mvar) = stg_END_TSO_QUEUE_closure;
-#if defined(SMP)
- foreign "C" unlockClosure(mvar "ptr", stg_EMPTY_MVAR_info);
+#if defined(THREADED_RTS)
+ foreign "C" unlockClosure(mvar "ptr", stg_EMPTY_MVAR_info) [];
#else
SET_INFO(mvar,stg_EMPTY_MVAR_info);
#endif
mvar = R1;
-#if defined(SMP)
- "ptr" info = foreign "C" lockClosure(mvar "ptr");
+#if defined(THREADED_RTS)
+ "ptr" info = foreign "C" lockClosure(mvar "ptr") [];
#else
info = GET_INFO(mvar);
#endif
if (info == stg_EMPTY_MVAR_info) {
-#if defined(SMP)
- foreign "C" unlockClosure(mvar "ptr", stg_EMPTY_MVAR_info);
+#if defined(THREADED_RTS)
+ foreign "C" unlockClosure(mvar "ptr", stg_EMPTY_MVAR_info) [];
#endif
/* HACK: we need a pointer to pass back,
* so we abuse NO_FINALIZER_closure
/* actually perform the putMVar for the thread that we just woke up */
tso = StgMVar_head(mvar);
PerformPut(tso,StgMVar_value(mvar));
+ foreign "C" dirtyTSO(tso "ptr") [];
#if defined(GRAN) || defined(PAR)
/* ToDo: check 2nd arg (mvar) is right */
if (StgMVar_head(mvar) == stg_END_TSO_QUEUE_closure) {
StgMVar_tail(mvar) = stg_END_TSO_QUEUE_closure;
}
-#if defined(SMP)
- foreign "C" unlockClosure(mvar "ptr", stg_FULL_MVAR_info);
+#if defined(THREADED_RTS)
+ foreign "C" unlockClosure(mvar "ptr", stg_FULL_MVAR_info) [];
#endif
}
else
{
/* No further putMVars, MVar is now empty */
StgMVar_value(mvar) = stg_END_TSO_QUEUE_closure;
-#if defined(SMP)
- foreign "C" unlockClosure(mvar "ptr", stg_EMPTY_MVAR_info);
+#if defined(THREADED_RTS)
+ foreign "C" unlockClosure(mvar "ptr", stg_EMPTY_MVAR_info) [];
#else
SET_INFO(mvar,stg_EMPTY_MVAR_info);
#endif
/* args: R1 = MVar, R2 = value */
mvar = R1;
-#if defined(SMP)
- "ptr" info = foreign "C" lockClosure(mvar "ptr");
+#if defined(THREADED_RTS)
+ "ptr" info = foreign "C" lockClosure(mvar "ptr") [R2];
#else
info = GET_INFO(mvar);
#endif
/* actually perform the takeMVar */
tso = StgMVar_head(mvar);
PerformTake(tso, R2);
+ foreign "C" dirtyTSO(tso "ptr") [];
#if defined(GRAN) || defined(PAR)
/* ToDo: check 2nd arg (mvar) is right */
StgMVar_tail(mvar) = stg_END_TSO_QUEUE_closure;
}
-#if defined(SMP)
- foreign "C" unlockClosure(mvar "ptr", stg_EMPTY_MVAR_info);
+#if defined(THREADED_RTS)
+ foreign "C" unlockClosure(mvar "ptr", stg_EMPTY_MVAR_info) [];
#endif
jump %ENTRY_CODE(Sp(0));
}
/* No further takes, the MVar is now full. */
StgMVar_value(mvar) = R2;
-#if defined(SMP)
- foreign "C" unlockClosure(mvar "ptr", stg_FULL_MVAR_info);
+#if defined(THREADED_RTS)
+ foreign "C" unlockClosure(mvar "ptr", stg_FULL_MVAR_info) [];
#else
SET_INFO(mvar,stg_FULL_MVAR_info);
#endif
/* args: R1 = MVar, R2 = value */
mvar = R1;
-#if defined(SMP)
- "ptr" info = foreign "C" lockClosure(mvar "ptr");
+#if defined(THREADED_RTS)
+ "ptr" info = foreign "C" lockClosure(mvar "ptr") [R2];
#else
info = GET_INFO(mvar);
#endif
if (info == stg_FULL_MVAR_info) {
-#if defined(SMP)
- foreign "C" unlockClosure(mvar "ptr", stg_FULL_MVAR_info);
+#if defined(THREADED_RTS)
+ foreign "C" unlockClosure(mvar "ptr", stg_FULL_MVAR_info) [];
#endif
RET_N(0);
}
/* actually perform the takeMVar */
tso = StgMVar_head(mvar);
PerformTake(tso, R2);
+ foreign "C" dirtyTSO(tso "ptr") [];
#if defined(GRAN) || defined(PAR)
/* ToDo: check 2nd arg (mvar) is right */
StgMVar_tail(mvar) = stg_END_TSO_QUEUE_closure;
}
-#if defined(SMP)
- foreign "C" unlockClosure(mvar "ptr", stg_EMPTY_MVAR_info);
+#if defined(THREADED_RTS)
+ foreign "C" unlockClosure(mvar "ptr", stg_EMPTY_MVAR_info) [];
#endif
- jump %ENTRY_CODE(Sp(0));
}
else
{
/* No further takes, the MVar is now full. */
StgMVar_value(mvar) = R2;
-#if defined(SMP)
- foreign "C" unlockClosure(mvar "ptr", stg_FULL_MVAR_info);
+#if defined(THREADED_RTS)
+ foreign "C" unlockClosure(mvar "ptr", stg_FULL_MVAR_info) [];
#else
SET_INFO(mvar,stg_FULL_MVAR_info);
#endif
- jump %ENTRY_CODE(Sp(0));
}
+ RET_N(1);
/* ToDo: yield afterward for better communication performance? */
}
/* could probably allocate this on the heap instead */
"ptr" ares = foreign "C" stgMallocBytes(SIZEOF_StgAsyncIOResult,
- stg_asyncReadzh_malloc_str);
- reqID = foreign "C" addIORequest(R1, 0/*FALSE*/,R2,R3,R4 "ptr");
+ stg_asyncReadzh_malloc_str)
+ [R1,R2,R3,R4];
+ reqID = foreign "C" addIORequest(R1, 0/*FALSE*/,R2,R3,R4 "ptr") [];
StgAsyncIOResult_reqID(ares) = reqID;
StgAsyncIOResult_len(ares) = 0;
StgAsyncIOResult_errCode(ares) = 0;
StgTSO_why_blocked(CurrentTSO) = BlockedOnWrite::I16;
"ptr" ares = foreign "C" stgMallocBytes(SIZEOF_StgAsyncIOResult,
- stg_asyncWritezh_malloc_str);
- reqID = foreign "C" addIORequest(R1, 1/*TRUE*/,R2,R3,R4 "ptr");
+ stg_asyncWritezh_malloc_str)
+ [R1,R2,R3,R4];
+ reqID = foreign "C" addIORequest(R1, 1/*TRUE*/,R2,R3,R4 "ptr") [];
StgAsyncIOResult_reqID(ares) = reqID;
StgAsyncIOResult_len(ares) = 0;
/* could probably allocate this on the heap instead */
"ptr" ares = foreign "C" stgMallocBytes(SIZEOF_StgAsyncIOResult,
- stg_asyncDoProczh_malloc_str);
- reqID = foreign "C" addDoProcRequest(R1 "ptr",R2 "ptr");
+ stg_asyncDoProczh_malloc_str)
+ [R1,R2];
+ reqID = foreign "C" addDoProcRequest(R1 "ptr",R2 "ptr") [];
StgAsyncIOResult_reqID(ares) = reqID;
StgAsyncIOResult_len(ares) = 0;
StgAsyncIOResult_errCode(ares) = 0;