1
1

* Initial try at making OMPI atomic operations work properly on Solaris

- SPARC32 has spinlocks and "pseudo atomic" math
  - SPARC64 has spinlocks, compare & set, atomic math (still in s/w)

This commit was SVN r4433.
Этот коммит содержится в:
Brian Barrett 2005-02-14 22:07:08 +00:00
родитель 7a7c598391
Коммит a2caf839c0
12 изменённых файлов: 289 добавлений и 55 удалений

Просмотреть файл

@ -290,20 +290,30 @@ AC_DEFUN([OMPI_CHECK_ASM_TYPE],[
AC_MSG_CHECKING([prefix for function in .type])
ompi_cv_asm_type=""
for type in @ \# % ; do
asm_result=0
echo "configure: trying $type" >& AC_FD_CC
OMPI_TRY_ASSEMBLE([ .type mysym, ${type}function],
[# ok, we succeeded at assembling. see if there was
# a warning in the output.
if test "`cat conftest.out`" = "" ; then
ompi_cv_asm_type="${type}"
asm_result=1
fi])
if test "$asm_result" = "1" ; then
break
fi
done
case "${host}" in
*-sun-solaris*)
# GCC on solaris seems to accept just about anything, not
# that what it defines actually works... So just hardwire
# to the right answer
ompi_cv_asm_type="#"
;;
*)
for type in @ \# % ; do
asm_result=0
echo "configure: trying $type" >& AC_FD_CC
OMPI_TRY_ASSEMBLE([ .type mysym, ${type}function],
[# ok, we succeeded at assembling. see if there was
# a warning in the output.
if test "`cat conftest.out`" = "" ; then
ompi_cv_asm_type="${type}"
asm_result=1
fi])
if test "$asm_result" = "1" ; then
break
fi
done
;;
esac
rm -f conftest.out
AC_MSG_RESULT([$ompi_cv_asm_type])
@ -618,7 +628,7 @@ case "${host}" in
ompi_cv_asm_arch="POWERPC32"
# Note that on some platforms (Apple G5), even if we are
# compiling in 32 bit more (and therefore should assume
# compiling in 32 bit mode (and therefore should assume
# sizeof(long) == 4), we can use the 64 bit test and set
# operations.
OMPI_CHECK_POWERPC_64BIT(OMPI_ASM_SUPPORT_64BIT=1)
@ -633,14 +643,15 @@ case "${host}" in
sparc-*)
if test "$ac_cv_sizeof_long" = "4" ; then
OMPI_ASM_SUPPORT_64BIT=0
ompi_cv_asm_arch="SPARC32"
elif test "$ac_cv_sizeof_long" = "8" ; then
OMPI_ASM_SUPPORT_64BIT=1
ompi_cv_asm_arch="SPARC64"
else
AC_MSG_ERROR([Could not determine Sparc word size: $ac_cv_sizeof_long])
fi
OMPI_ASM_SUPPORT_64BIT=1
OMPI_GCC_INLINE_ASSIGN='"mov 0,%0" : : "=&r"(ret)'
OMPI_GCC_INLINE_ASSIGN='"mov 0,%0" : "=&r"(ret)'
;;
*)
@ -716,12 +727,13 @@ dnl do all the evil mojo to provide a working assembly file
dnl
dnl #################################################################
AC_DEFUN([OMPI_ASM_FIND_FILE], [
AC_REQUIRE([AC_PROG_FGREP])
AC_CHECK_PROG([PERL], [perl], [perl])
# see if we have a pre-built one already
AC_MSG_CHECKING([for pre-built assembly file])
ompi_cv_asm_file=""
if grep "$ompi_cv_asm_arch" "${top_ompi_srcdir}/src/asm/asm-data.txt" | grep -F "$ompi_cv_asm_format" >conftest.out 2>&1 ; then
if grep "$ompi_cv_asm_arch" "${top_ompi_srcdir}/src/asm/asm-data.txt" | $FGREP "$ompi_cv_asm_format" >conftest.out 2>&1 ; then
ompi_cv_asm_file="`cut -f3 conftest.out`"
if test ! "$ompi_cv_asm_file" = "" ; then
ompi_cv_asm_file="atomic-${ompi_cv_asm_file}.s"

Просмотреть файл

@ -22,11 +22,13 @@
# Assembly Format field:
# config_file-text-global-label_suffix-gsym-lsym-type-size-align_log-ppc_r_reg-64_bit
AMD64 default-.text-.globl-:--.L-@-1-0-1-0 amd64-linux
IA32 default-.text-.globl-:--.L-@-1-0-1-0 ia32-linux
AMD64 default-.text-.globl-:--.L-@-1-0-1-1 amd64-linux
IA32 default-.text-.globl-:--.L-@-1-0-1-1 ia32-linux
POWERPC32 default-.text-.globl-:-_-L--0-1-1-0 powerpc32-osx
POWERPC32 default-.text-.globl-:-_-L--0-1-1-1 powerpc32-64-osx
POWERPC32 default-.text-.globl-:--.L-@-1-1-0-0 powerpc32-linux
POWERPC32 aix-.csect .text[PR]-.globl-:-.-L--0-1-0-0 powerpc32-aix
POWERPC64 default-.text-.globl-:-_-L--0-1-1-1 powerpc64-osx
POWERPC64 aix-.csect .text[PR]-.globl-:-.-L--0-1-0-1 powerpc64-aix
SPARC32 default-.text-.globl-:--.L-#-1-0-1-0 sparc32-solaris
SPARC64 default-.text-.globl-:--.L-#-1-0-1-1 sparc64-solaris

Просмотреть файл

@ -28,14 +28,14 @@
/* have to fix if you change LOCKS_TABLE_SIZE */
static ompi_lock_t locks_table[LOCKS_TABLE_SIZE] = {
OMPI_ATOMIC_UNLOCKED,
OMPI_ATOMIC_UNLOCKED,
OMPI_ATOMIC_UNLOCKED,
OMPI_ATOMIC_UNLOCKED,
OMPI_ATOMIC_UNLOCKED,
OMPI_ATOMIC_UNLOCKED,
OMPI_ATOMIC_UNLOCKED,
OMPI_ATOMIC_UNLOCKED
{ { OMPI_ATOMIC_UNLOCKED } },
{ { OMPI_ATOMIC_UNLOCKED } },
{ { OMPI_ATOMIC_UNLOCKED } },
{ { OMPI_ATOMIC_UNLOCKED } },
{ { OMPI_ATOMIC_UNLOCKED } },
{ { OMPI_ATOMIC_UNLOCKED } },
{ { OMPI_ATOMIC_UNLOCKED } },
{ { OMPI_ATOMIC_UNLOCKED } }
};
# else /* OMPI_WANT_SMP_LOCKS */
@ -49,7 +49,7 @@ static ompi_lock_t locks_table[1] = { OMPI_ATOMIC_UNLOCKED };
int32_t
ompi_atomic_sub_32(volatile int32_t *addr, int delta)
ompi_atomic_add_32(volatile int32_t *addr, int delta)
{
int32_t ret;

80
src/asm/base/SPARC32.asm Обычный файл
Просмотреть файл

@ -0,0 +1,80 @@
START_FILE
TEXT
ALIGN(4)
START_FUNC(ompi_atomic_mb)
!#PROLOGUE# 0
!#PROLOGUE# 1
retl
nop
END_FUNC(ompi_atomic_mb)
START_FUNC(ompi_atomic_rmb)
!#PROLOGUE# 0
!#PROLOGUE# 1
retl
nop
END_FUNC(ompi_atomic_rmb)
START_FUNC(ompi_atomic_wmb)
!#PROLOGUE# 0
!#PROLOGUE# 1
retl
nop
END_FUNC(ompi_atomic_wmb)
START_FUNC(ompi_atomic_init)
!#PROLOGUE# 0
!#PROLOGUE# 1
stb %o1, [%o0]
retl
nop
END_FUNC(ompi_atomic_init)
START_FUNC(ompi_atomic_trylock)
!#PROLOGUE# 0
!#PROLOGUE# 1
ldstub [%o0], %o0
and %o0, 0xff, %o0
subcc %g0, %o0, %g0
retl
subx %g0, -1, %o0
END_FUNC(ompi_atomic_trylock)
START_FUNC(ompi_atomic_lock)
!#PROLOGUE# 0
save %sp, -112, %sp
!#PROLOGUE# 1
LSYM(retry)
ldstub [%i0], %l0
tst %l0
be REFLSYM(out)
nop
LSYM(loop)
ldub [%i0], %l0
tst %l0
bne REFLSYM(loop)
nop
ba,a REFLSYM(retry)
LSYM(out)
nop
ret
restore
END_FUNC(ompi_atomic_lock)
START_FUNC(ompi_atomic_unlock)
!#PROLOGUE# 0
!#PROLOGUE# 1
stbar
stb %g0, [%o0]
retl
nop
END_FUNC(ompi_atomic_unlock)

116
src/asm/base/SPARC64.asm Обычный файл
Просмотреть файл

@ -0,0 +1,116 @@
START_FILE
TEXT
ALIGN(4)
START_FUNC(ompi_atomic_mb)
!#PROLOGUE# 0
!#PROLOGUE# 1
membar #LoadLoad | #LoadStore | #StoreStore | #StoreLoad
retl
nop
END_FUNC(ompi_atomic_mb)
START_FUNC(ompi_atomic_rmb)
!#PROLOGUE# 0
!#PROLOGUE# 1
membar #LoadLoad
retl
nop
END_FUNC(ompi_atomic_rmb)
START_FUNC(ompi_atomic_wmb)
!#PROLOGUE# 0
!#PROLOGUE# 1
membar #StoreStore
retl
nop
END_FUNC(ompi_atomic_wmb)
START_FUNC(ompi_atomic_cmpset_32)
!#PROLOGUE# 0
!#PROLOGUE# 1
mov %o1, %g1
casa [%o0] 0x80, %o2, %g1
xor %g1, %o1, %g1
subcc %g0, %g1, %g0
retl
subx %g0, -1, %o0
END_FUNC(ompi_atomic_cmpset_32)
START_FUNC(ompi_atomic_cmpset_acq_32)
!#PROLOGUE# 0
save %sp, -192, %sp
!#PROLOGUE# 1
mov %i0, %o0
mov %i1, %o1
call ompi_atomic_cmpset_32, 0
mov %i2, %o2
call ompi_atomic_rmb, 0
mov %o0, %i0
return %i7+8
sra %o0, 0, %o0
END_FUNC(ompi_atomic_cmpset_acq_32)
START_FUNC(ompi_atomic_cmpset_rel_32)
!#PROLOGUE# 0
save %sp, -192, %sp
!#PROLOGUE# 1
call ompi_atomic_wmb, 0
sra %i1, 0, %i1
sra %i2, 0, %i2
mov %i0, %o0
mov %i1, %o1
call ompi_atomic_cmpset_32, 0
mov %i2, %o2
ret
restore %g0, %o0, %o0
END_FUNC(ompi_atomic_cmpset_rel_32)
START_FUNC(ompi_atomic_cmpset_64)
!#PROLOGUE# 0
!#PROLOGUE# 1
mov %o1, %g1
casxa [%o0] 0x80, %o2, %g1
xor %g1, %o1, %g1
mov 0, %o0
retl
movre %g1, 1, %o0
END_FUNC(ompi_atomic_cmpset_64)
START_FUNC(ompi_atomic_cmpset_acq_64)
!#PROLOGUE# 0
save %sp, -192, %sp
!#PROLOGUE# 1
mov %i0, %o0
mov %i1, %o1
call ompi_atomic_cmpset_64, 0
mov %i2, %o2
call ompi_atomic_rmb, 0
mov %o0, %i0
return %i7+8
sra %o0, 0, %o0
END_FUNC(ompi_atomic_cmpset_acq_64)
START_FUNC(ompi_atomic_cmpset_rel_64)
!#PROLOGUE# 0
save %sp, -192, %sp
!#PROLOGUE# 1
call ompi_atomic_wmb, 0
nop
mov %i0, %o0
mov %i1, %o1
call ompi_atomic_cmpset_64, 0
mov %i2, %o2
ret
restore %g0, %o0, %o0
END_FUNC(ompi_atomic_cmpset_rel_64)

Просмотреть файл

@ -27,6 +27,9 @@ int32_t new32;
int
main(int argc, char *argv[])
{
#if ! OMPI_HAVE_ATOMIC_CMPSET_32
return 77;
#else
vol32 = 42, old32 = 42, new32 = 50;
assert(ompi_atomic_cmpset_32(&vol32, old32, new32) == 1);
@ -53,4 +56,5 @@ main(int argc, char *argv[])
assert(vol32 == 42);
return 0;
#endif
}

Просмотреть файл

@ -33,6 +33,8 @@ struct start_info {
ompi_lock_t *lock;
};
#if OMPI_HAVE_POSIX_THREADS
static void* atomic_spinlock_start(void* arg)
{
struct start_info *data = (struct start_info*) arg;
@ -40,6 +42,7 @@ static void* atomic_spinlock_start(void* arg)
return (void*) (unsigned long) atomic_spinlock_test(data->lock, data->count,
data->tid);
}
#endif
int

Просмотреть файл

@ -62,6 +62,28 @@
#if defined(c_plusplus) || defined(__cplusplus)
extern "C" {
#endif
/**********************************************************************
*
* Data structures for atomic ops
*
*********************************************************************/
/**
* Volatile lock object (with optional padding).
*
* \note The internals of the lock are included here, but should be
* considered private. The implementation currently in use may choose
* to use an int or unsigned char as the lock value - the user is not
* informed either way.
*/
struct ompi_lock_t {
union {
volatile int lock; /**< The lock address (an integer) */
volatile unsigned char sparc_lock; /**< The lock address on sparc */
char padding[sizeof(int)]; /**< Array for optional padding */
} u;
};
typedef struct ompi_lock_t ompi_lock_t;
/**********************************************************************
*
@ -161,22 +183,6 @@ void ompi_atomic_wmb(void);
* Atomic spinlocks - always inlined, if have atomic cmpset
*
*********************************************************************/
/**
* Volatile lock object (with optional padding).
*
* \note The internals of the lock are included here, but should be
* considered private. The implementation currently in use may choose
* to use an int or unsigned char as the lock value - the user is not
* informed either way.
*/
struct ompi_lock_t {
union {
volatile int lock; /**< The lock address (an integer) */
volatile unsigned char sparc_lock; /**< The lock address on sparc */
char padding[sizeof(int)]; /**< Array for optional padding */
} u;
};
typedef struct ompi_lock_t ompi_lock_t;
#if !defined(OMPI_HAVE_ATOMIC_SPINLOCKS) && !defined(DOXYGEN)
/* 0 is more like "pending" - we'll fix up at the end after all

Просмотреть файл

@ -22,13 +22,23 @@
#define MB()
#endif
#ifdef OMPI_GENERATE_ASM_FILE
struct ompi_lock_t {
union {
volatile int lock; /**< The lock address (an integer) */
volatile unsigned char sparc_lock; /**< The lock address on sparc */
char padding[sizeof(int)]; /**< Array for optional padding */
} u;
};
typedef struct ompi_lock_t ompi_lock_t;
#endif
/**********************************************************************
*
* Define constants for UltraSparc 64
*
*********************************************************************/
#define OMPI_HAVE_MEM_BARRIER 1
#define OMPI_HAVE_ATOMIC_MEM_BARRIER 1
#define OMPI_HAVE_ATOMIC_CMPSET_32 0
#define OMPI_HAVE_ATOMIC_CMPSET_64 0
@ -79,7 +89,7 @@ static inline void ompi_atomic_wmb(void)
static inline void ompi_atomic_init(ompi_lock_t* lock, int value)
{
lock->sparc_lock = (unsigned char) value;
lock->u.sparc_lock = (unsigned char) value;
}
@ -94,7 +104,7 @@ static inline int ompi_atomic_trylock(ompi_lock_t *lock)
__asm__ __volatile__ ("\t"
"ldstub [%1], %0"
: "=r"(result)
: "r"(&(lock->sparc_lock))
: "r"(&(lock->u.sparc_lock))
: "memory");
return (result == 0);
}
@ -107,10 +117,10 @@ static inline void ompi_atomic_lock(ompi_lock_t *lock)
"retry: \n\t"
"ldstub [%0], %%l0 \n\t"
"tst %%l0 \n\t"
"bw out \n\t"
"be out \n\t"
"nop \n"
"loop: \n\t"
"ldb [%0], %%l0 \n\t"
"ldub [%0], %%l0 \n\t"
"tst %%l0 \n\t"
"bne loop \n\t"
"nop \n\t"
@ -118,7 +128,7 @@ static inline void ompi_atomic_lock(ompi_lock_t *lock)
"out: \n\t"
"nop"
:
: "r"(&(lock->sparc_lock))
: "r"(&(lock->u.sparc_lock))
: "%l0", "memory");
}
@ -130,7 +140,7 @@ static inline void ompi_atomic_unlock(ompi_lock_t *lock)
"stbar \n\t"
"stb %%g0, [%0] \n\t"
:
: "r"(&(lock->sparc_lock))
: "r"(&(lock->u.sparc_lock))
: "memory");
}

Просмотреть файл

@ -26,7 +26,8 @@ cat > $CFILE<<EOF
#define inline
#define OMPI_GCC_INLINE_ASSEMBLY 1
#define OMPI_WANT_SMP_LOCKS 1
#define OMPI_GENERATE_ASM_FILE
#include "atomic.h"
EOF
gcc -I. -S $CFILE -o atomic.s
gcc -O1 -I. -S $CFILE -o atomic.s

Просмотреть файл

@ -22,7 +22,7 @@
#define ASI_P "0x80"
#if OMPI_WANT_SMP_LOCKS
#define MEMBAR(type) __asm__ __volatile__ ("membar" type : : : "memory")
#define MEMBAR(type) __asm__ __volatile__ ("membar " type : : : "memory")
#else
#define MEMBAR(type)
#endif

Просмотреть файл

@ -29,4 +29,4 @@ cat > $CFILE<<EOF
#include "atomic.h"
EOF
gcc -I. -S $CFILE -o atomic.s
gcc -m64 -O1 -I. -S $CFILE -o atomic.s