From 4c60783e4d3c4830f717e1feb43f50b3f2e62a9f Mon Sep 17 00:00:00 2001 From: rlar Date: Sat, 7 May 2016 15:28:44 +0200 Subject: [PATCH] xspice, implement EVTdest() to fix xspice memory leaks --- src/include/ngspice/evtproto.h | 2 + src/spicelib/analysis/cktdest.c | 203 +------------------- src/xspice/evt/Makefile.am | 1 + src/xspice/evt/evtdest.c | 320 ++++++++++++++++++++++++++++++++ src/xspice/evt/evtload.c | 2 + visualc/sharedspice.vcxproj | 1 + visualc/vngspice-fftw.vcxproj | 1 + visualc/vngspice.vcxproj | 1 + 8 files changed, 330 insertions(+), 201 deletions(-) create mode 100644 src/xspice/evt/evtdest.c diff --git a/src/include/ngspice/evtproto.h b/src/include/ngspice/evtproto.h index 813813a6d..41cddde1d 100644 --- a/src/include/ngspice/evtproto.h +++ b/src/include/ngspice/evtproto.h @@ -66,6 +66,8 @@ void EVTtermInsert( int EVTsetup(CKTcircuit *ckt); +int EVTdest(Evt_Ckt_Data_t *evt); + int EVTiter(CKTcircuit *ckt); void EVTbackup(CKTcircuit *ckt, double new_time); diff --git a/src/spicelib/analysis/cktdest.c b/src/spicelib/analysis/cktdest.c index f7fea2805..b2c5331f9 100644 --- a/src/spicelib/analysis/cktdest.c +++ b/src/spicelib/analysis/cktdest.c @@ -16,8 +16,7 @@ Author: 1985 Thomas L. Quarles #include "ngspice/sperror.h" #ifdef XSPICE -#include "ngspice/evt.h" -static int evt_dest(Evt_Ckt_Data_t *evt); +#include "ngspice/evtproto.h" #endif int @@ -70,7 +69,7 @@ CKTdestroy(CKTcircuit *ckt) FREE(ckt->CKThead); #ifdef XSPICE - evt_dest(ckt->evt); + EVTdest(ckt->evt); FREE(ckt->enh); FREE(ckt->evt); #endif @@ -80,201 +79,3 @@ CKTdestroy(CKTcircuit *ckt) FREE(ckt); return(OK); } - -#ifdef XSPICE -static int -evt_dest(Evt_Ckt_Data_t *evt) -{ - int i; - - /* Get temporary pointers for fast access */ - Evt_Output_Queue_t *output_queue; - Evt_Node_Queue_t *node_queue; - Evt_Inst_Queue_t *inst_queue; - - Evt_Output_Info_t **output_table; - Evt_Node_Info_t **node_table; - Evt_Port_Info_t **port_table; - - Evt_State_Data_t *state_data; - Evt_State_t *statenext, *state; - - Evt_Node_Data_t *node_data; - Evt_Node_t *rhs, *rhsnext; - - Evt_Node_t *node, *nodenext; - - Evt_Msg_Data_t *msg_data; - Evt_Msg_t *msg, *msgnext; - - Evt_Inst_Event_t *here; - Evt_Inst_Event_t *next; - - Evt_Output_Event_t *outhere; - Evt_Output_Event_t *outnext; - - /* Exit immediately if no event-driven instances in circuit */ - if (evt->counts.num_insts == 0) - return(OK); - - output_queue = &(evt->queue.output); - node_queue = &(evt->queue.node); - inst_queue = &(evt->queue.inst); - - output_table = evt->info.output_table; - node_table = evt->info.node_table; - port_table = evt->info.port_table; - - node_data = evt->data.node; - - state_data = evt->data.state; - msg_data = evt->data.msg; - - /* instance queue */ - for (i = 0; i < evt->counts.num_insts; i++) { - here = inst_queue->head[i]; - while (here) { - next = here->next; - tfree(here); - here = next; - } - } - tfree(inst_queue->head); - tfree(inst_queue->current); - tfree(inst_queue->last_step); - tfree(inst_queue->free); - - tfree(inst_queue->modified_index); - tfree(inst_queue->modified); - tfree(inst_queue->pending_index); - tfree(inst_queue->pending); - tfree(inst_queue->to_call_index); - tfree(inst_queue->to_call); - - /* node queue */ - - tfree(node_queue->to_eval_index); - tfree(node_queue->to_eval); - tfree(node_queue->changed_index); - tfree(node_queue->changed); - - /* output queue */ - for (i = 0; i < evt->counts.num_outputs; i++) { - outhere = output_queue->head[i]; - while (outhere) { - outnext = outhere->next; - tfree(outhere); - outhere = outnext; - } - } - tfree(output_queue->head); - tfree(output_queue->current); - tfree(output_queue->last_step); - tfree(output_queue->free); - - tfree(output_queue->modified_index); - tfree(output_queue->modified); - tfree(output_queue->pending_index); - tfree(output_queue->pending); - tfree(output_queue->changed_index); - tfree(output_queue->changed); - - /* state data */ - /* only if digital states are there */ - if (state_data) { - for (i = 0; i < evt->counts.num_insts; i++) { - state = state_data->head[i]; - while (state) { - statenext = state->next; - tfree(state->block); - tfree(state); - state = statenext; - } - } - - tfree(state_data->head); - tfree(state_data->tail); - tfree(state_data->last_step); - tfree(state_data->free); - - tfree(state_data->modified); - tfree(state_data->modified_index); - tfree(state_data->total_size); - /* FIXME: more on desc ? */ - tfree(state_data->desc); - } - - /* node data */ - /* only if digital nodes are there */ - if (node_data) { - for (i = 0; i < evt->counts.num_nodes; i++) { - node = node_data->head[i]; - while (node) { - nodenext = node->next; - tfree(node); - node = nodenext; - } - } - tfree(node_data->head); - tfree(node_data->tail); - tfree(node_data->last_step); - tfree(node_data->free); - - tfree(node_data->modified); - tfree(node_data->modified_index); - - for (i = 0; i < evt->counts.num_nodes; i++) { - rhs = &(node_data->rhs[i]); - while (rhs) { - rhsnext = rhs->next; - tfree(rhs->inverted_value); - tfree(rhs->output_value); - tfree(rhs->node_value); - rhs = rhsnext; - } - } - tfree(node_data->rhs); - for (i = 0; i < evt->counts.num_nodes; i++) { - rhs = &(node_data->rhsold[i]); - while (rhs) { - rhsnext = rhs->next; - tfree(rhs->inverted_value); - tfree(rhs->output_value); - tfree(rhs->node_value); - rhs = rhsnext; - } - } - tfree(node_data->rhsold); - tfree(node_data->total_load); - } - - /* msg data */ - - if (msg_data) { - for (i = 0; i < evt->counts.num_ports; i++) { - msg = msg_data->head[i]; - while (msg) { - msgnext = msg->next; - tfree(msg); - msg = msgnext; - } - } - - tfree(msg_data->head); - tfree(msg_data->tail); - tfree(msg_data->last_step); - tfree(msg_data->free); - - tfree(msg_data->modified); - tfree(msg_data->modified_index); - } - - /* still to care for : - * output_table - * node_table - * port_table - */ - - return(OK); -} -#endif diff --git a/src/xspice/evt/Makefile.am b/src/xspice/evt/Makefile.am index 9eba09fe2..827f9e614 100644 --- a/src/xspice/evt/Makefile.am +++ b/src/xspice/evt/Makefile.am @@ -13,6 +13,7 @@ libevtxsp_la_SOURCES = \ evtop.c \ evtprint.c \ evtsetup.c \ + evtdest.c \ evtbackup.c \ evtdeque.c \ evtinit.c \ diff --git a/src/xspice/evt/evtdest.c b/src/xspice/evt/evtdest.c new file mode 100644 index 000000000..7dae8340c --- /dev/null +++ b/src/xspice/evt/evtdest.c @@ -0,0 +1,320 @@ +#include "ngspice/ngspice.h" +#include "ngspice/iferrmsg.h" + +#include "ngspice/evt.h" +#include "ngspice/evtproto.h" + + +static void Evt_Node_destroy(Evt_Node_Info_t *info, Evt_Node_t *node); +static void Evt_Node_Data_destroy(Evt_Ckt_Data_t *evt, Evt_Node_Data_t *node_data); +static void Evt_Msg_Data_destroy(Evt_Ckt_Data_t *evt, Evt_Msg_Data_t *msg_data); +static void Evt_Queue_destroy(Evt_Ckt_Data_t *evt, Evt_Queue_t *queue); +static void Evt_State_Data_destroy(Evt_Ckt_Data_t *evt, Evt_State_Data_t *state_data); +static void Evt_Data_destroy(Evt_Ckt_Data_t *evt, Evt_Data_t *data); +static void Evt_Job_destroy(Evt_Job_t *job); +static void Evt_Info_destroy(Evt_Info_t *info); + + +int +EVTdest(Evt_Ckt_Data_t *evt) +{ + /* Exit immediately if no event-driven instances in circuit */ + if (evt->counts.num_insts == 0) + return OK; + + Evt_Queue_destroy(evt, & evt->queue); + Evt_Data_destroy(evt, & evt->data); + Evt_Job_destroy(& evt->jobs); + Evt_Info_destroy(& evt->info); + + return OK; +} + + +static void +Evt_Queue_destroy(Evt_Ckt_Data_t *evt, Evt_Queue_t *queue) +{ + Evt_Output_Queue_t *output_queue = &(queue->output); + Evt_Node_Queue_t *node_queue = &(queue->node); + Evt_Inst_Queue_t *inst_queue = &(queue->inst); + + int i; + + /* instance queue */ + for (i = 0; i < evt->counts.num_insts; i++) { + Evt_Inst_Event_t *event = inst_queue->head[i]; + while (event) { + Evt_Inst_Event_t *next = event->next; + tfree(event); + event = next; + } + } + tfree(inst_queue->head); + tfree(inst_queue->current); + tfree(inst_queue->last_step); + tfree(inst_queue->free); + + tfree(inst_queue->modified_index); + tfree(inst_queue->modified); + tfree(inst_queue->pending_index); + tfree(inst_queue->pending); + tfree(inst_queue->to_call_index); + tfree(inst_queue->to_call); + + /* node queue */ + + tfree(node_queue->to_eval_index); + tfree(node_queue->to_eval); + tfree(node_queue->changed_index); + tfree(node_queue->changed); + + /* output queue */ + for (i = 0; i < evt->counts.num_outputs; i++) { + Evt_Output_Event_t *event; + event = output_queue->head[i]; + while (event) { + Evt_Output_Event_t *next = event->next; + tfree(event->value); + tfree(event); + event = next; + } + event = output_queue->free[i]; + while (event) { + Evt_Output_Event_t *next = event->next; + tfree(event->value); + tfree(event); + event = next; + } + } + tfree(output_queue->head); + tfree(output_queue->current); + tfree(output_queue->last_step); + tfree(output_queue->free); + + tfree(output_queue->modified_index); + tfree(output_queue->modified); + tfree(output_queue->pending_index); + tfree(output_queue->pending); + tfree(output_queue->changed_index); + tfree(output_queue->changed); +} + + +static void +Evt_Data_destroy(Evt_Ckt_Data_t *evt, Evt_Data_t *data) +{ + Evt_State_Data_destroy(evt, data->state); + Evt_Node_Data_destroy(evt, data->node); + Evt_Msg_Data_destroy(evt, data->msg); + + tfree(data->node); + tfree(data->state); + tfree(data->msg); + tfree(data->statistics); +} + + +static void +Evt_State_Data_destroy(Evt_Ckt_Data_t *evt, Evt_State_Data_t *state_data) +{ + int i; + + if (!state_data) + return; + + for (i = 0; i < evt->counts.num_insts; i++) { + Evt_State_t *state = state_data->head[i]; + while (state) { + Evt_State_t *next = state->next; + tfree(state->block); + tfree(state); + state = next; + } + } + + tfree(state_data->head); + tfree(state_data->tail); + tfree(state_data->last_step); + tfree(state_data->free); + + tfree(state_data->modified); + tfree(state_data->modified_index); + tfree(state_data->total_size); + + for (i = 0; i < evt->counts.num_insts; i++) { + Evt_State_Desc_t *p = state_data->desc[i]; + while (p) { + Evt_State_Desc_t *next_p = p->next; + tfree(p); + p = next_p; + } + } + + tfree(state_data->desc); +} + + +static void +Evt_Node_Data_destroy(Evt_Ckt_Data_t *evt, Evt_Node_Data_t *node_data) +{ + int i; + + if (!node_data) + return; + + for (i = 0; i < evt->counts.num_nodes; i++) { + Evt_Node_Info_t *info = evt->info.node_table[i]; + Evt_Node_t *node; + node = node_data->head[i]; + while (node) { + Evt_Node_t *next = node->next; + Evt_Node_destroy(info, node); + tfree(node); + node = next; + } + node = node_data->free[i]; + while (node) { + Evt_Node_t *next = node->next; + Evt_Node_destroy(info, node); + tfree(node); + node = next; + } + } + tfree(node_data->head); + tfree(node_data->tail); + tfree(node_data->last_step); + tfree(node_data->free); + + tfree(node_data->modified); + tfree(node_data->modified_index); + + for (i = 0; i < evt->counts.num_nodes; i++) { + Evt_Node_Info_t *info = evt->info.node_table[i]; + Evt_Node_destroy(info, &(node_data->rhs[i])); + Evt_Node_destroy(info, &(node_data->rhsold[i])); + } + + tfree(node_data->rhs); + tfree(node_data->rhsold); + tfree(node_data->total_load); +} + + +static void +Evt_Node_destroy(Evt_Node_Info_t *info, Evt_Node_t *node) +{ + tfree(node->node_value); + tfree(node->inverted_value); + + if (node->output_value) { + int k = info->num_outputs; + while (--k >= 0) + tfree(node->output_value[k]); + tfree(node->output_value); + } +} + + +static void +Evt_Msg_Data_destroy(Evt_Ckt_Data_t *evt, Evt_Msg_Data_t *msg_data) +{ + int i; + + if (!msg_data) + return; + + for (i = 0; i < evt->counts.num_ports; i++) { + Evt_Msg_t *msg; + msg = msg_data->head[i]; + while (msg) { + Evt_Msg_t *next = msg->next; + if (msg->text) + tfree(msg->text); + tfree(msg); + msg = next; + } + msg = msg_data->free[i]; + while (msg) { + Evt_Msg_t *next = msg->next; + if (msg->text) + tfree(msg->text); + tfree(msg); + msg = next; + } + } + + tfree(msg_data->head); + tfree(msg_data->tail); + tfree(msg_data->last_step); + tfree(msg_data->free); + + tfree(msg_data->modified); + tfree(msg_data->modified_index); +} + + +static void +Evt_Job_destroy(Evt_Job_t *job) +{ + int i; + + for (i = 0; i < job->num_jobs; i++) + tfree(job->job_name[i]); + + tfree(job->job_name); + tfree(job->node_data); + tfree(job->state_data); + tfree(job->msg_data); + tfree(job->statistics); +} + + +static void +Evt_Info_destroy(Evt_Info_t *info) +{ + Evt_Inst_Info_t *inst = info->inst_list; + while (inst) { + Evt_Inst_Info_t *next_inst = inst->next; + tfree(inst); + inst = next_inst; + } + tfree(info->inst_table); + + Evt_Node_Info_t *nodei = info->node_list; + while (nodei) { + Evt_Node_Info_t *next_nodei = nodei->next; + tfree(nodei->name); + + Evt_Inst_Index_t *p = nodei->inst_list; + while (p) { + Evt_Inst_Index_t *next_p = p->next; + tfree(p); + p = next_p; + } + + tfree(nodei); + nodei = next_nodei; + } + tfree(info->node_table); + + Evt_Port_Info_t *port = info->port_list; + while (port) { + Evt_Port_Info_t *next_port = port->next; + tfree(port->node_name); + tfree(port->inst_name); + tfree(port->conn_name); + tfree(port); + port = next_port; + } + tfree(info->port_table); + + Evt_Output_Info_t *output = info->output_list; + while (output) { + Evt_Output_Info_t *next_output = output->next; + tfree(output); + output = next_output; + } + tfree(info->output_table); + + tfree(info->hybrid_index); +} diff --git a/src/xspice/evt/evtload.c b/src/xspice/evt/evtload.c index d4ace6f19..ca6b718b6 100644 --- a/src/xspice/evt/evtload.c +++ b/src/xspice/evt/evtload.c @@ -443,6 +443,8 @@ static void EVTadd_msg( if(msg_data->free[port_index]) { *msg_ptr = msg_data->free[port_index]; msg_data->free[port_index] = msg_data->free[port_index]->next; + if ((*msg_ptr)->text) + tfree((*msg_ptr)->text); } else { *msg_ptr = TMALLOC(Evt_Msg_t, 1); diff --git a/visualc/sharedspice.vcxproj b/visualc/sharedspice.vcxproj index 1be1a5c07..cd1e2b954 100644 --- a/visualc/sharedspice.vcxproj +++ b/visualc/sharedspice.vcxproj @@ -2125,6 +2125,7 @@ + diff --git a/visualc/vngspice-fftw.vcxproj b/visualc/vngspice-fftw.vcxproj index 6e0e82d11..42f1425ea 100644 --- a/visualc/vngspice-fftw.vcxproj +++ b/visualc/vngspice-fftw.vcxproj @@ -2743,6 +2743,7 @@ lib /machine:x64 /def:..\..\fftw-3.3.4-dll64\libfftw3-3.def /out:$(IntDir)libfft + diff --git a/visualc/vngspice.vcxproj b/visualc/vngspice.vcxproj index f904d3e8c..9f2c9b403 100644 --- a/visualc/vngspice.vcxproj +++ b/visualc/vngspice.vcxproj @@ -2709,6 +2709,7 @@ +