From 5b2f249dccf74353556a2fa9b7c355a85badb8fe Mon Sep 17 00:00:00 2001 From: Cary R Date: Thu, 20 Mar 2008 19:01:20 -0700 Subject: [PATCH] Thread deletion is now scheduled after rosync. Threads used to be deleted when they finished processing code. The problem with this is that some of the code could be rescheduled to run at rosync ($strobe, etc.). This allowed the thread data the code depended on to be reaped too soon. This patch uses a new queue to schedule thread deletion. The queue is processed after rosync has finished. --- vvp/schedule.cc | 63 +++++++++++++++++++++++++++++++++++++++++++------ vvp/schedule.h | 8 +++---- vvp/vthread.cc | 10 +++++--- vvp/vthread.h | 52 ++++------------------------------------ 4 files changed, 71 insertions(+), 62 deletions(-) diff --git a/vvp/schedule.cc b/vvp/schedule.cc index bbc088b21..5dee5aab4 100644 --- a/vvp/schedule.cc +++ b/vvp/schedule.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2007 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2008 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 @@ -16,9 +16,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -#ifdef HAVE_CVS_IDENT -#ident "$Id: schedule.cc,v 1.45 2007/01/16 05:44:16 steve Exp $" -#endif # include "schedule.h" # include "memory.h" @@ -63,6 +60,7 @@ struct event_time_s { struct event_s*nbassign; struct event_s*rwsync; struct event_s*rosync; + struct event_s*del_thr; struct event_time_s*next; @@ -88,6 +86,16 @@ void vthread_event_s::run_run(void) vthread_run(thr); } +struct del_thr_event_s : public event_s { + vthread_t thr; + void run_run(void); +}; + +void del_thr_event_s::run_run(void) +{ + vthread_delete(thr); +} + struct assign_vector4_event_s : public event_s { /* Where to do the assign. */ vvp_net_ptr_t ptr; @@ -280,7 +288,8 @@ static void signals_revert(void) * itself, and the structure is placed in the right place in the * queue. */ -typedef enum event_queue_e { SEQ_ACTIVE, SEQ_NBASSIGN, SEQ_RWSYNC, SEQ_ROSYNC } event_queue_t; +typedef enum event_queue_e { SEQ_ACTIVE, SEQ_NBASSIGN, SEQ_RWSYNC, SEQ_ROSYNC, + DEL_THREAD } event_queue_t; static void schedule_event_(struct event_s*cur, vvp_time64_t delay, event_queue_t select_queue) @@ -297,6 +306,7 @@ static void schedule_event_(struct event_s*cur, vvp_time64_t delay, ctim->nbassign = 0; ctim->rwsync = 0; ctim->rosync = 0; + ctim->del_thr = 0; ctim->delay = delay; ctim->next = 0; sched_list = ctim; @@ -310,6 +320,7 @@ static void schedule_event_(struct event_s*cur, vvp_time64_t delay, tmp->nbassign = 0; tmp->rwsync = 0; tmp->rosync = 0; + tmp->del_thr = 0; tmp->delay = delay; tmp->next = ctim; ctim->delay -= delay; @@ -331,6 +342,7 @@ static void schedule_event_(struct event_s*cur, vvp_time64_t delay, tmp->nbassign = 0; tmp->rwsync = 0; tmp->rosync = 0; + tmp->del_thr = 0; tmp->delay = delay; tmp->next = prev->next; prev->next = tmp; @@ -347,6 +359,7 @@ static void schedule_event_(struct event_s*cur, vvp_time64_t delay, tmp->nbassign = 0; tmp->rwsync = 0; tmp->rosync = 0; + tmp->del_thr = 0; tmp->delay = delay - ctim->delay; tmp->next = 0; ctim->next = tmp; @@ -408,6 +421,18 @@ static void schedule_event_(struct event_s*cur, vvp_time64_t delay, ctim->rosync = cur; } break; + + case DEL_THREAD: + if (ctim->del_thr == 0) { + ctim->del_thr = cur; + + } else { + /* Put the cur event on the end of the active list. */ + cur->next = ctim->del_thr->next; + ctim->del_thr->next = cur; + ctim->del_thr = cur; + } + break; } } @@ -549,6 +574,15 @@ void schedule_init_vector(vvp_net_ptr_t ptr, double bit) schedule_init_list = cur; } +void schedule_del_thr(vthread_t thr) +{ + struct del_thr_event_s*cur = new del_thr_event_s; + + cur->thr = thr; + + schedule_event_(cur, 0, DEL_THREAD); +} + void schedule_generic(vvp_gen_event_t obj, vvp_time64_t delay, bool sync_flag, bool ro_flag) { @@ -576,6 +610,9 @@ extern void vpiNextSimTime(void); * it is legal for a rosync callback to create other rosync * callbacks. It is *not* legal for them to create any other kinds of * events, and that is why the rosync is treated specially. + * + * Once all the rosync callbacks are done we can safely delete any + * threads that finished during this time step. */ static void run_rosync(struct event_time_s*ctim) { @@ -591,6 +628,18 @@ static void run_rosync(struct event_time_s*ctim) delete cur; } + while (ctim->del_thr) { + struct event_s*cur = ctim->del_thr->next; + if (cur->next == cur) { + ctim->del_thr = 0; + } else { + ctim->del_thr->next = cur->next; + } + + cur->run_run(); + delete cur; + } + if (ctim->active || ctim->nbassign || ctim->rwsync) { fprintf(stderr, "SCHEDULER ERROR: read-only sync events " "created RW events!\n"); @@ -655,7 +704,8 @@ void schedule_simulate(void) ctim->rwsync = 0; /* If out of rw events, then run the rosync - events and delete this timestep. */ + events and delete this timestep. This also + deletes threads as needed. */ if (ctim->active == 0) { run_rosync(ctim); sched_list = ctim->next; @@ -686,4 +736,3 @@ void schedule_simulate(void) // Execute post-simulation callbacks vpiPostsim(); } - diff --git a/vvp/schedule.h b/vvp/schedule.h index b1ccdb5d0..689694397 100644 --- a/vvp/schedule.h +++ b/vvp/schedule.h @@ -1,7 +1,7 @@ #ifndef __schedule_H #define __schedule_H /* - * Copyright (c) 2001-2007 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2008 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 @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -#ifdef HAVE_CVS_IDENT -#ident "$Id: schedule.h,v 1.29 2007/01/16 05:44:16 steve Exp $" -#endif # include "vthread.h" # include "pointers.h" @@ -110,6 +107,9 @@ typedef struct vvp_gen_event_s *vvp_gen_event_t; extern void schedule_generic(vvp_gen_event_t obj, vvp_time64_t delay, bool sync_flag, bool ro_flag =true); +/* Use this is schedule thread deletion (after rosync). */ +extern void schedule_del_thr(vthread_t thr); + struct vvp_gen_event_s { virtual ~vvp_gen_event_s() =0; diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 09ea32382..6343a88e5 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -265,8 +265,6 @@ vthread_t vthread_new(vvp_code_t pc, struct __vpiScope*scope) */ static void vthread_reap(vthread_t thr) { - thr->bits4 = vvp_vector4_t(); - if (thr->child) { assert(thr->child->parent == thr); thr->child->parent = thr->parent; @@ -290,10 +288,16 @@ 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); - delete thr; + schedule_del_thr(thr); } } +void vthread_delete(vthread_t thr) +{ + thr->bits4 = vvp_vector4_t(); + delete thr; +} + void vthread_mark_scheduled(vthread_t thr) { while (thr != 0) { diff --git a/vvp/vthread.h b/vvp/vthread.h index e9ef81c5b..b6ee59cf0 100644 --- a/vvp/vthread.h +++ b/vvp/vthread.h @@ -1,7 +1,7 @@ #ifndef __vthread_H #define __vthread_H /* - * Copyright (c) 2001-2003 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2008 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 @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -#ifdef HAVE_CVS_IDENT -#ident "$Id: vthread.h,v 1.12 2005/08/27 02:34:43 steve Exp $" -#endif # include "vvp_net.h" @@ -77,48 +74,7 @@ extern void vthread_put_bit(struct vthread_s*thr, unsigned addr, vvp_bit4_t bit) extern double vthread_get_real(struct vthread_s*thr, unsigned addr); extern void vthread_put_real(struct vthread_s*thr, unsigned addr, double val); -/* - * $Log: vthread.h,v $ - * Revision 1.12 2005/08/27 02:34:43 steve - * Bring threads into the vvp_vector4_t structure. - * - * Revision 1.11 2003/07/03 20:03:36 steve - * Remove the vvp_cpoint_t indirect code pointer. - * - * Revision 1.10 2003/01/27 00:14:37 steve - * Support in various contexts the $realtime - * system task. - * - * Revision 1.9 2003/01/26 18:16:22 steve - * Add %cvt/ir and %cvt/ri instructions, and support - * real values passed as arguments to VPI tasks. - * - * Revision 1.8 2002/08/12 01:35:09 steve - * conditional ident string using autoconfig. - * - * Revision 1.7 2001/05/20 00:45:43 steve - * include missing externs on vthread_put_bit. - * - * Revision 1.6 2001/05/10 00:26:53 steve - * VVP support for memories in expressions, - * including general support for thread bit - * vectors as system task parameters. - * (Stephan Boettcher) - * - * Revision 1.5 2001/04/21 00:34:39 steve - * Working %disable and reap handling references from scheduler. - * - * Revision 1.4 2001/04/18 04:21:23 steve - * Put threads into scopes. - * - * Revision 1.3 2001/04/13 03:55:18 steve - * More complete reap of all threads. - * - * Revision 1.2 2001/03/26 04:00:39 steve - * Add the .event statement and the %wait instruction. - * - * Revision 1.1 2001/03/11 00:29:39 steve - * Add the vvp engine to cvs. - * - */ +/* This is used to actually delete a thread once we are done with it. */ +extern void vthread_delete(vthread_t thr); + #endif