I thought I commented on it. Your saying "when the driver
decides to sleep and when the sleep_on is performed" is correct according to
me. This window is the cause of problem.
他说的这个window 我没有理解。
另外一个问题就是,我下了有git版本的源码。 我想从git的log里面看看对interruptible_sleep_on()函数修改的东西。
可能会有些原因上的解释,求教大虾,是要用什么命令去搜索呢?
--
Wizard
_______________________________________________
Linux 内核开发中文邮件列表
Linux-...@zh-kernel.org
http://zh-kernel.org/mailman/listinfo/linux-kernel
Linux 内核开发中文社区: http://zh-kernel.org
于 2010年12月02日 22:36, Wizard 写道:
> 我看到kernelnewbies的邮件列表上有这么一个讨论。
> 说 interruptible_sleep_on()是会有竞争的。但是邮件上分析的原因,我确实没有看懂。
> 连接是 http://mail.nl.linux.org/kernelnewbies/2006-09/msg00329.html
> 内容有这么一段
>> I dont care if it is depreceated or not. I just want to know why it is
>> depreceated.
>
> I thought I commented on it. Your saying "when the driver
> decides to sleep and when the sleep_on is performed" is correct according to
> me. This window is the cause of problem.
>
> 他说的这个window 我没有理解。
>
指的是“判断休眠条件”与“开始休眠”之间的这个时间差。也许你可以参考一下LDD中的介绍?
> 另外一个问题就是,我下了有git版本的源码。 我想从git的log里面看看对interruptible_sleep_on()函数修改的东西。
> 可能会有些原因上的解释,求教大虾,是要用什么命令去搜索呢?
>
哦 这个意思啊,嗯。。 。 这个概念我在ldd3上看到过的。
wait_event_interruptible在sleep之前,确实会再次判断条件是否符合,防止这期间唤醒的事件被丢失。
那就是说interruptible_sleep_on没有做第二次判断?所以会丢失这个事件?
那再问一下,
#define __wait_event_interruptible(wq, condition, ret) \
264 do { \
265 DEFINE_WAIT(__wait); \
266 \
267 for (;;) { \
268 prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE); \
269 if (condition) \
270 break; \
271 if (!signal_pending(current)) { \
272 schedule(); \
273 continue; \
274 } \
275 ret = -ERESTARTSYS; \
276 break; \
277 } \
278 finish_wait(&wq, &__wait); \
279 } while (0)
上面代码的 if(condition) 后 还是要判断signal_pending()的。
那这段时间要是发生的唤醒的事件,不是也会有竞争么?
--
Wizard
上面的这两个判断都是为了防止丢失prepare_to_wait()之前的事件。在prepare之后发生的事件,都会把current的状态变成running,schedule也不会让出CPU,除非当前时间片用完,或者是有更高优先级进程。所以事件不会丢失。信号处理也是这个原因,所以不会丢失信号。
> 272 schedule(); \
> 273 continue; \
> 274 } \
> 275 ret = -ERESTARTSYS; \
> 276 break; \
> 277 } \
> 278 finish_wait(&wq, &__wait); \
> 279 } while (0)
>
> 上面代码的 if(condition) 后 还是要判断signal_pending()的。
> 那这段时间要是发生的唤醒的事件,不是也会有竞争么?
>
--
Regards,
Changli Gao(xia...@gmail.com)
嗯,我现在就是大概了解了。 总之就是wait_event_interruptible是安全的。
虽然还不是很清楚这里面做的具体的事情 和 机制,还是谢谢大家哈
--
Wizard
不是吧,就算是在第2个if之后,它还有可能被抢占什么的,也就是说
事件有可能在第2个if和schedule()之间发生。
但是,它有个循环,所以当它醒来的时候会再次检查,这样才保证了不会丢失,
而不是简单的2个if。
BTW,RHEL5中的interruptible_sleep_on()确实连这两个if都没有。
事件只要在prepare之后发生就没问题了,因为current已经被加入了wq,事件发生时会wake_up
current,这样后面执行的schedule就不会实际意义上去睡眠。
如果如你所说,第二个if之后事件发生,那么schedule不会睡眠,他迟早要被调度的,即使没有新的事件到来(实际上,新的事件到来,也不会再唤醒current了,因为他已经是醒的了)。然后因为是个循环么,它会跑到if那里检查事件。
>
> 但是,它有个循环,所以当它醒来的时候会再次检查,这样才保证了不会丢失,
> 而不是简单的2个if。
>
--
Regards,
Changli Gao(xia...@gmail.com)
git blame -L'/interruptible_sleep_on/' kernel/sched.c
interruptible_sleep_on()同样也是先prepare,所以这里的问题不是先不先prepare的问题。
>如果如你所说,第二个if之后事件发生,那么schedule不会睡眠,他迟早要被调度的,即使没有新的事件到来(实际上,新的事件到来,也不会再唤醒current了,因为他已经是醒的了)。然后因为是个循环么,它会跑到if那里检查事件。
>
请问下面这种情况为什么不睡眠?UP。
Process A Process B
wait_event_interruptible()
for(;;){
prepare_to_wait();
if..
if..
<=== preempt
condition = true;
preempt ===>
schedule(); wake_up(A);
continue;
...
确实是interruptible_sleep_on()虽然没有显示调用 preprare...,但是也有类似代码。但是他prepare之后没有检查条件。
>
>
>>如果如你所说,第二个if之后事件发生,那么schedule不会睡眠,他迟早要被调度的,即使没有新的事件到来(实际上,新的事件到来,也不会再唤醒current了,因为他已经是醒的了)。然后因为是个循环么,它会跑到if那里检查事件。
>>
>
> 请问下面这种情况为什么不睡眠?UP。
>
> Process A Process B
>
> wait_event_interruptible()
> for(;;){
> prepare_to_wait();
> if..
> if..
> <=== preempt
> condition = true;
> preempt ===>
> schedule(); wake_up(A);
> continue;
> ...
> }
>
你说的情形是会睡眠。不过我说的是B调用wake_up后,再被A抢占,或者是把CPU给A,这个时候再调用schedule是不会睡眠的。
--
Regards,
Changli Gao(xia...@gmail.com)
最后一个"但是"正是我想说的,而且光if还不够,所以才有那个for(;;)。
光有if肯定是不行的。只要是事件在schedule之后发生,就需要for(;;),这也是实际中最可能出现的情形。在第二个if之后,current能察觉的事件只有别人对它的wake_up.
--
Regards,
Changli Gao(xia...@gmail.com)
--
Wizard
http://zh-kernel.org/pipermail/linux-kernel/2010-December/017499.html
我说过了。:)
--
Live like a child, think like the god.