注:代码为linux内核版本为2.6.22.6以及4.4.32,不代表其他版本内核的实现方式
spin_lock与spin_lock_irqsave
自旋锁是内核中最常见的锁,也就是线程争用被持有的自旋锁时,并不会睡眠挂起而是在busyloop等待锁重新可用,因此自旋锁更适用于时间短,加锁不睡眠的场景,由于信号量和互斥锁在挂起的时候需要让出cpu执行别的线程,因此涉及到两次上下文切换,当上下文切换带来的开销大于睡眠的开销时,选择自旋锁是更好的选择.
由于信号量会导致睡眠,因此中断处理程序只能使用自旋锁,在中断程序中使用自旋锁时一定要禁止本地中断,也就是当前处理器的中断请求,为了防止中断处理程序争用内核的自旋锁从而自旋,而当前程序必须在中断处理程序执行之后执行,因此中断处理程序会一直自旋下去.也就是双重请求死锁.只需要关闭本地中断,而不需要关心别的处理器的中断处理请求.
spin_lock_irqsave的声明,这个函数负责保存中断的当前状态,禁止本地中断,然后获取指定的锁
spin_unlock_irqsave,解锁,并中断恢复到加锁前的状态
#define spin_lock_irqsave(lock, flags) _spin_lock_irqsave(lock, flags)
#define _spin_lock_irqsave(lock, flags) __LOCK_IRQSAVE(lock, flags)
#define __LOCK_IRQSAVE(lock, flags) \
do { local_irq_save(flags); __LOCK(lock); } while (0)
下半部可以抢占进程上下文,因此当下半部和进程上下文共享数据时,需要禁止下半部执行.