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:
parent
b75901b3eb
commit
738ee3d4eb
|
|
@ -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;
|
new (&VerilatedImp::s_s) VerilatedImpData();
|
||||||
if (!done) {
|
|
||||||
new (&VerilatedImp::s_s) VerilatedImpData();
|
|
||||||
done = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
void VerilatedImp::teardown() {
|
void VerilatedImp::teardown() {
|
||||||
static bool done = false;
|
VerilatedImp::s_s.~VerilatedImpU();
|
||||||
if (!done) {
|
|
||||||
VerilatedImp::s_s.~VerilatedImpU();
|
|
||||||
done = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue