Re: Lots of bugs with current->state = TASK_*INTERRUPTIBLE

Steven Rostedt
2010-01-21T17:31:34Z

On Thu, 2010-01-21 at 11:47 +0100, Julia Lawall wrote:
> What about something like the following (drivers/macintosh/adb.c):
>
> add_wait_queue(&state->wait_queue, &wait);
> current->state = TASK_INTERRUPTIBLE;
>
> for (;;) {
> req = state->completed;
> if (req != NULL)
> state->completed = req->next;
> else if (atomic_read(&state->n_pending) = 0)
> ret = -EIO;
> if (req != NULL || ret != 0)
> break;
>
> if (file->f_flags & O_NONBLOCK) {
> ret = -EAGAIN;
> break;
> }
> if (signal_pending(current)) {
> ret = -ERESTARTSYS;
> break;
> }
> spin_unlock_irqrestore(&state->lock, flags);
> schedule();
> spin_lock_irqsave(&state->lock, flags);
> }
>
> current->state = TASK_RUNNING;
> remove_wait_queue(&state->wait_queue, &wait);
>
> There is a call to schedule eventually after the first current->state
> assignment, but it is not right after.

I looked at this code in a bit more detail. Seems that it does not need
the set_current_state(), because all activities between the state of the
task and the variables being checked (state->n_pending, et al) are under
the state->lock.

But there should be a comment stating that above the assignment of
current->state. Something like:

/*
* No need for the set_current_state() memory barrier since
* all checks between state and wakeups are done under the
* state->lock.
*/
current->state = TASK_INTERRUPTIBLE;

But I'd rather have the author of this code write that.

-- Steve