PR libgomp/51376 fix

Alan Modra amodra@gmail.com
Fri Dec 2 09:40:00 GMT 2011


On Thu, Dec 01, 2011 at 12:36:08PM +0100, Jakub Jelinek wrote:
> On Thu, Dec 01, 2011 at 09:58:08PM +1030, Alan Modra wrote:
> > The GOMP_task change fixes a similar potential problem.  Bootstrapped
> > and regression tested powerpc-linux.  OK to apply?
> > 
> > 	PR libgomp/51376
> > 	* task.c (GOMP_taskwait): Don't access task->children outside of
> > 	task_lock mutex region.
> > 	(GOMP_task): Likewise.
> 
> Can't this be solved just by adding a barrier?  The access to the var
> outside of the lock has been quite intentional, to avoid locking in the
> common case where there are no children.

No, I tried that and the task-6.C testcase still failed although not
quite as readily.  I was using

if (task == NULL
    || __atomic_load_n (&task->children, MEMMODEL_ACQUIRE) == 0)

You need a release in the child as well as the acquire to ensure
proper synchronisation, and there's a window for failure between the
child clearing task->children and performing a release as part of the
mutex unlock.

Oops, on looking at this email I see I attached an old patch..  This
one avoids a segfault on trying to lock team->task_lock when there
is no team.  This one really has been bootstrapped and regression
tested successfully.

	PR libgomp/51376
	* task.c (GOMP_taskwait): Don't access task->children outside of
	task_lock mutex region.
	(GOMP_task): Likewise.

Index: libgomp/task.c
===================================================================
--- libgomp/task.c	(revision 181902)
+++ libgomp/task.c	(working copy)
@@ -116,10 +116,11 @@ GOMP_task (void (*fn) (void *), void *da
 	}
       else
 	fn (data);
-      if (task.children)
+      if (team != NULL)
 	{
 	  gomp_mutex_lock (&team->task_lock);
-	  gomp_clear_parent (task.children);
+	  if (task.children != NULL)
+	    gomp_clear_parent (task.children);
 	  gomp_mutex_unlock (&team->task_lock);
 	}
       gomp_end_task ();
@@ -290,8 +291,9 @@ GOMP_taskwait (void)
   struct gomp_task *child_task = NULL;
   struct gomp_task *to_free = NULL;
 
-  if (task == NULL || task->children == NULL)
+  if (task == NULL || team == NULL)
     return;
+
   gomp_mutex_lock (&team->task_lock);
   while (1)
     {

-- 
Alan Modra
Australia Development Lab, IBM



More information about the Gcc-patches mailing list