ARM atomic question
M. Warner Losh
imp at bsdimp.com
Tue Mar 24 14:50:04 PDT 2009
In message: <200903242105.n2OL5phe074750 at casselton.net>
Mark Tinguely <tinguely at casselton.net> writes:
:
: 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.
The kernel looks at these addresses when it does a context switch.
Since there are no atomic ops, and you can't disable interrupts in
userland, we settle for the next worse thing: set critical sections
that are restarted if the kernel interrupts them.
: "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.
That I'm not sure of...
: "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?
Someone else will have to answer this.
Warner
More information about the freebsd-arm
mailing list