Commit 146f6697 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: pcm: oss: Unlock mutex temporarily for sleeping at read/write

ALSA PCM OSS layer calls the generic __snd_pcm_lib_xfer() helper for
the actual transfer of the audio data.  The xfer helper may sleep long
for waiting for the enough space becoming empty for read/write, and
it does unlock/relock for the substream lock.  This works fine, so
far, but a slight problem specific to OSS layer is that OSS layer
wraps yet more mutex (runtime->oss.params_lock) over
__snd_pcm_lib_xfer() call; so this mutex is still locked during a
possible long sleep, and it prevents the whole ioctl and other actions
applied to the given stream.

This patch adds the temporarily unlock and relock of the mutex around
__snd_pcm_lib_xfer() call in the OSS layer to be more friendly to the
concurrent accesses.  The long mutex protection itself shouldn't be a
real issue for the normal systems, and its influence appears only on
strange things like fuzzers.

Link: https://lore.kernel.org/r/20200214171643.26212-1-tiwai@suse.deSigned-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent e9a0ef0b
...@@ -1217,8 +1217,10 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const ...@@ -1217,8 +1217,10 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const
if (ret < 0) if (ret < 0)
break; break;
} }
mutex_unlock(&runtime->oss.params_lock);
ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true, ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true,
frames, in_kernel); frames, in_kernel);
mutex_lock(&runtime->oss.params_lock);
if (ret != -EPIPE && ret != -ESTRPIPE) if (ret != -EPIPE && ret != -ESTRPIPE)
break; break;
/* test, if we can't store new data, because the stream */ /* test, if we can't store new data, because the stream */
...@@ -1254,8 +1256,10 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p ...@@ -1254,8 +1256,10 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p
ret = snd_pcm_oss_capture_position_fixup(substream, &delay); ret = snd_pcm_oss_capture_position_fixup(substream, &delay);
if (ret < 0) if (ret < 0)
break; break;
mutex_unlock(&runtime->oss.params_lock);
ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true, ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true,
frames, in_kernel); frames, in_kernel);
mutex_lock(&runtime->oss.params_lock);
if (ret == -EPIPE) { if (ret == -EPIPE) {
if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment