Search code examples
assemblykernelarminline-assemblyspinlock

Use of STREXEQ instead of STREX for spinlock implementation in ARM


The following is a sample spin-lock implementation in the ARM manual. Please check here: http://infocenter.arm.com/help/topic/com.arm.doc.genc007826/Barrier_Litmus_Tests_and_Cookbook_A08.pdf . Section on "Use of Wait For Event (WFE) and Send Event (SEV) with Locks".

Locking code:

Loop:
     LDREX R5, [R1]       ; read lock
     CMP R5, #0           ; check if 0
     WFENE                ; sleep if the lock is held
     STREXEQ R5, R0, [R1] ; attempt to store new value
     CMPEQ R5, #0         ; test if store suceeded
     BNE Loop             ; retry if not
     DMB ; ensures that all subsequent accesses are observed after the
         ; gaining of the lock is observed
         ; loads and stores in the critical region can now be performed

Lock release code:

     MOV R0, #0
     DMB          ; ensure all previous accesses are observed before the lock is cleared
     STR R0, [R1] ; clear the lock.
     DSB ; ensure completion of the store that cleared the lock before sending the event
     SEV

Question: Why is STREXEQ used? What if STREX is used instead? As I understand it strexeq will execute only if EQ flag is set. But anyway, if EQ is not set, then WFENE will ensure that we are waiting for the event? So isn't STREX EQ unnecessary?

Thanks in advance!


Solution

  • No, WFE does not have the guarantees you're thinking it does. The ARM manual describes a large set of events that must cause you to come out from WFE but the core is allowed to wake up for other reasons. For example a core is allowed to implement a timeout on its WFE implementation. These events are the same as the events for WFI with the addition of some processor executing an SEV instruction. It does not however have any requirement to stay asleep. In fact, NOP is an architecturally valid albeit power hungry implementation of WFE. It is never safe for you to assume that you woke up because you saw an SEV. For example, there may have been an interrupt, the processor processed the interrupt and returned control to the thread. The thread then executed the next instruction in the series, the STREX.