s390/vtime: correct idle time calculation
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Mon, 28 Oct 2013 11:15:32 +0000 (12:15 +0100)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Thu, 31 Oct 2013 08:52:52 +0000 (09:52 +0100)
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.

Cc: stable@vger.kernel.org # 3.6+
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/kernel/smp.c
arch/s390/kernel/vtime.c

index 739313db71e5e2431f32c59472cdaa89ccbae2ef..dc4a534650604a972967ab5dedd2c1b7155c29ad 100644 (file)
@@ -920,7 +920,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);
@@ -938,7 +938,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 e312c48a1c405741a4e1675002aa9bf16003f821..8c34363d6f1e88571074b01593b1efaa80c007d0 100644 (file)
@@ -191,7 +191,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;
 }