spinlocks from QEMU

This commit is contained in:
gbeauche 2003-09-29 08:27:56 +00:00
parent f9dd276a47
commit 2d92ad6dfb

View File

@ -177,6 +177,129 @@ static inline uint32 tswap32(uint32 x) { return bswap_32(x); }
static inline uint64 tswap64(uint64 x) { return bswap_64(x); }
#endif
// spin locks
#ifdef __GNUC__
#ifdef __powerpc__
#define HAVE_TEST_AND_SET 1
static inline int testandset(int *p)
{
int ret;
__asm__ __volatile__("0: lwarx %0,0,%1 ;"
" xor. %0,%3,%0;"
" bne 1f;"
" stwcx. %2,0,%1;"
" bne- 0b;"
"1: "
: "=&r" (ret)
: "r" (p), "r" (1), "r" (0)
: "cr0", "memory");
return ret;
}
#endif
#ifdef __i386__
#define HAVE_TEST_AND_SET 1
static inline int testandset(int *p)
{
char ret;
long int readval;
__asm__ __volatile__("lock; cmpxchgl %3, %1; sete %0"
: "=q" (ret), "=m" (*p), "=a" (readval)
: "r" (1), "m" (*p), "a" (0)
: "memory");
return ret;
}
#endif
#ifdef __s390__
#define HAVE_TEST_AND_SET 1
static inline int testandset(int *p)
{
int ret;
__asm__ __volatile__("0: cs %0,%1,0(%2)\n"
" jl 0b"
: "=&d" (ret)
: "r" (1), "a" (p), "0" (*p)
: "cc", "memory" );
return ret;
}
#endif
#ifdef __alpha__
#define HAVE_TEST_AND_SET 1
static inline int testandset(int *p)
{
int ret;
unsigned long one;
__asm__ __volatile__("0: mov 1,%2\n"
" ldl_l %0,%1\n"
" stl_c %2,%1\n"
" beq %2,1f\n"
".subsection 2\n"
"1: br 0b\n"
".previous"
: "=r" (ret), "=m" (*p), "=r" (one)
: "m" (*p));
return ret;
}
#endif
#ifdef __sparc__
#define HAVE_TEST_AND_SET 1
static inline int testandset(int *p)
{
int ret;
__asm__ __volatile__("ldstub [%1], %0"
: "=r" (ret)
: "r" (p)
: "memory");
return (ret ? 1 : 0);
}
#endif
#ifdef __arm__
#define HAVE_TEST_AND_SET 1
static inline int testandset(int *p)
{
register unsigned int ret;
__asm__ __volatile__("swp %0, %1, [%2]"
: "=r"(ret)
: "0"(1), "r"(p));
return ret;
}
#endif
#endif /* __GNUC__ */
#if HAVE_TEST_AND_SET
#define HAVE_SPINLOCKS 1
typedef int spinlock_t;
const spinlock_t SPIN_LOCK_UNLOCKED = 0;
static inline void spin_lock(spinlock_t *lock)
{
while (testandset(lock));
}
static inline void spin_unlock(spinlock_t *lock)
{
*lock = 0;
}
static inline int spin_trylock(spinlock_t *lock)
{
return !testandset(lock);
}
#endif
// Time data type for Time Manager emulation
#ifdef HAVE_CLOCK_GETTIME
typedef struct timespec tm_time_t;