aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
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
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')
-rw-r--r--arch/s390/include/asm/cputime.h2
-rw-r--r--arch/s390/kernel/smp.c28
-rw-r--r--arch/s390/kernel/vtime.c22
3 files changed, 35 insertions, 17 deletions
diff --git a/arch/s390/include/asm/cputime.h b/arch/s390/include/asm/cputime.h
index ec917d42ee6d..7a3817a656df 100644
--- a/arch/s390/include/asm/cputime.h
+++ b/arch/s390/include/asm/cputime.h
@@ -178,7 +178,7 @@ cputime64_to_clock_t(cputime64_t cputime)
178} 178}
179 179
180struct s390_idle_data { 180struct s390_idle_data {
181 spinlock_t lock; 181 unsigned int sequence;
182 unsigned long long idle_count; 182 unsigned long long idle_count;
183 unsigned long long idle_enter; 183 unsigned long long idle_enter;
184 unsigned long long idle_time; 184 unsigned long long idle_time;
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index fd8e3111a4e8..2270730f5354 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -856,13 +856,20 @@ static ssize_t show_idle_count(struct sys_device *dev,
856{ 856{
857 struct s390_idle_data *idle; 857 struct s390_idle_data *idle;
858 unsigned long long idle_count; 858 unsigned long long idle_count;
859 unsigned int sequence;
859 860
860 idle = &per_cpu(s390_idle, dev->id); 861 idle = &per_cpu(s390_idle, dev->id);
861 spin_lock(&idle->lock); 862repeat:
863 sequence = idle->sequence;
864 smp_rmb();
865 if (sequence & 1)
866 goto repeat;
862 idle_count = idle->idle_count; 867 idle_count = idle->idle_count;
863 if (idle->idle_enter) 868 if (idle->idle_enter)
864 idle_count++; 869 idle_count++;
865 spin_unlock(&idle->lock); 870 smp_rmb();
871 if (idle->sequence != sequence)
872 goto repeat;
866 return sprintf(buf, "%llu\n", idle_count); 873 return sprintf(buf, "%llu\n", idle_count);
867} 874}
868static SYSDEV_ATTR(idle_count, 0444, show_idle_count, NULL); 875static SYSDEV_ATTR(idle_count, 0444, show_idle_count, NULL);
@@ -872,15 +879,22 @@ static ssize_t show_idle_time(struct sys_device *dev,
872{ 879{
873 struct s390_idle_data *idle; 880 struct s390_idle_data *idle;
874 unsigned long long now, idle_time, idle_enter; 881 unsigned long long now, idle_time, idle_enter;
882 unsigned int sequence;
875 883
876 idle = &per_cpu(s390_idle, dev->id); 884 idle = &per_cpu(s390_idle, dev->id);
877 spin_lock(&idle->lock);
878 now = get_clock(); 885 now = get_clock();
886repeat:
887 sequence = idle->sequence;
888 smp_rmb();
889 if (sequence & 1)
890 goto repeat;
879 idle_time = idle->idle_time; 891 idle_time = idle->idle_time;
880 idle_enter = idle->idle_enter; 892 idle_enter = idle->idle_enter;
881 if (idle_enter != 0ULL && idle_enter < now) 893 if (idle_enter != 0ULL && idle_enter < now)
882 idle_time += now - idle_enter; 894 idle_time += now - idle_enter;
883 spin_unlock(&idle->lock); 895 smp_rmb();
896 if (idle->sequence != sequence)
897 goto repeat;
884 return sprintf(buf, "%llu\n", idle_time >> 12); 898 return sprintf(buf, "%llu\n", idle_time >> 12);
885} 899}
886static SYSDEV_ATTR(idle_time_us, 0444, show_idle_time, NULL); 900static SYSDEV_ATTR(idle_time_us, 0444, show_idle_time, NULL);
@@ -908,11 +922,7 @@ static int __cpuinit smp_cpu_notify(struct notifier_block *self,
908 case CPU_ONLINE: 922 case CPU_ONLINE:
909 case CPU_ONLINE_FROZEN: 923 case CPU_ONLINE_FROZEN:
910 idle = &per_cpu(s390_idle, cpu); 924 idle = &per_cpu(s390_idle, cpu);
911 spin_lock_irq(&idle->lock); 925 memset(idle, 0, sizeof(struct s390_idle_data));
912 idle->idle_enter = 0;
913 idle->idle_time = 0;
914 idle->idle_count = 0;
915 spin_unlock_irq(&idle->lock);
916 if (sysfs_create_group(&s->kobj, &cpu_online_attr_group)) 926 if (sysfs_create_group(&s->kobj, &cpu_online_attr_group))
917 return NOTIFY_BAD; 927 return NOTIFY_BAD;
918 break; 928 break;
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