[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