Atomic Swap Instructions

X86 Instructions:

XCHG mem reg temp <- reg, reg <- mem, mem <- temp with LOCK line asserted

LOCK BTS mem, # CF <- mem bit# , mem bit# <- 1 with LOCK line asserted

BTS -- Bit Test and . Also BTR -- Bit Test ad Reset and BTC -- Bit Test and Complement Note: LOCK prefix required for BTS but not XCHG

MIPS

RMW (Read Modify Write) instructions are not possible in the MIPS pipeline and in load-store RISC architectures in general. MIPS opts for a pair of instructions that can detect if an intervening access to the semaphore possibly occurred. These are ll (load linked or load locked) and sc (store conditional). ll reg, mem reg <- mem, link_reg <- &mem sc reg, mem if link_reg = &mem then mem <- reg, reg <- 1 else reg <- 0

The intent is that link_reg gets set to 0 (causing sc to fail) if the memory location matching the address in link_reg is modified between the ll and sc instructions. In current implementations, link_reg gets set to 0 if the cache line containing the address in link_reg is modified or invalidated, or if there is an ( eret is executed). Note that this doesn't necessarily mean that the semaphore in mem was actually modified by another processor or , only that it might have been. Also, any access to memory between the ll and sc instructions could cause the cache line to be modified or invalidated, so no load or store instructions must appear between the ll and sc or the sc could always fail, and loops based on it would never exit. And, keeping the number of instructions between the ll and sc instructions to an absolute minimum increases the likelihood that code segment will not be interrupted. Using cache line modification as an indication that the ll/sc pair was not atomic is useful since it provides a way to detect if the memory location was potentially modified by another (cache coherent) processor but it also means than only cacheable memory can be used for semaphores. If sc succeeds, then the access to mem was effectively atomic (that is, there may have been other bus cycles between the ll and sc , but not to mem ). try: addu $t3, $0, 1 #put locking value in t3 ll $t2, 0($t1) #load linked current value of semaphore sc $t3, 0($t1) #store conditional lock, # $t3 <- 1 if sc succeeds beq $t3, $0, try #if sc fails, try again. mov $t4, $t2 #save loaded semaphore #if $t4 is 0, we have the lock