Commit 61cc3790 authored by Martin Schwidefsky's avatar Martin Schwidefsky

s390/vtime: correct scaled cputime for SMT

The scaled cputime is supposed to be derived from the normal per-thread
cputime by dividing it with the average thread density in the last interval.

The calculation of the scaling values for the average thread density is
incorrect. The current, incorrect calculation:

    Ci = cycle count with i active threads
    T = unscaled cputime, sT = scaled cputime
    sT = T * (C1 + C2 + ... + Cn) / (1*C1 + 2*C2 + ... + n*Cn)

The calculation happens to yield the correct numbers for the simple cases
with only one Ci value not zero. But for cases with multiple Ci values not
zero it fails. E.g. on a SMT-2 system with one thread active half the time
and two threads active for the other half of the time it fails, the scaling
factor should be 3/4 but the formula gives 2/3.

The correct formula is

    sT = T * (C1/1 + C2/2 + ... + Cn/n) / (C1 + C2 + ... + Cn)
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 58f8e9da
...@@ -89,17 +89,21 @@ static int do_account_vtime(struct task_struct *tsk, int hardirq_offset) ...@@ -89,17 +89,21 @@ static int do_account_vtime(struct task_struct *tsk, int hardirq_offset)
if (smp_cpu_mtid && if (smp_cpu_mtid &&
time_after64(jiffies_64, __this_cpu_read(mt_scaling_jiffies))) { time_after64(jiffies_64, __this_cpu_read(mt_scaling_jiffies))) {
u64 cycles_new[32], *cycles_old; u64 cycles_new[32], *cycles_old;
u64 delta, mult, div; u64 delta, fac, mult, div;
cycles_old = this_cpu_ptr(mt_cycles); cycles_old = this_cpu_ptr(mt_cycles);
if (stcctm5(smp_cpu_mtid + 1, cycles_new) < 2) { if (stcctm5(smp_cpu_mtid + 1, cycles_new) < 2) {
fac = 1;
mult = div = 0; mult = div = 0;
for (i = 0; i <= smp_cpu_mtid; i++) { for (i = 0; i <= smp_cpu_mtid; i++) {
delta = cycles_new[i] - cycles_old[i]; delta = cycles_new[i] - cycles_old[i];
mult += delta; div += delta;
div += (i + 1) * delta; mult *= i + 1;
mult += delta * fac;
fac *= i + 1;
} }
if (mult > 0) { div *= fac;
if (div > 0) {
/* Update scaling factor */ /* Update scaling factor */
__this_cpu_write(mt_scaling_mult, mult); __this_cpu_write(mt_scaling_mult, mult);
__this_cpu_write(mt_scaling_div, div); __this_cpu_write(mt_scaling_div, div);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment