Fix for br931.

Task and function calls are handled in vvp using the fork/join
instructions. The join instruction after a call must reap the
task/function thread.
This commit is contained in:
Martin Whitaker 2013-05-27 09:34:44 +01:00
parent 6f8eede371
commit cbaf36d4b8
1 changed files with 18 additions and 14 deletions

View File

@ -63,11 +63,11 @@ using namespace std;
* child of the current thread, and the current thread a parent of the * child of the current thread, and the current thread a parent of the
* new thread. Any child can be reaped by a %join. * new thread. Any child can be reaped by a %join.
* *
* Children placed into an automatic scope are given special * Children placed into a task or function scope are given special
* treatment, which is required to make function/tasks calls that they * treatment, which is required to make task/function calls that they
* represent work correctly. These automatic children are copied into * represent work correctly. These task/function children are copied
* an automatic_children set to mark them for this handling. %join * into a task_func_children set to mark them for this handling. %join
* operations will guarantee that automatic threads are joined first, * operations will guarantee that task/function threads are joined first,
* before any non-automatic threads. * before any non-automatic threads.
* *
* It is a programming error for a thread that created threads to not * It is a programming error for a thread that created threads to not
@ -204,8 +204,8 @@ struct vthread_s {
unsigned delay_delete :1; unsigned delay_delete :1;
/* This points to the children of the thread. */ /* This points to the children of the thread. */
set<struct vthread_s*>children; set<struct vthread_s*>children;
/* No more than 1 of the children are automatic. */ /* No more than 1 of the children are tasks or functions. */
set<vthread_s*>automatic_children; set<vthread_s*>task_func_children;
/* This points to my parent, if I have one. */ /* This points to my parent, if I have one. */
struct vthread_s*parent; struct vthread_s*parent;
/* This points to the containing scope. */ /* This points to the containing scope. */
@ -2743,16 +2743,18 @@ bool of_FORK(vthread_t thr, vvp_code_t cp)
on the write context stack. */ on the write context stack. */
child->wt_context = thr->wt_context; child->wt_context = thr->wt_context;
child->rd_context = thr->wt_context; child->rd_context = thr->wt_context;
thr->automatic_children.insert(child);
} }
child->parent = thr; child->parent = thr;
thr->children.insert(child); thr->children.insert(child);
int child_type = cp->scope->get_type_code();
if ((child_type == vpiTask) || (child_type == vpiFunction))
thr->task_func_children.insert(child);
/* If the new child was created to evaluate a function, /* If the new child was created to evaluate a function,
run it immediately, then return to this thread. */ run it immediately, then return to this thread. */
if (cp->scope->get_type_code() == vpiFunction) { if (child_type == vpiFunction) {
child->is_scheduled = 1; child->is_scheduled = 1;
vthread_run(child); vthread_run(child);
running_thread = thr; running_thread = thr;
@ -3065,8 +3067,8 @@ bool of_JMP1(vthread_t thr, vvp_code_t cp)
static bool test_joinable(vthread_t thr, vthread_t child) static bool test_joinable(vthread_t thr, vthread_t child)
{ {
set<vthread_t>::iterator auto_cur = thr->automatic_children.find(child); set<vthread_t>::iterator cur = thr->task_func_children.find(child);
if (!thr->automatic_children.empty() && auto_cur == thr->automatic_children.end()) if (!thr->task_func_children.empty() && cur == thr->task_func_children.end())
return false; return false;
return true; return true;
@ -3076,8 +3078,10 @@ static void do_join(vthread_t thr, vthread_t child)
{ {
assert(child->parent == thr); assert(child->parent == thr);
thr->task_func_children.erase(child);
/* If the immediate child thread is in an automatic scope... */ /* If the immediate child thread is in an automatic scope... */
if (thr->automatic_children.erase(child) != 0) { if (child->wt_context) {
/* and is the top level task/function thread... */ /* and is the top level task/function thread... */
if (thr->wt_context != thr->rd_context) { if (thr->wt_context != thr->rd_context) {
/* Pop the child context from the write context stack. */ /* Pop the child context from the write context stack. */
@ -3128,7 +3132,7 @@ bool of_JOIN_DETACH(vthread_t thr, vvp_code_t cp)
{ {
unsigned long count = cp->number; unsigned long count = cp->number;
assert(thr->automatic_children.empty()); assert(thr->task_func_children.empty());
assert(count == thr->children.size()); assert(count == thr->children.size());
while (!thr->children.empty()) { while (!thr->children.empty()) {