sh: Add a simple cmpxchg().

We didn't have one of these before, a simple implementation
borrowed from MIPS as well as the __HAVE_ARCH_CMPXCHG bits.

Signed-off-by: Tom Rini <trini@kernel.crashing.org>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
This commit is contained in:
Tom Rini 2006-09-27 11:28:20 +09:00 committed by Paul Mundt
parent 0c91c1a701
commit e4e3b5ccd7

View File

@ -6,6 +6,7 @@
* Copyright (C) 2002 Paul Mundt * Copyright (C) 2002 Paul Mundt
*/ */
#include <asm/types.h>
/* /*
* switch_to() should switch tasks to task nr n, first * switch_to() should switch tasks to task nr n, first
@ -260,6 +261,45 @@ static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr, int
return x; return x;
} }
static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old,
unsigned long new)
{
__u32 retval;
unsigned long flags;
local_irq_save(flags);
retval = *m;
if (retval == old)
*m = new;
local_irq_restore(flags); /* implies memory barrier */
return retval;
}
/* This function doesn't exist, so you'll get a linker error
* if something tries to do an invalid cmpxchg(). */
extern void __cmpxchg_called_with_bad_pointer(void);
#define __HAVE_ARCH_CMPXCHG 1
static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
unsigned long new, int size)
{
switch (size) {
case 4:
return __cmpxchg_u32(ptr, old, new);
}
__cmpxchg_called_with_bad_pointer();
return old;
}
#define cmpxchg(ptr,o,n) \
({ \
__typeof__(*(ptr)) _o_ = (o); \
__typeof__(*(ptr)) _n_ = (n); \
(__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \
(unsigned long)_n_, sizeof(*(ptr))); \
})
/* XXX /* XXX
* disable hlt during certain critical i/o operations * disable hlt during certain critical i/o operations
*/ */