summarylogtreecommitdiffstats
path: root/fix-race-in-PRT-wait-for-completion-simple-wait-code_Nvidia-RT-160319.patch
diff options
context:
space:
mode:
authorsirlucjan2016-04-02 20:06:24 +0200
committersirlucjan2016-04-02 20:06:24 +0200
commitd43990080a046ad4d9de4e5d11bbc963da28d28b (patch)
tree7d7ffb197f63cfa99855c820a47594d08c050971 /fix-race-in-PRT-wait-for-completion-simple-wait-code_Nvidia-RT-160319.patch
parentdd3d1308452165254e8ad16316a0f0e3a8931cf9 (diff)
downloadaur-d43990080a046ad4d9de4e5d11bbc963da28d28b.tar.gz
Bump to 4.4.6-rt13
Diffstat (limited to 'fix-race-in-PRT-wait-for-completion-simple-wait-code_Nvidia-RT-160319.patch')
-rw-r--r--fix-race-in-PRT-wait-for-completion-simple-wait-code_Nvidia-RT-160319.patch75
1 files changed, 75 insertions, 0 deletions
diff --git a/fix-race-in-PRT-wait-for-completion-simple-wait-code_Nvidia-RT-160319.patch b/fix-race-in-PRT-wait-for-completion-simple-wait-code_Nvidia-RT-160319.patch
new file mode 100644
index 000000000000..7e9e9c825def
--- /dev/null
+++ b/fix-race-in-PRT-wait-for-completion-simple-wait-code_Nvidia-RT-160319.patch
@@ -0,0 +1,75 @@
+From: Joakim Hernberg <jhernberg@alchemy.lu>
+Date: Sat, 19 Mar 2016 13:03:55 +0100
+Subject: [PATCH] Fix a race in the PRT wait for completion simple wait code
+ for NVIDIA on the rt patch
+
+-Note refactored again 160319.
+
+-NOTE: this patch is a rebase of John Blackwood's patch. On his kernel, he must be using
+-an older simple wait patch - as his applies to kernel/sched/core.c, while the simple wait
+-completion code lives in kernel/sched/completion.c ... I have ported this to test with
+-nvidia, as i would like to see if it fixes the semaphore issues i have seen.
+
+-I've kept the original patch comment in tact;
+
+I'm not 100% sure that the patch below will fix your problem, but we
+saw something that sounds pretty familiar to your issue involving the
+nvidia driver and the preempt-rt patch. The nvidia driver uses the
+completion support to create their own driver's notion of an internally
+used semaphore.
+
+Fix a race in the PRT wait for completion simple wait code.
+
+A wait_for_completion() waiter task can be awoken by a task calling
+complete(), but fail to consume the 'done' completion resource if it
+looses a race with another task calling wait_for_completion() just as
+it is waking up.
+
+In this case, the awoken task will call schedule_timeout() again
+without being in the simple wait queue.
+
+So if the awoken task is unable to claim the 'done' completion resource,
+check to see if it needs to be re-inserted into the wait list before
+waiting again in schedule_timeout().
+
+Fix-by: John Blackwood <john.blackwood@ccur.com>
+
+---
+ kernel/sched/completion.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/kernel/sched/completion.c b/kernel/sched/completion.c
+index b62cf64..c01bbd8 100644
+--- a/kernel/sched/completion.c
++++ b/kernel/sched/completion.c
+@@ -61,11 +61,19 @@ static inline long __sched
+ do_wait_for_common(struct completion *x,
+ long (*action)(long), long timeout, int state)
+ {
++ int again = 0;
++
+ if (!x->done) {
+ DECLARE_SWAITQUEUE(wait);
+
+ __prepare_to_swait(&x->wait, &wait);
+ do {
++ /* Check to see if we lost race for 'done' and are
++ * no longer in the wait list.
++ */
++ if (unlikely(again) && list_empty(&wait.task_list))
++ __prepare_to_swait(&x->wait, &wait);
++
+ if (signal_pending_state(state, current)) {
+ timeout = -ERESTARTSYS;
+ break;
+@@ -74,6 +82,7 @@ do_wait_for_common(struct completion *x,
+ raw_spin_unlock_irq(&x->wait.lock);
+ timeout = action(timeout);
+ raw_spin_lock_irq(&x->wait.lock);
++ again = 1;
+ } while (!x->done && timeout);
+ __finish_swait(&x->wait, &wait);
+ if (!x->done)
+--
+2.7.2
+