Reduce memory use for simulations that run in zero time.

The fix for pr1830834 causes vvp to only delete a completed thread
when the simulation time next advances. If a procedural model is
being simulated which makes many task or function calls within a
single time step, this can lead to excessive memory use. This patch
modifies the behaviour so that thread deletion is only delayed if
that thread has caused a sync event to be placed in the event queue.
This should catch all cases where the thread private data can be
accessed after a thread has terminated.
(cherry picked from commit c7b0aef414)
This commit is contained in:
Martin Whitaker 2009-12-06 23:34:14 +00:00 committed by Stephen Williams
parent 1eb593e8ad
commit 33c852d2b4
3 changed files with 30 additions and 5 deletions

View File

@ -669,6 +669,9 @@ void schedule_generic(vvp_gen_event_t obj, vvp_time64_t delay,
cur->delete_obj_when_done = delete_when_done;
schedule_event_(cur, delay,
sync_flag? (ro_flag?SEQ_ROSYNC:SEQ_RWSYNC) : SEQ_ACTIVE);
if (sync_flag)
vthread_delay_delete();
}
void schedule_at_start_of_simtime(vvp_gen_event_t obj, vvp_time64_t delay)

View File

@ -111,6 +111,7 @@ struct vthread_s {
unsigned i_have_ended :1;
unsigned waiting_for_event :1;
unsigned is_scheduled :1;
unsigned delay_delete :1;
unsigned fork_count :8;
/* This points to the sole child of the thread. */
struct vthread_s*child;
@ -411,6 +412,7 @@ vthread_t vthread_new(vvp_code_t pc, struct __vpiScope*scope)
thr->schedule_parent_on_end = 0;
thr->is_scheduled = 0;
thr->i_have_ended = 0;
thr->delay_delete = 0;
thr->waiting_for_event = 0;
thr->fork_count = 0;
thr->event = 0;
@ -498,7 +500,10 @@ static void vthread_reap(vthread_t thr)
if ((thr->is_scheduled == 0) && (thr->waiting_for_event == 0)) {
assert(thr->fork_count == 0);
assert(thr->wait_next == 0);
if (thr->delay_delete)
schedule_del_thr(thr);
else
vthread_delete(thr);
}
}
@ -517,6 +522,12 @@ void vthread_mark_scheduled(vthread_t thr)
}
}
void vthread_delay_delete()
{
if (running_thread)
running_thread->delay_delete = 1;
}
/*
* This function runs each thread by fetching an instruction,
* incrementing the PC, and executing the instruction. The thread may
@ -4541,9 +4552,12 @@ bool of_XOR(vthread_t thr, vvp_code_t cp)
bool of_ZOMBIE(vthread_t thr, vvp_code_t)
{
thr->pc = codespace_null();
if ((thr->parent == 0) && (thr->child == 0))
if ((thr->parent == 0) && (thr->child == 0)) {
if (thr->delay_delete)
schedule_del_thr(thr);
else
vthread_delete(thr);
}
return false;
}

View File

@ -1,7 +1,7 @@
#ifndef __vthread_H
#define __vthread_H
/*
* Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -48,6 +48,14 @@ extern vthread_t vthread_new(vvp_code_t sa, struct __vpiScope*scope);
*/
extern void vthread_mark_scheduled(vthread_t thr);
/*
* This function causes deletion of the currently running thread to
* be delayed until after all sync events have been processed for the
* time step in which the thread terminates. It is only used by the
* schedule_generic function.
*/
extern void vthread_delay_delete();
/*
* Cause this thread to execute instructions until in is put to sleep
* by executing some sort of delay or wait instruction.