mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
ALSA: pcm: Allow aborting mutex lock at OSS read/write loops
commit 900498a34a upstream.
PCM OSS read/write loops keep taking the mutex lock for the whole
read/write, and this might take very long when the exceptionally high
amount of data is given. Also, since it invokes with mutex_lock(),
the concurrent read/write becomes unbreakable.
This patch tries to address these issues by replacing mutex_lock()
with mutex_lock_interruptible(), and also splits / re-takes the lock
at each read/write period chunk, so that it can switch the context
more finely if requested.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
9bb4bb18cc
commit
fa6c1876ec
@@ -1369,8 +1369,11 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha
|
||||
|
||||
if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)
|
||||
return tmp;
|
||||
mutex_lock(&runtime->oss.params_lock);
|
||||
while (bytes > 0) {
|
||||
if (mutex_lock_interruptible(&runtime->oss.params_lock)) {
|
||||
tmp = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) {
|
||||
tmp = bytes;
|
||||
if (tmp + runtime->oss.buffer_used > runtime->oss.period_bytes)
|
||||
@@ -1414,18 +1417,18 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha
|
||||
xfer += tmp;
|
||||
if ((substream->f_flags & O_NONBLOCK) != 0 &&
|
||||
tmp != runtime->oss.period_bytes)
|
||||
break;
|
||||
tmp = -EAGAIN;
|
||||
}
|
||||
err:
|
||||
mutex_unlock(&runtime->oss.params_lock);
|
||||
if (tmp < 0)
|
||||
break;
|
||||
if (signal_pending(current)) {
|
||||
tmp = -ERESTARTSYS;
|
||||
goto err;
|
||||
break;
|
||||
}
|
||||
tmp = 0;
|
||||
}
|
||||
mutex_unlock(&runtime->oss.params_lock);
|
||||
return xfer;
|
||||
|
||||
err:
|
||||
mutex_unlock(&runtime->oss.params_lock);
|
||||
return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
|
||||
}
|
||||
|
||||
@@ -1473,8 +1476,11 @@ static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __use
|
||||
|
||||
if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)
|
||||
return tmp;
|
||||
mutex_lock(&runtime->oss.params_lock);
|
||||
while (bytes > 0) {
|
||||
if (mutex_lock_interruptible(&runtime->oss.params_lock)) {
|
||||
tmp = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) {
|
||||
if (runtime->oss.buffer_used == 0) {
|
||||
tmp = snd_pcm_oss_read2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1);
|
||||
@@ -1505,16 +1511,16 @@ static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __use
|
||||
bytes -= tmp;
|
||||
xfer += tmp;
|
||||
}
|
||||
err:
|
||||
mutex_unlock(&runtime->oss.params_lock);
|
||||
if (tmp < 0)
|
||||
break;
|
||||
if (signal_pending(current)) {
|
||||
tmp = -ERESTARTSYS;
|
||||
goto err;
|
||||
break;
|
||||
}
|
||||
tmp = 0;
|
||||
}
|
||||
mutex_unlock(&runtime->oss.params_lock);
|
||||
return xfer;
|
||||
|
||||
err:
|
||||
mutex_unlock(&runtime->oss.params_lock);
|
||||
return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user