转自旋锁spin_lock和raw_spin_lock
Posted fukan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了转自旋锁spin_lock和raw_spin_lock相关的知识,希望对你有一定的参考价值。
本文转自http://blog.csdn.net/droidphone/article/details/7395983
本文不打算详细探究spin_lock的详细实现机制,只是最近对raw_spin_lock的出现比较困扰,搞不清楚什么时候用spin_lock,什么时候用raw_spin_lock,因此有了这篇文章。
/*****************************************************************************************************/
声明:本博内容均由http://blog.csdn.net/droidphone原创,转载请注明出处,谢谢!
/*****************************************************************************************************/
1. 临界区(Critical Section)
- (1) 在可以抢占(preemption)的系统中,两个线程同时访问同一个对象;
- (2) 线程和中断同时访问同一个对象;
- (3) 在多核系统中(SMP),可能两个CPU可能同时访问同一个对象;
2. 自旋锁(spin_lock)
- preempt_disable();
- .....
- // 访问共享对象的代码
- ......
- preempt_enable();
同样地,针对单处理器系统,第二种情况,只要临时关闭中断即可,我们可以使用以下方法:
- local_irq_disable();
- ......
- // 访问共享对象的代码
- ......
- local_irq_enable();
那么,针对多处理器的系统,以上的方法还成立么?答案很显然:不成立。
对于第一种情况,虽然抢占被禁止了,可是另一个CPU上还有线程在运行,如果这个线程也正好要访问该共享对象,上面的代码段显然是无能为力了。
对于第二种情况,虽然本地CPU的中断被禁止了,可是另一个CPU依然可以产生中断,如果他的中断服务程序也正好要访问该共享对象,上面的代码段也一样无法对共享对象进行保护。
- spin_lock(spinlock_t *lock);
- spin_unlock(spinlock_t *lock);
- spin_lock_irq(spinlock_t *lock);
- spin_unlock_irq(spinlock_t *lock);
- spin_lock_irqsave(lock, flags);
- spin_lock_irqrestore(lock, flags);
- 如果只是在普通线程之间同时访问共享对象,使用spin_lock()/spin_unlock();
- 如果是在中断和普通线程之间同时访问共享对象,并且确信退出临界区后要打开中断,使用spin_lock_irq()/spin_unlock_irq();
- 如果是在中断和普通线程之间同时访问共享对象,并且退出临界区后要保持中断的状态,使用spin_lock_irqsave()/spin_unlock_irqrestore();
3. raw_spin_lock
- 把原来的raw_spin_lock改为arch_spin_lock;
- 把原来的spin_lock改为raw_spin_lock;
- 实现一个新的spin_lock;
- 尽可能使用spin_lock;
- 绝对不允许被抢占和休眠的地方,使用raw_spin_lock,否则使用spin_lock;
- 如果你的临界区足够小,使用raw_spin_lock;
以上是关于转自旋锁spin_lock和raw_spin_lock的主要内容,如果未能解决你的问题,请参考以下文章