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: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
76439c2ac6
commit
1a1e0a80ce
@ -239,7 +239,6 @@ struct sound_queue {
|
||||
int busy, syncing, xruns, died;
|
||||
};
|
||||
|
||||
#define SLEEP(queue) interruptible_sleep_on_timeout(&queue, HZ)
|
||||
#define WAKE_UP(queue) (wake_up_interruptible(&queue))
|
||||
|
||||
extern struct sound_queue dmasound_write_sq;
|
||||
|
@ -619,15 +619,27 @@ static ssize_t sq_write(struct file *file, const char __user *src, size_t uLeft,
|
||||
}
|
||||
|
||||
while (uLeft) {
|
||||
DEFINE_WAIT(wait);
|
||||
|
||||
while (write_sq.count >= write_sq.max_active) {
|
||||
prepare_to_wait(&write_sq.action_queue, &wait, TASK_INTERRUPTIBLE);
|
||||
sq_play();
|
||||
if (write_sq.non_blocking)
|
||||
if (write_sq.non_blocking) {
|
||||
finish_wait(&write_sq.action_queue, &wait);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
finish_wait(&write_sq.action_queue, &wait);
|
||||
|
||||
/* Here, we can avoid disabling the interrupt by first
|
||||
* copying and translating the data, and then updating
|
||||
* the write_sq variables. Until this is done, the interrupt
|
||||
@ -707,11 +719,8 @@ static int sq_open2(struct sound_queue *sq, struct file *file, fmode_t mode,
|
||||
if (file->f_flags & O_NONBLOCK)
|
||||
return rc;
|
||||
rc = -EINTR;
|
||||
while (sq->busy) {
|
||||
SLEEP(sq->open_queue);
|
||||
if (signal_pending(current))
|
||||
return rc;
|
||||
}
|
||||
if (wait_event_interruptible(sq->open_queue, !sq->busy))
|
||||
return rc;
|
||||
rc = 0;
|
||||
#else
|
||||
/* OSS manual says we will return EBUSY regardless
|
||||
@ -844,7 +853,8 @@ static int sq_fsync(void)
|
||||
sq_play(); /* there may be an incomplete frame waiting */
|
||||
|
||||
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)) {
|
||||
/* While waiting for audio output to drain, an
|
||||
* interrupt occurred. Stop audio output immediately
|
||||
|
Loading…
Reference in New Issue
Block a user