interruptible_sleep_on() vs wait_event_interruptible()

130 views
Skip to first unread message

Wizard

unread,
Dec 2, 2010, 9:36:29 AM12/2/10
to linux-...@zh-kernel.org
我看到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 我没有理解。

另外一个问题就是,我下了有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

Li Yu

unread,
Dec 2, 2010, 8:58:27 PM12/2/10
to Wizard, linux-...@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()函数修改的东西。
> 可能会有些原因上的解释,求教大虾,是要用什么命令去搜索呢?
>

Wizard

unread,
Dec 2, 2010, 11:41:08 PM12/2/10
to Li Yu, linux-...@zh-kernel.org
在 2010年12月3日 上午9:58,Li Yu <raise...@gmail.com> 写道:
>
>
> 于 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

Changli Gao

unread,
Dec 2, 2010, 11:49:57 PM12/2/10
to Wizard, linux-...@zh-kernel.org
2010/12/3 Wizard <wizard...@gmail.com>:

> 那再问一下,
> #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)) { \

上面的这两个判断都是为了防止丢失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)

Wizard

unread,
Dec 3, 2010, 12:14:25 AM12/3/10
to Changli Gao, linux-...@zh-kernel.org

嗯,我现在就是大概了解了。 总之就是wait_event_interruptible是安全的。
虽然还不是很清楚这里面做的具体的事情 和 机制,还是谢谢大家哈

--
Wizard

Américo Wang

unread,
Dec 3, 2010, 2:40:44 AM12/3/10
to Changli Gao, linux-...@zh-kernel.org
On Fri, Dec 03, 2010 at 12:49:57PM +0800, Changli Gao wrote:
>2010/12/3 Wizard <wizard...@gmail.com>:
>> 那再问一下,
>> #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)) { \
>
>上面的这两个判断都是为了防止丢失prepare_to_wait()之前的事件。在prepare之后发生的事件,都会把current的状态变成running,schedule也不会让出CPU,除非当前时间片用完,或者是有更高优先级进程。所以事件不会丢失。信号处理也是这个原因,所以不会丢失信号。


不是吧,就算是在第2个if之后,它还有可能被抢占什么的,也就是说
事件有可能在第2个if和schedule()之间发生。

但是,它有个循环,所以当它醒来的时候会再次检查,这样才保证了不会丢失,
而不是简单的2个if。

BTW,RHEL5中的interruptible_sleep_on()确实连这两个if都没有。

Changli Gao

unread,
Dec 3, 2010, 2:58:09 AM12/3/10
to Américo Wang, linux-...@zh-kernel.org
2010/12/3 Américo Wang <xiyou.w...@gmail.com>:

> On Fri, Dec 03, 2010 at 12:49:57PM +0800, Changli Gao wrote:
>>2010/12/3 Wizard <wizard...@gmail.com>:
>>> 那再问一下,
>>> #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)) { \
>>
>>上面的这两个判断都是为了防止丢失prepare_to_wait()之前的事件。在prepare之后发生的事件,都会把current的状态变成running,schedule也不会让出CPU,除非当前时间片用完,或者是有更高优先级进程。所以事件不会丢失。信号处理也是这个原因,所以不会丢失信号。
>
>
> 不是吧,就算是在第2个if之后,它还有可能被抢占什么的,也就是说
> 事件有可能在第2个if和schedule()之间发生。

事件只要在prepare之后发生就没问题了,因为current已经被加入了wq,事件发生时会wake_up
current,这样后面执行的schedule就不会实际意义上去睡眠。

如果如你所说,第二个if之后事件发生,那么schedule不会睡眠,他迟早要被调度的,即使没有新的事件到来(实际上,新的事件到来,也不会再唤醒current了,因为他已经是醒的了)。然后因为是个循环么,它会跑到if那里检查事件。

>
> 但是,它有个循环,所以当它醒来的时候会再次检查,这样才保证了不会丢失,
> 而不是简单的2个if。
>


--
Regards,
Changli Gao(xia...@gmail.com)

Américo Wang

unread,
Dec 3, 2010, 3:07:54 AM12/3/10
to Wizard, linux-...@zh-kernel.org
On Thu, Dec 02, 2010 at 10:36:29PM +0800, Wizard wrote:
>
>另外一个问题就是,我下了有git版本的源码。 我想从git的log里面看看对interruptible_sleep_on()函数修改的东西。
>可能会有些原因上的解释,求教大虾,是要用什么命令去搜索呢?
>

git blame -L'/interruptible_sleep_on/' kernel/sched.c

Américo Wang

unread,
Dec 3, 2010, 3:37:43 AM12/3/10
to Changli Gao, linux-...@zh-kernel.org
On Fri, Dec 03, 2010 at 03:58:09PM +0800, Changli Gao wrote:
>2010/12/3 Américo Wang <xiyou.w...@gmail.com>:
>> On Fri, Dec 03, 2010 at 12:49:57PM +0800, Changli Gao wrote:
>>>2010/12/3 Wizard <wizard...@gmail.com>:
>>>> 那再问一下,
>>>> #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)) { \
>>>
>>>上面的这两个判断都是为了防止丢失prepare_to_wait()之前的事件。在prepare之后发生的事件,都会把current的状态变成running,schedule也不会让出CPU,除非当前时间片用完,或者是有更高优先级进程。所以事件不会丢失。信号处理也是这个原因,所以不会丢失信号。
>>
>>
>> 不是吧,就算是在第2个if之后,它还有可能被抢占什么的,也就是说
>> 事件有可能在第2个if和schedule()之间发生。
>
>事件只要在prepare之后发生就没问题了,因为current已经被加入了wq,事件发生时会wake_up
>current,这样后面执行的schedule就不会实际意义上去睡眠。
>

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;
...

Changli Gao

unread,
Dec 3, 2010, 3:50:58 AM12/3/10
to Américo Wang, linux-...@zh-kernel.org
2010/12/3 Américo Wang <xiyou.w...@gmail.com>:
> On Fri, Dec 03, 2010 at 03:58:09PM +0800, Changli Gao wrote:
>>2010/12/3 Américo Wang <xiyou.w...@gmail.com>:
>>> On Fri, Dec 03, 2010 at 12:49:57PM +0800, Changli Gao wrote:
>>>>2010/12/3 Wizard <wizard...@gmail.com>:
>>>>> 那再问一下,
>>>>> #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)) { \
>>>>
>>>>上面的这两个判断都是为了防止丢失prepare_to_wait()之前的事件。在prepare之后发生的事件,都会把current的状态变成running,schedule也不会让出CPU,除非当前时间片用完,或者是有更高优先级进程。所以事件不会丢失。信号处理也是这个原因,所以不会丢失信号。
>>>
>>>
>>> 不是吧,就算是在第2个if之后,它还有可能被抢占什么的,也就是说
>>> 事件有可能在第2个if和schedule()之间发生。
>>
>>事件只要在prepare之后发生就没问题了,因为current已经被加入了wq,事件发生时会wake_up
>>current,这样后面执行的schedule就不会实际意义上去睡眠。
>>
>
> interruptible_sleep_on()同样也是先prepare,所以这里的问题不是先不先prepare的问题。

确实是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)

Américo Wang

unread,
Dec 3, 2010, 5:25:33 AM12/3/10
to Changli Gao, linux-...@zh-kernel.org
On Fri, Dec 03, 2010 at 04:50:58PM +0800, Changli Gao wrote:
>2010/12/3 Américo Wang <xiyou.w...@gmail.com>:
>> On Fri, Dec 03, 2010 at 03:58:09PM +0800, Changli Gao wrote:
>>>2010/12/3 Américo Wang <xiyou.w...@gmail.com>:
>>>> On Fri, Dec 03, 2010 at 12:49:57PM +0800, Changli Gao wrote:
>>>>>2010/12/3 Wizard <wizard...@gmail.com>:
>>>>>> 那再问一下,
>>>>>> #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)) { \
>>>>>
>>>>>上面的这两个判断都是为了防止丢失prepare_to_wait()之前的事件。在prepare之后发生的事件,都会把current的状态变成running,schedule也不会让出CPU,除非当前时间片用完,或者是有更高优先级进程。所以事件不会丢失。信号处理也是这个原因,所以不会丢失信号。
>>>>
>>>>
>>>> 不是吧,就算是在第2个if之后,它还有可能被抢占什么的,也就是说
>>>> 事件有可能在第2个if和schedule()之间发生。
>>>
>>>事件只要在prepare之后发生就没问题了,因为current已经被加入了wq,事件发生时会wake_up
>>>current,这样后面执行的schedule就不会实际意义上去睡眠。
>>>
>>
>> interruptible_sleep_on()同样也是先prepare,所以这里的问题不是先不先prepare的问题。
>
>确实是interruptible_sleep_on()虽然没有显示调用 preprare...,但是也有类似代码。但是他prepare之后没有检查条件。
>

最后一个"但是"正是我想说的,而且光if还不够,所以才有那个for(;;)。

Changli Gao

unread,
Dec 3, 2010, 6:07:55 AM12/3/10
to Américo Wang, linux-...@zh-kernel.org
2010/12/3 Américo Wang <xiyou.w...@gmail.com>:

>
> 最后一个"但是"正是我想说的,而且光if还不够,所以才有那个for(;;)。
>

光有if肯定是不行的。只要是事件在schedule之后发生,就需要for(;;),这也是实际中最可能出现的情形。在第二个if之后,current能察觉的事件只有别人对它的wake_up.

--
Regards,
Changli Gao(xia...@gmail.com)

Wizard

unread,
Dec 3, 2010, 8:50:22 PM12/3/10
to Changli Gao, linux-...@zh-kernel.org
2010/12/3 Changli Gao <xia...@gmail.com>:

> 2010/12/3 Américo Wang <xiyou.w...@gmail.com>:
>>
>> 最后一个"但是"正是我想说的,而且光if还不够,所以才有那个for(;;)。
>>
>
> 光有if肯定是不行的。只要是事件在schedule之后发生,就需要for(;;),这也是实际中最可能出现的情形。在第二个if之后,current能察觉的事件只有别人对它的wake_up.
>
> --
> Regards,
> Changli Gao(xia...@gmail.com)
>
额,你们讨论的已经超出了我的理解范围 @@
抓一个重点,意思就是一定要用for循环才能保证不会丢掉事件。仅有两个if是不够的?


--
Wizard

Américo Wang

unread,
Dec 4, 2010, 11:56:30 AM12/4/10
to Changli Gao, linux-...@zh-kernel.org
On Fri, Dec 03, 2010 at 07:07:55PM +0800, Changli Gao wrote:
>2010/12/3 Américo Wang <xiyou.w...@gmail.com>:
>>
>> 最后一个"但是"正是我想说的,而且光if还不够,所以才有那个for(;;)。
>>
>
>光有if肯定是不行的。只要是事件在schedule之后发生,就需要for(;;),这也是实际中最可能出现的情形。在第二个if之后,current能察觉的事件只有别人对它的wake_up.
>

http://zh-kernel.org/pipermail/linux-kernel/2010-December/017499.html

我说过了。:)

--
Live like a child, think like the god.

Reply all
Reply to author
Forward
0 new messages