diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2015-09-18 10:41:36 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2015-09-30 10:22:38 -0400 |
commit | 72d38b19781de457def0a62dfaa50134fc6e15f0 (patch) | |
tree | 142bbab792f048ffbad3980f11150a19f47c4604 /arch/s390/kernel/vtime.c | |
parent | adc0b7fbf6fe9967505c0254d9535ec7288186ae (diff) |
s390/vtime: correct scaled cputime of partially idle CPUs
The calculation for the SMT scaling factor for a hardware thread
which has been partially idle needs to disregard the cycles spent
by the other threads of the core while the thread is idle.
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 | 66 |
1 files changed, 37 insertions, 29 deletions
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index c8653435c70d..dafc44f519c3 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c | |||
@@ -25,7 +25,7 @@ static DEFINE_SPINLOCK(virt_timer_lock); | |||
25 | static atomic64_t virt_timer_current; | 25 | static atomic64_t virt_timer_current; |
26 | static atomic64_t virt_timer_elapsed; | 26 | static atomic64_t virt_timer_elapsed; |
27 | 27 | ||
28 | static DEFINE_PER_CPU(u64, mt_cycles[32]); | 28 | DEFINE_PER_CPU(u64, mt_cycles[8]); |
29 | static DEFINE_PER_CPU(u64, mt_scaling_mult) = { 1 }; | 29 | static DEFINE_PER_CPU(u64, mt_scaling_mult) = { 1 }; |
30 | static DEFINE_PER_CPU(u64, mt_scaling_div) = { 1 }; | 30 | static DEFINE_PER_CPU(u64, mt_scaling_div) = { 1 }; |
31 | static DEFINE_PER_CPU(u64, mt_scaling_jiffies); | 31 | static DEFINE_PER_CPU(u64, mt_scaling_jiffies); |
@@ -60,6 +60,34 @@ static inline int virt_timer_forward(u64 elapsed) | |||
60 | return elapsed >= atomic64_read(&virt_timer_current); | 60 | return elapsed >= atomic64_read(&virt_timer_current); |
61 | } | 61 | } |
62 | 62 | ||
63 | static void update_mt_scaling(void) | ||
64 | { | ||
65 | u64 cycles_new[8], *cycles_old; | ||
66 | u64 delta, fac, mult, div; | ||
67 | int i; | ||
68 | |||
69 | stcctm5(smp_cpu_mtid + 1, cycles_new); | ||
70 | cycles_old = this_cpu_ptr(mt_cycles); | ||
71 | fac = 1; | ||
72 | mult = div = 0; | ||
73 | for (i = 0; i <= smp_cpu_mtid; i++) { | ||
74 | delta = cycles_new[i] - cycles_old[i]; | ||
75 | div += delta; | ||
76 | mult *= i + 1; | ||
77 | mult += delta * fac; | ||
78 | fac *= i + 1; | ||
79 | } | ||
80 | div *= fac; | ||
81 | if (div > 0) { | ||
82 | /* Update scaling factor */ | ||
83 | __this_cpu_write(mt_scaling_mult, mult); | ||
84 | __this_cpu_write(mt_scaling_div, div); | ||
85 | memcpy(cycles_old, cycles_new, | ||
86 | sizeof(u64) * (smp_cpu_mtid + 1)); | ||
87 | } | ||
88 | __this_cpu_write(mt_scaling_jiffies, jiffies_64); | ||
89 | } | ||
90 | |||
63 | /* | 91 | /* |
64 | * Update process times based on virtual cpu times stored by entry.S | 92 | * Update process times based on virtual cpu times stored by entry.S |
65 | * to the lowcore fields user_timer, system_timer & steal_clock. | 93 | * to the lowcore fields user_timer, system_timer & steal_clock. |
@@ -69,7 +97,6 @@ static int do_account_vtime(struct task_struct *tsk, int hardirq_offset) | |||
69 | struct thread_info *ti = task_thread_info(tsk); | 97 | struct thread_info *ti = task_thread_info(tsk); |
70 | u64 timer, clock, user, system, steal; | 98 | u64 timer, clock, user, system, steal; |
71 | u64 user_scaled, system_scaled; | 99 | u64 user_scaled, system_scaled; |
72 | int i; | ||
73 | 100 | ||
74 | timer = S390_lowcore.last_update_timer; | 101 | timer = S390_lowcore.last_update_timer; |
75 | clock = S390_lowcore.last_update_clock; | 102 | clock = S390_lowcore.last_update_clock; |
@@ -85,34 +112,10 @@ static int do_account_vtime(struct task_struct *tsk, int hardirq_offset) | |||
85 | S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer; | 112 | S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer; |
86 | S390_lowcore.steal_timer += S390_lowcore.last_update_clock - clock; | 113 | S390_lowcore.steal_timer += S390_lowcore.last_update_clock - clock; |
87 | 114 | ||
88 | /* Do MT utilization calculation */ | 115 | /* Update MT utilization calculation */ |
89 | if (smp_cpu_mtid && | 116 | if (smp_cpu_mtid && |
90 | time_after64(jiffies_64, __this_cpu_read(mt_scaling_jiffies))) { | 117 | time_after64(jiffies_64, this_cpu_read(mt_scaling_jiffies))) |
91 | u64 cycles_new[32], *cycles_old; | 118 | update_mt_scaling(); |
92 | u64 delta, fac, mult, div; | ||
93 | |||
94 | cycles_old = this_cpu_ptr(mt_cycles); | ||
95 | if (stcctm5(smp_cpu_mtid + 1, cycles_new) < 2) { | ||
96 | fac = 1; | ||
97 | mult = div = 0; | ||
98 | for (i = 0; i <= smp_cpu_mtid; i++) { | ||
99 | delta = cycles_new[i] - cycles_old[i]; | ||
100 | div += delta; | ||
101 | mult *= i + 1; | ||
102 | mult += delta * fac; | ||
103 | fac *= i + 1; | ||
104 | } | ||
105 | div *= fac; | ||
106 | if (div > 0) { | ||
107 | /* Update scaling factor */ | ||
108 | __this_cpu_write(mt_scaling_mult, mult); | ||
109 | __this_cpu_write(mt_scaling_div, div); | ||
110 | memcpy(cycles_old, cycles_new, | ||
111 | sizeof(u64) * (smp_cpu_mtid + 1)); | ||
112 | } | ||
113 | } | ||
114 | __this_cpu_write(mt_scaling_jiffies, jiffies_64); | ||
115 | } | ||
116 | 119 | ||
117 | user = S390_lowcore.user_timer - ti->user_timer; | 120 | user = S390_lowcore.user_timer - ti->user_timer; |
118 | S390_lowcore.steal_timer -= user; | 121 | S390_lowcore.steal_timer -= user; |
@@ -181,6 +184,11 @@ void vtime_account_irq_enter(struct task_struct *tsk) | |||
181 | S390_lowcore.last_update_timer = get_vtimer(); | 184 | S390_lowcore.last_update_timer = get_vtimer(); |
182 | S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer; | 185 | S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer; |
183 | 186 | ||
187 | /* Update MT utilization calculation */ | ||
188 | if (smp_cpu_mtid && | ||
189 | time_after64(jiffies_64, this_cpu_read(mt_scaling_jiffies))) | ||
190 | update_mt_scaling(); | ||
191 | |||
184 | system = S390_lowcore.system_timer - ti->system_timer; | 192 | system = S390_lowcore.system_timer - ti->system_timer; |
185 | S390_lowcore.steal_timer -= system; | 193 | S390_lowcore.steal_timer -= system; |
186 | ti->system_timer = S390_lowcore.system_timer; | 194 | ti->system_timer = S390_lowcore.system_timer; |