fix InterlockedCompareExchange on ARM-Linux: kuser_cmpxchg destroys r3, which needs to be restored, if we have to loop

git-svn-id: trunk@32063 -
This commit is contained in:
Károly Balogh 2015-10-16 18:53:35 +00:00
parent 7e6ba9db2a
commit c81290bc94

View File

@ -970,8 +970,6 @@ asm
{$else}
{$ifdef SYSTEM_HAS_KUSER_CMPXCHG}
stmfd r13!, {r4, lr}
mvn r3, #0x0000f000
sub r3, r3, #0x3F
mov r4, r2 // Swap parameters around
mov r2, r0
@ -979,9 +977,13 @@ asm
// r1 and r2 will not be clobbered by kuser_cmpxchg
// If we have to loop, r0 will be set to the original Comperand
// kuser_cmpxchg is documented to destroy r3, therefore setting
// r3 must be in the loop
.Linterlocked_compare_exchange_loop:
mvn r3, #0x0000f000
sub r3, r3, #0x3F
{$ifdef CPUARM_HAS_BLX}
blx r3 // Call kuser_cmpxchg, sets C-Flag on success
blx r3 // Call kuser_cmpxchg, sets C-Flag on success
{$else}
mov lr, pc
{$ifdef CPUARM_HAS_BX}
@ -997,11 +999,11 @@ asm
// The loop case is HIGHLY unlikely, it would require that we got rescheduled between
// calling kuser_cmpxchg and the ldr. While beeing rescheduled another process/thread
// would have the set the value to our comperand
ldr r0, [r2] // Load the currently set value
ldr r0, [r2] // Load the currently set value
cmp r0, r4 // Return if Comperand != current value, otherwise loop again
ldmnefd r13!, {r4, pc}
// If we need to loop here, we have to
b .Linterlocked_compare_exchange_loop
b .Linterlocked_compare_exchange_loop
{$else}
// lock