diff mbox

[committed] Fix GOMP_taskgroup_end

Message ID 20140804160814.GO7393@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Aug. 4, 2014, 4:08 p.m. UTC
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  <jakub@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.


	Jakub
diff mbox

Patch

--- 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"