From mboxrd@z Thu Jan 1 00:00:00 1970 From: Robin Farine To: nobody@gcc.gnu.org Cc: gcc-prs@gcc.gnu.org Subject: Re: libstdc++/3584: arm-specific atomic operations not atomic Date: Thu, 12 Jul 2001 07:16:00 -0000 Message-id: <20010712141602.27253.qmail@sourceware.cygnus.com> X-SW-Source: 2001-07/msg00335.html List-Id: The following reply was made to PR libstdc++/3584; it has been noted by GNATS. From: Robin Farine To: Richard.Earnshaw@arm.com Cc: robin.farine@terminus.org, gcc-gnats@gcc.gnu.org Subject: Re: libstdc++/3584: arm-specific atomic operations not atomic Date: 12 Jul 2001 16:08:17 +0200 Robin Farine writes: [...] > > @ r0 = address (struct {int lock, int value}), r1 = increment. > ... @ prolog > mov r2, 1 > 0: > swp r3, r2, [r0] > teq r3, #0 > beq 1f @ got the lock > mov lr, pc > ldr pc, .thread_yield > b 0b > .thread_yield: .word thread_yield > > 1: > @ We now have the lock > ldr r2, [r0, #4] > add r2, r2, r1 > str r2, [r0, #4] > str r3, [r0] @ Release the lock. Besides the fact that the label "0:" should *precede* the "mov r2, 1" instruction, this version too would allow starvation of a low-priority thread. I suppose that a multi-threads and multi-processors safe implementation of atomic_add() would look more like this: void atomic_add(volatile _Atomic_word *__mem, int __val) { int __lock; int __tmp = 1; thread_suspend_scheduler(); __asm__ __volatile__ ( "\n" /* spin while another CPU holds the lock */ "0:\t" "swp %0, %1, [%2] \n\t" "teq %0, #0 \n\t" "bne 0b \n\t" /* we now have the lock */ "ldr %1, [%2, #4] \n\t" "add %1, %1, %3 \n\t" "str %1, [%2, #4] \n\t" /* release the lock */ "str %0, [%2] \n\t" "" : "=&r"(__lock), "=&r"(__tmp) : "r" (__mem), "r"(__val) : "cc", "memory"); thread_resume_scheduler(); } This routine relies on the structured version of _Atomic_word and on nestable primitives to suspend/resume threads scheduling, which the POSIX threads API doesn't provide, if I remember correctly ...