Skip site navigation (1)Skip section navigation (2)
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>