Commit 1a1e0a80 authored by Arnd Bergmann's avatar Arnd Bergmann Committed by Takashi Iwai

sound: oss: dmasound: kill SLEEP() macro to avoid race

The use of interruptible_sleep_on_timeout in the dmasound driver
is questionable and we want to kill off all sleep_on variants.
This replaces the calls with wait_event_interruptible_timeout
where possible, to wait for a particular event instead of blocking
in a racy way. In the sq_write function, the easiest solution is
an open-coded prepare_to_wait loop.
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 76439c2a
...@@ -239,7 +239,6 @@ struct sound_queue { ...@@ -239,7 +239,6 @@ struct sound_queue {
int busy, syncing, xruns, died; int busy, syncing, xruns, died;
}; };
#define SLEEP(queue) interruptible_sleep_on_timeout(&queue, HZ)
#define WAKE_UP(queue) (wake_up_interruptible(&queue)) #define WAKE_UP(queue) (wake_up_interruptible(&queue))
extern struct sound_queue dmasound_write_sq; extern struct sound_queue dmasound_write_sq;
......
...@@ -619,14 +619,26 @@ static ssize_t sq_write(struct file *file, const char __user *src, size_t uLeft, ...@@ -619,14 +619,26 @@ static ssize_t sq_write(struct file *file, const char __user *src, size_t uLeft,
} }
while (uLeft) { while (uLeft) {
DEFINE_WAIT(wait);
while (write_sq.count >= write_sq.max_active) { while (write_sq.count >= write_sq.max_active) {
prepare_to_wait(&write_sq.action_queue, &wait, TASK_INTERRUPTIBLE);
sq_play(); sq_play();
if (write_sq.non_blocking) if (write_sq.non_blocking) {
finish_wait(&write_sq.action_queue, &wait);
return uWritten > 0 ? uWritten : -EAGAIN; return uWritten > 0 ? uWritten : -EAGAIN;
SLEEP(write_sq.action_queue); }
if (signal_pending(current)) if (write_sq.count < write_sq.max_active)
break;
schedule_timeout(HZ);
if (signal_pending(current)) {
finish_wait(&write_sq.action_queue, &wait);
return uWritten > 0 ? uWritten : -EINTR; return uWritten > 0 ? uWritten : -EINTR;
} }
}
finish_wait(&write_sq.action_queue, &wait);
/* Here, we can avoid disabling the interrupt by first /* Here, we can avoid disabling the interrupt by first
* copying and translating the data, and then updating * copying and translating the data, and then updating
...@@ -707,11 +719,8 @@ static int sq_open2(struct sound_queue *sq, struct file *file, fmode_t mode, ...@@ -707,11 +719,8 @@ static int sq_open2(struct sound_queue *sq, struct file *file, fmode_t mode,
if (file->f_flags & O_NONBLOCK) if (file->f_flags & O_NONBLOCK)
return rc; return rc;
rc = -EINTR; rc = -EINTR;
while (sq->busy) { if (wait_event_interruptible(sq->open_queue, !sq->busy))
SLEEP(sq->open_queue);
if (signal_pending(current))
return rc; return rc;
}
rc = 0; rc = 0;
#else #else
/* OSS manual says we will return EBUSY regardless /* OSS manual says we will return EBUSY regardless
...@@ -844,7 +853,8 @@ static int sq_fsync(void) ...@@ -844,7 +853,8 @@ static int sq_fsync(void)
sq_play(); /* there may be an incomplete frame waiting */ sq_play(); /* there may be an incomplete frame waiting */
while (write_sq.active) { while (write_sq.active) {
SLEEP(write_sq.sync_queue); wait_event_interruptible_timeout(write_sq.sync_queue,
!write_sq.active, HZ);
if (signal_pending(current)) { if (signal_pending(current)) {
/* While waiting for audio output to drain, an /* While waiting for audio output to drain, an
* interrupt occurred. Stop audio output immediately * interrupt occurred. Stop audio output immediately
......
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