semaphore_take: mov w2, #1 // LOCK value dmb sy // ensure all observers observe data before aquire is attempted ldaxr w1, [x0] // attempt to read and aquire lock cbnz w1, semaphore_take // lock is not zero so loop and try and aquire again stxr w3, w2, [x0] // attempt to store LOCK value cbnz w3, semaphore_take // retry if store failed dmb sy // ensures that all subsequent accesses are observed after gaining of the lock is observed
The above semaphore code worked flawlessly until the moment I added FIQ code.
Now the semaphore leaks thru critical sections even though the FIQ does not come anywhere near the semaphore.
Is there something I need to know about FIQ and LDREX/STREX functions?
The FIQ has the effect of clearing the local monitor on exception return.
(See the architecture manual https://developer.arm.com/docs/ddi0487/latest, B2.9.4 Context switch support)
... but then the store should fail.
If the fiq upset the local monitors as per what vstehle says then another core can get an aquire lock if an fiq occured between the one core getting a lock and it storing in that compare bit.
It only cropped up in testing when I was testing for race conditions, you really have to belt the system to get it to occur. On normal operation I had not even noticed the problem as the chances of an fiq in that exact section was low.
Sorry I should say if it returns from an FIQ at that exact opcode not gets an FIQ.