Date: Tue, 24 Mar 2009 16:05:51 -0500 (CDT) From: Mark Tinguely <tinguely@casselton.net> To: freebsd-arm@freebsd.org Subject: ARM atomic question Message-ID: <200903242105.n2OL5phe074750@casselton.net>
next in thread | raw e-mail | index | archive | help
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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200903242105.n2OL5phe074750>