PAUSE |
nanoMIPS |
Pause |
Pause. Pause until LL Bit is cleared.
nanoMIPS
100000 |
00000 |
x |
1100 |
x |
0000 |
00101 |
6 |
5 |
5 |
4 |
3 |
4 |
5 |
if C0.LLAddr.LLB: CPU.in_pause_state = True
The purpose ofthe PAUSE instruction is halt a thread (rather than entering a spin loop) when itis waiting to acquire an LL/SC lock. This is particularly useful on multi-threaded processors, since the
waiting thread may be using the same instruction pipeline as the thread which currently owns the lock, and hence entering a spin loop will delay the other thread from completing its task and freeing the
lock.
When a thread is in the paused state,it should not issue any instructions. The paused state will be
cleared either if the LLBit for the thread gets cleared, or if the thread takes an interrupt.If an interrupt occurs,
it is implementation dependent whether C0.EPC points to the PAUSE instruction or the
instruction after the PAUSE.
In LL/SC lock software, the LLBit of the waiting thread will always be cleared when the thread which owns the lock does a store instruction to the lock address in order to clear the lock. Thus the paused
thread will always be woken when it has another opportunity to acquire the lock. After the PAUSE instruction completes, software is expected to attempt to acquire the lock again by re-executing the
LL/SC sequence.
It is legal to implement PAUSE as a NOP instruction.In this case, the behavior of LL/SC lock software will be equivalent to executing a spin loop to acquire the lock. Software using PAUSE will still work,
but the benefit of having the waiting thread not consume instruction issue slots will be lost.
PAUSE is encoded as an SLL instruction with a shift value of 5, targeting GPR $0. Hence PAUSE will behave as a NOP instruction if no additional behavior beyond that of SLL is implemented.
The following assembly code example shows how the PAUSE instruction can be used to halt a thread while it is waiting to acquire an LL/SC lock.
acquire_lock: ll t0, 0(a0) /* Read softwarelock, set LLBit. */ bnezc t0, acquire_lock_retry /* Branch if softwarelock is taken.*/ addiu t0, t0, 1 /* Set the software lock. */ sc t0, 0(a0) /* Try to store the softwarelock. */ bnezc t0, 10f /* Branchiflockacquired successfully.*/ sync acquire_lock_retry: pause /* Wait for LLBITtoclear before retrying. */ bc acquire_lock /* Now retrytheoperation. */ 10: /* Critical Region Code */ ... release_lock: sync sw zero, 0(a0) /* Releasesoftwarelock,clearing LLBIT for any PAUSEd waiters */
None.