Fix unordered data hazards in multi-threaded scheduling (#8133)

The OrderGraph used during V3Order step deliberately omits some variable
accesses from the dependency graph. E.g.: a read of a variable that is
in the reading block's own hybrid sensitivity list emits no edge, nor
does a read ignored due to a force/release, nor an access to a variable
marked 'ignoreSchedWrite' and friends. For serial mode that is fine, the
logic runs one block at a time. In parallel mode two such blocks can run
concurrently, and if one writes what the other reads, that is a data
race at runtime.

These accesses cannot be recovered from the graph edges. They are now
collected from the AST while the OrderGraph is built, and held by the
OrderLogicVertex performing them.

FixDataHazards is reworked around these access lists stored in
OrderLogicVertex, so it is now aware of all variable accesses the logic
makes, including those not encoded by the dependency graph edges. The
previous heuristic of fixing data hazards by merging same-rank MTasks is
removed. Additional edges are inserted instead to prescribe a fixed
ordering of conflicting MTasks. To insert edges without unduly
increasing the critical path, or introducing cycles, new edges are
added such that they preserve topological ordering, and they are
inserted between vertices sorted by critical path length. See algorithm
details in the code.

Also add a data hazard checker under '--debug-partition', reporting every
unordered accessor pair left in the final MTask graph.

This fixes the race demonstrated by t_sched_hybrid_hazard (#7913),
which is no longer expected to fail.

Under ThreadSanitizer over the vltmt tests: 17 failing before, 3 after,
with no regressions. The 3 remaining are different defects.
This commit is contained in:
Geza Lore
2026-08-18 08:50:50 +02:00
committed by GitHub
parent 96ea587df0
commit d4a18d4dfb
10 changed files with 477 additions and 259 deletions
+3 -2
View File
@@ -527,8 +527,9 @@ class Contraction final {
m_mTaskGraph.mergeMTasks(recipientp, donorp);
VL_DANGLING(donorp);
// Confirm we haven't botched the CP updates.
m_mTaskGraph.validate();
// Confirm we haven't botched the CP updates. This is a whole graph walk after every single
// merge, so it is quadratic in the size of the graph, hence only under '--debug 9'.
if (VL_UNLIKELY(debug() >= 9)) m_mTaskGraph.validate();
// Add the EdgeMCs of the merged MTask
addEdgeMCs(recipientp);