ordered.c (gomp_ordered_sync): Add MEMMODEL_ACQ_REL fence.

* ordered.c (gomp_ordered_sync): Add MEMMODEL_ACQ_REL fence.
	* critical.c (GOMP_critical_start): Add MEMMODEL_RELEASE fence.
	* config/linux/mutex.h: Use atomic rather than sync builtins.
	* config/linux/mutex.c: Likewise.  Comment.  Use -1 for waiting state.
	* config/linux/omp-lock.h: Comment fix.
	* config/linux/arm/mutex.h: Delete.
	* config/linux/powerpc/mutex.h: Delete.
	* config/linux/ia64/mutex.h: Delete.
	* config/linux/mips/mutex.h: Delete.

From-SVN: r181832
This commit is contained in:
Alan Modra 2011-11-30 14:32:53 +10:30 committed by Alan Modra
parent 3e348fccfa
commit b40c885f18
10 changed files with 55 additions and 157 deletions

View File

@ -1,3 +1,15 @@
2011-11-30 Alan Modra <amodra@gmail.com>
* ordered.c (gomp_ordered_sync): Add MEMMODEL_ACQ_REL fence.
* critical.c (GOMP_critical_start): Add MEMMODEL_RELEASE fence.
* config/linux/mutex.h: Use atomic rather than sync builtins.
* config/linux/mutex.c: Likewise. Comment. Use -1 for waiting state.
* config/linux/omp-lock.h: Comment fix.
* config/linux/arm/mutex.h: Delete.
* config/linux/powerpc/mutex.h: Delete.
* config/linux/ia64/mutex.h: Delete.
* config/linux/mips/mutex.h: Delete.
2011-11-30 Alan Modra <amodra@gmail.com>
PR libgomp/51249

View File

@ -1,28 +0,0 @@
/* Copyright (C) 2010 Free Software Foundation, Inc.
Contributed by ARM Ltd.
This file is part of the GNU OpenMP Library (libgomp).
Libgomp is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
/* ARM needs the same correct usage of __sync_synchronize and
__sync_lock_test_and_set as ia64. So we just use its mutex.h. */
#include "config/linux/ia64/mutex.h"

View File

@ -1,66 +0,0 @@
/* 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).
Libgomp is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
/* This is a Linux specific implementation of a mutex synchronization
mechanism for libgomp. This type is private to the library. This
implementation uses atomic instructions and the futex syscall. */
#ifndef GOMP_MUTEX_H
#define GOMP_MUTEX_H 1
typedef int gomp_mutex_t;
#define GOMP_MUTEX_INIT_0 1
static inline void gomp_mutex_init (gomp_mutex_t *mutex)
{
*mutex = 0;
}
extern void gomp_mutex_lock_slow (gomp_mutex_t *mutex, int);
static inline void gomp_mutex_lock (gomp_mutex_t *mutex)
{
int oldval = __sync_val_compare_and_swap (mutex, 0, 1);
if (__builtin_expect (oldval, 0))
gomp_mutex_lock_slow (mutex, oldval);
}
extern void gomp_mutex_unlock_slow (gomp_mutex_t *mutex);
/* IA64 needs a __sync_synchronize call before __sync_lock_test_and_set
because __sync_lock_test_and_set is not a full memory fence. */
static inline void gomp_mutex_unlock (gomp_mutex_t *mutex)
{
int val;
__sync_synchronize ();
val = __sync_lock_test_and_set (mutex, 0);
if (__builtin_expect (val > 1, 0))
gomp_mutex_unlock_slow (mutex);
}
static inline void gomp_mutex_destroy (gomp_mutex_t *mutex)
{
}
#endif /* GOMP_MUTEX_H */

View File

@ -1,27 +0,0 @@
/* Copyright (C) 2009 Free Software Foundation, Inc.
This file is part of the GNU OpenMP Library (libgomp).
Libgomp is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
/* MIPS needs the same correct usage of __sync_synchronize and
__sync_lock_test_and_set as ia64. So we just use its mutex.h. */
#include "config/linux/ia64/mutex.h"

View File

@ -34,25 +34,32 @@ long int gomp_futex_wait = FUTEX_WAIT | FUTEX_PRIVATE_FLAG;
void
gomp_mutex_lock_slow (gomp_mutex_t *mutex, int oldval)
{
/* First loop spins a while. */
while (oldval == 1)
{
if (do_spin (mutex, 1))
{
oldval = __sync_lock_test_and_set (mutex, 2);
/* Spin timeout, nothing changed. Set waiting flag. */
oldval = __atomic_exchange_n (mutex, -1, MEMMODEL_ACQUIRE);
if (oldval == 0)
return;
futex_wait (mutex, 2);
futex_wait (mutex, -1);
break;
}
else
{
oldval = __sync_val_compare_and_swap (mutex, 0, 1);
if (oldval == 0)
/* Something changed. If now unlocked, we're good to go. */
oldval = 0;
if (__atomic_compare_exchange_n (mutex, &oldval, 1, false,
MEMMODEL_ACQUIRE, MEMMODEL_RELAXED))
return;
}
}
while ((oldval = __sync_lock_test_and_set (mutex, 2)))
do_wait (mutex, 2);
/* Second loop waits until mutex is unlocked. We always exit this
loop with wait flag set, so next unlock will awaken a thread. */
while ((oldval = __atomic_exchange_n (mutex, -1, MEMMODEL_ACQUIRE)))
do_wait (mutex, -1);
}
void

View File

@ -33,39 +33,34 @@ typedef int gomp_mutex_t;
#define GOMP_MUTEX_INIT_0 1
static inline void gomp_mutex_init (gomp_mutex_t *mutex)
extern void gomp_mutex_lock_slow (gomp_mutex_t *mutex, int);
extern void gomp_mutex_unlock_slow (gomp_mutex_t *mutex);
static inline void
gomp_mutex_init (gomp_mutex_t *mutex)
{
*mutex = 0;
}
extern void gomp_mutex_lock_slow (gomp_mutex_t *mutex, int);
static inline void gomp_mutex_lock (gomp_mutex_t *mutex)
static inline void
gomp_mutex_destroy (gomp_mutex_t *mutex)
{
int oldval = __sync_val_compare_and_swap (mutex, 0, 1);
if (__builtin_expect (oldval, 0))
}
static inline void
gomp_mutex_lock (gomp_mutex_t *mutex)
{
int oldval = 0;
if (!__atomic_compare_exchange_n (mutex, &oldval, 1, false,
MEMMODEL_ACQUIRE, MEMMODEL_RELAXED))
gomp_mutex_lock_slow (mutex, oldval);
}
extern void gomp_mutex_unlock_slow (gomp_mutex_t *mutex);
static inline void gomp_mutex_unlock (gomp_mutex_t *mutex)
static inline void
gomp_mutex_unlock (gomp_mutex_t *mutex)
{
/* Warning: By definition __sync_lock_test_and_set() does not have
proper memory barrier semantics for a mutex unlock operation.
However, this default implementation is written assuming that it
does, which is true for some targets.
Targets that require additional memory barriers before
__sync_lock_test_and_set to achieve the release semantics of
mutex unlock, are encouraged to include
"config/linux/ia64/mutex.h" in a target specific mutex.h instead
of using this file. */
int val = __sync_lock_test_and_set (mutex, 0);
if (__builtin_expect (val > 1, 0))
int wait = __atomic_exchange_n (mutex, 0, MEMMODEL_RELEASE);
if (__builtin_expect (wait < 0, 0))
gomp_mutex_unlock_slow (mutex);
}
static inline void gomp_mutex_destroy (gomp_mutex_t *mutex)
{
}
#endif /* GOMP_MUTEX_H */

View File

@ -3,8 +3,8 @@
structures without polluting the namespace.
When using the Linux futex primitive, non-recursive locks require
only one int. Recursive locks require we identify the owning task
and so require one int and a pointer. */
one int. Recursive locks require we identify the owning task
and so require in addition one int and a pointer. */
typedef int omp_lock_t;
typedef struct { int lock, count; void *owner; } omp_nest_lock_t;

View File

@ -1,2 +0,0 @@
/* On PowerPC __sync_lock_test_and_set isn't a full barrier. */
#include "config/linux/ia64/mutex.h"

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2005, 2009 Free Software Foundation, Inc.
/* Copyright (C) 2005, 2009, 2011 Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@redhat.com>.
This file is part of the GNU OpenMP Library (libgomp).
@ -33,6 +33,8 @@ static gomp_mutex_t default_lock;
void
GOMP_critical_start (void)
{
/* There is an implicit flush on entry to a critical region. */
__atomic_thread_fence (MEMMODEL_RELEASE);
gomp_mutex_lock (&default_lock);
}

View File

@ -207,8 +207,13 @@ gomp_ordered_sync (void)
post to our release semaphore. So the two cases are that we will
either win the race an momentarily block on the semaphore, or lose
the race and find the semaphore already unlocked and so not block.
Either way we get correct results. */
Either way we get correct results.
However, there is an implicit flush on entry to an ordered region,
so we do need to have a barrier here. If we were taking a lock
this could be MEMMODEL_RELEASE since the acquire would be coverd
by the lock. */
__atomic_thread_fence (MEMMODEL_ACQ_REL);
if (ws->ordered_owner != thr->ts.team_id)
{
gomp_sem_wait (team->ordered_release[thr->ts.team_id]);