Chinaunix首页 | 论坛 | 博客

  • 博客访问: 11958
  • 博文数量: 8
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 81
  • 用 户 组: 普通用户
  • 注册时间: 2015-04-09 22:57
个人简介

高中学历的渣渣

文章分类
文章存档

2015年(8)

我的朋友

分类: LINUX

2015-04-15 18:48:01


ARM Linux 源码分析系列文章基于 Linux 2.6.22 讲解,转


载请标明原处!


读写自旋锁是增强版的自旋锁,其和自旋锁的主要区别是:自旋锁不管请求类型如何,他只允许一个请求来处理资源;读写自旋锁则不一样,他把请求分为读者(对资源进行读操作的请求)和写者(对资源执行写操作的请求),他允许有多个读者同时访问资源,但写者必须独占访问资源。

 

内核使用rwlock_t 结构来描述一个读写自旋锁。



我们可以发现读写自旋锁的定义和自旋锁完全相同,当然他们的锁值的内涵不同,读写自旋锁锁值的最高位被置一时,说明有写者在使用资源,而低 30 位则用来记录读者数量。

 

读自旋锁的获取和释放

我们可以调用 read_lock 宏来为读者得到一个读写自旋锁。read_lock 实际上又被替换成对 _read_lock() 函数的调用,下面是 _read_lock() 的定义。



 

_read_lock() 几乎和 _spin_lock() 完全相同,唯一不同的是他最后使用 _raw_read_lock 宏来执行真正的取锁操作,而 _raw_read_lock 又会被替换成对 __raw_read_lock() 函数的调用。




173 行读出读写自旋锁的锁值,由于我们取得的是读锁(即又一个读者来了),所以在 174 行递增读出的锁值并根据修改后的结果修改 CPSR 的相关位,如果锁值被递增后为正数,就说明现在没有写锁存在(如果写锁存在,那么其值必然大于 0x80000000,而对于有符号数而言,大于 0x80000000 就是负数),没有写锁存在就说明我们可以获取这个读锁(写锁是独占资源的),那么就在 175 行写回锁值(得到读锁)。strex 命令会把写操作的结果写到 tmp2

179 行检查 175 行的写入操作是否成功,如果 减去 tmp2 的值为负数,就说明写入锁值失败(如果写入成功,那么 tmp2 0,故应是 减 结果不会是负数),那么就在 180 行跳回到 173 重新获取读锁。在这里大家可能会觉得有些奇怪,那就是为什么不直接判断 tmp2 是否为 呢?这是因为如果在 174 行检测出读写自旋锁上已经有了一个写者的话,其结果为负数,那么他也会在 180 行跳回到上面重新得到读锁(即开始自旋)。

 

释放读自旋锁实际上和释放自旋锁也非常类似,他最后会调用到__raw_read_unlock() 来释放读自旋锁。我们下面直接讲解 __raw_read_unlock() 的代码。 




197 行读出锁值,然后在 198 行递减锁值(释放读锁,少了一个读者嘛!),最后在 199 行递减后的锁值写回读自旋锁。

200 行检查 199 行的写操作是否成功,如果失败,则跳回到 197 行重新开始释放读自旋锁的操作;如果成功,则函数退出。



写自旋锁的获取和释放

我们可以使用 write_lock 宏来得到一个写锁,他和获取读锁的操作几乎完全相同,他最后会调用到__raw_write_lock () 函数来得到写锁。





101 行先取出锁值,然后在 102 行查看是否已经有读者或写者得到这把锁了,如果这个锁已经被获得了(锁值不为0),由于写者必须是独占资源的,所以他会直接在 108 行调回到 101 行准备进入自旋状态。如果锁没有被获得,那么就会在 106 行把 0x80000000 写入锁值(最高位置1,表示有写者在使用资源),然后在 107 行检查是否写入成功,若写入失败就会在 108 行跳回到 101 行重新开始。

 

我们可以使用 write_unlock 宏来释放写锁,他最后会调用到__raw_write_unlock() 函数来释放写锁。




由于写者是独占资源的,不可能存在其他读者或写者,所以我们直接把锁值清零即可。


阅读(323) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~