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:
parent
1eb593e8ad
commit
33c852d2b4
|
|
@ -669,6 +669,9 @@ void schedule_generic(vvp_gen_event_t obj, vvp_time64_t delay,
|
||||||
cur->delete_obj_when_done = delete_when_done;
|
cur->delete_obj_when_done = delete_when_done;
|
||||||
schedule_event_(cur, delay,
|
schedule_event_(cur, delay,
|
||||||
sync_flag? (ro_flag?SEQ_ROSYNC:SEQ_RWSYNC) : SEQ_ACTIVE);
|
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)
|
void schedule_at_start_of_simtime(vvp_gen_event_t obj, vvp_time64_t delay)
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,7 @@ struct vthread_s {
|
||||||
unsigned i_have_ended :1;
|
unsigned i_have_ended :1;
|
||||||
unsigned waiting_for_event :1;
|
unsigned waiting_for_event :1;
|
||||||
unsigned is_scheduled :1;
|
unsigned is_scheduled :1;
|
||||||
|
unsigned delay_delete :1;
|
||||||
unsigned fork_count :8;
|
unsigned fork_count :8;
|
||||||
/* This points to the sole child of the thread. */
|
/* This points to the sole child of the thread. */
|
||||||
struct vthread_s*child;
|
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->schedule_parent_on_end = 0;
|
||||||
thr->is_scheduled = 0;
|
thr->is_scheduled = 0;
|
||||||
thr->i_have_ended = 0;
|
thr->i_have_ended = 0;
|
||||||
|
thr->delay_delete = 0;
|
||||||
thr->waiting_for_event = 0;
|
thr->waiting_for_event = 0;
|
||||||
thr->fork_count = 0;
|
thr->fork_count = 0;
|
||||||
thr->event = 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)) {
|
if ((thr->is_scheduled == 0) && (thr->waiting_for_event == 0)) {
|
||||||
assert(thr->fork_count == 0);
|
assert(thr->fork_count == 0);
|
||||||
assert(thr->wait_next == 0);
|
assert(thr->wait_next == 0);
|
||||||
schedule_del_thr(thr);
|
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,
|
* This function runs each thread by fetching an instruction,
|
||||||
* incrementing the PC, and executing the instruction. The thread may
|
* 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)
|
bool of_ZOMBIE(vthread_t thr, vvp_code_t)
|
||||||
{
|
{
|
||||||
thr->pc = codespace_null();
|
thr->pc = codespace_null();
|
||||||
if ((thr->parent == 0) && (thr->child == 0))
|
if ((thr->parent == 0) && (thr->child == 0)) {
|
||||||
schedule_del_thr(thr);
|
if (thr->delay_delete)
|
||||||
|
schedule_del_thr(thr);
|
||||||
|
else
|
||||||
|
vthread_delete(thr);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __vthread_H
|
#ifndef __vthread_H
|
||||||
#define __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
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* 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);
|
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
|
* Cause this thread to execute instructions until in is put to sleep
|
||||||
* by executing some sort of delay or wait instruction.
|
* by executing some sort of delay or wait instruction.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue