This is the mail archive of the
gcc-prs@gcc.gnu.org
mailing list for the GCC project.
libstdc++/3584: arm-specific atomic operations not atomic
- To: gcc-gnats at gcc dot gnu dot org
- Subject: libstdc++/3584: arm-specific atomic operations not atomic
- From: robin dot farine at terminus dot org
- Date: 6 Jul 2001 09:46:36 -0000
- Cc: acnrf at dial dot eunet dot ch
- Reply-To: robin dot farine at terminus dot org
>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)
....