Add memory freeing and pool management for valgrind.

This patch adds code to free most of the memory when vvp
finishes. It also adds valgrind hooks to manage the various
memory pools. The functionality is enabled by passing
--with-valgrind to configure. It requires that the
valgrind/memcheck.h header from a recent version of
valgrind be available. It check for the existence of this
file, but not that it is new enough (version 3.1.3 is known
to not work and version 3.4.0 is known to work).

You can still use valgrind when this option is not given,
but you will have memory that is not released and the
memory pools show as a single block.

With this vvp is 100% clean for many of the tests in the
test suite. There are still a few things that need to be
cleaned up, but it should be much easier to find any real
leaks now.

Enabling this causes a negligible increase in run time and
memory. The memory could be a problem for very large
simulations. The increase in run time is only noticeable on
very short simulations where it should not matter.
This commit is contained in:
Cary R
2009-02-01 06:55:28 -08:00
committed by Stephen Williams
parent 51307c0a3e
commit 7b1905b997
29 changed files with 812 additions and 23 deletions
+44 -4
View File
@@ -24,6 +24,10 @@
#include "schedule.h"
#include "symbols.h"
#include "compile.h"
#include "config.h"
#ifdef CHECK_WITH_VALGRIND
#include "vvp_cleanup.h"
#endif
#include <assert.h>
#ifdef HAVE_MALLOC_H
#include <malloc.h>
@@ -33,8 +37,37 @@
#include <stdio.h>
#include <iostream>
// We may need these later when we build the VPI interface to
// UDP definitions.
#ifdef CHECK_WITH_VALGRIND
static vvp_udp_s **udp_defns = 0;
static unsigned udp_defns_count = 0;
void udp_defns_delete()
{
for (unsigned idx = 0; idx < udp_defns_count; idx += 1) {
if (udp_defns[idx]->is_sequential()) {
vvp_udp_seq_s *obj = (vvp_udp_seq_s *) udp_defns[idx];
delete obj;
} else {
vvp_udp_comb_s *obj = (vvp_udp_comb_s *) udp_defns[idx];
delete obj;
}
}
free(udp_defns);
udp_defns = 0;
udp_defns_count = 0;
}
#endif
static symbol_table_t udp_table;
void delete_udp_symbols()
{
delete_symbol_table(udp_table);
udp_table = 0;
}
struct vvp_udp_s *udp_find(const char *label)
{
symbol_value_t v = sym_get_value(udp_table, label);
@@ -49,8 +82,8 @@ ostream& operator <<(ostream&o, const struct udp_levels_table&table)
return o;
}
vvp_udp_s::vvp_udp_s(char*label, unsigned ports, vvp_bit4_t init)
: ports_(ports), init_(init)
vvp_udp_s::vvp_udp_s(char*label, unsigned ports, vvp_bit4_t init, bool type)
: ports_(ports), init_(init), seq_(type)
{
if (!udp_table)
udp_table = new_symbol_table();
@@ -60,6 +93,13 @@ vvp_udp_s::vvp_udp_s(char*label, unsigned ports, vvp_bit4_t init)
symbol_value_t v;
v.ptr = this;
sym_set_value(udp_table, label, v);
#ifdef CHECK_WITH_VALGRIND
udp_defns_count += 1;
udp_defns = (vvp_udp_s **) realloc(udp_defns,
udp_defns_count*sizeof(vvp_udp_s **));
udp_defns[udp_defns_count-1] = this;
#endif
}
vvp_udp_s::~vvp_udp_s()
@@ -77,7 +117,7 @@ vvp_bit4_t vvp_udp_s::get_init() const
}
vvp_udp_comb_s::vvp_udp_comb_s(char*label, char*name, unsigned ports)
: vvp_udp_s(label, ports, BIT4_X)
: vvp_udp_s(label, ports, BIT4_X, false)
{
name_ = name;
levels0_ = 0;
@@ -257,7 +297,7 @@ void vvp_udp_comb_s::compile_table(char**tab)
vvp_udp_seq_s::vvp_udp_seq_s(char*label, char*name,
unsigned ports, vvp_bit4_t init)
: vvp_udp_s(label, ports, init)
: vvp_udp_s(label, ports, init, true)
{
levels0_ = 0;
levels1_ = 0;