为什么在等待为空时仅使用__add_wait_queueq,wait?

问题描述

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_INITlist_del_initwait.h的用法,则可以发现prepare_to_wait函数是仅允许wait对象使用

  1. 使用DEFINE_WAIT宏或DEFINE_WAIT_*宏之一创建。
  2. init_wait函数初始化,例如来自wait_event_*宏之一。
  3. 已传递给finish_wait函数。

但是prepare_to_wait函数不能用于由wait宏创建的DECLARE_WAITQUEUE对象:此宏用{初始化task_list字段{1}},因此{NULL,NULL}会为此返回false(就像已经将wait对象添加到wait队列中一样)。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...