Dear NXP Support,
for our PPC OS we want to use reservation instructions (lwarx, stwcx) to implement the spinlock mechanism to achieve mutual exclusion between different cores. We want to solve it in software because of compatibility issues (not all controllers have a semaphore unit) and to evade the restriction of a limited number of configurable spinlocks.
Our solution looks as follows (Greenhills assembler macro on MPC5775K):
__asm uint32 AtomicSpinlockWrite(uint32 Addr, uint32 Value)
%reg Addr %con Value %lab NoSuccess, Success
se_li r5, Value /* load value in r5 */
lwarx r3,0,Addr /* load and reserve */
e_cmpwi r3,0 /* if not eq 0 */
se_bne NoSuccess /* spinlock locked, return 0*/
stwcx. r5,0,Addr /* try to store non-0 */
se_bne NoSuccess /* if lost reservation return 0 */
se_li r3, 1 /* else load return-value 1 */
e_b Success /* and goto Success */
se_li r3, 0 /* return 0 */
We expect, that if Core0 executes lwarx and reads the value 0, it will proceed with writing the value 1 to the memory address. This write should work, if the value at address "Addr" has not been changed (e.g. by writing of another core) and it should fail otherwise. But currently this mechanism does not work. We checked it with the Lauterbach Debugger.
- Core0 executes lwarx --> reads value 0 in r3 and after comparison we stopped before execution of stwcx
- Core1 executed lwarx --> reads value 0 (because Core0 has not written anything) in r3 and after comparison we stopped before execution of stwcx
- In both Cores HID1[ATS] is 1, so reservation was done
- Core0 executes the stwcx command, value 1 is written to addr and EQ is set in CR, so the write succeeds and we return 1
- Core1 executes the stwcx command and even there it works, EQ is set and we return success, so both cores now have the spinlock - damn ;-)
Can you please explain where we did not understand the behavior of lwarx/stwcx or where our mistake is ?
Thanks in advance!