Commit ec0e3558 authored by Oliver Neukum's avatar Oliver Neukum Committed by Greg Kroah-Hartman

[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
parent 4808f141
...@@ -319,7 +319,9 @@ static int mdc800_usb_waitForIRQ (int mode, int msec) ...@@ -319,7 +319,9 @@ static int mdc800_usb_waitForIRQ (int mode, int msec)
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
if (!mdc800->irq_woken) 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); remove_wait_queue(&mdc800->irq_wait, &wait);
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
...@@ -718,7 +720,9 @@ static ssize_t mdc800_device_read (struct file *file, char *buf, size_t len, lof ...@@ -718,7 +720,9 @@ static ssize_t mdc800_device_read (struct file *file, char *buf, size_t len, lof
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
if (!mdc800->downloaded) 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); set_current_state(TASK_RUNNING);
remove_wait_queue(&mdc800->download_wait, &wait); remove_wait_queue(&mdc800->download_wait, &wait);
...@@ -842,7 +846,9 @@ static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t l ...@@ -842,7 +846,9 @@ static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t l
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
if (!mdc800->written) 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); set_current_state(TASK_RUNNING);
remove_wait_queue(&mdc800->write_wait, &wait); remove_wait_queue(&mdc800->write_wait, &wait);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment