Try to implement atomic operations using swp, instead of disabling interrupts.

This commit is contained in:
cognet 2004-11-04 19:14:50 +00:00
parent f124567fde
commit 4603da4464

View File

@ -71,127 +71,116 @@
: "cc" ); \
} while(0)
static __inline uint32_t
__swp(uint32_t val, volatile uint32_t *ptr)
{
__asm __volatile("swp %0, %1, [%2]"
: "=r" (val) : "r" (val) , "r" (ptr) : "memory");
return (val);
}
#define atomic_op(v, op, p) ({ \
uint32_t e, r, s; \
for (e = *(volatile uint32_t *)p;; e = r) { \
s = e op v; \
r = __swp(s, p); \
if (r == e) \
break; \
} \
e; \
})
static __inline void
atomic_set_32(volatile uint32_t *address, uint32_t setmask)
{
__with_interrupts_disabled( *address |= setmask);
atomic_op(setmask, |, address);
}
static __inline void
atomic_set_ptr(volatile void *ptr, uint32_t src)
{
atomic_set_32((volatile uint32_t *)ptr, (uint32_t)src);
}
#define atomic_set_rel_int atomic_set_32
#define atomic_set_int atomic_set_32
#define atomic_readandclear_int atomic_readandclear_32
static __inline void
atomic_clear_32(volatile uint32_t *address, uint32_t clearmask)
{
__with_interrupts_disabled( *address &= ~clearmask);
}
static __inline void
atomic_clear_ptr(volatile void *ptr, uint32_t src)
{
atomic_clear_32((volatile uint32_t *)ptr, (uint32_t)src);
atomic_op(clearmask, &~, address);
}
static __inline int
atomic_load_acq_int(volatile uint32_t *v)
atomic_load_32(volatile uint32_t *v)
{
int bla;
__with_interrupts_disabled(bla = *v);
return (bla);
return (__swp(*v, v));
}
#define atomic_clear_int atomic_clear_32
static __inline void
atomic_store_32(volatile uint32_t *dst, uint32_t src)
{
__with_interrupts_disabled(*dst = src);
__swp(src, dst);
}
static __inline void
atomic_store_ptr(volatile void *dst, void *src)
{
atomic_store_32((volatile uint32_t *)dst, (uint32_t) src);
}
#define atomic_store_rel_ptr atomic_store_ptr
#define atomic_store_rel_int atomic_store_32
static __inline uint32_t
atomic_readandclear_32(volatile u_int32_t *p)
{
uint32_t ret;
__with_interrupts_disabled((ret = *p) != 0 ? *p = 0 : 0);
return (ret);
return (__swp(0, p));
}
static __inline u_int32_t
atomic_cmpset_32(volatile u_int32_t *p, u_int32_t cmpval, u_int32_t newval)
{
int done = 0;
__with_interrupts_disabled(*p = (*p == cmpval ? newval + done++ : *p));
return (done);
uint32_t r, e;
for (e = *p;; e = r) {
if (*p == cmpval) {
r = __swp(newval, p);
if (r == e)
return (1);
} else
return (0);
}
}
static __inline void
atomic_add_32(volatile u_int32_t *p, u_int32_t val)
{
__with_interrupts_disabled(*p += val);
atomic_op(val, +, p);
}
static __inline void
atomic_subtract_32(volatile u_int32_t *p, u_int32_t val)
{
__with_interrupts_disabled(*p -= val);
atomic_op(val, -, p);
}
#define atomic_subtract_int atomic_subtract_32
#define atomic_subtract_rel_int atomic_subtract_32
#define atomic_subtract_acq_int atomic_subtract_32
#define atomic_add_int atomic_add_32
#define atomic_add_rel_int atomic_add_32
#define atomic_add_acq_int atomic_add_32
#define atomic_cmpset_int atomic_cmpset_32
#define atomic_cmpset_rel_int atomic_cmpset_32
#define atomic_cmpset_acq_int atomic_cmpset_32
static __inline u_int32_t
atomic_cmpset_ptr(volatile void *dst, void *exp, void *src)
{
return (atomic_cmpset_32((volatile u_int32_t *)dst, (u_int32_t)exp,
(u_int32_t)src));
}
static __inline u_int32_t
atomic_cmpset_rel_32(volatile u_int32_t *p, u_int32_t cmpval, u_int32_t newval)
{
return (atomic_cmpset_32(p, cmpval, newval));
}
static __inline u_int32_t
atomic_cmpset_rel_ptr(volatile void *dst, void *exp, void *src)
{
return (atomic_cmpset_32((volatile u_int32_t *)dst,
(u_int32_t)exp, (u_int32_t)src));
}
#define atomic_cmpset_acq_ptr atomic_cmpset_ptr
#if !defined(ATOMIC_SET_BIT_NOINLINE)
#define atomic_set_bit(a,m) atomic_set_32(a,m)
#define atomic_clear_bit(a,m) atomic_clear_32(a,m)
#endif
#undef __with_interrupts_disabled
#endif /* _LOCORE */
#define atomic_set_rel_int atomic_set_32
#define atomic_set_int atomic_set_32
#define atomic_readandclear_int atomic_readandclear_32
#define atomic_clear_int atomic_clear_32
#define atomic_subtract_int atomic_subtract_32
#define atomic_subtract_rel_int atomic_subtract_32
#define atomic_subtract_acq_int atomic_subtract_32
#define atomic_add_int atomic_add_32
#define atomic_add_rel_int atomic_add_32
#define atomic_add_acq_int atomic_add_32
#define atomic_cmpset_int atomic_cmpset_32
#define atomic_cmpset_rel_int atomic_cmpset_32
#define atomic_cmpset_rel_ptr atomic_cmpset_ptr
#define atomic_cmpset_acq_int atomic_cmpset_32
#define atomic_cmpset_acq_ptr atomic_cmpset_ptr
#define atomic_store_rel_ptr atomic_store_ptr
#define atomic_store_rel_int atomic_store_32
#define atomic_cmpset_rel_32 atomic_cmpset_32
#define atomic_smpset_rel_ptr atomic_cmpset_ptr
#define atomic_load_acq_int atomic_load_32
#define atomic_clear_ptr(ptr, bit) atomic_clear_32( \
(volatile uint32_t *)ptr, (uint32_t)bit)
#define atomic_store_ptr(ptr, bit) atomic_store_32( \
(volatile uint32_t *)ptr, (uint32_t)bit)
#define atomic_cmpset_ptr(dst, exp, s) atomic_cmpset_32( \
(volatile uint32_t *)dst, (uint32_t)exp, (uint32_t)s)
#define atomic_set_ptr(ptr, src) atomic_set_32( \
(volatile uint32_t *)ptr, (uint32_t)src)
#endif /* _MACHINE_ATOMIC_H_ */