cputimer: Cure lock inversion
Fix regression introduced in 3.0.7. Update the rt patch accordingly. svn path=/dists/sid/linux-2.6/; revision=18171
This commit is contained in:
parent
2c1c73c51b
commit
d8a35d2c97
|
@ -11,6 +11,9 @@ linux-2.6 (3.0.0-6) UNRELEASED; urgency=low
|
||||||
For the complete list of changes, see:
|
For the complete list of changes, see:
|
||||||
http://www.kernel.org/pub/linux/kernel/v3.0/ChangeLog-3.0.7
|
http://www.kernel.org/pub/linux/kernel/v3.0/ChangeLog-3.0.7
|
||||||
|
|
||||||
|
[ Ben Hutchings ]
|
||||||
|
* cputimer: Cure lock inversion
|
||||||
|
|
||||||
-- Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Fri, 07 Oct 2011 15:48:22 +0200
|
-- Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Fri, 07 Oct 2011 15:48:22 +0200
|
||||||
|
|
||||||
linux-2.6 (3.0.0-5) unstable; urgency=low
|
linux-2.6 (3.0.0-5) unstable; urgency=low
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
From: Peter Zijlstra <a.p.zijlstra@chello.nl>
|
||||||
|
Date: Mon, 17 Oct 2011 11:50:30 +0200
|
||||||
|
Subject: [PATCH] cputimer: Cure lock inversion
|
||||||
|
|
||||||
|
commit bcd5cff7216f9b2de0a148cc355eac199dc6f1cf upstream.
|
||||||
|
|
||||||
|
There's a lock inversion between the cputimer->lock and rq->lock;
|
||||||
|
notably the two callchains involved are:
|
||||||
|
|
||||||
|
update_rlimit_cpu()
|
||||||
|
sighand->siglock
|
||||||
|
set_process_cpu_timer()
|
||||||
|
cpu_timer_sample_group()
|
||||||
|
thread_group_cputimer()
|
||||||
|
cputimer->lock
|
||||||
|
thread_group_cputime()
|
||||||
|
task_sched_runtime()
|
||||||
|
->pi_lock
|
||||||
|
rq->lock
|
||||||
|
|
||||||
|
scheduler_tick()
|
||||||
|
rq->lock
|
||||||
|
task_tick_fair()
|
||||||
|
update_curr()
|
||||||
|
account_group_exec()
|
||||||
|
cputimer->lock
|
||||||
|
|
||||||
|
Where the first one is enabling a CLOCK_PROCESS_CPUTIME_ID timer, and
|
||||||
|
the second one is keeping up-to-date.
|
||||||
|
|
||||||
|
This problem was introduced by e8abccb7193 ("posix-cpu-timers: Cure
|
||||||
|
SMP accounting oddities").
|
||||||
|
|
||||||
|
Cure the problem by removing the cputimer->lock and rq->lock nesting,
|
||||||
|
this leaves concurrent enablers doing duplicate work, but the time
|
||||||
|
wasted should be on the same order otherwise wasted spinning on the
|
||||||
|
lock and the greater-than assignment filter should ensure we preserve
|
||||||
|
monotonicity.
|
||||||
|
|
||||||
|
Reported-by: Dave Jones <davej@redhat.com>
|
||||||
|
Reported-by: Simon Kirby <sim@hostway.ca>
|
||||||
|
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
|
||||||
|
Cc: stable@kernel.org
|
||||||
|
Cc: Linus Torvalds <torvalds@linux-foundation.org>
|
||||||
|
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
|
||||||
|
Link: http://lkml.kernel.org/r/1318928713.21167.4.camel@twins
|
||||||
|
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||||
|
---
|
||||||
|
kernel/posix-cpu-timers.c | 7 ++++---
|
||||||
|
1 files changed, 4 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
|
||||||
|
index c8008dd..640ded8 100644
|
||||||
|
--- a/kernel/posix-cpu-timers.c
|
||||||
|
+++ b/kernel/posix-cpu-timers.c
|
||||||
|
@@ -274,9 +274,7 @@ void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times)
|
||||||
|
struct task_cputime sum;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
- spin_lock_irqsave(&cputimer->lock, flags);
|
||||||
|
if (!cputimer->running) {
|
||||||
|
- cputimer->running = 1;
|
||||||
|
/*
|
||||||
|
* The POSIX timer interface allows for absolute time expiry
|
||||||
|
* values through the TIMER_ABSTIME flag, therefore we have
|
||||||
|
@@ -284,8 +282,11 @@ void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times)
|
||||||
|
* it.
|
||||||
|
*/
|
||||||
|
thread_group_cputime(tsk, &sum);
|
||||||
|
+ spin_lock_irqsave(&cputimer->lock, flags);
|
||||||
|
+ cputimer->running = 1;
|
||||||
|
update_gt_cputime(&cputimer->cputime, &sum);
|
||||||
|
- }
|
||||||
|
+ } else
|
||||||
|
+ spin_lock_irqsave(&cputimer->lock, flags);
|
||||||
|
*times = cputimer->cputime;
|
||||||
|
spin_unlock_irqrestore(&cputimer->lock, flags);
|
||||||
|
}
|
||||||
|
--
|
||||||
|
1.7.7
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
[bwh: Dropped fix to kernel/taskstats.c applied separately in
|
[bwh: Dropped fix to kernel/taskstats.c applied separately in
|
||||||
bugfix/all/Make-TASKSTATS-require-root-access.patch]
|
bugfix/all/Make-TASKSTATS-require-root-access.patch]
|
||||||
|
[bwh: Updated raw spinlock changes in kernel/posix-cput-timers.c to apply after
|
||||||
|
bugfix/all/cputime-Cure-lock-inversion.patch]
|
||||||
|
|
||||||
Index: linux-2.6/mm/memory.c
|
Index: linux-2.6/mm/memory.c
|
||||||
===================================================================
|
===================================================================
|
||||||
|
@ -5964,18 +5966,17 @@ Index: linux-2.6/kernel/posix-cpu-timers.c
|
||||||
===================================================================
|
===================================================================
|
||||||
--- linux-2.6.orig/kernel/posix-cpu-timers.c
|
--- linux-2.6.orig/kernel/posix-cpu-timers.c
|
||||||
+++ linux-2.6/kernel/posix-cpu-timers.c
|
+++ linux-2.6/kernel/posix-cpu-timers.c
|
||||||
@@ -274,7 +274,7 @@ void thread_group_cputimer(struct task_s
|
@@ -280,13 +280,13 @@ void thread_group_cputimer(struct task_s
|
||||||
struct task_cputime sum;
|
* it.
|
||||||
unsigned long flags;
|
*/
|
||||||
|
thread_group_cputime(tsk, &sum);
|
||||||
- spin_lock_irqsave(&cputimer->lock, flags);
|
- spin_lock_irqsave(&cputimer->lock, flags);
|
||||||
+ raw_spin_lock_irqsave(&cputimer->lock, flags);
|
+ raw_spin_lock_irqsave(&cputimer->lock, flags);
|
||||||
if (!cputimer->running) {
|
|
||||||
cputimer->running = 1;
|
cputimer->running = 1;
|
||||||
/*
|
|
||||||
@@ -287,7 +287,7 @@ void thread_group_cputimer(struct task_s
|
|
||||||
update_gt_cputime(&cputimer->cputime, &sum);
|
update_gt_cputime(&cputimer->cputime, &sum);
|
||||||
}
|
} else
|
||||||
|
- spin_lock_irqsave(&cputimer->lock, flags);
|
||||||
|
+ raw_spin_lock_irqsave(&cputimer->lock, flags);
|
||||||
*times = cputimer->cputime;
|
*times = cputimer->cputime;
|
||||||
- spin_unlock_irqrestore(&cputimer->lock, flags);
|
- spin_unlock_irqrestore(&cputimer->lock, flags);
|
||||||
+ raw_spin_unlock_irqrestore(&cputimer->lock, flags);
|
+ raw_spin_unlock_irqrestore(&cputimer->lock, flags);
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
+ bugfix/all/stable/3.0.7.patch
|
+ bugfix/all/stable/3.0.7.patch
|
||||||
|
+ bugfix/all/cputimer-Cure-lock-inversion.patch
|
||||||
|
|
Loading…
Reference in New Issue