POOL32A 000000 |
0 00000 |
0 00000 |
5 00101 |
0 00000 |
SLL 000000 |
6 |
5 |
5 |
5 |
5 |
6 |
PAUSE |
microMIPS |
Wait for the LLBit to clear. |
Wait for the LLBit to clear.
Locks implemented using the LL/SC (or LLD/SCD) instructions are a common method of synchronization between threads of control. A lock implementation does a load-linked instruction and checks the value returned to determine whether the software lock is set. If it is, the code branches back to retry the load-linked instruction, implementing an active busy-wait sequence. The PAUSE instruction is intended to be placed into the busy-wait sequence to block the instruction stream until such time as the load-linked instruction has a chance to succeed in obtaining the software lock.
The PAUSE instruction is implementation-dependent, but it usually involves descheduling the instruction stream until the LLBit is zero.
In a single-threaded processor, this may be implemented as a short-term WAIT operation which resumes at the next instruction when the LLBit is zero or on some other external event such as an interrupt.
On a multi-threaded processor, this may be implemented as a short term YIELD operation which resumes at the next instruction when the LLBit is zero.
In either case, it is assumed that the instruction stream which gives up the software lock does so via a write to the lock variable, which causes the processor to clear the LLBit as seen by this thread of execution.
The encoding of the instruction is such that it is backward compatible with all previous implementations of the architecture. The PAUSE instruction can therefore be placed into existing lock sequences and treated as a NOP by the processor, even if the processor does not implement the PAUSE instruction.
Pre-Release 6: The operation of the processor is UNPREDICTABLE if a PAUSE instruction is executed placed in the delay slot of a branch or jump instruction. This restriction does not apply in Release 6.
if LLBit != 0 then EPC = PC + 4 /* Resume at the following instruction */ DescheduleInstructionStream() endif
None
The PAUSE instruction is intended to be inserted into the instruction stream after an LL instruction has set the LLBit and found the software lock set. The program may wait forever if a PAUSE instruction is executed and there is no possibility that the LLBit will ever be cleared.
An example use of the PAUSE instruction is shown below:
acquire_lock: ll t0, 0(a0) /* Read software lock, set hardware lock */ bnezc t0, acquire_lock_retry: /* Branch if software lock is taken; */ /* Release 6 branch */ addiu t0, t0, 1 /* Set the software lock */ sc t0, 0(a0) /* Try to store the software lock */ bnezc t0, 10f /* Branch if lock acquired successfully */ sync acquire_lock_retry: pause /* Wait for LLBIT to clear before retry */ bc acquire_lock /* and retry the operation; Release 6 branch */ 10: Critical region code release_lock: sync sw zero, 0(a0) /* Release software lock, clearing LLBIT */ /* for any PAUSEd waiters */