Rework the scope thread list to use a std::set

The scope contains the threads running within. The rework of this
patch allows all threads to know their scope, and cleans up the
handling of threads listed in the scope.
This commit is contained in:
Stephen Williams 2010-01-06 18:43:53 -08:00
parent 3ddb421fbf
commit dda197e39b
3 changed files with 16 additions and 49 deletions

View File

@ -23,6 +23,8 @@
# include "vvp_net.h"
# include "config.h"
# include <set>
/*
* Added to use some "vvp_fun_modpath_src"
* and "vvp_fun_modpath" classes definitions
@ -204,7 +206,7 @@ struct __vpiScope {
/* Keep a list of freed contexts. */
vvp_context_t free_contexts;
/* Keep a list of threads in the scope. */
vthread_t threads;
std::set<vthread_t> threads;
signed int time_units :8;
signed int time_precision :8;
};

View File

@ -447,7 +447,6 @@ compile_scope_decl(char*label, char*type, char*name, char*tname,
scope->nitem = 0;
scope->live_contexts = 0;
scope->free_contexts = 0;
scope->threads = 0;
current_scope = scope;

View File

@ -116,17 +116,12 @@ struct vthread_s {
unsigned fork_count :8;
/* This points to the sole child of the thread. */
struct vthread_s*child;
union {
/* This points to my parent, if I have one. */
struct vthread_s*parent;
/* If this is a header cell, then point to the
containing scope. */
struct __vpiScope*parent_scope;
};
/* This points to my parent, if I have one. */
struct vthread_s*parent;
/* This points to the containing scope. */
struct __vpiScope*parent_scope;
/* This is used for keeping wait queues. */
struct vthread_s*wait_next;
/* These are used to keep the thread in a scope. */
struct vthread_s*scope_next, *scope_prev;
/* These are used to access automatically allocated items. */
vvp_context_t wt_context, rd_context;
/* These are used to pass non-blocking event control information. */
@ -136,10 +131,6 @@ struct vthread_s {
struct __vpiScope* vthread_scope(struct vthread_s*thr)
{
while (thr->bits4.size() > 0) {
thr = thr->scope_next;
}
return thr->parent_scope;
}
@ -413,31 +404,11 @@ vthread_t vthread_new(vvp_code_t pc, struct __vpiScope*scope)
thr->bits4 = vvp_vector4_t(32);
thr->child = 0;
thr->parent = 0;
thr->parent_scope = scope;
thr->wait_next = 0;
thr->wt_context = 0;
thr->rd_context = 0;
/* If the target scope never held a thread, then create a
header cell for it. This is a stub to make circular lists
easier to work with. */
if (scope->threads == 0) {
scope->threads = new struct vthread_s;
scope->threads->pc = codespace_null();
scope->threads->bits4 = vvp_vector4_t();
scope->threads->child = 0;
scope->threads->parent = 0;
scope->threads->parent_scope = scope;
scope->threads->scope_prev = scope->threads;
scope->threads->scope_next = scope->threads;
}
{ vthread_t tmp = scope->threads;
thr->scope_next = tmp->scope_next;
thr->scope_prev = tmp;
thr->scope_next->scope_prev = thr;
thr->scope_prev->scope_next = thr;
}
thr->schedule_parent_on_end = 0;
thr->is_scheduled = 0;
thr->i_have_ended = 0;
@ -452,6 +423,7 @@ vthread_t vthread_new(vvp_code_t pc, struct __vpiScope*scope)
thr_put_bit(thr, 2, BIT4_X);
thr_put_bit(thr, 3, BIT4_Z);
scope->threads .insert(thr);
return thr;
}
@ -518,8 +490,8 @@ static void vthread_reap(vthread_t thr)
thr->child = 0;
thr->parent = 0;
thr->scope_next->scope_prev = thr->scope_prev;
thr->scope_prev->scope_next = thr->scope_next;
// Remove myself from the containing scope.
thr->parent_scope->threads.erase(thr);
thr->pc = codespace_null();
@ -1955,8 +1927,7 @@ static bool do_disable(vthread_t thr, vthread_t match)
bool flag = false;
/* Pull the target thread out of its scope. */
thr->scope_next->scope_prev = thr->scope_prev;
thr->scope_prev->scope_next = thr->scope_next;
thr->parent_scope->threads.erase(thr);
/* Turn the thread off by setting is program counter to
zero and setting an OFF bit. */
@ -2011,23 +1982,18 @@ static bool do_disable(vthread_t thr, vthread_t match)
bool of_DISABLE(vthread_t thr, vvp_code_t cp)
{
struct __vpiScope*scope = (struct __vpiScope*)cp->handle;
if (scope->threads == 0)
return true;
struct vthread_s*head = scope->threads;
bool disabled_myself_flag = false;
while (head->scope_next != head) {
vthread_t tmp = head->scope_next;
while (scope->threads.size() > 0) {
set<vthread_t>::iterator cur = scope->threads.begin();
/* If I am disabling myself, that remember that fact so
that I can finish this statement differently. */
if (tmp == thr)
if (*cur == thr)
disabled_myself_flag = true;
if (do_disable(tmp, thr))
if (do_disable(*cur, thr))
disabled_myself_flag = true;
}