Reputation: 1184
I'm reading "Linux Kernel Development" by Robert Love and found the code below to wait for an event.
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);
My question is as in the code above. What happens if condition is changed and wake_up()
is called after condition check but before prepare_to_wait
?
My (probably wrong) interpretation here is that because prepare_to_wait
makes the thread TASK_INTERRUPTIBLE
and calls schedule()
after the condition is changed, it sleeps forever (unless it gets signaled or another wake_up
is called).
Upvotes: 2
Views: 841
Reputation: 65870
Yes, this code is actually raced, between prepare_to_wait
and schedule
calls it should be a check for the condition
(and breaking if it is satisfied).
Funny enough, in the following description the book refers (at page 60) to the implementation of function inotify_read()
in fs/notify/inotify/inotify_user.c
file:
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);
...
which according to the author "follows the pattern":
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
.
However, that code exhibits another pattern, which checks the condition between prepare_to_wait
and schedule
call. And that code is actually correct (race-free).
Also that code doesn't use add_wait_queue
, which is superfluous in presence of prepare_to_wait
.
In another book of the same author, Linux Driver Development (3d revision), usage of wait queues seems to be more accurate. See e.g. chapter 6, Advanced Char Driver Operations.
Upvotes: 5