免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12345下一页
最近访问板块 发新帖
查看: 13604 | 回复: 43

[内核同步] 关中断或关软中断后,禁抢占是否必要 [复制链接]

论坛徽章:
0
发表于 2012-06-01 16:29 |显示全部楼层
关中断或关软中断后,当前进程不可能发生切换,或者说被抢占,为什么要禁抢占呢,岂不是多此一举?

代码如下:
        
void __lockfunc _spin_lock_irq(spinlock_t *lock)
{      
        local_irq_disable();
        preempt_disable();
        spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
        _raw_spin_lock(lock);
}      
EXPORT_SYMBOL(_spin_lock_irq);

void __lockfunc _spin_lock_bh(spinlock_t *lock)
{              
        local_bh_disable();
        preempt_disable();
        spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
        _raw_spin_lock(lock);
}        

关中断后,cpu执行下面的代码在中断重新打开之前不可能被打断,所以不可能切换到别的进程,所以即使不禁抢占,抢占也不可能发生。
关软中断后,cpu虽可被中断中断,但中断处理过程中肯定不会切换,中断恢复时由于current_thread_info()->preempt_count不为零(关软中断保证这一点)也不会切换,所以即使不禁中断,抢占也不会发生。 为什么两种情况一定要preempt_disable()呢?

论坛徽章:
0
发表于 2012-06-01 16:32 |显示全部楼层
书写有误。 应该是:所以即使不禁抢占,抢占也不会发生

论坛徽章:
0
发表于 2012-06-01 17:36 |显示全部楼层
自己主动让出cpu呢

论坛徽章:
0
发表于 2012-06-01 18:13 |显示全部楼层
运行在临界区,怎会自己主动让出呢。

论坛徽章:
2
CU大牛徽章
日期:2013-04-17 11:46:28CU大牛徽章
日期:2013-04-17 11:46:39
发表于 2012-06-01 18:46 |显示全部楼层
禁止其他cpu进入

论坛徽章:
0
发表于 2012-06-01 19:39 |显示全部楼层
如果在临界区中, 唤醒某一线程 wake_up_interruptible
在这个函数里面, 是否会发生调度? (如果不禁止内核抢占的话)

论坛徽章:
0
发表于 2012-06-02 12:11 |显示全部楼层
本帖最后由 honkiko 于 2012-06-02 22:13 编辑

回复 1# zhenggn123

有同样的想法。

只想到,如果有人写下面这样的代码,而spin_lock_irq又没有preempt_disable()的话,就有问题了。
spin_lock_irq()
...
local_irq_enable()
...                             /* --> could be preempted with spinlock held*/
spin_unlock()
   

论坛徽章:
1
双鱼座
日期:2013-08-28 13:47:26
发表于 2012-06-02 14:28 |显示全部楼层
回复 1# zhenggn123
会不会是和preempt_count本身的定义有关系,加锁等同于显示的禁止抢占,所以preempt_count值要加1。

   

论坛徽章:
3
15-16赛季CBA联赛之山东
日期:2016-10-30 08:47:3015-16赛季CBA联赛之佛山
日期:2016-12-17 00:06:31CU十四周年纪念徽章
日期:2017-12-03 01:04:02
发表于 2012-06-03 06:29 |显示全部楼层
本帖最后由 captivated 于 2012-06-03 06:54 编辑

回复 8# firkraag

嗯... 基本同意你的看法, 以下是我个人的想法, 请指正:

1. LZ给的代码好像就是某个内核函数的实现? 可以想像, 调用这个函数的时候, 是在内核进程上下文中.

2. preempt_disable()的实现是增加preempt_count:
  #define preempt_disable() \
  do { \
      inc_preempt_count(); \
      barrier(); \
  } while (0)
内核抢占在抢占之前都会检查 preempt_count, 如果 preempt_count 不为 0 则无法抢占.

3. 内核抢占发生的时机是在中断处理程序完成返回内核空间之前(或者显式地调用schedule()). 既然禁止了本地处理器的所有中断, 意味着时钟中断也是禁止的. 这样的话本地处理器上的内核调度根本没机会发生.

4. 个人猜测, 在smp系统上, 考虑到其它处理机的存在, 其它的处理器是可以调度的. 虽然某种程度上来说, 每个处理器只会调度自己的task队列, 但是考虑到这里处于内核空间(加上处理器负载均衡之类的?...) -- 因此其它的处理器可能有机会调度到这里并接着执行余下的代码? -- 由于其它的处理器并没有禁止中断, (假设这里没有preempt_disable的话)又发现preempt_count不为0, 所以可能发生调度?

期待正解ing...

论坛徽章:
1
双鱼座
日期:2013-08-28 13:47:26
发表于 2012-06-03 09:35 |显示全部楼层
本帖最后由 firkraag 于 2012-06-03 09:38 编辑

回复 9# captivated
1 该函数出现在.8以后.34以前,这个是内核自旋锁,一般应用于内核态不可睡眠时。
2 是的。
3 是的。
4 load balancing不会移动正在运行的remote进程。   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP