ARM atomic question
Mark Tinguely
tinguely at casselton.net
Tue Mar 24 14:05:54 PDT 2009
I am rewriting the existing ARM atomic instruction for the new ldrex/strex
in the ARMv6 architecture.
I have 3 questions for atomic_fetchadd_32():
#ifdef KERNEL
static __inline uint32_t
atomic_fetchadd_32(volatile uint32_t *p, uint32_t v)
{
uint32_t value;
__with_interrupts_disabled(
{
value = *p;
*p += v;
});
return (value);
}
#else /* !_KERNEL */
static __inline uint32_t
atomic_fetchadd_32(volatile uint32_t *p, uint32_t v)
{
uint32_t start, ras_start = ARM_RAS_START;
__asm __volatile("1:\n"
"adr %1, 1b\n"
"str %1, [%0]\n"
"adr %1, 2f\n"
"str %1, [%0, #4]\n"
"ldr %1, [%2]\n"
1) how does this make it atomic? no one reads ras_start or ras_end
to verify that it has not changed since I set it. This applies
to all non-kernel atomic commands.
"add %1, %1, %3\n"
^^
2) start is now (*p + v) not *p. It will return the wrong value
compared to the kernel version.
"str %0, [%2]\n"
^^
3) *p is assigned the ras_start address.
"2:\n"
"mov %3, #0\n"
"str %3, [%0]\n"
"mov %3, #0xffffffff\n"
"str %3, [%0, #4]\n"
: "+r" (ras_start), "=r" (start), "+r" (p), "+r" (v)
: : "memory");
return (start);
#endif
4) Is there a list of atomic commands that should be implemented?
--Mark Tinguely
More information about the freebsd-arm
mailing list