Implement atomic_testandset_{32,int,long,64} for ARMv6. Only
little-endian configuration for 64-bit variant is supported. Reviewed by: mmel Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D4113
This commit is contained in:
parent
4e3a5b4299
commit
60024cd7aa
@ -593,6 +593,54 @@ atomic_store_rel_long(volatile u_long *p, u_long v)
|
|||||||
*p = v;
|
*p = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static __inline int
|
||||||
|
atomic_testandset_32(volatile uint32_t *p, u_int v)
|
||||||
|
{
|
||||||
|
uint32_t tmp, tmp2, res, mask;
|
||||||
|
|
||||||
|
mask = 1u << (v & 0x1f);
|
||||||
|
tmp = tmp2 = 0;
|
||||||
|
__asm __volatile(
|
||||||
|
"1: ldrex %0, [%4] \n"
|
||||||
|
" orr %1, %0, %3 \n"
|
||||||
|
" strex %2, %1, [%4] \n"
|
||||||
|
" cmp %2, #0 \n"
|
||||||
|
" it ne \n"
|
||||||
|
" bne 1b \n"
|
||||||
|
: "=&r" (res), "=&r" (tmp), "=&r" (tmp2)
|
||||||
|
: "r" (mask), "r" (p)
|
||||||
|
: "cc", "memory");
|
||||||
|
return ((res & mask) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline int
|
||||||
|
atomic_testandset_int(volatile u_int *p, u_int v)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (atomic_testandset_32((volatile uint32_t *)p, v));
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline int
|
||||||
|
atomic_testandset_long(volatile u_long *p, u_int v)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (atomic_testandset_32((volatile uint32_t *)p, v));
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline int
|
||||||
|
atomic_testandset_64(volatile uint64_t *p, u_int v)
|
||||||
|
{
|
||||||
|
volatile uint32_t *p32;
|
||||||
|
|
||||||
|
p32 = (volatile uint32_t *)p;
|
||||||
|
/* Assume little-endian */
|
||||||
|
if (v >= 32) {
|
||||||
|
v &= 0x1f;
|
||||||
|
p32++;
|
||||||
|
}
|
||||||
|
return (atomic_testandset_32(p32, v));
|
||||||
|
}
|
||||||
|
|
||||||
#undef ATOMIC_ACQ_REL
|
#undef ATOMIC_ACQ_REL
|
||||||
#undef ATOMIC_ACQ_REL_LONG
|
#undef ATOMIC_ACQ_REL_LONG
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user