mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-24 03:14:08 +08:00
re PR libgomp/51298 (libgomp team_barrier locking failures)
PR libgomp/51298 * config/linux/bar.h: Use atomic rather than sync builtins. * config/linux/bar.c: Likewise. Add missing acquire synchronisation on generation field. * task.c (gomp_barrier_handle_tasks): Regain lock so as to not double unlock. From-SVN: r181833
This commit is contained in:
parent
b40c885f18
commit
ab6dd406ba
@ -1,3 +1,12 @@
|
||||
2011-11-30 Alan Modra <amodra@gmail.com>
|
||||
|
||||
PR libgomp/51298
|
||||
* config/linux/bar.h: Use atomic rather than sync builtins.
|
||||
* config/linux/bar.c: Likewise. Add missing acquire
|
||||
synchronisation on generation field.
|
||||
* task.c (gomp_barrier_handle_tasks): Regain lock so as to not
|
||||
double unlock.
|
||||
|
||||
2011-11-30 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* ordered.c (gomp_ordered_sync): Add MEMMODEL_ACQ_REL fence.
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2005, 2008, 2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2005, 2008, 2009, 2011 Free Software Foundation, Inc.
|
||||
Contributed by Richard Henderson <rth@redhat.com>.
|
||||
|
||||
This file is part of the GNU OpenMP Library (libgomp).
|
||||
@ -37,17 +37,15 @@ gomp_barrier_wait_end (gomp_barrier_t *bar, gomp_barrier_state_t state)
|
||||
{
|
||||
/* Next time we'll be awaiting TOTAL threads again. */
|
||||
bar->awaited = bar->total;
|
||||
atomic_write_barrier ();
|
||||
bar->generation += 4;
|
||||
__atomic_store_n (&bar->generation, bar->generation + 4,
|
||||
MEMMODEL_RELEASE);
|
||||
futex_wake ((int *) &bar->generation, INT_MAX);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int generation = state;
|
||||
|
||||
do
|
||||
do_wait ((int *) &bar->generation, generation);
|
||||
while (bar->generation == generation);
|
||||
do_wait ((int *) &bar->generation, state);
|
||||
while (__atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE) == state);
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,15 +79,15 @@ gomp_team_barrier_wake (gomp_barrier_t *bar, int count)
|
||||
void
|
||||
gomp_team_barrier_wait_end (gomp_barrier_t *bar, gomp_barrier_state_t state)
|
||||
{
|
||||
unsigned int generation;
|
||||
unsigned int generation, gen;
|
||||
|
||||
if (__builtin_expect ((state & 1) != 0, 0))
|
||||
{
|
||||
/* Next time we'll be awaiting TOTAL threads again. */
|
||||
struct gomp_thread *thr = gomp_thread ();
|
||||
struct gomp_team *team = thr->ts.team;
|
||||
|
||||
bar->awaited = bar->total;
|
||||
atomic_write_barrier ();
|
||||
if (__builtin_expect (team->task_count, 0))
|
||||
{
|
||||
gomp_barrier_handle_tasks (state);
|
||||
@ -97,7 +95,7 @@ gomp_team_barrier_wait_end (gomp_barrier_t *bar, gomp_barrier_state_t state)
|
||||
}
|
||||
else
|
||||
{
|
||||
bar->generation = state + 3;
|
||||
__atomic_store_n (&bar->generation, state + 3, MEMMODEL_RELEASE);
|
||||
futex_wake ((int *) &bar->generation, INT_MAX);
|
||||
return;
|
||||
}
|
||||
@ -107,12 +105,16 @@ gomp_team_barrier_wait_end (gomp_barrier_t *bar, gomp_barrier_state_t state)
|
||||
do
|
||||
{
|
||||
do_wait ((int *) &bar->generation, generation);
|
||||
if (__builtin_expect (bar->generation & 1, 0))
|
||||
gomp_barrier_handle_tasks (state);
|
||||
if ((bar->generation & 2))
|
||||
gen = __atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE);
|
||||
if (__builtin_expect (gen & 1, 0))
|
||||
{
|
||||
gomp_barrier_handle_tasks (state);
|
||||
gen = __atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE);
|
||||
}
|
||||
if ((gen & 2) != 0)
|
||||
generation |= 2;
|
||||
}
|
||||
while (bar->generation != state + 4);
|
||||
while (gen != state + 4);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2005, 2008, 2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2005, 2008, 2009, 2011 Free Software Foundation, Inc.
|
||||
Contributed by Richard Henderson <rth@redhat.com>.
|
||||
|
||||
This file is part of the GNU OpenMP Library (libgomp).
|
||||
@ -50,7 +50,7 @@ static inline void gomp_barrier_init (gomp_barrier_t *bar, unsigned count)
|
||||
|
||||
static inline void gomp_barrier_reinit (gomp_barrier_t *bar, unsigned count)
|
||||
{
|
||||
__sync_fetch_and_add (&bar->awaited, count - bar->total);
|
||||
__atomic_add_fetch (&bar->awaited, count - bar->total, MEMMODEL_ACQ_REL);
|
||||
bar->total = count;
|
||||
}
|
||||
|
||||
@ -69,10 +69,13 @@ extern void gomp_team_barrier_wake (gomp_barrier_t *, int);
|
||||
static inline gomp_barrier_state_t
|
||||
gomp_barrier_wait_start (gomp_barrier_t *bar)
|
||||
{
|
||||
unsigned int ret = bar->generation & ~3;
|
||||
/* Do we need any barrier here or is __sync_add_and_fetch acting
|
||||
as the needed LoadLoad barrier already? */
|
||||
ret += __sync_add_and_fetch (&bar->awaited, -1) == 0;
|
||||
unsigned int ret = __atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE) & ~3;
|
||||
/* A memory barrier is needed before exiting from the various forms
|
||||
of gomp_barrier_wait, to satisfy OpenMP API version 3.1 section
|
||||
2.8.6 flush Construct, which says there is an implicit flush during
|
||||
a barrier region. This is a convenient place to add the barrier,
|
||||
so we use MEMMODEL_ACQ_REL here rather than MEMMODEL_ACQUIRE. */
|
||||
ret += __atomic_add_fetch (&bar->awaited, -1, MEMMODEL_ACQ_REL) == 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -273,6 +273,7 @@ gomp_barrier_handle_tasks (gomp_barrier_state_t state)
|
||||
gomp_team_barrier_done (&team->barrier, state);
|
||||
gomp_mutex_unlock (&team->task_lock);
|
||||
gomp_team_barrier_wake (&team->barrier, 0);
|
||||
gomp_mutex_lock (&team->task_lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user