免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4325 | 回复: 7
打印 上一主题 下一主题

【求教】请问线程在spin_lock函数忙等时,是否禁止抢占? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-11-28 20:47 |只看该作者 |倒序浏览
看代码确实调用了preempt_disable(),
可《深入理解Linux内核(第三版)》中说“在spin_lock函数忙等时,可以被优先级更高的线程抢占”

请大侠们赐教,另外关于内核同步有没有比较好的文档推荐?

论坛徽章:
0
2 [报告]
发表于 2011-11-28 21:16 |只看该作者
在操作自旋锁内部数据的时候,需要禁止内核抢占,操作完内部数据的时候,释放内核抢占。当无法获得锁,需要循环等待的时候,需要循环等待,此时是可以被抢占的。

论坛徽章:
0
3 [报告]
发表于 2011-11-29 09:22 |只看该作者
在操作自旋锁内部数据的时候,需要禁止内核抢占,操作完内部数据的时候,释放内核抢占。当无法获得锁,需要 ...
wangjl_sdu 发表于 2011-11-28 21:16



    看来兄台认为死锁这种情况是不存在的咯

论坛徽章:
0
4 [报告]
发表于 2011-11-29 10:16 |只看该作者
回复 3# azzurris


    Sorry, 你是对的,昨晚想错了。内核中实现的获取自旋锁的时候就自动禁止内核抢占了。

   获取自旋锁 和 试图获取自旋锁的时候都是 禁止内核抢占的。只有在释放内核锁之后才可以。

static inline void __raw_spin_lock(raw_spinlock_t *lock)
{
        preempt_disable();
   
static inline void __raw_spin_unlock(raw_spinlock_t *lock)
{
        spin_release(&lock->dep_map, 1, _RET_IP_);

论坛徽章:
0
5 [报告]
发表于 2011-11-29 14:37 |只看该作者
回复 1# jakepain


    Otherwise, the kernel control path failed in acquiring the spin lock, thus the macro must cycle until the spin lock is released by a kernel control path running on some other CPU. Invokes preempt_enable( ) to undo the increase of the preemption counter done in step 1. If kernel preemption was enabled before executing the spin_lock macro, another process can now replace this process while it waits for the spin lock.

你提的是这一段吧,这一段是说如果获取spin_lock失败,那就循环忙等。直到别的CPU上占用spin_lock的内核代码释放锁。
在这里,原文插述了一句:调用preempt_enable可以使抢占计数-1。如果在调用spin_lock之前调用了preempt_enable的话,那么即使你调用spin_lock,也会在spin_lock忙等的时候出现抢占的情况。

不知道中文版是怎么翻译的,英文版看的就挺蛋疼,作者遮遮掩掩的说的前言不搭后语的,只是想说明,抢占计数preempt_count这个玩意是可以随便操作的。我们知道,preempt_count这个值在thread_info中,如果大于0,那么就代表不能抢占,等于0就可以抢占。而preempt_disable的动作只是将这个count+1,对应的,enable的动作就是将这个count-1。

回到这段英文,作者的意思是,本来preempt_count的值就是0——可以抢占。你要是闲的无聊或者不小心,在spin_lock之前再调用了preempt_enable,那么preempt_count=-1了。这之后你再正常调用spin_lock,里面会有preempt_disable的动作,preempt_count又加上了1,现在preempt_count=0了。等于之前加的一句preempt_enable,和spin_lock里的preempt_disable抵消了。
你看,你本来的愿望是期望spin_lock能关抢占的,但是现在没关上,自然可以在你忙等锁的时候发生抢占了。也就是原文中说的“ If kernel preemption was enabled before executing the spin_lock macro, another process can now replace this process while it waits for the spin lock.

不知道我罗哩罗嗦的有没有讲清。这里提一句,preempt_count和spin_lock的机制是不一样的。preempt_count是对这个值进行加1减1的操作;而spin_lock是拿lock的值不停的去和“0”比是否相等,若相等,那么就把“1”写入lock中,获得锁了;若不等,就跳回去再读lock的值去与“0”比较,一直循环下去。可以看出,spin_lock不是像preempt_count那样加减的。因此,很重要的一点,同一个spin_lock不能像preempt_enable/disable操作那样嵌套。因为preempt_count加加减减又不会死,但是同一个spin_lock一旦嵌套了,外层的lock已经获得了,lock=1。而内层的lock还会傻乎乎的痴心的等待lock=0的那一天。。。。

论坛徽章:
0
6 [报告]
发表于 2011-11-29 16:39 |只看该作者
说的很清楚。。。

论坛徽章:
0
7 [报告]
发表于 2011-11-29 17:27 |只看该作者
回复 5# azzurris

赞~ 确实,建议阅读原版~最好结合代码,所谓艺术大于形象,代码是很质朴的,书中解释代码的角度却可以有很多种,也可以通过很多种表达方式来解释同一个问题~

论坛徽章:
0
8 [报告]
发表于 2011-11-30 21:37 |只看该作者
回复 5# azzurris


    bingo, 大侠你说的很清楚,受教了。

我看的是另一段文字
As a general rule, kernel preemption is disabled in every critical region protected by spin locks. In the case of a uniprocessor system, the locks themselves are useless, and the spin lock primitives just disable or enable the kernel preemption. Please notice that kernel preemption is still enabled during the busy wait phase, thus a process waiting for a spin lock to be released could be replaced by a higher priority process.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP