spin_lock, spin_lock_irq, spin_lock_irqsave的区别
2016-12-27 10:45
537 查看
kernel version: 2.6.26
linux kernel代码中有很多自旋锁的使用场景,同时存在很多spin_lock的接口定义,那么怎么去区分这些接口的使用场景呢?
首先来看spin_lock的实现:
spin_lock_irq的实现,我们按照smp来看:
spin_lock_irqsave的实现
显而易见,spin_lock_irq还调用了local_irq_disable函数,禁用本地中断;
假设当进程A调用spin_lock访问临界区时,如果中断来临,刚好调度到这个cpu核上,并且也去获取spin_lock,此时进程A已经被设置为TASK_INTERRUPT,同时中断处理程序因为拿不到锁,一直在忙等,进程调度无法调度进程A,导致死锁。而如果这个中断是在另一个cpu核上,就不会出现这种情况,因为另一个cpu核的中断并不会导致进程A运行状态被设置为TASK_INTERRUPT,只是被调度换出。
所以在使用spin_lock接口时,需要注意是否会在中断处理中获取锁。
而spin_lock_irqsave在进入临界区前,会保存当前中断状态flag,关闭本地中断,然后进入临界区,在退出临界区时,把保存的flag写回到中断寄存器。
spin_lock_irq在进入临界区前不保存中断状态,关中断,进入临界区,在退出临界区时,开中断。
spin_lock_irqsave锁返回时,中断状态不会被改变,调用spin_lock_irqsave前是开中断返回就开中断。
spin_lock_irq锁返回时,永远都是开中断,即使spin_lock_irq前是关中断
linux kernel代码中有很多自旋锁的使用场景,同时存在很多spin_lock的接口定义,那么怎么去区分这些接口的使用场景呢?
首先来看spin_lock的实现:
#define spin_lock(lock) _spin_lock(lock) void __lockfunc _spin_lock(spinlock_t *lock) { preempt_disable(); spin_acquire(&lock->dep_map, 0, 0, _RET_IP_); LOCK_CONTENDED(lock, _raw_spin_trylock, _raw_spin_lock); }
spin_lock_irq的实现,我们按照smp来看:
#define spin_lock_irq(lock) _spin_lock_irq(lock) void __lockfunc _spin_lock_irq(spinlock_t *lock) { local_irq_disable(); preempt_disable(); spin_acquire(&lock->dep_map, 0, 0, _RET_IP_); LOCK_CONTENDED(lock, _raw_spin_trylock, _raw_spin_lock); }
spin_lock_irqsave的实现
#define spin_lock_irqsave(lock, flags) flags = _spin_lock_irqsave(lock) unsigned long __lockfunc _spin_lock_irqsave(spinlock_t *lock) { unsigned long flags; local_irq_save(flags); preempt_disable(); spin_acquire(&lock->dep_map, 0, 0, _RET_IP_); /* * On lockdep we dont want the hand-coded irq-enable of * _raw_spin_lock_flags() code, because lockdep assumes * that interrupts are not re-enabled during lock-acquire: */ #ifdef CONFIG_LOCKDEP LOCK_CONTENDED(lock, _raw_spin_trylock, _raw_spin_lock); #else _raw_spin_lock_flags(lock, &flags); #endif return flags; }
显而易见,spin_lock_irq还调用了local_irq_disable函数,禁用本地中断;
假设当进程A调用spin_lock访问临界区时,如果中断来临,刚好调度到这个cpu核上,并且也去获取spin_lock,此时进程A已经被设置为TASK_INTERRUPT,同时中断处理程序因为拿不到锁,一直在忙等,进程调度无法调度进程A,导致死锁。而如果这个中断是在另一个cpu核上,就不会出现这种情况,因为另一个cpu核的中断并不会导致进程A运行状态被设置为TASK_INTERRUPT,只是被调度换出。
所以在使用spin_lock接口时,需要注意是否会在中断处理中获取锁。
而spin_lock_irqsave在进入临界区前,会保存当前中断状态flag,关闭本地中断,然后进入临界区,在退出临界区时,把保存的flag写回到中断寄存器。
spin_lock_irq在进入临界区前不保存中断状态,关中断,进入临界区,在退出临界区时,开中断。
spin_lock_irqsave锁返回时,中断状态不会被改变,调用spin_lock_irqsave前是开中断返回就开中断。
spin_lock_irq锁返回时,永远都是开中断,即使spin_lock_irq前是关中断
相关文章推荐
- spin_lock、spin_lock_irq、spin_lock_irqsave区别【转】
- spin_lock、spin_lock_irq、spin_lock_irqsave区别【转】
- spin_lock、spin_lock_irq、spin_lock_irqsave区别
- spin_lock、spin_lock_irq、spin_lock_irqsave区别
- request_irq()、free_irq(),以及spin_lock_irqsave和spin_lock区别
- Linux内核spin_lock、spin_lock_irq 和 spin_lock_irqsave 分析
- spin_lock, spin_lock_irq, spin_lock_irqsave 的使用场景
- 自旋锁spin_lock、spin_lock_irq 和 spin_lock_irqsave 分析
- 嵌入式 Linux内核spin_lock与spin_lock_irq以及spin_lock_irqsave分析
- 自旋锁spin_lock、spin_lock_irq 和 spin_lock_irqsave 分析
- Linux内核spin_lock、spin_lock_irq 和 spin_lock_irqsave 分析
- 【转】 Linux内核spin_lock、spin_lock_irq 和 spin_lock_irqsave 分析
- spin_lock & spin_lock_irqsave
- 释疑spin_lock_irq spin_lock_irqsave spin_unlock_irqrestore spin_lock_bh
- [内核同步]自旋锁spin_lock、spin_lock_irq 和 spin_lock_irqsave 分析
- [内核同步]自旋锁spin_lock、spin_lock_irq 和 spin_lock_irqsave 分析
- [内核同步]自旋锁spin_lock、spin_lock_irq 和 spin_lock_irqsave 分析
- 那些情况该使用它们spin_lock到spin_lock_irqsave【转】
- spin_lock_irqsave和spin_lock
- 在spin_lock_irqsave与spin_unlock_irqrestore中的内核抢占