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
+41
View File
@@ -25,7 +25,10 @@
# include "vpi_priv.h"
# include "vthread.h"
# include "compile.h"
# include "config.h"
#ifdef CHECK_WITH_VALGRIND
# include "vvp_cleanup.h"
#endif
# include <stdio.h>
#ifdef HAVE_MALLOC_H
# include <malloc.h>
@@ -520,6 +523,7 @@ static struct __vpiUserSystf* allocate_def(void)
return def_table[def_count++];
}
#ifdef CHECK_WITH_VALGRIND
void def_table_delete(void)
{
for (unsigned idx = 0; idx < def_count; idx += 1) {
@@ -530,6 +534,7 @@ void def_table_delete(void)
def_table = 0;
def_count = 0;
}
#endif
struct __vpiUserSystf* vpip_find_systf(const char*name)
{
@@ -630,6 +635,42 @@ vpiHandle vpip_build_vpi_call(const char*name, unsigned vbit, int vwid,
return &obj->base;
}
#ifdef CHECK_WITH_VALGRIND
void vpi_call_delete(vpiHandle item)
{
struct __vpiSysTaskCall*obj = (struct __vpiSysTaskCall *) item;
for (unsigned arg = 0; arg < obj->nargs; arg += 1) {
switch (obj->args[arg]->vpi_type->type_code) {
case vpiConstant:
switch (vpi_get(_vpiFromThr, obj->args[arg])) {
case _vpiNoThr:
constant_delete(obj->args[arg]);
break;
case _vpiVThr:
thread_vthr_delete(obj->args[arg]);
break;
case _vpiWord:
thread_word_delete(obj->args[arg]);
break;
default:
assert(0);;
}
break;
case vpiMemoryWord:
if (vpi_get(_vpiFromThr, obj->args[arg]) == _vpi_at_A) {
A_delete(obj->args[arg]);
}
break;
case vpiPartSelect:
assert(vpi_get(_vpiFromThr, obj->args[arg]) == _vpi_at_PV);
PV_delete(obj->args[arg]);
break;
}
}
free(obj->args);
delete obj;
}
#endif
/*
* This function is used by the %vpi_call instruction to actually