等待队列和竞争条件
Wait queue and race condition
我正在阅读 Robert Love 的“Linux 内核开发”并找到下面的代码来等待事件。
DEFINE_WAIT(wait);
add_wait_queue(q, &wait);
while (!condition) {
// What happens if condition is changed and wake_up() is called here ?
prepare_to_wait(&q, &wait, TASK_INTERRUPTIBLE);
if (signal_pending(current))
/* handle signal */
schedule();
}
finish_wait(&q, &wait);
我的问题和上面的代码一样。如果条件更改并且在条件检查之后但在 prepare_to_wait
之前调用 wake_up()
会发生什么情况?
我的(可能是错误的)解释是因为 prepare_to_wait
使线程 TASK_INTERRUPTIBLE
并在条件改变后调用 schedule()
,它会永远休眠(除非它收到信号或另一个 wake_up
被调用)。
是的,这段代码实际上是 raced,在 prepare_to_wait
和 schedule
调用之间它应该是对 condition
的检查(并且满意就破)。
有趣的是,在以下描述中,本书(第 60 页)提到 fs/notify/inotify/inotify_user.c
文件中函数 inotify_read()
的实现:
DEFINE_WAIT(wait);
...
while (1) {
prepare_to_wait(&group->notification_waitq,
&wait,
TASK_INTERRUPTIBLE);
if (<condition>) // very simplified form of checks
break;
if (signal_pending(current))
break;
schedule();
}
finish_wait(&group->notification_waitq, &wait);
...
根据作者的说法“遵循模式”:
This function follows the pattern laid out in our example. The main difference is that
it checks for the condition in the body of the while()
loop, instead of in the while()
statement itself. This is because checking the condition is complicated and requires grabbing locks. The loop is terminated via break
.
但是,该代码展示了另一种模式,它检查prepare_to_wait
和schedule
调用之间的条件。该代码实际上 正确 (无竞争)。
此外,该代码不使用 add_wait_queue
,这在存在 prepare_to_wait
.
的情况下是多余的
在同一作者的另一本书Linux Driver Development (3d revision)中,等待队列的用法似乎更准确。参见例如第 6 章,高级字符驱动程序操作。
我正在阅读 Robert Love 的“Linux 内核开发”并找到下面的代码来等待事件。
DEFINE_WAIT(wait);
add_wait_queue(q, &wait);
while (!condition) {
// What happens if condition is changed and wake_up() is called here ?
prepare_to_wait(&q, &wait, TASK_INTERRUPTIBLE);
if (signal_pending(current))
/* handle signal */
schedule();
}
finish_wait(&q, &wait);
我的问题和上面的代码一样。如果条件更改并且在条件检查之后但在 prepare_to_wait
之前调用 wake_up()
会发生什么情况?
我的(可能是错误的)解释是因为 prepare_to_wait
使线程 TASK_INTERRUPTIBLE
并在条件改变后调用 schedule()
,它会永远休眠(除非它收到信号或另一个 wake_up
被调用)。
是的,这段代码实际上是 raced,在 prepare_to_wait
和 schedule
调用之间它应该是对 condition
的检查(并且满意就破)。
有趣的是,在以下描述中,本书(第 60 页)提到 fs/notify/inotify/inotify_user.c
文件中函数 inotify_read()
的实现:
DEFINE_WAIT(wait);
...
while (1) {
prepare_to_wait(&group->notification_waitq,
&wait,
TASK_INTERRUPTIBLE);
if (<condition>) // very simplified form of checks
break;
if (signal_pending(current))
break;
schedule();
}
finish_wait(&group->notification_waitq, &wait);
...
根据作者的说法“遵循模式”:
This function follows the pattern laid out in our example. The main difference is that it checks for the condition in the body of the
while()
loop, instead of in thewhile()
statement itself. This is because checking the condition is complicated and requires grabbing locks. The loop is terminated viabreak
.
但是,该代码展示了另一种模式,它检查prepare_to_wait
和schedule
调用之间的条件。该代码实际上 正确 (无竞争)。
此外,该代码不使用 add_wait_queue
,这在存在 prepare_to_wait
.
在同一作者的另一本书Linux Driver Development (3d revision)中,等待队列的用法似乎更准确。参见例如第 6 章,高级字符驱动程序操作。