ChangeSet 1.1587.3.49, 2004/05/11 15:45:25-07:00, oliver@neukum.org [PATCH] USB: fixes of assumptions about waitqueues quoting Linus: -- > so there is no need to recheck the bit in do/while loop, because > there is no false wakeups now. You should never assume this. You should assume that there are _always_ false wakeups. Why? Because Linux has always allowed people to leave wait-queues active, without being "atomic". For example, the tty read/write layer used to (still does?) add itself on the wait-queue _once_, and then leave itself on the wait-queue while in a loop it does copies from/to user space. -- Unfortunately, this means us. Here's the first fix. Comments? - make sure timeouts are observed even if somebody left us on a queue drivers/usb/image/mdc800.c | 12 +++++++++--- 1 files changed, 9 insertions(+), 3 deletions(-) diff -Nru a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c --- a/drivers/usb/image/mdc800.c Fri May 14 15:28:47 2004 +++ b/drivers/usb/image/mdc800.c Fri May 14 15:28:47 2004 @@ -319,7 +319,9 @@ set_current_state(TASK_INTERRUPTIBLE); if (!mdc800->irq_woken) { - schedule_timeout (msec*HZ/1000); + long timeout = msec*HZ/1000; + while(timeout) + timeout = schedule_timeout (timeout); } remove_wait_queue(&mdc800->irq_wait, &wait); set_current_state(TASK_RUNNING); @@ -718,7 +720,9 @@ set_current_state(TASK_INTERRUPTIBLE); if (!mdc800->downloaded) { - schedule_timeout (TO_DOWNLOAD_GET_READY*HZ/1000); + long timeout = TO_DOWNLOAD_GET_READY*HZ/1000; + while(timeout) + timeout = schedule_timeout (timeout); } set_current_state(TASK_RUNNING); remove_wait_queue(&mdc800->download_wait, &wait); @@ -842,7 +846,9 @@ set_current_state(TASK_INTERRUPTIBLE); if (!mdc800->written) { - schedule_timeout (TO_WRITE_GET_READY*HZ/1000); + long timeout = TO_WRITE_GET_READY*HZ/1000; + while(timeout) + timeout = schedule_timeout (timeout); } set_current_state(TASK_RUNNING); remove_wait_queue(&mdc800->write_wait, &wait);