aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/vtime.c
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2009-06-22 06:08:20 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2009-06-22 06:08:23 -0400
commite98bbaafcd1c47d30f3245517fb585f1aaaca4db (patch)
tree8c8c88910db0197acc92bf1ddef999816f1a778b /arch/s390/kernel/vtime.c
parent4f0076f77fb64889d4e5e425b63333e5764b446d (diff)
[S390] lockless idle time accounting
Replace the spinlock used in the idle time accounting with a sequence counter mechanism analog to seqlock. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel/vtime.c')
-rw-r--r--arch/s390/kernel/vtime.c22
1 files changed, 15 insertions, 7 deletions
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index ade17e771f05..c41bb0d416e1 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -27,9 +27,7 @@
27 27
28static DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer); 28static DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer);
29 29
30DEFINE_PER_CPU(struct s390_idle_data, s390_idle) = { 30DEFINE_PER_CPU(struct s390_idle_data, s390_idle);
31 .lock = __SPIN_LOCK_UNLOCKED(s390_idle.lock)
32};
33 31
34static inline __u64 get_vtimer(void) 32static inline __u64 get_vtimer(void)
35{ 33{
@@ -151,11 +149,13 @@ void vtime_start_cpu(void)
151 vq->elapsed -= vq->idle - S390_lowcore.async_enter_timer; 149 vq->elapsed -= vq->idle - S390_lowcore.async_enter_timer;
152 } 150 }
153 151
154 spin_lock(&idle->lock); 152 idle->sequence++;
153 smp_wmb();
155 idle->idle_time += idle_time; 154 idle->idle_time += idle_time;
156 idle->idle_enter = 0ULL; 155 idle->idle_enter = 0ULL;
157 idle->idle_count++; 156 idle->idle_count++;
158 spin_unlock(&idle->lock); 157 smp_wmb();
158 idle->sequence++;
159} 159}
160 160
161void vtime_stop_cpu(void) 161void vtime_stop_cpu(void)
@@ -242,15 +242,23 @@ cputime64_t s390_get_idle_time(int cpu)
242{ 242{
243 struct s390_idle_data *idle; 243 struct s390_idle_data *idle;
244 unsigned long long now, idle_time, idle_enter; 244 unsigned long long now, idle_time, idle_enter;
245 unsigned int sequence;
245 246
246 idle = &per_cpu(s390_idle, cpu); 247 idle = &per_cpu(s390_idle, cpu);
247 spin_lock(&idle->lock); 248
248 now = get_clock(); 249 now = get_clock();
250repeat:
251 sequence = idle->sequence;
252 smp_rmb();
253 if (sequence & 1)
254 goto repeat;
249 idle_time = 0; 255 idle_time = 0;
250 idle_enter = idle->idle_enter; 256 idle_enter = idle->idle_enter;
251 if (idle_enter != 0ULL && idle_enter < now) 257 if (idle_enter != 0ULL && idle_enter < now)
252 idle_time = now - idle_enter; 258 idle_time = now - idle_enter;
253 spin_unlock(&idle->lock); 259 smp_rmb();
260 if (idle->sequence != sequence)
261 goto repeat;
254 return idle_time; 262 return idle_time;
255} 263}
256 264