This is the mail archive of the gcc-prs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

libstdc++/3584: arm-specific atomic operations not atomic



>Number:         3584
>Category:       libstdc++
>Synopsis:       arm-specific atomic operations not atomic
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    unassigned
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Jul 06 02:56:00 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator:     Robin Farine
>Release:        gcc version 3.0
>Organization:
>Environment:
build/host: Debian GNU/Linux
target: arm-unknown-elf
>Description:
Routines such as atomic_add() that reads a memory location,
apply an operation to the read value, uses the swp
instruction to update the memory location and swp again if
the value read the 2nd time does equal the initial value
introduce a race condition. The attachment illustrates such
a case.
>How-To-Repeat:

>Fix:
For single CPU systems, disable thread scheduling during the
operation.
>Release-Note:
>Audit-Trail:
>Unformatted:
----gnatsweb-attachment----
Content-Type: text/plain; name="arm-atomic-add.txt"
Content-Disposition: inline; filename="arm-atomic-add.txt"

The atomic_add() for ARM (with instructions numbering):

static inline void
__attribute__ ((__unused__))
__atomic_add (volatile _Atomic_word *__mem, int __val)
{
  _Atomic_word __tmp, __tmp2, __tmp3;
  __asm__ __volatile__ (
        "\n"
        "0:\t"
1       "ldr     %0, [%3] \n\t"
2       "add     %1, %0, %4 \n\t"
3       "swp     %2, %1, [%3] \n\t"
4       "cmp     %0, %2 \n\t"
5       "swpne   %1, %2, [%3] \n\t"
6       "bne     0b \n\t"
7       ""
        : "=&r"(__tmp), "=&r"(__tmp2), "=&r"(__tmp3) 
        : "r" (__mem), "r"(__val) 
        : "cc", "memory");
}


Example of sequence that produces an invalid result (*__mem == 2 instead of 4 at
the end):

T1 (%0 %1 %2)   T2 (%0 %1 %2)   *__mem

1 (x x x) __val=1               0
2 (0 x x)
3 (0 1 x) <-- reschedule
                1 (x x x) __val=1
                2 (0 x x)
                3 (0 1 x)
                4 (0 1 0)       1
                5 (0 1 0)
                6 (0 1 0)
                7 (0 1 0)
                ...      <-- reschedule
4 (0 1 1)                       1
5 (0 1 1) <-- reschedule
                1 (x x x) __val=2
                2 (1 x x)
                3 (1 3 x)
                4 (1 3 1)       3
                5 (1 3 1)
                6 (1 3 1)
                7 (1 3 1)
                ....      <-- reschedule
6 (0 3 1)                       1
1 (0 3 1)
2 (1 3 1)
3 (1 2 1)
4 (1 2 1)                       2
5 (1 2 1)
6 (1 2 1)
7 (1 2 1)
....


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]