diff mbox series

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

Message ID 20200214171643.26212-1-tiwai@suse.de (mailing list archive)
State New, archived
Headers show
Series ALSA: pcm: oss: Unlock mutex temporarily for sleeping at read/write | expand

Commit Message

Takashi Iwai Feb. 14, 2020, 5:16 p.m. UTC
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.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/core/oss/pcm_oss.c | 4 ++++
 1 file changed, 4 insertions(+)
diff mbox series

Patch

diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 707eb2a9d50c..930def8201f4 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -1217,8 +1217,10 @@  snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const
 			if (ret < 0)
 				break;
 		}
+		mutex_unlock(&runtime->oss.params_lock);
 		ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true,
 					 frames, in_kernel);
+		mutex_lock(&runtime->oss.params_lock);
 		if (ret != -EPIPE && ret != -ESTRPIPE)
 			break;
 		/* 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
 		ret = snd_pcm_oss_capture_position_fixup(substream, &delay);
 		if (ret < 0)
 			break;
+		mutex_unlock(&runtime->oss.params_lock);
 		ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true,
 					 frames, in_kernel);
+		mutex_lock(&runtime->oss.params_lock);
 		if (ret == -EPIPE) {
 			if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
 				ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);