This is the mail archive of the
gcc-prs@gcc.gnu.org
mailing list for the GCC project.
Re: libstdc++/3584: arm-specific atomic operations not atomic
- To: nobody at gcc dot gnu dot org
- Subject: Re: libstdc++/3584: arm-specific atomic operations not atomic
- From: Robin Farine <acnrf at dial dot eunet dot ch>
- Date: 12 Jul 2001 14:16:02 -0000
- Cc: gcc-prs at gcc dot gnu dot org,
- Reply-To: Robin Farine <acnrf at dial dot eunet dot ch>
The following reply was made to PR libstdc++/3584; it has been noted by GNATS.
From: Robin Farine <acnrf@dial.eunet.ch>
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 <rfarine@halftrack.hq.acn-group.ch> 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 ...