问题描述
https://elixir.bootlin.com/linux/v4.5/source/kernel/sched/wait.c#L172
void prepare_to_wait(wait_queue_head_t *q,wait_queue_t *wait,int state)
{
unsigned long flags;
wait->flags &= ~WQ_FLAG_EXCLUSIVE;
spin_lock_irqsave(&q->lock,flags);
if (list_empty(&wait->task_list))
__add_wait_queue(q,wait);
set_current_state(state);
spin_unlock_irqrestore(&q->lock,flags);
}
在上面的代码中,我们可以看到 __ add_wait_queue(q,wait)仅在 list_empty(&wait-> task_list)为true时执行。
为什么&wait-> task_list 不为空,那么 wait 不需要添加到q( wait_queue_head_t )中吗?
这是否意味着如果 wait (wait_queue_t)已在 q (wait_queue_head_t)中,则不要更改它?
解决方法
这是否意味着如果
wait
(wait_queue_head_t)中已经有q
(wait_queue_t),则不要更改它?
是的,分支
if (list_empty(&wait->task_list))
__add_wait_queue(q,wait);
意味着,wait
仅在q
还不属于任何队列时才添加到等待队列wait
中。
否则,如果确定wait
已经属于(某些)等待队列,则假定wait
具体属于q
,并且不再添加。
为对象调用list_empty
函数有一些特定要求,该函数可以是列表的 element (不是列表的头)。
list_empty
始终返回 false 。
但是,如果对象不属于任何列表,则返回值通常为未指定(在大多数情况下,返回值也为 false )。
异常是一个对象,该对象使用INIT_LIST_HEAD
函数或LIST_HEAD_INIT
宏初始化,或者使用list_del_init
函数从列表中删除:在这种情况下,list_empty
返回 true 。
如果在INIT_LIST_HEAD
标头中查找LIST_HEAD_INIT
,list_del_init
或wait.h
的用法,则可以发现prepare_to_wait
函数是仅允许wait
对象使用:
- 使用
DEFINE_WAIT
宏或DEFINE_WAIT_*
宏之一创建。 - 由
init_wait
函数初始化,例如来自wait_event_*
宏之一。 - 已传递给
finish_wait
函数。
但是prepare_to_wait
函数不能用于由wait
宏创建的DECLARE_WAITQUEUE
对象:此宏用{初始化task_list
字段{1}},因此{NULL,NULL}
会为此返回false(就像已经将wait对象添加到wait队列中一样)。