From 5afdbd6e84c7fbdaa7cfde4cbee0d3a5f4f56da2 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 15 May 2006 09:43:59 -0700 Subject: [PATCH] s390: exploit rcu_needs_cpu() interface Exploit rcu_needs_cpu() interface to keep the cpu 'ticking' if necessary. Signed-off-by: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/kernel/time.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'arch/s390/kernel/time.c') diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index fea043b69b9..029f09901b8 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -249,18 +249,19 @@ static inline void stop_hz_timer(void) unsigned long flags; unsigned long seq, next; __u64 timer, todval; + int cpu = smp_processor_id(); if (sysctl_hz_timer != 0) return; - cpu_set(smp_processor_id(), nohz_cpu_mask); + cpu_set(cpu, nohz_cpu_mask); /* * Leave the clock comparator set up for the next timer * tick if either rcu or a softirq is pending. */ - if (rcu_pending(smp_processor_id()) || local_softirq_pending()) { - cpu_clear(smp_processor_id(), nohz_cpu_mask); + if (rcu_needs_cpu(cpu) || local_softirq_pending()) { + cpu_clear(cpu, nohz_cpu_mask); return; } -- cgit v1.2.3 From 92f63cd000059366af18712367216d96180e0ec0 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Sat, 20 May 2006 15:00:25 -0700 Subject: [PATCH] s390: next_timer_interrupt overflow in stop_hz_timer The 32 bit unsigned substraction (next - jiffies) in stop_hz_timer can overflow if jiffies gets advanced between next_timer_interrupt and the read under the xtime lock. The cast to a u64 then results in a large value which causes the cpu to wait too long. Fix this by casting next and jiffies independently to u64 before subtracting them. (Spotted by Zachary Amsden ) Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/kernel/time.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/s390/kernel/time.c') diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 029f09901b8..ce19ad4e92e 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -272,7 +272,7 @@ static inline void stop_hz_timer(void) next = next_timer_interrupt(); do { seq = read_seqbegin_irqsave(&xtime_lock, flags); - timer = (__u64)(next - jiffies) + jiffies_64; + timer = (__u64 next) - (__u64 jiffies) + jiffies_64; } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); todval = -1ULL; /* Be careful about overflows. */ -- cgit v1.2.3