s390/vtime: correct idle time calculation
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Mon, 28 Oct 2013 11:15:32 +0000 (12:15 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 29 Nov 2013 19:11:53 +0000 (11:11 -0800)
commit 4560e7c3317c7a2b370e36dadd3a3bac2ed70818 upstream.

Use the ACCESS_ONCE macro for both accesses to idle->sequence in the
loops to calculate the idle time. If only one access uses the macro,
the compiler is free to cache the value for the second access which
can cause endless loops.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/s390/kernel/smp.c
arch/s390/kernel/vtime.c

index 4f977d0d25c2d1b1af674314a0b3da263d602b5a..14647fe09d0cd6e1a1d956405bd147769235bb4d 100644 (file)
@@ -933,7 +933,7 @@ static ssize_t show_idle_count(struct device *dev,
                idle_count = ACCESS_ONCE(idle->idle_count);
                if (ACCESS_ONCE(idle->clock_idle_enter))
                        idle_count++;
-       } while ((sequence & 1) || (idle->sequence != sequence));
+       } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));
        return sprintf(buf, "%llu\n", idle_count);
 }
 static DEVICE_ATTR(idle_count, 0444, show_idle_count, NULL);
@@ -951,7 +951,7 @@ static ssize_t show_idle_time(struct device *dev,
                idle_time = ACCESS_ONCE(idle->idle_time);
                idle_enter = ACCESS_ONCE(idle->clock_idle_enter);
                idle_exit = ACCESS_ONCE(idle->clock_idle_exit);
-       } while ((sequence & 1) || (idle->sequence != sequence));
+       } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));
        idle_time += idle_enter ? ((idle_exit ? : now) - idle_enter) : 0;
        return sprintf(buf, "%llu\n", idle_time >> 12);
 }
index 3fb09359eda621b65eba743a2c704376225fb844..737d50caa4feac06c5af1a89d0123c470c7d5fc8 100644 (file)
@@ -190,7 +190,7 @@ cputime64_t s390_get_idle_time(int cpu)
                sequence = ACCESS_ONCE(idle->sequence);
                idle_enter = ACCESS_ONCE(idle->clock_idle_enter);
                idle_exit = ACCESS_ONCE(idle->clock_idle_exit);
-       } while ((sequence & 1) || (idle->sequence != sequence));
+       } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));
        return idle_enter ? ((idle_exit ?: now) - idle_enter) : 0;
 }