From mboxrd@z Thu Jan 1 00:00:00 1970 From: robin.farine@terminus.org To: gcc-gnats@gcc.gnu.org Cc: acnrf@dial.eunet.ch Subject: libstdc++/3584: arm-specific atomic operations not atomic Date: Fri, 06 Jul 2001 02:56:00 -0000 Message-id: <20010706094636.12604.qmail@sourceware.cygnus.com> X-SW-Source: 2001-07/msg00144.html List-Id: >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) ....