[tip:timers/urgent] hrtimer: migration: do not check expiry time on current CPU

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Commit-ID:  7e0c5086c172ecf8b0c2ad860b02a586967d17d0
Gitweb:     http://git.kernel.org/tip/7e0c5086c172ecf8b0c2ad860b02a586967d17d0
Author:     Thomas Gleixner <tglx@xxxxxxxxxxxxx>
AuthorDate: Thu, 9 Jul 2009 13:52:32 +0200
Committer:  Thomas Gleixner <tglx@xxxxxxxxxxxxx>
CommitDate: Fri, 10 Jul 2009 17:22:20 +0200

hrtimer: migration: do not check expiry time on current CPU

The timer migration code needs to check whether the expiry time of the
timer is before the programmed clock event expiry time when the timer
is enqueued on another CPU because we can not reprogram the timer
device on the other CPU. The current logic checks the expiry time even
if we enqueue on the current CPU when nohz_get_load_balancer() returns
current CPU. This might lead to an endless loop in the expiry check
code when the expiry time of the timer is before the current
programmed next event.

Check whether nohz_get_load_balancer() returns current CPU and skip
the expiry check if this is the case.

The bug was triggered from the networking code. The patch fixes the
regression http://bugzilla.kernel.org/show_bug.cgi?id=13738
(Soft-Lockup/Race in networking in 2.6.31-rc1+195)

Cc: Arun Bharadwaj <arun@xxxxxxxxxxxxxxxxxx
Tested-by: Joao Correia <joaomiguelcorreia@xxxxxxxxx>
Tested-by: Andres Freund <andres@xxxxxxxxxxx>
Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx>


---
 kernel/hrtimer.c |   15 +++++++++++++--
 1 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index 9002958..126b980 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -206,8 +206,19 @@ switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_clock_base *base,
 #if defined(CONFIG_NO_HZ) && defined(CONFIG_SMP)
 	if (!pinned && get_sysctl_timer_migration() && idle_cpu(cpu)) {
 		preferred_cpu = get_nohz_load_balancer();
-		if (preferred_cpu >= 0)
-			cpu = preferred_cpu;
+		if (preferred_cpu >= 0) {
+			/*
+			 * We must not check the expiry value when
+			 * preferred_cpu is the current cpu. If base
+			 * != new_base we would loop forever when the
+			 * timer expires before the current programmed
+			 * next timer event.
+			 */
+			if (preferred_cpu != cpu)
+				cpu = preferred_cpu;
+			else
+				preferred_cpu = -1;
+		}
 	}
 #endif
 
--
To unsubscribe from this list: send the line "unsubscribe linux-tip-commits" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Stable Commits]     [Linux Stable Kernel]     [Linux Kernel]     [Linux USB Devel]     [Linux Video &Media]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux