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;
struct VerilatedImpInitializer {
VerilatedImpInitializer() { VerilatedImp::setup(); }
~VerilatedImpInitializer() { VerilatedImp::teardown(); }
} s_VerilatedImpInitializer;
// Guarantees to call setup() and teardown() just once.
struct VerilatedInitializer {
VerilatedInitializer() { setup(); }
~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
@ -261,10 +278,10 @@ Verilated::Serialized::Serialized() {
s_timeprecision = VL_TIME_PRECISION; // Initial value until overriden by _Vconfigure
}
Verilated::NonSerialized::NonSerialized() {
void Verilated::NonSerialized::setup() {
s_profThreadsFilenamep = strdup("profile_threads.dat");
}
Verilated::NonSerialized::~NonSerialized() {
void Verilated::NonSerialized::teardown() {
if (s_profThreadsFilenamep) {
VL_DO_CLEAR(free(const_cast<char*>(s_profThreadsFilenamep)),
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.
// 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() {
static bool done = false;
if (!done) {
new (&VerilatedImp::s_s) VerilatedImpData();
done = true;
}
new (&VerilatedImp::s_s) VerilatedImpData();
}
void VerilatedImp::teardown() {
static bool done = false;
if (!done) {
VerilatedImp::s_s.~VerilatedImpU();
done = true;
}
VerilatedImp::s_s.~VerilatedImpU();
}
//===========================================================================

View File

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