Fix subtle issues related to fork/join of tasks.

When a fork/join contains a task, the task completion may become
confused with the completion of another thread if any of the
threads are embedded in the main thread. So always create threads
for all the fork paths, and joins to match.
This commit is contained in:
Stephen Williams 2013-08-29 20:31:26 -07:00
parent a10e07908e
commit 15cda5fef2
2 changed files with 10 additions and 28 deletions

View File

@ -1388,30 +1388,20 @@ static int show_stmt_fork(ivl_statement_t net, ivl_scope_t sscope)
unsigned join_detach_count = 0;
ivl_scope_t scope = ivl_stmt_block_scope(net);
int is_named = (scope != 0);
/* This is TRUE if it is allowed to embed one of the threads
into this thread. */
int is_embeddable = 1;
unsigned out = transient_id++;
unsigned id_base = transient_id;
/* Children are certainly not embeddable if they are going
into a new scope. */
if (is_named)
is_embeddable = 0;
switch (ivl_statement_type(net)) {
case IVL_ST_FORK:
break;
case IVL_ST_FORK_JOIN_ANY:
if (join_count < 2)
break;
is_embeddable = 0;
join_detach_count = join_count - 1;
join_count = 1;
break;
case IVL_ST_FORK_JOIN_NONE:
is_embeddable = 0;
join_detach_count = join_count;
join_count = 0;
break;
@ -1419,12 +1409,6 @@ static int show_stmt_fork(ivl_statement_t net, ivl_scope_t sscope)
assert(0);
}
/* cnt is the number of sub-threads. If the fork-join has no
name, then we can put one of the sub-threads in the current
thread, so decrement the count by one and use the current
scope for all the threads. */
if (is_embeddable)
join_count -= 1;
if (scope==0)
scope = sscope;
@ -1438,11 +1422,6 @@ static int show_stmt_fork(ivl_statement_t net, ivl_scope_t sscope)
id_base+idx, scope);
}
/* If we are putting one sub-thread into the current thread,
then draw its code here. */
if (is_embeddable)
rc += show_statement(ivl_stmt_block_stmt(net, join_count), scope);
/* Generate enough joins to collect all the sub-threads. */
for (idx = 0 ; idx < join_count ; idx += 1)

View File

@ -2717,17 +2717,20 @@ bool of_FORK(vthread_t thr, vvp_code_t cp)
/* If the child scope is not the same as the current scope,
infer that this is a task or function call. */
if (cp->scope != thr->parent_scope)
switch (cp->scope->get_type_code()) {
case vpiFunction:
thr->task_func_children.insert(child);
/* If the new child was created to evaluate a function,
run it immediately, then return to this thread. */
if (cp->scope->get_type_code() == vpiFunction) {
child->is_scheduled = 1;
vthread_run(child);
running_thread = thr;
} else {
running_thread = thr;
break;
case vpiTask:
thr->task_func_children.insert(child);
schedule_vthread(child, 0, true);
break;
default:
schedule_vthread(child, 0, true);
break;
}
return true;