diff options
author | Rik van Riel <riel@redhat.com> | 2014-09-30 15:59:47 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2014-10-02 23:46:55 -0400 |
commit | 347abad981c1ef815ea5ba861adba6a8c6aa1580 (patch) | |
tree | ea18690dcb71d23c29a92a602c1d5373f9360e7a | |
parent | 43f4d66637bc752e93a77ff2536474a5a3888442 (diff) |
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@arndb.de>
Signed-off-by: Rik van Riel <riel@redhat.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: umgwanakikbuti@gmail.com
Cc: fweisbec@gmail.com
Cc: srao@redhat.com
Cc: lwoodman@redhat.com
Cc: atheurer@redhat.com
Cc: oleg@redhat.com
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Paul Mackerras <paulus@samba.org>
Cc: linux390@de.ibm.com
Cc: linux-arch@vger.kernel.org
Cc: linuxppc-dev@lists.ozlabs.org
Cc: linux-s390@vger.kernel.org
Link: http://lkml.kernel.org/r/20140930155947.070cdb1f@annuminas.surriel.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | arch/powerpc/include/asm/cputime.h | 2 | ||||
-rw-r--r-- | arch/s390/include/asm/cputime.h | 2 | ||||
-rw-r--r-- | include/asm-generic/cputime_jiffies.h | 2 | ||||
-rw-r--r-- | include/asm-generic/cputime_nsecs.h | 2 | ||||
-rw-r--r-- | 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 607559ab271f..6c840ceab820 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) { } | |||
32 | typedef u64 __nocast cputime_t; | 32 | typedef u64 __nocast cputime_t; |
33 | typedef u64 __nocast cputime64_t; | 33 | typedef u64 __nocast cputime64_t; |
34 | 34 | ||
35 | #define cmpxchg_cputime(ptr, old, new) cmpxchg(ptr, old, new) | ||
36 | |||
35 | #ifdef __KERNEL__ | 37 | #ifdef __KERNEL__ |
36 | 38 | ||
37 | /* | 39 | /* |
diff --git a/arch/s390/include/asm/cputime.h b/arch/s390/include/asm/cputime.h index f65bd3634519..3001887f94b7 100644 --- a/arch/s390/include/asm/cputime.h +++ b/arch/s390/include/asm/cputime.h | |||
@@ -18,6 +18,8 @@ | |||
18 | typedef unsigned long long __nocast cputime_t; | 18 | typedef unsigned long long __nocast cputime_t; |
19 | typedef unsigned long long __nocast cputime64_t; | 19 | typedef unsigned long long __nocast cputime64_t; |
20 | 20 | ||
21 | #define cmpxchg_cputime(ptr, old, new) cmpxchg64(ptr, old, new) | ||
22 | |||
21 | static inline unsigned long __div(unsigned long long n, unsigned long base) | 23 | static inline unsigned long __div(unsigned long long n, unsigned long base) |
22 | { | 24 | { |
23 | #ifndef CONFIG_64BIT | 25 | #ifndef CONFIG_64BIT |
diff --git a/include/asm-generic/cputime_jiffies.h b/include/asm-generic/cputime_jiffies.h index d5cb78f53986..fe386fc6e85e 100644 --- a/include/asm-generic/cputime_jiffies.h +++ b/include/asm-generic/cputime_jiffies.h | |||
@@ -3,6 +3,8 @@ | |||
3 | 3 | ||
4 | typedef unsigned long __nocast cputime_t; | 4 | typedef unsigned long __nocast cputime_t; |
5 | 5 | ||
6 | #define cmpxchg_cputime(ptr, old, new) cmpxchg(ptr, old, new) | ||
7 | |||
6 | #define cputime_one_jiffy jiffies_to_cputime(1) | 8 | #define cputime_one_jiffy jiffies_to_cputime(1) |
7 | #define cputime_to_jiffies(__ct) (__force unsigned long)(__ct) | 9 | #define cputime_to_jiffies(__ct) (__force unsigned long)(__ct) |
8 | #define cputime_to_scaled(__ct) (__ct) | 10 | #define cputime_to_scaled(__ct) (__ct) |
diff --git a/include/asm-generic/cputime_nsecs.h b/include/asm-generic/cputime_nsecs.h index 4e817606c549..0419485891f2 100644 --- a/include/asm-generic/cputime_nsecs.h +++ b/include/asm-generic/cputime_nsecs.h | |||
@@ -21,6 +21,8 @@ | |||
21 | typedef u64 __nocast cputime_t; | 21 | typedef u64 __nocast cputime_t; |
22 | typedef u64 __nocast cputime64_t; | 22 | typedef u64 __nocast cputime64_t; |
23 | 23 | ||
24 | #define cmpxchg_cputime(ptr, old, new) cmpxchg64(ptr, old, new) | ||
25 | |||
24 | #define cputime_one_jiffy jiffies_to_cputime(1) | 26 | #define cputime_one_jiffy jiffies_to_cputime(1) |
25 | 27 | ||
26 | #define cputime_div(__ct, divisor) div_u64((__force u64)__ct, divisor) | 28 | #define cputime_div(__ct, divisor) div_u64((__force u64)__ct, divisor) |
diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c index 64492dff8a81..8394b1ee600c 100644 --- a/kernel/sched/cputime.c +++ b/kernel/sched/cputime.c | |||
@@ -555,6 +555,23 @@ drop_precision: | |||
555 | } | 555 | } |
556 | 556 | ||
557 | /* | 557 | /* |
558 | * Atomically advance counter to the new value. Interrupts, vcpu | ||
559 | * scheduling, and scaling inaccuracies can cause cputime_advance | ||
560 | * to be occasionally called with a new value smaller than counter. | ||
561 | * Let's enforce atomicity. | ||
562 | * | ||
563 | * Normally a caller will only go through this loop once, or not | ||
564 | * at all in case a previous caller updated counter the same jiffy. | ||
565 | */ | ||
566 | static void cputime_advance(cputime_t *counter, cputime_t new) | ||
567 | { | ||
568 | cputime_t old; | ||
569 | |||
570 | while (new > (old = ACCESS_ONCE(*counter))) | ||
571 | cmpxchg_cputime(counter, old, new); | ||
572 | } | ||
573 | |||
574 | /* | ||
558 | * Adjust tick based cputime random precision against scheduler | 575 | * Adjust tick based cputime random precision against scheduler |
559 | * runtime accounting. | 576 | * runtime accounting. |
560 | */ | 577 | */ |
@@ -599,16 +616,8 @@ static void cputime_adjust(struct task_cputime *curr, | |||
599 | utime = rtime - stime; | 616 | utime = rtime - stime; |
600 | } | 617 | } |
601 | 618 | ||
602 | /* | 619 | cputime_advance(&prev->stime, stime); |
603 | * If the tick based count grows faster than the scheduler one, | 620 | cputime_advance(&prev->utime, utime); |
604 | * the result of the scaling may go backward. | ||
605 | * Let's enforce monotonicity. | ||
606 | * Atomic exchange protects against concurrent cputime_adjust(). | ||
607 | */ | ||
608 | while (stime > (rtime = ACCESS_ONCE(prev->stime))) | ||
609 | cmpxchg(&prev->stime, rtime, stime); | ||
610 | while (utime > (rtime = ACCESS_ONCE(prev->utime))) | ||
611 | cmpxchg(&prev->utime, rtime, utime); | ||
612 | 621 | ||
613 | out: | 622 | out: |
614 | *ut = prev->utime; | 623 | *ut = prev->utime; |