From 15cda5fef26e5f811dc33b0b0f021921793f05c6 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Thu, 29 Aug 2013 20:31:26 -0700 Subject: [PATCH] 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. --- tgt-vvp/vvp_process.c | 21 --------------------- vvp/vthread.cc | 17 ++++++++++------- 2 files changed, 10 insertions(+), 28 deletions(-) diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index 6d57a3910..432a35de7 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -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) diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 92077f0e6..b9d3de756 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -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;