From 5afb0c9897d86bbc9a3755813d0b0f5aa16ae9f5 Mon Sep 17 00:00:00 2001
From: Jonathan Peyton <jonathan.l.peyton@intel.com>
Date: Wed, 29 Jun 2016 19:46:52 +0000
Subject: [PATCH] Fix omp_sections_nowait.c test to address Bugzilla Bug 28336

This rewrite of the omp_sections_nowait.c test file causes it to hang if the
nowait is not respected. If the nowait isn't respected, the lone thread which
can escape the first sections construct will just sleep at a barrier which
shouldn't exist. All reliance on timers is taken out. For good measure, the test
makes sure that all eight sections are executed as well. The test should take no
longer than a few seconds on any modern machine.

Differential Revision: http://reviews.llvm.org/D21842


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@274151 91177308-0d34-0410-b5e6-96231b3b80d8
---
 .../sections/omp_sections_nowait.c            | 83 +++++++++++++------
 1 file changed, 59 insertions(+), 24 deletions(-)

diff --git a/runtime/test/worksharing/sections/omp_sections_nowait.c b/runtime/test/worksharing/sections/omp_sections_nowait.c
index 5d93df6..caff254 100644
--- a/runtime/test/worksharing/sections/omp_sections_nowait.c
+++ b/runtime/test/worksharing/sections/omp_sections_nowait.c
@@ -1,18 +1,45 @@
 // RUN: %libomp-compile-and-run
 #include <stdio.h>
 #include "omp_testsuite.h"
-#include "omp_my_sleep.h"
 
-int test_omp_sections_nowait()
+/*
+ * This test will hang if the nowait is not working properly
+ *
+ * It relies on a thread skipping to the second sections construct to
+ * release the threads in the first sections construct
+ *
+ * Also, since scheduling of sections is implementation defined, it is
+ * necessary to have all four sections in the second sections construct
+ * release the threads since we can't guarantee which section a single thread
+ * will execute.
+ */
+volatile int release;
+volatile int count;
+
+void wait_for_release_then_increment(int rank)
+{
+  fprintf(stderr, "Thread nr %d enters first section"
+    " and waits.\n", rank);
+  while (release == 0);
+  #pragma omp atomic
+  count++;
+}
+
+void release_and_increment(int rank)
 {
-  int result;
-  int count;
-  int j;
+  fprintf(stderr, "Thread nr %d sets release to 1\n", rank);
+  release = 1;
+  #pragma omp flush(release)
+  #pragma omp atomic
+  count++;
+}
 
-  result = 0;
+int test_omp_sections_nowait()
+{
+  release = 0;
   count = 0;
 
-  #pragma omp parallel
+  #pragma omp parallel num_threads(4)
   {
     int rank;
     rank = omp_get_thread_num ();
@@ -20,18 +47,22 @@ int test_omp_sections_nowait()
     {
       #pragma omp section
       {
-        fprintf(stderr, "Thread nr %d enters first section"
-          " and gets sleeping.\n", rank);
-        my_sleep(SLEEPTIME);
-        count = 1;
-        fprintf(stderr, "Thread nr %d woke up an set"
-          " count to 1.\n", rank);
-        #pragma omp flush(count)
+        wait_for_release_then_increment(rank);
+      }
+      #pragma omp section
+      {
+        wait_for_release_then_increment(rank);
       }
       #pragma omp section
       {
-        fprintf(stderr, "Thread nr %d executed work in the"
-          " first section.\n", rank);
+        wait_for_release_then_increment(rank);
+      }
+      #pragma omp section
+      {
+        fprintf(stderr, "Thread nr %d enters first sections and goes "
+          "immediately to next sections construct to release.\n", rank);
+        #pragma omp atomic
+        count++;
       }
     }
     /* Begin of second sections environment */
@@ -39,20 +70,24 @@ int test_omp_sections_nowait()
     {
       #pragma omp section
       {
-        fprintf(stderr, "Thread nr %d executed work in the"
-          " second section.\n", rank);
+        release_and_increment(rank);
+      }
+      #pragma omp section
+      {
+        release_and_increment(rank);
+      }
+      #pragma omp section
+      {
+        release_and_increment(rank);
       }
       #pragma omp section
       {
-        fprintf(stderr, "Thread nr %d executed work in the"
-          " second section and controls the value of count\n", rank);
-        if (count == 0)
-          result = 1;
-        fprintf(stderr, "count was %d\n", count);
+        release_and_increment(rank);
       }
     }
   }
-  return result;
+  // Check to make sure all eight sections were executed
+  return (count==8);
 }
 
 int main()
-- 
GitLab