From d8a35d2c9774adbe4675684f6915703261edd5ef Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 19 Oct 2011 02:36:03 +0000 Subject: [PATCH] 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 --- debian/changelog | 3 + .../all/cputimer-Cure-lock-inversion.patch | 81 +++++++++++++++++++ .../features/all/rt/patch-3.0.6-rt18.patch | 21 ++--- debian/patches/series/6 | 1 + 4 files changed, 96 insertions(+), 10 deletions(-) create mode 100644 debian/patches/bugfix/all/cputimer-Cure-lock-inversion.patch diff --git a/debian/changelog b/debian/changelog index c6cc865e0..d6fdc8a9d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -11,6 +11,9 @@ linux-2.6 (3.0.0-6) UNRELEASED; urgency=low For the complete list of changes, see: http://www.kernel.org/pub/linux/kernel/v3.0/ChangeLog-3.0.7 + [ Ben Hutchings ] + * cputimer: Cure lock inversion + -- Uwe Kleine-König Fri, 07 Oct 2011 15:48:22 +0200 linux-2.6 (3.0.0-5) unstable; urgency=low diff --git a/debian/patches/bugfix/all/cputimer-Cure-lock-inversion.patch b/debian/patches/bugfix/all/cputimer-Cure-lock-inversion.patch new file mode 100644 index 000000000..d77f18f94 --- /dev/null +++ b/debian/patches/bugfix/all/cputimer-Cure-lock-inversion.patch @@ -0,0 +1,81 @@ +From: Peter Zijlstra +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 +Reported-by: Simon Kirby +Signed-off-by: Peter Zijlstra +Cc: stable@kernel.org +Cc: Linus Torvalds +Cc: Martin Schwidefsky +Link: http://lkml.kernel.org/r/1318928713.21167.4.camel@twins +Signed-off-by: Thomas Gleixner +--- + 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 + diff --git a/debian/patches/features/all/rt/patch-3.0.6-rt18.patch b/debian/patches/features/all/rt/patch-3.0.6-rt18.patch index 288920558..4c0fac4a6 100644 --- a/debian/patches/features/all/rt/patch-3.0.6-rt18.patch +++ b/debian/patches/features/all/rt/patch-3.0.6-rt18.patch @@ -1,5 +1,7 @@ [bwh: Dropped fix to kernel/taskstats.c applied separately in 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 =================================================================== @@ -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/kernel/posix-cpu-timers.c -@@ -274,7 +274,7 @@ void thread_group_cputimer(struct task_s - struct task_cputime sum; - unsigned long flags; - -- spin_lock_irqsave(&cputimer->lock, flags); -+ raw_spin_lock_irqsave(&cputimer->lock, flags); - if (!cputimer->running) { +@@ -280,13 +280,13 @@ void thread_group_cputimer(struct task_s + * it. + */ + thread_group_cputime(tsk, &sum); +- spin_lock_irqsave(&cputimer->lock, flags); ++ raw_spin_lock_irqsave(&cputimer->lock, flags); cputimer->running = 1; - /* -@@ -287,7 +287,7 @@ void thread_group_cputimer(struct task_s update_gt_cputime(&cputimer->cputime, &sum); - } + } else +- spin_lock_irqsave(&cputimer->lock, flags); ++ raw_spin_lock_irqsave(&cputimer->lock, flags); *times = cputimer->cputime; - spin_unlock_irqrestore(&cputimer->lock, flags); + raw_spin_unlock_irqrestore(&cputimer->lock, flags); diff --git a/debian/patches/series/6 b/debian/patches/series/6 index e389cbb3b..0c81165bc 100644 --- a/debian/patches/series/6 +++ b/debian/patches/series/6 @@ -1 +1,2 @@ + bugfix/all/stable/3.0.7.patch ++ bugfix/all/cputimer-Cure-lock-inversion.patch