diff options
author | Takashi Iwai <tiwai@suse.de> | 2020-02-14 18:16:43 +0100 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2020-02-14 18:17:13 +0100 |
commit | 146f66975bafbcfab349901c9f9c9f521ac96cbb (patch) | |
tree | 0463626fdde9562d85dcabb03b85b8bfd929dce0 /sound/core | |
parent | e9a0ef0b5ddcbc0d56c65aefc0f18d16e6f71207 (diff) | |
download | linux-146f66975bafbcfab349901c9f9c9f521ac96cbb.tar.gz linux-146f66975bafbcfab349901c9f9c9f521ac96cbb.tar.bz2 linux-146f66975bafbcfab349901c9f9c9f521ac96cbb.zip |
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.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core')
-rw-r--r-- | sound/core/oss/pcm_oss.c | 4 |
1 files changed, 4 insertions, 0 deletions
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); |