aboutsummaryrefslogtreecommitdiffstats
path: root/sound/oss/dmasound/dmasound_core.c
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2014-01-02 07:07:50 -0500
committerTakashi Iwai <tiwai@suse.de>2014-01-14 10:12:07 -0500
commit1a1e0a80ceb766852e8abd5d4c3d9475611a7d85 (patch)
tree0efe9224215eca736bbf6a06538651eb54b9516f /sound/oss/dmasound/dmasound_core.c
parent76439c2ac686c547ca2f53bfe964c100e697ff4a (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/dmasound/dmasound_core.c')
-rw-r--r--sound/oss/dmasound/dmasound_core.c28
1 files changed, 19 insertions, 9 deletions
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