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:
parent
a10e07908e
commit
15cda5fef2
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue