diff options
author | Arnd Bergmann <arnd@arndb.de> | 2014-01-02 07:07:50 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2014-01-14 10:12:07 -0500 |
commit | 1a1e0a80ceb766852e8abd5d4c3d9475611a7d85 (patch) | |
tree | 0efe9224215eca736bbf6a06538651eb54b9516f /sound/oss | |
parent | 76439c2ac686c547ca2f53bfe964c100e697ff4a (diff) |
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>
Diffstat (limited to 'sound/oss')
-rw-r--r-- | sound/oss/dmasound/dmasound.h | 1 | ||||
-rw-r--r-- | sound/oss/dmasound/dmasound_core.c | 28 |
2 files changed, 19 insertions, 10 deletions
diff --git a/sound/oss/dmasound/dmasound.h b/sound/oss/dmasound/dmasound.h index 1308d8d34186..01019f06fa91 100644 --- a/sound/oss/dmasound/dmasound.h +++ b/sound/oss/dmasound/dmasound.h | |||
@@ -239,7 +239,6 @@ struct sound_queue { | |||
239 | int busy, syncing, xruns, died; | 239 | int busy, syncing, xruns, died; |
240 | }; | 240 | }; |
241 | 241 | ||
242 | #define SLEEP(queue) interruptible_sleep_on_timeout(&queue, HZ) | ||
243 | #define WAKE_UP(queue) (wake_up_interruptible(&queue)) | 242 | #define WAKE_UP(queue) (wake_up_interruptible(&queue)) |
244 | 243 | ||
245 | extern struct sound_queue dmasound_write_sq; | 244 | extern struct sound_queue dmasound_write_sq; |
diff --git a/sound/oss/dmasound/dmasound_core.c b/sound/oss/dmasound/dmasound_core.c index bac43b5b6e95..f4ee85a4c42f 100644 --- a/sound/oss/dmasound/dmasound_core.c +++ b/sound/oss/dmasound/dmasound_core.c | |||
@@ -619,15 +619,27 @@ static ssize_t sq_write(struct file *file, const char __user *src, size_t uLeft, | |||
619 | } | 619 | } |
620 | 620 | ||
621 | while (uLeft) { | 621 | while (uLeft) { |
622 | DEFINE_WAIT(wait); | ||
623 | |||
622 | while (write_sq.count >= write_sq.max_active) { | 624 | while (write_sq.count >= write_sq.max_active) { |
625 | prepare_to_wait(&write_sq.action_queue, &wait, TASK_INTERRUPTIBLE); | ||
623 | sq_play(); | 626 | sq_play(); |
624 | if (write_sq.non_blocking) | 627 | if (write_sq.non_blocking) { |
628 | finish_wait(&write_sq.action_queue, &wait); | ||
625 | return uWritten > 0 ? uWritten : -EAGAIN; | 629 | return uWritten > 0 ? uWritten : -EAGAIN; |
626 | SLEEP(write_sq.action_queue); | 630 | } |
627 | if (signal_pending(current)) | 631 | if (write_sq.count < write_sq.max_active) |
632 | break; | ||
633 | |||
634 | schedule_timeout(HZ); | ||
635 | if (signal_pending(current)) { | ||
636 | finish_wait(&write_sq.action_queue, &wait); | ||
628 | return uWritten > 0 ? uWritten : -EINTR; | 637 | return uWritten > 0 ? uWritten : -EINTR; |
638 | } | ||
629 | } | 639 | } |
630 | 640 | ||
641 | finish_wait(&write_sq.action_queue, &wait); | ||
642 | |||
631 | /* Here, we can avoid disabling the interrupt by first | 643 | /* Here, we can avoid disabling the interrupt by first |
632 | * copying and translating the data, and then updating | 644 | * copying and translating the data, and then updating |
633 | * the write_sq variables. Until this is done, the interrupt | 645 | * 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, | |||
707 | if (file->f_flags & O_NONBLOCK) | 719 | if (file->f_flags & O_NONBLOCK) |
708 | return rc; | 720 | return rc; |
709 | rc = -EINTR; | 721 | rc = -EINTR; |
710 | while (sq->busy) { | 722 | if (wait_event_interruptible(sq->open_queue, !sq->busy)) |
711 | SLEEP(sq->open_queue); | 723 | return rc; |
712 | if (signal_pending(current)) | ||
713 | return rc; | ||
714 | } | ||
715 | rc = 0; | 724 | rc = 0; |
716 | #else | 725 | #else |
717 | /* OSS manual says we will return EBUSY regardless | 726 | /* OSS manual says we will return EBUSY regardless |
@@ -844,7 +853,8 @@ static int sq_fsync(void) | |||
844 | sq_play(); /* there may be an incomplete frame waiting */ | 853 | sq_play(); /* there may be an incomplete frame waiting */ |
845 | 854 | ||
846 | while (write_sq.active) { | 855 | while (write_sq.active) { |
847 | SLEEP(write_sq.sync_queue); | 856 | wait_event_interruptible_timeout(write_sq.sync_queue, |
857 | !write_sq.active, HZ); | ||
848 | if (signal_pending(current)) { | 858 | if (signal_pending(current)) { |
849 | /* While waiting for audio output to drain, an | 859 | /* While waiting for audio output to drain, an |
850 | * interrupt occurred. Stop audio output immediately | 860 | * interrupt occurred. Stop audio output immediately |