Spin locks allow resource execution control through fast lock context switching.
Spin locks are a type of lock mechanism. In a spin lock, the thread will simply wait in a loop checking for the resource to become available. It is the execution of the thread waiting in a loop ("spins"), that gives this lock mechanism its name. The thread will only come out of the loop once the resource is available.
When using a spin lock, the following should be noted :
Spin locks should only be used in environments where the waiting period will be short
Spin locks are very wasteful, since the thread in question is always in the active state
Spin locks can lock/unlock very quickly, since the thread never changes state
For spin locks to work on the Symbian platform, the interrupts have to be disabled before use. This is due to the fact that spin locks do not protect against interrupts from occurring on the same CPU.
Because of these properties, spin locks are used in environments where the operation has to be fast and where the waiting times have to be short. For this reason, on the Symbian platform they are only used in kernel code. If a more efficient use of thread processing time is required, then a mutex should be used.
There are two types of spin lock:
spin locks and
read write spin locks.
The difference between the two types of spin locks is that the read write spin locks have been optimised to allow multiple reading threads to acquire the lock simultaneously.
When using spin locks, the following steps have to be carried out:
If the above steps have not been carried out, then a dead lock condition could occur.
There are two types of spin locks on the Symbian platform. These are spin locks and read write spin locks. Read write spin locks are described in the next section.
There are two ways of implementing spin locks on the Symbian platform:
A Spin lock API and
the use of spin lock macros.
The spin lock API should never be used directly, instead the macros should be used. This is due to:
The spin lock macros carry out the required interrupt enable/disable operations
The spin lock macros provide compatibility between SMP and non-SMP builds.
The spin lock API is only for internal use and should never be used. For spin locks it is provided by the TSpinLock class and is defined in nkern.h. It will not be discussed any further.
The spin lock macros available are :
Macro |
Parameter 1 Purpose and Data Type |
Parameter 2 Purpose and Data Type |
Return Value Purpose and Data Type |
Operation |
__SPIN_LOCK_IRQSAVE(lock) |
The spin lock order. TSpinLock |
N/A |
The original interrupt state. TInt |
Disable interrupts and acquire the lock. |
__SPIN_UNLOCK_IRQRESTORE(lock,irq) |
The spin lock order. TSpinLock |
The interrupt state TInt |
N/A |
Release the lock, then restore the interrupt state. |
__SPIN_FLASH_IRQRESTORE(lock,irq) |
The spin lock order. TSpinLock |
The interrupt state. TInt |
ETrue if the lock/unlock operation has occurred, otherwise EFalse. TBool |
If another thread is waiting for the spin lock or there is an interrupt pending, then execute the __SPIN_UNLOCK_IRQRESTORE macro and then execute the __SPIN_LOCK_IRQ macro. |
__SPIN_LOCK(lock) |
The spin lock order. TSpinLock |
N/A |
N/A |
Acquire the lock, assuming the interrupts and preemption have been disabled. |
__SPIN_UNLOCK(lock) |
The spin lock order. TSpinLock |
N/A |
N/A |
Release the lock without changing the interrupt and preemption states. |
__SPIN_FLASH_PREEMPT(lock) |
The spin lock order. TSpinLock |
N/A |
ETrue if the lock/unlock operation has occurred, otherwise EFalse. TBool |
If another thread is waiting for the lock, then execute (after the unlock NKern::PreemptionPoint has been called) the __SPIN_UNLOCK macro and then the __SPIN_LOCK macro. |
__SPIN_LOCK_IRQ(lock) |
The spin lock order. TSpinLock |
N/A |
N/A |
Disable interrupts and acquire the lock. |
__SPIN_UNLOCK_IRQ(lock) |
The spin lock order. TSpinLock |
N/A |
N/A |
Release the lock, then enable the interrupts. |
__SPIN_FLASH_IRQ(lock) |
The spin lock order. TSpinLock |
N/A |
ETrue if the lock/unlock operation has occurred, otherwise EFalse. TBool |
If another thread is waiting for the spin lock or if there is an interrupt pending, then execute the __SPIN_UNLOCK_IRQ macro and then execute the __SPIN_LOCK_IRQ macro. |
The spin lock order parameter is used to provide a priority of the spin lock. The spin lock order parameter allows spin locks to be nested and to guard against deadlocks.
The list of acceptable spin lock order values are defined in nkern.h.
Which spin lock macro should be used is shown in the following table :
Is the spin lock to be used within an ISR ? |
The ISR State |
Other Circumstances to Consider |
The Spin Lock Macros to Use |
Yes |
Unknown |
None |
__SPIN_LOCK_IRQSAVE(lock) |
__SPIN_UNLOCK_IRQRESTORE(lock,irq) |
|||
__SPIN_FLASH_IRQRESTORE(lock,irq) |
|||
N/A |
The interrupts have already been disabled. |
None |
__SPIN_LOCK(lock) |
__SPIN_UNLOCK(lock) |
|||
__SPIN_FLASH_IRQRESTORE(lock,irq) |
|||
No |
N/A |
Code is within a pair of NKern::Lock/NKern::Unlock statements. |
__SPIN_LOCK(lock) |
__SPIN_UNLOCK(lock) |
|||
__SPIN_FLASH_PREEMPT(lock) |
|||
Yes |
Known |
The interrupts must already be disabled. |
__SPIN_LOCK_IRQ(lock) |
__SPIN_UNLOCK_IRQ(lock) |
|||
__SPIN_FLASH_IRQ(lock) |
Only the above combinations of interrupt states and spin lock macros are allowed.
The spin lock macros __SPIN_LOCK_IRQSAVE and __SPIN_UNLOCK_IRQRESTORE would be used in almost all cases.
An example of how to use the spin lock macros is :
TInt irq = __SPIN_LOCK_IRQSAVE(EOrderThread); // some code... __SPIN_UNLOCK_IRQSTORE(EOrderThread,irq);
The first line calls the macro to disable the interrupts and acquire the spin lock. This line returns the original interrupt state (stored in the variable irq).
The last line calls the macro to release the spin lock and then restore the IRQ to its original state.
This sub set of spin locks allows for the multiple reading threads to acquire the lock simultaneously. The operation of read write spin locks is :
Behaviour |
Required Conditions |
Acquire the lock for a read operation |
The lock is either free or is being held for reading |
Blocked for a read operation |
The lock is held for a write operation |
Acquire the lock for a write operation |
The lock is free |
Blocked for a write operation |
The lock is held for a read or a write operation |
The macros are the same name as for the spin locks, except :
An example of the use of read write spin lock macros are __SPIN_LOCK_IRQ_R(lock) and __SPIN_UNLOCK_IRQ_W(lock).
Read write spin locks are implemented by the TRWSpinLock class. As with the TSpinLock class, this class is for internal use only and will not be discussed any further.
An example of the use of read write spin locks is :
__SPIN_LOCK_IRQ_R(EOrderThread); // some code... __SPIN_UNLOCK_IRQ_R(EOrderThread);
Copyright ©2010 Nokia Corporation and/or its subsidiary(-ies).
All rights
reserved. Unless otherwise stated, these materials are provided under the terms of the Eclipse Public License
v1.0.