[tip:sched/core] sched, time: Fix build error with 64 bit cputime_t on 32 bit systems

From: tip-bot for Rik van Riel
Date: Fri Oct 03 2014 - 01:29:13 EST


Commit-ID: 347abad981c1ef815ea5ba861adba6a8c6aa1580
Gitweb: http://git.kernel.org/tip/347abad981c1ef815ea5ba861adba6a8c6aa1580
Author: Rik van Riel <riel@xxxxxxxxxx>
AuthorDate: Tue, 30 Sep 2014 15:59:47 -0400
Committer: Ingo Molnar <mingo@xxxxxxxxxx>
CommitDate: Fri, 3 Oct 2014 05:46:55 +0200

sched, time: Fix build error with 64 bit cputime_t on 32 bit systems

On 32 bit systems cmpxchg cannot handle 64 bit values, so
some additional magic is required to allow a 32 bit system
with CONFIG_VIRT_CPU_ACCOUNTING_GEN=y enabled to build.

Make sure the correct cmpxchg function is used when doing
an atomic swap of a cputime_t.

Reported-by: Arnd Bergmann <arnd@xxxxxxxx>
Signed-off-by: Rik van Riel <riel@xxxxxxxxxx>
Acked-by: Arnd Bergmann <arnd@xxxxxxxx>
Signed-off-by: Peter Zijlstra (Intel) <peterz@xxxxxxxxxxxxx>
Cc: umgwanakikbuti@xxxxxxxxx
Cc: fweisbec@xxxxxxxxx
Cc: srao@xxxxxxxxxx
Cc: lwoodman@xxxxxxxxxx
Cc: atheurer@xxxxxxxxxx
Cc: oleg@xxxxxxxxxx
Cc: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>
Cc: Benjamin Herrenschmidt <benh@xxxxxxxxxxxxxxxxxxx>
Cc: Heiko Carstens <heiko.carstens@xxxxxxxxxx>
Cc: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx>
Cc: Martin Schwidefsky <schwidefsky@xxxxxxxxxx>
Cc: Michael Ellerman <mpe@xxxxxxxxxxxxxx>
Cc: Paul Mackerras <paulus@xxxxxxxxx>
Cc: linux390@xxxxxxxxxx
Cc: linux-arch@xxxxxxxxxxxxxxx
Cc: linuxppc-dev@xxxxxxxxxxxxxxxx
Cc: linux-s390@xxxxxxxxxxxxxxx
Link: http://lkml.kernel.org/r/20140930155947.070cdb1f@xxxxxxxxxxxxxxxxxxxxx
Signed-off-by: Ingo Molnar <mingo@xxxxxxxxxx>
---
arch/powerpc/include/asm/cputime.h | 2 ++
arch/s390/include/asm/cputime.h | 2 ++
include/asm-generic/cputime_jiffies.h | 2 ++
include/asm-generic/cputime_nsecs.h | 2 ++
kernel/sched/cputime.c | 29 +++++++++++++++++++----------
5 files changed, 27 insertions(+), 10 deletions(-)

diff --git a/arch/powerpc/include/asm/cputime.h b/arch/powerpc/include/asm/cputime.h
index 607559a..6c840ce 100644
--- a/arch/powerpc/include/asm/cputime.h
+++ b/arch/powerpc/include/asm/cputime.h
@@ -32,6 +32,8 @@ static inline void setup_cputime_one_jiffy(void) { }
typedef u64 __nocast cputime_t;
typedef u64 __nocast cputime64_t;

+#define cmpxchg_cputime(ptr, old, new) cmpxchg(ptr, old, new)
+
#ifdef __KERNEL__

/*
diff --git a/arch/s390/include/asm/cputime.h b/arch/s390/include/asm/cputime.h
index f65bd36..3001887 100644
--- a/arch/s390/include/asm/cputime.h
+++ b/arch/s390/include/asm/cputime.h
@@ -18,6 +18,8 @@
typedef unsigned long long __nocast cputime_t;
typedef unsigned long long __nocast cputime64_t;

+#define cmpxchg_cputime(ptr, old, new) cmpxchg64(ptr, old, new)
+
static inline unsigned long __div(unsigned long long n, unsigned long base)
{
#ifndef CONFIG_64BIT
diff --git a/include/asm-generic/cputime_jiffies.h b/include/asm-generic/cputime_jiffies.h
index d5cb78f5..fe386fc 100644
--- a/include/asm-generic/cputime_jiffies.h
+++ b/include/asm-generic/cputime_jiffies.h
@@ -3,6 +3,8 @@

typedef unsigned long __nocast cputime_t;

+#define cmpxchg_cputime(ptr, old, new) cmpxchg(ptr, old, new)
+
#define cputime_one_jiffy jiffies_to_cputime(1)
#define cputime_to_jiffies(__ct) (__force unsigned long)(__ct)
#define cputime_to_scaled(__ct) (__ct)
diff --git a/include/asm-generic/cputime_nsecs.h b/include/asm-generic/cputime_nsecs.h
index 4e81760..0419485 100644
--- a/include/asm-generic/cputime_nsecs.h
+++ b/include/asm-generic/cputime_nsecs.h
@@ -21,6 +21,8 @@
typedef u64 __nocast cputime_t;
typedef u64 __nocast cputime64_t;

+#define cmpxchg_cputime(ptr, old, new) cmpxchg64(ptr, old, new)
+
#define cputime_one_jiffy jiffies_to_cputime(1)

#define cputime_div(__ct, divisor) div_u64((__force u64)__ct, divisor)
diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c
index 64492df..8394b1e 100644
--- a/kernel/sched/cputime.c
+++ b/kernel/sched/cputime.c
@@ -555,6 +555,23 @@ drop_precision:
}

/*
+ * Atomically advance counter to the new value. Interrupts, vcpu
+ * scheduling, and scaling inaccuracies can cause cputime_advance
+ * to be occasionally called with a new value smaller than counter.
+ * Let's enforce atomicity.
+ *
+ * Normally a caller will only go through this loop once, or not
+ * at all in case a previous caller updated counter the same jiffy.
+ */
+static void cputime_advance(cputime_t *counter, cputime_t new)
+{
+ cputime_t old;
+
+ while (new > (old = ACCESS_ONCE(*counter)))
+ cmpxchg_cputime(counter, old, new);
+}
+
+/*
* Adjust tick based cputime random precision against scheduler
* runtime accounting.
*/
@@ -599,16 +616,8 @@ static void cputime_adjust(struct task_cputime *curr,
utime = rtime - stime;
}

- /*
- * If the tick based count grows faster than the scheduler one,
- * the result of the scaling may go backward.
- * Let's enforce monotonicity.
- * Atomic exchange protects against concurrent cputime_adjust().
- */
- while (stime > (rtime = ACCESS_ONCE(prev->stime)))
- cmpxchg(&prev->stime, rtime, stime);
- while (utime > (rtime = ACCESS_ONCE(prev->utime)))
- cmpxchg(&prev->utime, rtime, utime);
+ cputime_advance(&prev->stime, stime);
+ cputime_advance(&prev->utime, utime);

out:
*ut = prev->utime;
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/