Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -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;
+19 −9
Original line number Diff line number Diff line
@@ -619,14 +619,26 @@ 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
@@ -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))
			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