This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[gomp3] Fix schedule(dynamic) ws->mode setting


Hi!

As can be seen on the attached testcase, chunk_size is supposed to
be multiplied by incr when doing the check.  I've added also an overflow
protection to avoid overflow on (nthreads + 1) * ws->chunk_size,
while I believe OpenMP standard says chunk_size * incr must not overflow,
certainly (num_threads + 1) * chunk_size * incr already could in a valid
program.

2008-03-26  Jakub Jelinek  <jakub@redhat.com>

	* loop.c (gomp_loop_init): Fix GFS_DYNAMIC ws->mode setting.
	* testsuite/libgomp.c/loop-4.c: New test.

--- libgomp/loop.c	(revision 133510)
+++ libgomp/loop.c	(working copy)
@@ -47,20 +47,36 @@ gomp_loop_init (struct gomp_work_share *
   ws->next = start;
   if (sched == GFS_DYNAMIC)
     {
+      ws->chunk_size *= incr;
+
 #ifdef HAVE_SYNC_BUILTINS
-      /* For dynamic scheduling prepare things to make each iteration
-	 faster.  */
-      struct gomp_thread *thr = gomp_thread ();
-      struct gomp_team *team = thr->ts.team;
-      unsigned long nthreads = team ? team->nthreads : 1;
-
-      if (incr > 0)
-	ws->mode = ws->end < LONG_MAX - (nthreads + 1) * chunk_size;
-      else
-	ws->mode = ws->end > (nthreads + 1) * chunk_size - LONG_MAX;
+      {
+	/* For dynamic scheduling prepare things to make each iteration
+	   faster.  */
+	struct gomp_thread *thr = gomp_thread ();
+	struct gomp_team *team = thr->ts.team;
+	long nthreads = team ? team->nthreads : 1;
+
+	if (__builtin_expect (incr > 0, 1))
+	  {
+	    /* Cheap overflow protection.  */
+	    if (__builtin_expect ((nthreads | ws->chunk_size)
+				  >= 1UL << (sizeof (long)
+					     * __CHAR_BIT__ / 2 - 1), 0))
+	      ws->mode = 0;
+	    else
+	      ws->mode = ws->end < (LONG_MAX
+				    - (nthreads + 1) * ws->chunk_size);
+	  }
+	/* Cheap overflow protection.  */
+	else if (__builtin_expect ((nthreads | -ws->chunk_size)
+				   >= 1UL << (sizeof (long)
+					      * __CHAR_BIT__ / 2 - 1), 0))
+	  ws->mode = 0;
+	else
+	  ws->mode = ws->end > (nthreads + 1) * -ws->chunk_size - LONG_MAX;
+      }
 #endif
-
-      ws->chunk_size *= incr;
     }
 }
 
--- libgomp/testsuite/libgomp.c/loop-4.c	(revision 0)
+++ libgomp/testsuite/libgomp.c/loop-4.c	(revision 0)
@@ -0,0 +1,28 @@
+/* { dg-do run } */
+
+extern void abort (void);
+
+int
+main (void)
+{
+  int e = 0;
+#pragma omp parallel num_threads (4) reduction(+:e)
+  {
+    long i;
+    #pragma omp for schedule(dynamic,1)
+    for (i = __LONG_MAX__ - 30001; i <= __LONG_MAX__ - 10001; i += 10000)
+      if (i != __LONG_MAX__ - 30001
+	  && i != __LONG_MAX__ - 20001
+	  && i != __LONG_MAX__ - 10001)
+	e = 1;
+    #pragma omp for schedule(dynamic,1)
+    for (i = -__LONG_MAX__ + 30000; i >= -__LONG_MAX__ + 10000; i -= 10000)
+      if (i != -__LONG_MAX__ + 30000
+	  && i != -__LONG_MAX__ + 20000
+	  && i != -__LONG_MAX__ + 10000)
+	e = 1;
+  }
+  if (e)
+    abort ();
+  return 0;
+}

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]