Hello

This patch fixes the issue where a call to omp_fulfill_event could fail to trigger the execution of tasks that were dependent on the task whose completion event is being fulfilled.

This mainly (or can only?) occurs when the thread is external to OpenMP, and all the barrier threads are sleeping when the omp_fulfill_event is called. omp_fulfill_event wakes the appropriate number of threads, but if BAR_TASK_PENDING is not set on bar->generation, the threads go back to sleep again rather than process new tasks.

I have added a new testcase using a pthread thread to call omp_fulfill_event on a suspended task after a short delay. I have not included a Fortran version as there doesn't appear to be a standard interface for threading on Fortran.

I have tested all the task-detach-* libgomp tests (which are the only tests that call omp_fulfill_event) with no offloading and offloading to Nvidia, with no fails. Okay to commit to master, releases/gcc-11 and devel/omp/gcc-11?

Thanks

Kwok
From 348c7cd00e358a8dc0b7563055f367fce2713fa5 Mon Sep 17 00:00:00 2001
From: Kwok Cheung Yeung <k...@codesourcery.com>
Date: Fri, 14 May 2021 09:59:11 -0700
Subject: [PATCH] openmp: Notify team barrier of pending tasks in
 omp_fulfill_event

The team barrier should be notified of any new tasks that become runnable
as the result of a completing task, otherwise the barrier threads might
not resume processing available tasks, resulting in a hang.

2021-05-17  Kwok Cheung Yeung  <k...@codesourcery.com>

        libgomp/
        * task.c (omp_fulfill_event): Call gomp_team_barrier_set_task_pending
        if new tasks generated.
        * testsuite/libgomp.c-c++-common/task-detach-13.c: New.
---
 libgomp/task.c                                |  1 +
 .../libgomp.c-c++-common/task-detach-13.c     | 60 +++++++++++++++++++
 2 files changed, 61 insertions(+)
 create mode 100644 libgomp/testsuite/libgomp.c-c++-common/task-detach-13.c

diff --git a/libgomp/task.c b/libgomp/task.c
index 1c73c759a8d..feb4796a3ac 100644
--- a/libgomp/task.c
+++ b/libgomp/task.c
@@ -2460,6 +2460,7 @@ omp_fulfill_event (omp_event_handle_t event)
   if (new_tasks > 0)
     {
       /* Wake up threads to run new tasks.  */
+      gomp_team_barrier_set_task_pending (&team->barrier);
       do_wake = team->nthreads - team->task_running_count;
       if (do_wake > new_tasks)
        do_wake = new_tasks;
diff --git a/libgomp/testsuite/libgomp.c-c++-common/task-detach-13.c 
b/libgomp/testsuite/libgomp.c-c++-common/task-detach-13.c
new file mode 100644
index 00000000000..4306524526d
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/task-detach-13.c
@@ -0,0 +1,60 @@
+/* { dg-do run } */
+/* { dg-options "-fopenmp" } */
+/* { dg-timeout 10 } */
+
+/* Test that omp_fulfill_event works when called from an external
+   non-OpenMP thread.  */
+
+#include <omp.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <stdio.h>
+
+int finished = 0;
+int event_pending = 0;
+omp_event_handle_t detach_event;
+
+void*
+fulfill_thread (void *)
+{
+  while (!__atomic_load_n (&finished, __ATOMIC_RELAXED))
+    {
+      if (__atomic_load_n (&event_pending, __ATOMIC_ACQUIRE))
+       {
+         omp_fulfill_event (detach_event);
+         __atomic_store_n (&event_pending, 0, __ATOMIC_RELEASE);
+       }
+
+      sleep(1);
+    }
+
+  return 0;
+}
+
+int
+main (void)
+{
+  pthread_t thr;
+  int dep;
+  pthread_create (&thr, NULL, fulfill_thread, 0);
+
+  #pragma omp parallel
+    #pragma omp single
+      {
+       omp_event_handle_t ev;
+
+       #pragma omp task depend (out: dep) detach (ev)
+       {
+         detach_event = ev;
+         __atomic_store_n (&event_pending, 1, __ATOMIC_RELEASE);
+       }
+
+       #pragma omp task depend (in: dep)
+       {
+         __atomic_store_n (&finished, 1, __ATOMIC_RELAXED);
+       }
+      }
+
+
+  pthread_join (thr, 0);
+}
-- 
2.30.0.335.ge636282

Reply via email to