[S390] lockless idle time accounting
[pandora-kernel.git] / arch / s390 / kernel / vtime.c
index ade17e7..c41bb0d 100644 (file)
@@ -27,9 +27,7 @@
 
 static DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer);
 
-DEFINE_PER_CPU(struct s390_idle_data, s390_idle) = {
-       .lock = __SPIN_LOCK_UNLOCKED(s390_idle.lock)
-};
+DEFINE_PER_CPU(struct s390_idle_data, s390_idle);
 
 static inline __u64 get_vtimer(void)
 {
@@ -151,11 +149,13 @@ void vtime_start_cpu(void)
                vq->elapsed -= vq->idle - S390_lowcore.async_enter_timer;
        }
 
-       spin_lock(&idle->lock);
+       idle->sequence++;
+       smp_wmb();
        idle->idle_time += idle_time;
        idle->idle_enter = 0ULL;
        idle->idle_count++;
-       spin_unlock(&idle->lock);
+       smp_wmb();
+       idle->sequence++;
 }
 
 void vtime_stop_cpu(void)
@@ -242,15 +242,23 @@ cputime64_t s390_get_idle_time(int cpu)
 {
        struct s390_idle_data *idle;
        unsigned long long now, idle_time, idle_enter;
+       unsigned int sequence;
 
        idle = &per_cpu(s390_idle, cpu);
-       spin_lock(&idle->lock);
+
        now = get_clock();
+repeat:
+       sequence = idle->sequence;
+       smp_rmb();
+       if (sequence & 1)
+               goto repeat;
        idle_time = 0;
        idle_enter = idle->idle_enter;
        if (idle_enter != 0ULL && idle_enter < now)
                idle_time = now - idle_enter;
-       spin_unlock(&idle->lock);
+       smp_rmb();
+       if (idle->sequence != sequence)
+               goto repeat;
        return idle_time;
 }