Fix memory leaks when using shared protect-lib (#2707)

* Guarantee mechanism to initialize just once is now in VerilatedInitializer. No functional change is intended.

* Make sure to initialize Verilated::NonInitialized just once. Fixes
memory leak in t_prot_lib_shared and t_hier_block_prot_lib_shared.

* Call setup() and teardown() of Verilated::NonSerialized.
This commit is contained in:
Yutetsu TAKATSUKASA 2020-12-17 02:30:58 +09:00 committed by GitHub
parent b75901b3eb
commit 738ee3d4eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 30 additions and 19 deletions

View File

@ -72,10 +72,27 @@ Verilated::CommandArgValues Verilated::s_args;
VerilatedImp::VerilatedImpU VerilatedImp::s_s; VerilatedImp::VerilatedImpU VerilatedImp::s_s;
struct VerilatedImpInitializer { // Guarantees to call setup() and teardown() just once.
VerilatedImpInitializer() { VerilatedImp::setup(); } struct VerilatedInitializer {
~VerilatedImpInitializer() { VerilatedImp::teardown(); } VerilatedInitializer() { setup(); }
} s_VerilatedImpInitializer; ~VerilatedInitializer() { teardown(); }
void setup() {
static bool done = false;
if (!done) {
VerilatedImp::setup();
Verilated::s_ns.setup();
done = true;
}
}
void teardown() {
static bool done = false;
if (!done) {
VerilatedImp::teardown();
Verilated::s_ns.teardown();
done = true;
}
}
} s_VerilatedInitializer;
//=========================================================================== //===========================================================================
// User definable functions // User definable functions
@ -261,10 +278,10 @@ Verilated::Serialized::Serialized() {
s_timeprecision = VL_TIME_PRECISION; // Initial value until overriden by _Vconfigure s_timeprecision = VL_TIME_PRECISION; // Initial value until overriden by _Vconfigure
} }
Verilated::NonSerialized::NonSerialized() { void Verilated::NonSerialized::setup() {
s_profThreadsFilenamep = strdup("profile_threads.dat"); s_profThreadsFilenamep = strdup("profile_threads.dat");
} }
Verilated::NonSerialized::~NonSerialized() { void Verilated::NonSerialized::teardown() {
if (s_profThreadsFilenamep) { if (s_profThreadsFilenamep) {
VL_DO_CLEAR(free(const_cast<char*>(s_profThreadsFilenamep)), VL_DO_CLEAR(free(const_cast<char*>(s_profThreadsFilenamep)),
s_profThreadsFilenamep = nullptr); s_profThreadsFilenamep = nullptr);
@ -2478,21 +2495,13 @@ void Verilated::endOfEvalGuts(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE {
// //
// To avoid the trouble, all member variables are enclosed in VerilatedImpU union. // To avoid the trouble, all member variables are enclosed in VerilatedImpU union.
// ctor nor dtor of members are not called automatically. // ctor nor dtor of members are not called automatically.
// VerilatedImp::setup() and teardown() guarantees to initialize/destruct just once. // VerilatedInitializer::setup() and teardown() guarantees to initialize/destruct just once.
void VerilatedImp::setup() { void VerilatedImp::setup() {
static bool done = false;
if (!done) {
new (&VerilatedImp::s_s) VerilatedImpData(); new (&VerilatedImp::s_s) VerilatedImpData();
done = true;
}
} }
void VerilatedImp::teardown() { void VerilatedImp::teardown() {
static bool done = false;
if (!done) {
VerilatedImp::s_s.~VerilatedImpU(); VerilatedImp::s_s.~VerilatedImpU();
done = true;
}
} }
//=========================================================================== //===========================================================================

View File

@ -399,8 +399,8 @@ class Verilated final {
vluint32_t s_profThreadsWindow = 2; ///< +prof+threads window size vluint32_t s_profThreadsWindow = 2; ///< +prof+threads window size
// Slow path // Slow path
const char* s_profThreadsFilenamep; ///< +prof+threads filename const char* s_profThreadsFilenamep; ///< +prof+threads filename
NonSerialized(); void setup();
~NonSerialized(); void teardown();
} s_ns; } s_ns;
// no need to be save-restored (serialized) the // no need to be save-restored (serialized) the
@ -429,6 +429,8 @@ class Verilated final {
} t_s; } t_s;
private: private:
friend struct VerilatedInitializer;
// CONSTRUCTORS // CONSTRUCTORS
VL_UNCOPYABLE(Verilated); VL_UNCOPYABLE(Verilated);