bar->awaited = bar->total;
team->work_share_cancelled = 0;
- if (__builtin_expect (team->task_count, 0))
+ unsigned task_count
+ = __atomic_load_n (&team->task_count, MEMMODEL_ACQUIRE);
+ if (__builtin_expect (task_count, 0))
{
gomp_barrier_handle_tasks (state);
state &= ~BAR_WAS_LAST;
bar->awaited = bar->total;
team->work_share_cancelled = 0;
- if (__builtin_expect (team->task_count, 0))
+ unsigned task_count
+ = __atomic_load_n (&team->task_count, MEMMODEL_ACQUIRE);
+ if (__builtin_expect (task_count, 0))
{
gomp_barrier_handle_tasks (state);
state &= ~BAR_WAS_LAST;
static inline void
gomp_team_barrier_done (gomp_barrier_t *bar, gomp_barrier_state_t state)
{
- bar->generation = (state & -BAR_INCR) + BAR_INCR;
+ /* Need the atomic store for acquire-release synchronisation with the
+ load in `gomp_team_barrier_wait_{cancel_,}end`. See PR112356 */
+ __atomic_store_n (&bar->generation, (state & -BAR_INCR) + BAR_INCR,
+ MEMMODEL_RELEASE);
}
static inline bool
bar->awaited = bar->total;
team->work_share_cancelled = 0;
- if (__builtin_expect (team->task_count, 0))
+ unsigned task_count
+ = __atomic_load_n (&team->task_count, MEMMODEL_ACQUIRE);
+ if (__builtin_expect (task_count, 0))
{
gomp_barrier_handle_tasks (state);
state &= ~BAR_WAS_LAST;
bar->awaited = bar->total;
team->work_share_cancelled = 0;
- if (__builtin_expect (team->task_count, 0))
+ unsigned task_count
+ = __atomic_load_n (&team->task_count, MEMMODEL_ACQUIRE);
+ if (__builtin_expect (task_count, 0))
{
gomp_barrier_handle_tasks (state);
state &= ~BAR_WAS_LAST;
static inline void
gomp_team_barrier_done (gomp_barrier_t *bar, gomp_barrier_state_t state)
{
- bar->generation = (state & -BAR_INCR) + BAR_INCR;
+ /* Need the atomic store for acquire-release synchronisation with the
+ load in `gomp_team_barrier_wait_{cancel_,}end`. See PR112356 */
+ __atomic_store_n (&bar->generation, (state & -BAR_INCR) + BAR_INCR,
+ MEMMODEL_RELEASE);
}
static inline bool
struct gomp_team *team = thr->ts.team;
team->work_share_cancelled = 0;
- if (team->task_count)
+ unsigned task_count
+ = __atomic_load_n (&team->task_count, MEMMODEL_ACQUIRE);
+ if (task_count)
{
gomp_barrier_handle_tasks (state);
if (n > 0)
struct gomp_team *team = thr->ts.team;
team->work_share_cancelled = 0;
- if (team->task_count)
+ unsigned task_count
+ = __atomic_load_n (&team->task_count, MEMMODEL_ACQUIRE);
+ if (task_count)
{
gomp_barrier_handle_tasks (state);
if (n > 0)
static inline void
gomp_team_barrier_done (gomp_barrier_t *bar, gomp_barrier_state_t state)
{
- bar->generation = (state & -BAR_INCR) + BAR_INCR;
+ /* Need the atomic store for acquire-release synchronisation with the
+ load in `gomp_team_barrier_wait_{cancel_,}end`. See PR112356 */
+ __atomic_store_n (&bar->generation, (state & -BAR_INCR) + BAR_INCR,
+ MEMMODEL_RELEASE);
}
static inline bool
static inline void
gomp_team_barrier_done (gomp_barrier_t *bar, gomp_barrier_state_t state)
{
- bar->generation = (state & -BAR_INCR) + BAR_INCR;
+ /* Need the atomic store for acquire-release synchronisation with the
+ load in `gomp_team_barrier_wait_{cancel_,}end`. See PR112356 */
+ __atomic_store_n (&bar->generation, (state & -BAR_INCR) + BAR_INCR,
+ MEMMODEL_RELEASE);
}
static inline bool
if (do_wake > new_tasks)
do_wake = new_tasks;
}
- --team->task_count;
+ /* Need to use RELEASE to sync with barrier read outside of the
+ tasking code (See PR122356). Only care when decrementing to zero
+ because that's what the barrier cares about. */
+ if (team->task_count == 1)
+ __atomic_store_n (&team->task_count, 0, MEMMODEL_RELEASE);
+ else
+ team->task_count--;
}
}
}
--- /dev/null
+#include <omp.h>
+
+void abort ();
+
+#define NUM_THREADS 8
+unsigned full_data[NUM_THREADS] = {0};
+#pragma omp declare target enter(full_data)
+
+void
+test ()
+{
+#pragma omp parallel num_threads(8)
+ {
+#pragma omp for
+ for (int i = 0; i < 10; i++)
+#pragma omp task
+ {
+ full_data[omp_get_thread_num ()] += 1;
+ }
+#pragma omp barrier
+
+ unsigned total = 0;
+ for (int i = 0; i < NUM_THREADS; i++)
+ total += full_data[i];
+
+ if (total != 10)
+ abort ();
+ }
+}
+#pragma omp declare target enter(test)
+
+
+int
+main ()
+{
+ test ();
+
+ #pragma omp target
+ test ();
+}