diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2009-06-22 06:08:20 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2009-06-22 06:08:23 -0400 |
commit | e98bbaafcd1c47d30f3245517fb585f1aaaca4db (patch) | |
tree | 8c8c88910db0197acc92bf1ddef999816f1a778b /arch/s390/kernel/vtime.c | |
parent | 4f0076f77fb64889d4e5e425b63333e5764b446d (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.c | 22 |
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 | ||
28 | static DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer); | 28 | static DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer); |
29 | 29 | ||
30 | DEFINE_PER_CPU(struct s390_idle_data, s390_idle) = { | 30 | DEFINE_PER_CPU(struct s390_idle_data, s390_idle); |
31 | .lock = __SPIN_LOCK_UNLOCKED(s390_idle.lock) | ||
32 | }; | ||
33 | 31 | ||
34 | static inline __u64 get_vtimer(void) | 32 | static 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 | ||
161 | void vtime_stop_cpu(void) | 161 | void 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(); |
250 | repeat: | ||
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 | ||