Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] fix scaled & unscaled cputime accounting

The utimescaled / stimescaled fields in the task structure and the
global cpustat should be set on all architectures. On s390 the calls
to account_user_time_scaled and account_system_time_scaled never have
been added. In addition system time that is accounted as guest time
to the user time of a process is accounted to the scaled system time
instead of the scaled user time.
To fix the bugs and to prevent future forgetfulness this patch merges
account_system_time_scaled into account_system_time and
account_user_time_scaled into account_user_time.

Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Jeremy Fitzhardinge <jeremy@xensource.com>
Cc: Chris Wright <chrisw@sous-sol.org>
Cc: Michael Neuling <mikey@neuling.org>
Acked-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

+37 -56
+4 -8
arch/ia64/kernel/time.c
··· 93 93 now = ia64_get_itc(); 94 94 95 95 delta_stime = cycle_to_cputime(pi->ac_stime + (now - pi->ac_stamp)); 96 - account_system_time(prev, 0, delta_stime); 97 - account_system_time_scaled(prev, delta_stime); 96 + account_system_time(prev, 0, delta_stime, delta_stime); 98 97 99 98 if (pi->ac_utime) { 100 99 delta_utime = cycle_to_cputime(pi->ac_utime); 101 - account_user_time(prev, delta_utime); 102 - account_user_time_scaled(prev, delta_utime); 100 + account_user_time(prev, delta_utime, delta_utime); 103 101 } 104 102 105 103 pi->ac_stamp = ni->ac_stamp = now; ··· 120 122 now = ia64_get_itc(); 121 123 122 124 delta_stime = cycle_to_cputime(ti->ac_stime + (now - ti->ac_stamp)); 123 - account_system_time(tsk, 0, delta_stime); 124 - account_system_time_scaled(tsk, delta_stime); 125 + account_system_time(tsk, 0, delta_stime, delta_stime); 125 126 ti->ac_stime = 0; 126 127 127 128 ti->ac_stamp = now; ··· 140 143 141 144 if (ti->ac_utime) { 142 145 delta_utime = cycle_to_cputime(ti->ac_utime); 143 - account_user_time(p, delta_utime); 144 - account_user_time_scaled(p, delta_utime); 146 + account_user_time(p, delta_utime, delta_utime); 145 147 ti->ac_utime = 0; 146 148 } 147 149 }
+2 -5
arch/powerpc/kernel/time.c
··· 256 256 delta += sys_time; 257 257 get_paca()->system_time = 0; 258 258 } 259 - account_system_time(tsk, 0, delta); 260 - account_system_time_scaled(tsk, deltascaled); 259 + account_system_time(tsk, 0, delta, deltascaled); 261 260 per_cpu(cputime_last_delta, smp_processor_id()) = delta; 262 261 per_cpu(cputime_scaled_last_delta, smp_processor_id()) = deltascaled; 263 262 local_irq_restore(flags); ··· 274 275 275 276 utime = get_paca()->user_time; 276 277 get_paca()->user_time = 0; 277 - account_user_time(tsk, utime); 278 - 279 278 utimescaled = cputime_to_scaled(utime); 280 - account_user_time_scaled(tsk, utimescaled); 279 + account_user_time(tsk, utime, utimescaled); 281 280 } 282 281 283 282 /*
+5 -5
arch/s390/kernel/vtime.c
··· 50 50 rcu_user_flag = cputime != 0; 51 51 S390_lowcore.user_timer -= cputime << 12; 52 52 S390_lowcore.steal_clock -= cputime << 12; 53 - account_user_time(tsk, cputime); 53 + account_user_time(tsk, cputime, cputime); 54 54 55 55 cputime = S390_lowcore.system_timer >> 12; 56 56 S390_lowcore.system_timer -= cputime << 12; 57 57 S390_lowcore.steal_clock -= cputime << 12; 58 - account_system_time(tsk, HARDIRQ_OFFSET, cputime); 58 + account_system_time(tsk, HARDIRQ_OFFSET, cputime, cputime); 59 59 60 60 cputime = S390_lowcore.steal_clock; 61 61 if ((__s64) cputime > 0) { ··· 82 82 cputime = S390_lowcore.user_timer >> 12; 83 83 S390_lowcore.user_timer -= cputime << 12; 84 84 S390_lowcore.steal_clock -= cputime << 12; 85 - account_user_time(tsk, cputime); 85 + account_user_time(tsk, cputime, cputime); 86 86 87 87 cputime = S390_lowcore.system_timer >> 12; 88 88 S390_lowcore.system_timer -= cputime << 12; 89 89 S390_lowcore.steal_clock -= cputime << 12; 90 - account_system_time(tsk, 0, cputime); 90 + account_system_time(tsk, 0, cputime, cputime); 91 91 } 92 92 93 93 /* ··· 107 107 cputime = S390_lowcore.system_timer >> 12; 108 108 S390_lowcore.system_timer -= cputime << 12; 109 109 S390_lowcore.steal_clock -= cputime << 12; 110 - account_system_time(tsk, 0, cputime); 110 + account_system_time(tsk, 0, cputime, cputime); 111 111 } 112 112 EXPORT_SYMBOL_GPL(account_system_vtime); 113 113
+2 -4
include/linux/kernel_stat.h
··· 79 79 } 80 80 81 81 extern unsigned long long task_delta_exec(struct task_struct *); 82 - extern void account_user_time(struct task_struct *, cputime_t); 83 - extern void account_user_time_scaled(struct task_struct *, cputime_t); 84 - extern void account_system_time(struct task_struct *, int, cputime_t); 85 - extern void account_system_time_scaled(struct task_struct *, cputime_t); 82 + extern void account_user_time(struct task_struct *, cputime_t, cputime_t); 83 + extern void account_system_time(struct task_struct *, int, cputime_t, cputime_t); 86 84 extern void account_steal_time(struct task_struct *, cputime_t); 87 85 88 86 #endif /* _LINUX_KERNEL_STAT_H */
+16 -25
kernel/sched.c
··· 4080 4080 * Account user cpu time to a process. 4081 4081 * @p: the process that the cpu time gets accounted to 4082 4082 * @cputime: the cpu time spent in user space since the last update 4083 + * @cputime_scaled: cputime scaled by cpu frequency 4083 4084 */ 4084 - void account_user_time(struct task_struct *p, cputime_t cputime) 4085 + void account_user_time(struct task_struct *p, cputime_t cputime, 4086 + cputime_t cputime_scaled) 4085 4087 { 4086 4088 struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; 4087 4089 cputime64_t tmp; 4088 4090 4091 + /* Add user time to process. */ 4089 4092 p->utime = cputime_add(p->utime, cputime); 4093 + p->utimescaled = cputime_add(p->utimescaled, cputime_scaled); 4090 4094 account_group_user_time(p, cputime); 4091 4095 4092 4096 /* Add user time to cpustat. */ ··· 4107 4103 * Account guest cpu time to a process. 4108 4104 * @p: the process that the cpu time gets accounted to 4109 4105 * @cputime: the cpu time spent in virtual machine since the last update 4106 + * @cputime_scaled: cputime scaled by cpu frequency 4110 4107 */ 4111 - static void account_guest_time(struct task_struct *p, cputime_t cputime) 4108 + static void account_guest_time(struct task_struct *p, cputime_t cputime, 4109 + cputime_t cputime_scaled) 4112 4110 { 4113 4111 cputime64_t tmp; 4114 4112 struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; 4115 4113 4116 4114 tmp = cputime_to_cputime64(cputime); 4117 4115 4116 + /* Add guest time to process. */ 4118 4117 p->utime = cputime_add(p->utime, cputime); 4118 + p->utimescaled = cputime_add(p->utimescaled, cputime_scaled); 4119 4119 account_group_user_time(p, cputime); 4120 4120 p->gtime = cputime_add(p->gtime, cputime); 4121 4121 4122 + /* Add guest time to cpustat. */ 4122 4123 cpustat->user = cputime64_add(cpustat->user, tmp); 4123 4124 cpustat->guest = cputime64_add(cpustat->guest, tmp); 4124 - } 4125 - 4126 - /* 4127 - * Account scaled user cpu time to a process. 4128 - * @p: the process that the cpu time gets accounted to 4129 - * @cputime: the cpu time spent in user space since the last update 4130 - */ 4131 - void account_user_time_scaled(struct task_struct *p, cputime_t cputime) 4132 - { 4133 - p->utimescaled = cputime_add(p->utimescaled, cputime); 4134 4125 } 4135 4126 4136 4127 /* ··· 4133 4134 * @p: the process that the cpu time gets accounted to 4134 4135 * @hardirq_offset: the offset to subtract from hardirq_count() 4135 4136 * @cputime: the cpu time spent in kernel space since the last update 4137 + * @cputime_scaled: cputime scaled by cpu frequency 4136 4138 */ 4137 4139 void account_system_time(struct task_struct *p, int hardirq_offset, 4138 - cputime_t cputime) 4140 + cputime_t cputime, cputime_t cputime_scaled) 4139 4141 { 4140 4142 struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; 4141 4143 struct rq *rq = this_rq(); 4142 4144 cputime64_t tmp; 4143 4145 4144 4146 if ((p->flags & PF_VCPU) && (irq_count() - hardirq_offset == 0)) { 4145 - account_guest_time(p, cputime); 4147 + account_guest_time(p, cputime, cputime_scaled); 4146 4148 return; 4147 4149 } 4148 4150 4151 + /* Add system time to process. */ 4149 4152 p->stime = cputime_add(p->stime, cputime); 4153 + p->stimescaled = cputime_add(p->stimescaled, cputime_scaled); 4150 4154 account_group_system_time(p, cputime); 4151 4155 4152 4156 /* Add system time to cpustat. */ ··· 4166 4164 cpustat->idle = cputime64_add(cpustat->idle, tmp); 4167 4165 /* Account for system time used */ 4168 4166 acct_update_integrals(p); 4169 - } 4170 - 4171 - /* 4172 - * Account scaled system cpu time to a process. 4173 - * @p: the process that the cpu time gets accounted to 4174 - * @hardirq_offset: the offset to subtract from hardirq_count() 4175 - * @cputime: the cpu time spent in kernel space since the last update 4176 - */ 4177 - void account_system_time_scaled(struct task_struct *p, cputime_t cputime) 4178 - { 4179 - p->stimescaled = cputime_add(p->stimescaled, cputime); 4180 4167 } 4181 4168 4182 4169 /*
+3 -2
kernel/time/tick-sched.c
··· 420 420 int cpu = smp_processor_id(); 421 421 struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); 422 422 unsigned long ticks; 423 + cputime_t cputime; 423 424 ktime_t now; 424 425 425 426 local_irq_disable(); ··· 453 452 */ 454 453 if (ticks && ticks < LONG_MAX) { 455 454 add_preempt_count(HARDIRQ_OFFSET); 456 - account_system_time(current, HARDIRQ_OFFSET, 457 - jiffies_to_cputime(ticks)); 455 + cputime = jiffies_to_cputime(ticks); 456 + account_system_time(current, HARDIRQ_OFFSET, cputime, cputime); 458 457 sub_preempt_count(HARDIRQ_OFFSET); 459 458 } 460 459
+5 -7
kernel/timer.c
··· 1023 1023 { 1024 1024 cputime_t one_jiffy = jiffies_to_cputime(1); 1025 1025 1026 - if (user_tick) { 1027 - account_user_time(p, one_jiffy); 1028 - account_user_time_scaled(p, cputime_to_scaled(one_jiffy)); 1029 - } else { 1030 - account_system_time(p, HARDIRQ_OFFSET, one_jiffy); 1031 - account_system_time_scaled(p, cputime_to_scaled(one_jiffy)); 1032 - } 1026 + if (user_tick) 1027 + account_user_time(p, one_jiffy, cputime_to_scaled(one_jiffy)); 1028 + else 1029 + account_system_time(p, HARDIRQ_OFFSET, one_jiffy, 1030 + cputime_to_scaled(one_jiffy)); 1033 1031 } 1034 1032 #endif 1035 1033