Hi! As can be seen on the depend-8.c testcase, only trying to schedule taskgroup->children in GOMP_taskgroup_end can lead to deadlock if depend clauses are involved - some task in the current taskgroup can depend on a task with the same parent, but from another taskgroup (one of the parent taskgroups). This patch will schedule taskgroup->children if available, but if there are none and taskgroup->num_children is still non-zero, attempts to schedule parent->children. num_children is increased on deferred task creation, so it includes tasks in the taskgroup waiting on dependencies, while children linked list includes only tasks ready to be scheduled.
Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk and 4.9 branch. 2014-08-04 Jakub Jelinek <ja...@redhat.com> * task.c (GOMP_taskgroup_end): If taskgroup->num_children is not zero, but taskgroup->children is NULL and there are any task->children, schedule those instead of waiting. * testsuite/libgomp.c/depend-6.c: New test. * testsuite/libgomp.c/depend-7.c: New test. * testsuite/libgomp.c/depend-8.c: New test. * testsuite/libgomp.c/depend-9.c: New test. * testsuite/libgomp.c/depend-10.c: New test. --- libgomp/task.c.jj 2014-08-01 10:04:11.000000000 +0200 +++ libgomp/task.c 2014-08-04 10:02:10.931449395 +0200 @@ -1115,18 +1115,26 @@ GOMP_taskgroup_end (void) if (taskgroup->children == NULL) { if (taskgroup->num_children) - goto do_wait; - gomp_mutex_unlock (&team->task_lock); - if (to_free) { - gomp_finish_task (to_free); - free (to_free); + if (task->children == NULL) + goto do_wait; + child_task = task->children; + } + else + { + gomp_mutex_unlock (&team->task_lock); + if (to_free) + { + gomp_finish_task (to_free); + free (to_free); + } + goto finish; } - goto finish; } - if (taskgroup->children->kind == GOMP_TASK_WAITING) + else + child_task = taskgroup->children; + if (child_task->kind == GOMP_TASK_WAITING) { - child_task = taskgroup->children; cancelled = gomp_task_run_pre (child_task, child_task->parent, taskgroup, team); @@ -1143,6 +1151,7 @@ GOMP_taskgroup_end (void) } else { + child_task = NULL; do_wait: /* All tasks we are waiting for are already running in other threads. Wait for them. */ @@ -1174,20 +1183,9 @@ GOMP_taskgroup_end (void) finish_cancelled:; size_t new_tasks = gomp_task_run_post_handle_depend (child_task, team); - child_task->prev_taskgroup->next_taskgroup - = child_task->next_taskgroup; - child_task->next_taskgroup->prev_taskgroup - = child_task->prev_taskgroup; - --taskgroup->num_children; - if (taskgroup->children == child_task) - { - if (child_task->next_taskgroup != child_task) - taskgroup->children = child_task->next_taskgroup; - else - taskgroup->children = NULL; - } gomp_task_run_post_remove_parent (child_task); gomp_clear_parent (child_task->children); + gomp_task_run_post_remove_taskgroup (child_task); to_free = child_task; child_task = NULL; team->task_count--; --- libgomp/testsuite/libgomp.c/depend-6.c.jj 2014-08-04 10:31:59.877674051 +0200 +++ libgomp/testsuite/libgomp.c/depend-6.c 2014-08-04 10:31:28.531825917 +0200 @@ -0,0 +1,3 @@ +/* { dg-set-target-env-var OMP_NUM_THREADS "1" } */ + +#include "depend-1.c" --- libgomp/testsuite/libgomp.c/depend-7.c.jj 2014-08-04 10:31:59.877674051 +0200 +++ libgomp/testsuite/libgomp.c/depend-7.c 2014-08-04 10:32:06.328641868 +0200 @@ -0,0 +1,3 @@ +/* { dg-set-target-env-var OMP_NUM_THREADS "1" } */ + +#include "depend-2.c" --- libgomp/testsuite/libgomp.c/depend-8.c.jj 2014-08-04 10:31:59.877674051 +0200 +++ libgomp/testsuite/libgomp.c/depend-8.c 2014-08-04 10:32:12.556611152 +0200 @@ -0,0 +1,3 @@ +/* { dg-set-target-env-var OMP_NUM_THREADS "1" } */ + +#include "depend-3.c" --- libgomp/testsuite/libgomp.c/depend-9.c.jj 2014-08-04 10:31:59.877674051 +0200 +++ libgomp/testsuite/libgomp.c/depend-9.c 2014-08-04 10:32:18.501579242 +0200 @@ -0,0 +1,3 @@ +/* { dg-set-target-env-var OMP_NUM_THREADS "1" } */ + +#include "depend-4.c" --- libgomp/testsuite/libgomp.c/depend-10.c.jj 2014-08-04 10:31:59.877674051 +0200 +++ libgomp/testsuite/libgomp.c/depend-10.c 2014-08-04 10:32:25.070548201 +0200 @@ -0,0 +1,3 @@ +/* { dg-set-target-env-var OMP_NUM_THREADS "1" } */ + +#include "depend-5.c" Jakub