spinlock in linux kernel

作为一种锁机制, spinlock可以制造一段临界区, 同一时刻只有一个线程能进入这个临界区, 从而达到保护数据的目的. semaphore, mutext也有同样的作用.

spinlock采用busy waiting的实现方式, 无法获取锁时线程一直处于忙等待状态(而不是进入休眠,放弃处理器).

使用spinlock的注意事项

1. 持有spinlock的上下文不能主动放弃处理器. 包括禁止抢占, 不能休眠. 如果中断中也要获取spinlock, 需要禁止中断.

2. 持有spinlock的时间越短越好.

3. 锁被持有时, 持有者不允许再次尝试获取该锁.

4. 尽量避免使用多个锁, 否则复杂度会大大提高. 在必须获取多个锁时, 始终以相同的顺序获得.

linux kernel中的spinlock相关接口函数

o 定义时初始化: static DEFINE_SPINLOCK(lock);

o 动态初始化: spin_lock_init(lock);



o 获得/释放锁

void spin_lock(spinlock_t *lock);

void spin_unlock(spinlock_t *lock);



o 获得锁之前禁止中断, 并保存之前的中断状态, 以待恢复.

void spin_lock_irqsave(spinlock_t *lock, unsigned long flags);

void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags);



o 获得锁之前禁止中断

void spin_lock_irq(spinlock_t *lock);

void spin_unlock_irq(spinlock_t *lock);



o 获得锁之前禁止软中断

void spin_lock_bh(spinlock_t *lock);

void spin_unlock_bh(spinlock_t *lock);

arm linux kernel中spinlock的实现

include/linux/spinlock.h



对于单核处理器(UP: uniprocessor)和多核处理器(SMP: symmetric multiprocessor), 会包含不同的头文件.



在单核处理器的系统中, spinlock的实现比较简单. spin_lock()只会做禁止抢占动作, spin_lock_irqsave()会禁止中断. 除此之外并没有锁相关的工作.



在多核处理器的系统中, 获得spinlock之后会置一个标志, 下面是arm架构的实现:



arch/arm/include/asm/spinlock.h

static inline void arch_spin_lock(arch_spinlock_t *lock)
{
unsigned long tmp; __asm__ __volatile__(
"1: ldrex %0, [%1]\n"
" teq %0, #0\n"
WFE("ne")
" strexeq %0, %2, [%1]\n"
" teqeq %0, #0\n"
" bne 1b"
: "=&r" (tmp)
: "r" (&lock->lock), "r" (1)
: "cc"); smp_mb();
}

1. 把lock->lock中的值加载到tmp里. ldrex将&lock->lock这个地址标记为当前CPU独占访问, 此时如果另一个CPU执行后面的strexeq指令, 则会失败返回1. . 这就保证了lock操作的原子操作.

2. 如果tmp为0, 则锁可以被获取, 向&lock->lock中写1. 写成功后退出. strex解除当前CPU对&lock->lock地址的独占.

如果tmp不为0, 则当前CPU通过wfe指令进入省电状态.

3. sev指令或中断发生, CPU继续执行, 则"bne 1b"又跳到步骤1. 这里就是spinlock的自旋操作了.



wfe(wait for event)指令会使当前CPU停止执行, 直到发生了以下任一件事:



1. IRQ/FIQ产生.

2. Data abort异常产生.

3. Debug请求.

4. 其他处理器用sev(set event)指令发出事件消息.

最新文章

  1. 统计Apache或Nginx访问日志里的独立IP访问数量的Shell
  2. sql server 自增长id 允许插入显示值
  3. FireBug使用总结
  4. GNU make 总结 (二)
  5. 简单CSS hack:区分IE6、IE7、IE8、Firefox、Opera
  6. ubuntu装机
  7. 许令波老师的java的IO机制分析文章
  8. easyui的datagrid删除一条记录后更新出问题
  9. poj 1018 Communication System 枚举 VS 贪心
  10. scu - 3254 - Rain and Fgj(最小点权割)
  11. Elasticsearch学习随笔(二)-- Index 和 Doc 查询新建API总结
  12. 写给小白的JAVA链接MySQL数据库的步骤(JDBC):
  13. javascript实现双向数据绑定
  14. 这可能是把ZooKeeper概念讲的最清楚的一篇文章
  15. Spring Cloud 2-Hystrix 断路容错保护(四)
  16. Kali学习笔记36:AVWS10的使用
  17. pt-kill 用法记录
  18. learn
  19. CDH hive metastore启动报错:Unknown column 'A0.SCHEMA_VERSION_V2' in 'field list'
  20. [原][粒子特效][spark]粒子系统system、主节点group、渲染器render

热门文章

  1. 「 Luogu P2801 」 教主的魔法——分块
  2. 自制操作系统小样例——参考部分linux0.11内核源码
  3. python 06 8/28-8/30
  4. Python旅途——函数(1)
  5. STL中set求交集、并集、差集的方法
  6. angularjs ng-repeat下验证问题
  7. Go常量与枚举类型
  8. [NOIP1998] 提高组 洛谷P1013 进制位
  9. CF671D:Roads in Yusland
  10. POJ3233:Matrix Power Series