[Git][ghc/ghc][wip/andreask/stm] STM: Be more optimistic when validating in-flight transactions.
Andreas Klebinger (@AndreasK)
gitlab at gitlab.haskell.org
Tue Mar 12 14:07:21 UTC 2024
Andreas Klebinger pushed to branch wip/andreask/stm at Glasgow Haskell Compiler / GHC
Commits:
4bd1875d by Andreas Klebinger at 2024-03-12T14:47:16+01:00
STM: Be more optimistic when validating in-flight transactions.
* Don't lock tvars when performing non-committal validation.
* If we encounter a locked tvar don't consider it a failure.
This means in-flight validation will only fail if committing at the
moment of validation is *guaranteed* to fail.
This prevents in-flight validation from failing spuriously if it happens in
parallel on multiple threads or parallel to thread comitting.
- - - - -
3 changed files:
- rts/STM.c
- rts/STM.h
- rts/Schedule.c
Changes:
=====================================
rts/STM.c
=====================================
@@ -681,6 +681,42 @@ static void revert_ownership(Capability *cap STG_UNUSED,
/*......................................................................*/
+// validate_optimistic()
+StgBool validate_trec_optimistic (Capability *cap, StgTRecHeader *trec);
+
+StgBool validate_trec_optimistic (Capability *cap, StgTRecHeader *trec) {
+ StgBool result;
+ TRACE("cap %d, trec %p : validate_trec_optimistic",
+ cap->no, trec);
+
+ if (shake()) {
+ TRACE("%p : shake, pretending trec is invalid when it may not be", trec);
+ return false;
+ }
+
+ ASSERT((trec -> state == TREC_ACTIVE) ||
+ (trec -> state == TREC_WAITING) ||
+ (trec -> state == TREC_CONDEMNED));
+ result = !((trec -> state) == TREC_CONDEMNED);
+ if (result) {
+ FOR_EACH_ENTRY(trec, e, {
+ StgTVar *s;
+ s = e -> tvar;
+ StgClosure *current = RELAXED_LOAD(&s->current_value);
+ if(current != e->expected_value && (GET_INFO(UNTAG_CLOSURE(current)) != &stg_TREC_HEADER_info))
+ { TRACE("%p : failed optimistic validate %p", trec, s);
+ result = false;
+ BREAK_FOR_EACH;
+ }
+ });
+ }
+
+
+ TRACE("%p : validate_trec_optimistic, result: %d", trec, result);
+ return result;
+}
+
+
// validate_and_acquire_ownership : this performs the twin functions
// of checking that the TVars referred to by entries in trec hold the
// expected values and:
@@ -751,7 +787,7 @@ static StgBool validate_and_acquire_ownership (Capability *cap,
revert_ownership(cap, trec, acquire_all);
}
- // TRACE("%p : validate_and_acquire_ownership, result: %d", trec, result);
+ TRACE("%p : validate_and_acquire_ownership, result: %d", trec, result);
return result;
}
@@ -973,6 +1009,30 @@ StgBool stmValidateNestOfTransactions(Capability *cap, StgTRecHeader *trec) {
return result;
}
+StgBool stmValidateNestOfTransactionsOptimistic(Capability *cap, StgTRecHeader *trec) {
+ StgTRecHeader *t;
+
+ TRACE("%p : stmValidateNestOfTransactionsOptimistic", trec);
+ ASSERT(trec != NO_TREC);
+ ASSERT((trec -> state == TREC_ACTIVE) ||
+ (trec -> state == TREC_WAITING) ||
+ (trec -> state == TREC_CONDEMNED));
+
+ t = trec;
+ StgBool result = true;
+ while (t != NO_TREC) {
+ // TODO: I don't think there is a need to lock any tvars here, all even less so.
+ result &= validate_trec_optimistic(cap, t);
+ t = t -> enclosing_trec;
+ }
+
+ if (!result && trec -> state != TREC_WAITING) {
+ trec -> state = TREC_CONDEMNED;
+ }
+
+ TRACE("%p : stmValidateNestOfTransactions()=%d", trec, result);
+ return result;
+}
/*......................................................................*/
static TRecEntry *get_entry_for(StgTRecHeader *trec, StgTVar *tvar, StgTRecHeader **in) {
=====================================
rts/STM.h
=====================================
@@ -95,6 +95,8 @@ void stmCondemnTransaction(Capability *cap, StgTRecHeader *trec);
StgBool stmValidateNestOfTransactions(Capability *cap, StgTRecHeader *trec);
+StgBool stmValidateNestOfTransactionsOptimistic(Capability *cap, StgTRecHeader *trec);
+
/*----------------------------------------------------------------------
Commit/wait/rewait operations
=====================================
rts/Schedule.c
=====================================
@@ -1099,7 +1099,7 @@ schedulePostRunThread (Capability *cap, StgTSO *t)
// and a is never equal to b given a consistent view of memory.
//
if (t -> trec != NO_TREC && t -> why_blocked == NotBlocked) {
- if (!stmValidateNestOfTransactions(cap, t -> trec)) {
+ if (!stmValidateNestOfTransactionsOptimistic(cap, t -> trec)) {
debugTrace(DEBUG_sched | DEBUG_stm,
"trec %p found wasting its time", t);
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/4bd1875d1fd9c06c21fa28ae0dc6c64a84732f9d
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/4bd1875d1fd9c06c21fa28ae0dc6c64a84732f9d
You're receiving this email because of your account on gitlab.haskell.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20240312/15aede1e/attachment-0001.html>
More information about the ghc-commits
mailing list