From b23dc345ae915f5ffad10fc8ebbdd3668dc6c849 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Tue, 25 Nov 2025 01:02:01 +0000 Subject: [PATCH] Make it safe to access .c_str() for autoidx IDs in a multithreaded context --- kernel/rtlil.cc | 1 - kernel/rtlil.h | 19 +++++++++++++------ pyosys/generator.py | 3 +-- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 6077237ac..6960b7620 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -276,7 +276,6 @@ void RTLIL::OwningIdString::collect_garbage() ++it; continue; } - delete[] it->second.full_str; it = global_autoidx_id_storage_.erase(it); } diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 06c38c52e..f841df1ed 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -139,7 +139,11 @@ struct RTLIL::IdString // the real string. The prefix strings must live forever. const std::string *prefix; // Cache of the full string, or nullptr if not cached yet. - char *full_str; + std::atomic full_str; + + AutoidxStorage(const std::string *prefix) : prefix(prefix), full_str(nullptr) {} + AutoidxStorage(AutoidxStorage&& other) : prefix(other.prefix), full_str(other.full_str.exchange(nullptr, std::memory_order_relaxed)) {} + ~AutoidxStorage() { delete[] full_str.load(std::memory_order_acquire); } }; // the global id string cache @@ -209,7 +213,7 @@ struct RTLIL::IdString static IdString new_autoidx_with_prefix(const std::string *prefix) { log_assert(!Multithreading::active()); int index = -(autoidx++); - global_autoidx_id_storage_.insert({index, {prefix, nullptr}}); + global_autoidx_id_storage_.insert({index, prefix}); return from_index(index); } @@ -244,15 +248,18 @@ struct RTLIL::IdString return global_id_storage_.at(index_).buf; AutoidxStorage &s = global_autoidx_id_storage_.at(index_); - if (s.full_str != nullptr) - return s.full_str; + char *full_str = s.full_str.load(std::memory_order_acquire); + if (full_str != nullptr) + return full_str; const std::string &prefix = *s.prefix; std::string suffix = std::to_string(-index_); char *c = new char[prefix.size() + suffix.size() + 1]; memcpy(c, prefix.data(), prefix.size()); memcpy(c + prefix.size(), suffix.c_str(), suffix.size() + 1); - s.full_str = c; - return c; + if (s.full_str.compare_exchange_strong(full_str, c, std::memory_order_acq_rel)) + return c; + delete[] c; + return full_str; } inline std::string str() const { diff --git a/pyosys/generator.py b/pyosys/generator.py index 25f87d570..7d4293abd 100644 --- a/pyosys/generator.py +++ b/pyosys/generator.py @@ -164,8 +164,7 @@ pyosys_headers = [ { "global_id_storage_", "global_id_index_", - "global_negative_id_storage_", - "global_negative_id_prefix_storage_", + "global_autoidx_id_storage_", "global_refcount_storage_", "global_free_idx_list_", "builtin_ff_cell_types",