Spinlocks as locking construct in SMP systems



Introduction to spinlocks

I am reading some SMP related constructs for locking shared critical data and I found spinlocks as an efficient SMP locking construct. Hence I though of writing this article so as to introduce spinlocks to beginners. Spinlocks can be used to lock critical data both in Uniprocessor systems as well as Multiprocessor systems. However they are available only when global config option CONFIG_SMP is set to Y. They are used as follows

spinlock_t xxx_lock=SPINLOCK_UNLOCKED;
............................
............................
unsigned long flags;
............................
spin_lock_irqsave (&xxx_lock, flags);
............................
............................
....critical region.........
............................
............................
spin_unlock_irqsave (&xxx_lock, flags);

This will disable all interrupts locally and will give one single global lock to this particular CPU. meaning that exactly one thread would be executing the above metioned critical section. In case of a Uniprocessor system the above sequence is like this

unsigned long flags;
............................
save_flags (flags);
cli ();
............................
....critical region.........
............................
............................
restore_flags (flags);

One limitation or shortcoming in spinlocks exists. The above code sequence could disable interrupts on local CPU, however if this region is not locked in other CPU contexts then it would lead to data inconsistencies.

Spinlocks should in used in code that is highly organized into clear cut separate regions that modify shared data, which are all independent of each other. For example, device driver routines. Moreover, using multiple locks for same type of object is also not advisable as it would lead to a deadlock resulting in loss of efficiency. Further acquiring locks within a region guarded by an already acquired lock, is dangerous and it would surely lead to a deadlock situation.


Reader Writer spinlocks

Reader-Writer locks are best in case most of the processes have to only read a shared data object and require writing it very infrequently. Multiple reader processes can be in critical region; however if a process wants to modify the object, then it has to request and compete for an exclusive write lock. An exclusive write lock is given by kernel only when all reader processes have freed their read locks and no other reader process is in critical region.

The routines to use a read/write lock is as follows:

rwlock_t xxx_lock=RW_LOCK_UNLOCKED;
............................
unsigned long flags;
............................
read_lock_irqsave (&xxx_lock, flags);
............................
............................
....critical region.........
............................
............................
read_unlock_irqsave (&xxx_lock, flags);



rwlock_t xxx_lock=RW_LOCK_UNLOCKED;
............................
unsigned long flags;
............................
write_lock_irqsave (&xxx_lock, flags);
............................
............................
....critical region.........
............................
............................
write_unlock_irqsave (&xxx_lock, flags);

Upgradable locks can be a quick anda dirty soultion to it but I believe that it would lead to serious inconsistencies and problems.

Simple version of spinlocks

Spinlocks of type XXX_irqxxx (enable/disable interrupt routines) are very slow in operation. thjey should be used only when it is really needed to disable interrupts or when the code protected by spin lock runs in "interrupt context". If the developer is sure that code will always run in "proces context" then non irq version of spin locks are best.

spinlock_t xxx_lock=SPINLOCK_UNLOCKED;
............................
spin_lock (&xxx_lock);
............................
............................
....critical region.........
............................
............................
spin_unlock (&xxx_lock,);

However using this versionn of spinlock in a piece of code to be run in an interrupt context would lead to deadlock.



I am Nikhil Bhargava. I am curently working in C-DOT, India for past one year as a Research Engineer. All comments, bug fixes, and suggestions welcome.

1