From 76f7c620f6b0bf2f73bb3d152eac62fb6b409ab1 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 12 Jul 2025 13:58:47 +0200 Subject: [PATCH] [consider merging] Enabling Shapes-based RecursiveShapeIterators for MT-use This fixes a crash when using DRC fill in tiled mode with multiple threads. --- src/db/db/dbFillTool.cc | 3 ++- src/db/db/dbRecursiveShapeIterator.cc | 6 ++++++ src/db/db/dbShapes.cc | 10 ++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/db/db/dbFillTool.cc b/src/db/db/dbFillTool.cc index 50fa34cfe..d693be441 100644 --- a/src/db/db/dbFillTool.cc +++ b/src/db/db/dbFillTool.cc @@ -280,7 +280,8 @@ fill_polygon_impl (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type f { // In case we run this from a tiling processor we need to lock against multithread races - tl::MutexLocker locker (&db::TilingProcessor::output_lock ()); + tl_assert (cell->layout () != 0); + tl::MutexLocker locker (&cell->layout ()->lock ()); cell->insert (array); } diff --git a/src/db/db/dbRecursiveShapeIterator.cc b/src/db/db/dbRecursiveShapeIterator.cc index b3965f9ce..1f8758bd1 100644 --- a/src/db/db/dbRecursiveShapeIterator.cc +++ b/src/db/db/dbRecursiveShapeIterator.cc @@ -500,15 +500,21 @@ RecursiveShapeIterator::validate (RecursiveShapeReceiver *receiver) const } if (mp_shapes) { + // Ensures the trees are built properly - this is important in MT contexts (i.e. TilingProcessor) // TODO: get rid of that const cast (const_cast (mp_shapes))->update (); + start_shapes (); + } else if (mp_layout && (! m_has_layers || m_current_layer < m_layers.size ())) { + // Ensures the trees are built properly - this is important in MT contexts (i.e. TilingProcessor) mp_layout->update (); + new_cell (receiver); next_shape (receiver); + } if (mp_layout && ! at_end ()) { diff --git a/src/db/db/dbShapes.cc b/src/db/db/dbShapes.cc index 2c5e90f46..5774973b9 100644 --- a/src/db/db/dbShapes.cc +++ b/src/db/db/dbShapes.cc @@ -1127,10 +1127,20 @@ void Shapes::reset_bbox_dirty () void Shapes::update () { + std::unique_ptr locker; + + // If not in a layout context, we should lock here against multiple calls from different threads. + // In a layout context, the Layout object will do that for us. + if (layout () == 0) { + static tl::Mutex lock; + locker.reset (new tl::MutexLocker (&lock)); + } + for (tl::vector::const_iterator l = m_layers.begin (); l != m_layers.end (); ++l) { (*l)->sort (); (*l)->update_bbox (); } + set_dirty (false); }