Initialize
We can initialize Spinlock in two ways.
- Static Method
- Dynamic Method
Static Method
You can statically initialize a Spinlock using the macro given below.
1
|
DEFINE_SPINLOCK(etx_spinlock);
|
The macro given above will create spinlock_t variable in the name of
and initialize to UNLOCKED STATE. Take a look at the expansion of DEFINE_SPINLOCK
below.
1
|
#define DEFINE_SPINLOCK(x) spinlock_t x = __SPIN_LOCK_UNLOCKED(x)
|
Dynamic Method
If you want to initialize dynamically you can use the method as given below.
1
2
|
spinlock_t etx_spinlock;
spin_lock_init(&etx_spinlock);
|
You can use any one of the methods.
Locking between User context
Lock:
spin_lock(spinlock_t *lock)
This will take the lock if it is free, otherwise it’ll spin until that lock is free (Keep trying).
Try Lock:
spin_trylock(spinlock_t *lock)
Locks the spinlock if it is not already locked. If unable to obtain the lock it exits with an error and do not spin. It returns non-zero if obtains the lock otherwise returns zero.
Unlock:
spin_unlock(spinlock_t *lock)
It does the reverse of lock. It will unlock which is locked by above call.
Checking Lock:
spin_is_locked(spinlock_t *lock)
This is used to check whether the lock is available or not. It returns non-zero if the lock is currently acquired. otherwise returns zero.
//Thread 1
int thread_function1(void *pv)
{
while(!kthread_should_stop()) {
spin_lock(&etx_spinlock);
etx_global_variable++;
printk(KERN_INFO "In EmbeTronicX Thread Function1 %lu\n", etx_global_variable);
spin_unlock(&etx_spinlock);
msleep(1000);
}
return 0;
}
//Thread 2
int thread_function2(void *pv)
{
while(!kthread_should_stop()) {
spin_lock(&etx_spinlock);
etx_global_variable++;
printk(KERN_INFO "In EmbeTronicX Thread Function2 %lu\n", etx_global_variable);
spin_unlock(&etx_spinlock);
msleep(1000);
}
return 0;
}
Locking between User context and Bottom Halves
If you share data with a bottom half and user context (like Kernel Thread), then this approach will be useful.
Lock:
spin_lock_bh(spinlock_t *lock)
It disables soft interrupts on that CPU, then grabs the lock. This has the effect of preventing softirqs, tasklets, and bottom halves from running on the local CPU. Here the suffix ‘
_bh
‘ refers to “Bottom Halves“.
Unlock:
spin_unlock_bh(spinlock_t *lock)
Locking between Hard IRQ and Bottom Halves)
If you share data between Hardware ISR and Bottom halves then you have to disable the IRQ before lock. Because, the bottom halves processing can be interrupted by a hardware interrupt. So this will be used in that scenario.
Lock:
spin_lock_irq(spinlock_t *lock)
This will disable interrupts on that cpu, then grab the lock.
Unlock:
spin_unlock_irq(spinlock_t *lock)
No comments:
Post a Comment