]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.19.9/alsa-pcm-fix-starvation-on-down_write_nonblock.patch
drop queue-4.14/mips-make-sure-dt-memory-regions-are-valid.patch
[thirdparty/kernel/stable-queue.git] / releases / 4.19.9 / alsa-pcm-fix-starvation-on-down_write_nonblock.patch
1 From b888a5f713e4d17faaaff24316585a4eb07f35b7 Mon Sep 17 00:00:00 2001
2 From: Chanho Min <chanho.min@lge.com>
3 Date: Mon, 26 Nov 2018 14:36:37 +0900
4 Subject: ALSA: pcm: Fix starvation on down_write_nonblock()
5
6 From: Chanho Min <chanho.min@lge.com>
7
8 commit b888a5f713e4d17faaaff24316585a4eb07f35b7 upstream.
9
10 Commit 67ec1072b053 ("ALSA: pcm: Fix rwsem deadlock for non-atomic PCM
11 stream") fixes deadlock for non-atomic PCM stream. But, This patch
12 causes antother stuck.
13 If writer is RT thread and reader is a normal thread, the reader
14 thread will be difficult to get scheduled. It may not give chance to
15 release readlocks and writer gets stuck for a long time if they are
16 pinned to single cpu.
17
18 The deadlock described in the previous commit is because the linux
19 rwsem queues like a FIFO. So, we might need non-FIFO writelock, not
20 non-block one.
21
22 My suggestion is that the writer gives reader a chance to be scheduled
23 by using the minimum msleep() instaed of spinning without blocking by
24 writer. Also, The *_nonblock may be changed to *_nonfifo appropriately
25 to this concept.
26 In terms of performance, when trylock is failed, this minimum periodic
27 msleep will have the same performance as the tick-based
28 schedule()/wake_up_q().
29
30 [ Although this has a fairly high performance penalty, the relevant
31 code path became already rare due to the previous commit ("ALSA:
32 pcm: Call snd_pcm_unlink() conditionally at closing"). That is, now
33 this unconditional msleep appears only when using linked streams,
34 and this must be a rare case. So we accept this as a quick
35 workaround until finding a more suitable one -- tiwai ]
36
37 Fixes: 67ec1072b053 ("ALSA: pcm: Fix rwsem deadlock for non-atomic PCM stream")
38 Suggested-by: Wonmin Jung <wonmin.jung@lge.com>
39 Signed-off-by: Chanho Min <chanho.min@lge.com>
40 Cc: <stable@vger.kernel.org>
41 Signed-off-by: Takashi Iwai <tiwai@suse.de>
42 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
43
44 ---
45 sound/core/pcm_native.c | 11 ++++++-----
46 1 file changed, 6 insertions(+), 5 deletions(-)
47
48 --- a/sound/core/pcm_native.c
49 +++ b/sound/core/pcm_native.c
50 @@ -36,6 +36,7 @@
51 #include <sound/timer.h>
52 #include <sound/minors.h>
53 #include <linux/uio.h>
54 +#include <linux/delay.h>
55
56 #include "pcm_local.h"
57
58 @@ -91,12 +92,12 @@ static DECLARE_RWSEM(snd_pcm_link_rwsem)
59 * and this may lead to a deadlock when the code path takes read sem
60 * twice (e.g. one in snd_pcm_action_nonatomic() and another in
61 * snd_pcm_stream_lock()). As a (suboptimal) workaround, let writer to
62 - * spin until it gets the lock.
63 + * sleep until all the readers are completed without blocking by writer.
64 */
65 -static inline void down_write_nonblock(struct rw_semaphore *lock)
66 +static inline void down_write_nonfifo(struct rw_semaphore *lock)
67 {
68 while (!down_write_trylock(lock))
69 - cond_resched();
70 + msleep(1);
71 }
72
73 #define PCM_LOCK_DEFAULT 0
74 @@ -1967,7 +1968,7 @@ static int snd_pcm_link(struct snd_pcm_s
75 res = -ENOMEM;
76 goto _nolock;
77 }
78 - down_write_nonblock(&snd_pcm_link_rwsem);
79 + down_write_nonfifo(&snd_pcm_link_rwsem);
80 write_lock_irq(&snd_pcm_link_rwlock);
81 if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN ||
82 substream->runtime->status->state != substream1->runtime->status->state ||
83 @@ -2014,7 +2015,7 @@ static int snd_pcm_unlink(struct snd_pcm
84 struct snd_pcm_substream *s;
85 int res = 0;
86
87 - down_write_nonblock(&snd_pcm_link_rwsem);
88 + down_write_nonfifo(&snd_pcm_link_rwsem);
89 write_lock_irq(&snd_pcm_link_rwlock);
90 if (!snd_pcm_stream_linked(substream)) {
91 res = -EALREADY;