2004-05-05 19:19:47 +00:00
|
|
|
/*
|
|
|
|
* $HEADER$
|
|
|
|
*/
|
|
|
|
|
2004-08-16 01:13:25 +00:00
|
|
|
#ifndef OMPI_SYS_ARCH_ATOMIC_H
|
|
|
|
#define OMPI_SYS_ARCH_ATOMIC_H 1
|
2004-05-05 19:19:47 +00:00
|
|
|
|
2004-05-05 23:19:32 +00:00
|
|
|
/*
|
|
|
|
* On ia32, we use cmpxchg.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_SMP
|
2004-06-24 21:09:55 +00:00
|
|
|
#define SMPLOCK "lock; "
|
2004-05-05 23:19:32 +00:00
|
|
|
#define MB() __asm__ __volatile__("": : :"memory")
|
2004-05-05 19:19:47 +00:00
|
|
|
#else
|
2004-06-24 21:09:55 +00:00
|
|
|
#define SMPLOCK
|
2004-05-05 23:19:32 +00:00
|
|
|
#define MB()
|
2004-05-05 19:19:47 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2004-06-16 17:10:18 +00:00
|
|
|
static inline void ompi_atomic_mb(void)
|
2004-05-05 23:19:32 +00:00
|
|
|
{
|
|
|
|
MB();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-06-16 17:10:18 +00:00
|
|
|
static inline void ompi_atomic_rmb(void)
|
2004-05-05 23:19:32 +00:00
|
|
|
{
|
|
|
|
MB();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-06-16 17:10:18 +00:00
|
|
|
static inline void ompi_atomic_wmb(void)
|
2004-05-05 19:19:47 +00:00
|
|
|
{
|
2004-05-05 23:19:32 +00:00
|
|
|
MB();
|
|
|
|
}
|
|
|
|
|
2004-05-05 19:19:47 +00:00
|
|
|
|
2004-06-07 15:33:53 +00:00
|
|
|
static inline int ompi_atomic_cmpset_32(volatile uint32_t *addr,
|
2004-06-16 17:41:34 +00:00
|
|
|
uint32_t oldval,
|
|
|
|
uint32_t newval)
|
2004-05-05 23:19:32 +00:00
|
|
|
{
|
2004-08-23 16:03:46 +00:00
|
|
|
#if 1
|
|
|
|
uint32_t ret = *addr;
|
|
|
|
if(ret == oldval) {
|
|
|
|
*addr = newval;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
#else
|
2004-06-16 17:41:34 +00:00
|
|
|
uint32_t ret = oldval;
|
2004-05-05 23:19:32 +00:00
|
|
|
__asm__ __volatile (
|
2004-06-24 21:09:55 +00:00
|
|
|
SMPLOCK "cmpxchgl %1,%2 \n\
|
2004-05-05 23:19:32 +00:00
|
|
|
setz %%al \n\
|
|
|
|
movzbl %%al,%0 \n"
|
|
|
|
: "+a" (ret)
|
2004-08-28 01:15:19 +00:00
|
|
|
: "a" (oldval) "r" (newval), "m" (*addr)
|
2004-05-05 23:19:32 +00:00
|
|
|
: "memory");
|
|
|
|
|
2004-06-16 17:41:34 +00:00
|
|
|
return (ret == oldval);
|
2004-08-23 16:03:46 +00:00
|
|
|
#endif
|
2004-05-05 23:19:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-06-07 15:33:53 +00:00
|
|
|
static inline int ompi_atomic_cmpset_acq_32(volatile uint32_t *addr,
|
2004-06-16 17:41:34 +00:00
|
|
|
uint32_t oldval,
|
|
|
|
uint32_t newval)
|
2004-05-05 23:19:32 +00:00
|
|
|
{
|
2004-06-16 17:41:34 +00:00
|
|
|
return ompi_atomic_cmpset_32(addr, oldval, newval);
|
2004-05-05 19:19:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-06-07 15:33:53 +00:00
|
|
|
static inline int ompi_atomic_cmpset_rel_32(volatile uint32_t *addr,
|
2004-06-16 17:41:34 +00:00
|
|
|
uint32_t oldval,
|
|
|
|
uint32_t newval)
|
2004-05-05 19:19:47 +00:00
|
|
|
{
|
2004-06-16 17:41:34 +00:00
|
|
|
return ompi_atomic_cmpset_32(addr, oldval, newval);
|
2004-05-05 19:19:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-06-07 15:33:53 +00:00
|
|
|
static inline int ompi_atomic_cmpset_64(volatile uint64_t *addr,
|
2004-06-16 17:41:34 +00:00
|
|
|
uint64_t oldval,
|
|
|
|
uint64_t newval)
|
2004-05-05 19:19:47 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Compare EDX:EAX with m64. If equal, set ZF and load ECX:EBX into
|
|
|
|
* m64. Else, clear ZF and load m64 into EDX:EAX.
|
|
|
|
*/
|
|
|
|
|
2004-06-16 17:41:34 +00:00
|
|
|
uint64_t ret = oldval;
|
2004-06-16 17:10:18 +00:00
|
|
|
#if 0
|
2004-06-16 17:41:34 +00:00
|
|
|
struct { uint32_t lo; uint32_t hi; } *p = (struct lwords *) &newval;
|
2004-05-05 19:19:47 +00:00
|
|
|
|
2004-05-05 23:19:32 +00:00
|
|
|
__asm__ __volatile(
|
2004-06-24 21:09:55 +00:00
|
|
|
SMPLOCK "cmpxchg8b %1\n"
|
2004-05-05 23:19:32 +00:00
|
|
|
: "+A" (ret)
|
|
|
|
: "m" (*addr), "b" (p->lo), "c" (p->hi)
|
|
|
|
: "memory");
|
2004-06-16 17:10:18 +00:00
|
|
|
#endif
|
2004-06-16 17:41:34 +00:00
|
|
|
return (ret == oldval);
|
2004-05-05 23:19:32 +00:00
|
|
|
}
|
2004-05-05 19:19:47 +00:00
|
|
|
|
2004-05-05 23:19:32 +00:00
|
|
|
|
2004-06-07 15:33:53 +00:00
|
|
|
static inline int ompi_atomic_cmpset_acq_64(volatile uint64_t *addr,
|
2004-06-16 17:41:34 +00:00
|
|
|
uint64_t oldval,
|
|
|
|
uint64_t newval)
|
2004-05-05 23:19:32 +00:00
|
|
|
{
|
2004-06-16 17:41:34 +00:00
|
|
|
return ompi_atomic_cmpset_64(addr, oldval, newval);
|
2004-05-05 19:19:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-06-07 15:33:53 +00:00
|
|
|
static inline int ompi_atomic_cmpset_rel_64(volatile uint64_t *addr,
|
2004-06-16 17:41:34 +00:00
|
|
|
uint64_t oldval,
|
|
|
|
uint64_t newval)
|
2004-05-05 19:19:47 +00:00
|
|
|
{
|
2004-06-16 17:41:34 +00:00
|
|
|
return ompi_atomic_cmpset_64(addr, oldval, newval);
|
2004-05-05 19:19:47 +00:00
|
|
|
}
|
|
|
|
|
2004-08-16 01:13:25 +00:00
|
|
|
#endif /* ! OMPI_SYS_ARCH_ATOMIC_H */
|