diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2008-12-31 09:11:37 -0500 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2008-12-31 09:11:46 -0500 |
commit | 457533a7d3402d1d91fbc125c8bd1bd16dcd3cd4 (patch) | |
tree | cbe69310a66176dea2a9e7bd201db95efe4a2890 | |
parent | 6a94cb73064c952255336cc57731904174b2c58f (diff) |
[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>
-rw-r--r-- | arch/ia64/kernel/time.c | 12 | ||||
-rw-r--r-- | arch/powerpc/kernel/time.c | 7 | ||||
-rw-r--r-- | arch/s390/kernel/vtime.c | 10 | ||||
-rw-r--r-- | include/linux/kernel_stat.h | 6 | ||||
-rw-r--r-- | kernel/sched.c | 41 | ||||
-rw-r--r-- | kernel/time/tick-sched.c | 5 | ||||
-rw-r--r-- | kernel/timer.c | 12 |
7 files changed, 37 insertions, 56 deletions
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c index 65c10a42c88f..4ee367817049 100644 --- a/arch/ia64/kernel/time.c +++ b/arch/ia64/kernel/time.c | |||
@@ -93,13 +93,11 @@ void ia64_account_on_switch(struct task_struct *prev, struct task_struct *next) | |||
93 | now = ia64_get_itc(); | 93 | now = ia64_get_itc(); |
94 | 94 | ||
95 | delta_stime = cycle_to_cputime(pi->ac_stime + (now - pi->ac_stamp)); | 95 | delta_stime = cycle_to_cputime(pi->ac_stime + (now - pi->ac_stamp)); |
96 | account_system_time(prev, 0, delta_stime); | 96 | account_system_time(prev, 0, delta_stime, delta_stime); |
97 | account_system_time_scaled(prev, delta_stime); | ||
98 | 97 | ||
99 | if (pi->ac_utime) { | 98 | if (pi->ac_utime) { |
100 | delta_utime = cycle_to_cputime(pi->ac_utime); | 99 | delta_utime = cycle_to_cputime(pi->ac_utime); |
101 | account_user_time(prev, delta_utime); | 100 | account_user_time(prev, delta_utime, delta_utime); |
102 | account_user_time_scaled(prev, delta_utime); | ||
103 | } | 101 | } |
104 | 102 | ||
105 | pi->ac_stamp = ni->ac_stamp = now; | 103 | pi->ac_stamp = ni->ac_stamp = now; |
@@ -122,8 +120,7 @@ void account_system_vtime(struct task_struct *tsk) | |||
122 | now = ia64_get_itc(); | 120 | now = ia64_get_itc(); |
123 | 121 | ||
124 | delta_stime = cycle_to_cputime(ti->ac_stime + (now - ti->ac_stamp)); | 122 | delta_stime = cycle_to_cputime(ti->ac_stime + (now - ti->ac_stamp)); |
125 | account_system_time(tsk, 0, delta_stime); | 123 | account_system_time(tsk, 0, delta_stime, delta_stime); |
126 | account_system_time_scaled(tsk, delta_stime); | ||
127 | ti->ac_stime = 0; | 124 | ti->ac_stime = 0; |
128 | 125 | ||
129 | ti->ac_stamp = now; | 126 | ti->ac_stamp = now; |
@@ -143,8 +140,7 @@ void account_process_tick(struct task_struct *p, int user_tick) | |||
143 | 140 | ||
144 | if (ti->ac_utime) { | 141 | if (ti->ac_utime) { |
145 | delta_utime = cycle_to_cputime(ti->ac_utime); | 142 | delta_utime = cycle_to_cputime(ti->ac_utime); |
146 | account_user_time(p, delta_utime); | 143 | account_user_time(p, delta_utime, delta_utime); |
147 | account_user_time_scaled(p, delta_utime); | ||
148 | ti->ac_utime = 0; | 144 | ti->ac_utime = 0; |
149 | } | 145 | } |
150 | } | 146 | } |
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index e1f3a5140429..92650ccad2e1 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -256,8 +256,7 @@ void account_system_vtime(struct task_struct *tsk) | |||
256 | delta += sys_time; | 256 | delta += sys_time; |
257 | get_paca()->system_time = 0; | 257 | get_paca()->system_time = 0; |
258 | } | 258 | } |
259 | account_system_time(tsk, 0, delta); | 259 | account_system_time(tsk, 0, delta, deltascaled); |
260 | account_system_time_scaled(tsk, deltascaled); | ||
261 | per_cpu(cputime_last_delta, smp_processor_id()) = delta; | 260 | per_cpu(cputime_last_delta, smp_processor_id()) = delta; |
262 | per_cpu(cputime_scaled_last_delta, smp_processor_id()) = deltascaled; | 261 | per_cpu(cputime_scaled_last_delta, smp_processor_id()) = deltascaled; |
263 | local_irq_restore(flags); | 262 | local_irq_restore(flags); |
@@ -275,10 +274,8 @@ void account_process_tick(struct task_struct *tsk, int user_tick) | |||
275 | 274 | ||
276 | utime = get_paca()->user_time; | 275 | utime = get_paca()->user_time; |
277 | get_paca()->user_time = 0; | 276 | get_paca()->user_time = 0; |
278 | account_user_time(tsk, utime); | ||
279 | |||
280 | utimescaled = cputime_to_scaled(utime); | 277 | utimescaled = cputime_to_scaled(utime); |
281 | account_user_time_scaled(tsk, utimescaled); | 278 | account_user_time(tsk, utime, utimescaled); |
282 | } | 279 | } |
283 | 280 | ||
284 | /* | 281 | /* |
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index 75a6e62ea973..07283aea2e56 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c | |||
@@ -50,12 +50,12 @@ void account_process_tick(struct task_struct *tsk, int user_tick) | |||
50 | rcu_user_flag = cputime != 0; | 50 | rcu_user_flag = cputime != 0; |
51 | S390_lowcore.user_timer -= cputime << 12; | 51 | S390_lowcore.user_timer -= cputime << 12; |
52 | S390_lowcore.steal_clock -= cputime << 12; | 52 | S390_lowcore.steal_clock -= cputime << 12; |
53 | account_user_time(tsk, cputime); | 53 | account_user_time(tsk, cputime, cputime); |
54 | 54 | ||
55 | cputime = S390_lowcore.system_timer >> 12; | 55 | cputime = S390_lowcore.system_timer >> 12; |
56 | S390_lowcore.system_timer -= cputime << 12; | 56 | S390_lowcore.system_timer -= cputime << 12; |
57 | S390_lowcore.steal_clock -= cputime << 12; | 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 | cputime = S390_lowcore.steal_clock; | 60 | cputime = S390_lowcore.steal_clock; |
61 | if ((__s64) cputime > 0) { | 61 | if ((__s64) cputime > 0) { |
@@ -82,12 +82,12 @@ void account_vtime(struct task_struct *tsk) | |||
82 | cputime = S390_lowcore.user_timer >> 12; | 82 | cputime = S390_lowcore.user_timer >> 12; |
83 | S390_lowcore.user_timer -= cputime << 12; | 83 | S390_lowcore.user_timer -= cputime << 12; |
84 | S390_lowcore.steal_clock -= cputime << 12; | 84 | S390_lowcore.steal_clock -= cputime << 12; |
85 | account_user_time(tsk, cputime); | 85 | account_user_time(tsk, cputime, cputime); |
86 | 86 | ||
87 | cputime = S390_lowcore.system_timer >> 12; | 87 | cputime = S390_lowcore.system_timer >> 12; |
88 | S390_lowcore.system_timer -= cputime << 12; | 88 | S390_lowcore.system_timer -= cputime << 12; |
89 | S390_lowcore.steal_clock -= cputime << 12; | 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,7 +107,7 @@ void account_system_vtime(struct task_struct *tsk) | |||
107 | cputime = S390_lowcore.system_timer >> 12; | 107 | cputime = S390_lowcore.system_timer >> 12; |
108 | S390_lowcore.system_timer -= cputime << 12; | 108 | S390_lowcore.system_timer -= cputime << 12; |
109 | S390_lowcore.steal_clock -= cputime << 12; | 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 | EXPORT_SYMBOL_GPL(account_system_vtime); | 112 | EXPORT_SYMBOL_GPL(account_system_vtime); |
113 | 113 | ||
diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h index 4ee4b3d2316f..c78a459662a6 100644 --- a/include/linux/kernel_stat.h +++ b/include/linux/kernel_stat.h | |||
@@ -79,10 +79,8 @@ static inline unsigned int kstat_irqs(unsigned int irq) | |||
79 | } | 79 | } |
80 | 80 | ||
81 | extern unsigned long long task_delta_exec(struct task_struct *); | 81 | extern unsigned long long task_delta_exec(struct task_struct *); |
82 | extern void account_user_time(struct task_struct *, cputime_t); | 82 | extern void account_user_time(struct task_struct *, cputime_t, cputime_t); |
83 | extern void account_user_time_scaled(struct task_struct *, cputime_t); | 83 | extern void account_system_time(struct task_struct *, int, cputime_t, 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); | ||
86 | extern void account_steal_time(struct task_struct *, cputime_t); | 84 | extern void account_steal_time(struct task_struct *, cputime_t); |
87 | 85 | ||
88 | #endif /* _LINUX_KERNEL_STAT_H */ | 86 | #endif /* _LINUX_KERNEL_STAT_H */ |
diff --git a/kernel/sched.c b/kernel/sched.c index fff1c4a20b65..5b03679ff712 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -4080,13 +4080,17 @@ unsigned long long task_delta_exec(struct task_struct *p) | |||
4080 | * Account user cpu time to a process. | 4080 | * Account user cpu time to a process. |
4081 | * @p: the process that the cpu time gets accounted to | 4081 | * @p: the process that the cpu time gets accounted to |
4082 | * @cputime: the cpu time spent in user space since the last update | 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 | struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; | 4088 | struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; |
4087 | cputime64_t tmp; | 4089 | cputime64_t tmp; |
4088 | 4090 | ||
4091 | /* Add user time to process. */ | ||
4089 | p->utime = cputime_add(p->utime, cputime); | 4092 | p->utime = cputime_add(p->utime, cputime); |
4093 | p->utimescaled = cputime_add(p->utimescaled, cputime_scaled); | ||
4090 | account_group_user_time(p, cputime); | 4094 | account_group_user_time(p, cputime); |
4091 | 4095 | ||
4092 | /* Add user time to cpustat. */ | 4096 | /* Add user time to cpustat. */ |
@@ -4103,51 +4107,49 @@ void account_user_time(struct task_struct *p, cputime_t cputime) | |||
4103 | * Account guest cpu time to a process. | 4107 | * Account guest cpu time to a process. |
4104 | * @p: the process that the cpu time gets accounted to | 4108 | * @p: the process that the cpu time gets accounted to |
4105 | * @cputime: the cpu time spent in virtual machine since the last update | 4109 | * @cputime: the cpu time spent in virtual machine since the last update |
4110 | * @cputime_scaled: cputime scaled by cpu frequency | ||
4106 | */ | 4111 | */ |
4107 | static void account_guest_time(struct task_struct *p, cputime_t cputime) | 4112 | static void account_guest_time(struct task_struct *p, cputime_t cputime, |
4113 | cputime_t cputime_scaled) | ||
4108 | { | 4114 | { |
4109 | cputime64_t tmp; | 4115 | cputime64_t tmp; |
4110 | struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; | 4116 | struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; |
4111 | 4117 | ||
4112 | tmp = cputime_to_cputime64(cputime); | 4118 | tmp = cputime_to_cputime64(cputime); |
4113 | 4119 | ||
4120 | /* Add guest time to process. */ | ||
4114 | p->utime = cputime_add(p->utime, cputime); | 4121 | p->utime = cputime_add(p->utime, cputime); |
4122 | p->utimescaled = cputime_add(p->utimescaled, cputime_scaled); | ||
4115 | account_group_user_time(p, cputime); | 4123 | account_group_user_time(p, cputime); |
4116 | p->gtime = cputime_add(p->gtime, cputime); | 4124 | p->gtime = cputime_add(p->gtime, cputime); |
4117 | 4125 | ||
4126 | /* Add guest time to cpustat. */ | ||
4118 | cpustat->user = cputime64_add(cpustat->user, tmp); | 4127 | cpustat->user = cputime64_add(cpustat->user, tmp); |
4119 | cpustat->guest = cputime64_add(cpustat->guest, tmp); | 4128 | cpustat->guest = cputime64_add(cpustat->guest, tmp); |
4120 | } | 4129 | } |
4121 | 4130 | ||
4122 | /* | 4131 | /* |
4123 | * Account scaled user cpu time to a process. | ||
4124 | * @p: the process that the cpu time gets accounted to | ||
4125 | * @cputime: the cpu time spent in user space since the last update | ||
4126 | */ | ||
4127 | void account_user_time_scaled(struct task_struct *p, cputime_t cputime) | ||
4128 | { | ||
4129 | p->utimescaled = cputime_add(p->utimescaled, cputime); | ||
4130 | } | ||
4131 | |||
4132 | /* | ||
4133 | * Account system cpu time to a process. | 4132 | * Account system cpu time to a process. |
4134 | * @p: the process that the cpu time gets accounted to | 4133 | * @p: the process that the cpu time gets accounted to |
4135 | * @hardirq_offset: the offset to subtract from hardirq_count() | 4134 | * @hardirq_offset: the offset to subtract from hardirq_count() |
4136 | * @cputime: the cpu time spent in kernel space since the last update | 4135 | * @cputime: the cpu time spent in kernel space since the last update |
4136 | * @cputime_scaled: cputime scaled by cpu frequency | ||
4137 | */ | 4137 | */ |
4138 | void account_system_time(struct task_struct *p, int hardirq_offset, | 4138 | void account_system_time(struct task_struct *p, int hardirq_offset, |
4139 | cputime_t cputime) | 4139 | cputime_t cputime, cputime_t cputime_scaled) |
4140 | { | 4140 | { |
4141 | struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; | 4141 | struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; |
4142 | struct rq *rq = this_rq(); | 4142 | struct rq *rq = this_rq(); |
4143 | cputime64_t tmp; | 4143 | cputime64_t tmp; |
4144 | 4144 | ||
4145 | if ((p->flags & PF_VCPU) && (irq_count() - hardirq_offset == 0)) { | 4145 | if ((p->flags & PF_VCPU) && (irq_count() - hardirq_offset == 0)) { |
4146 | account_guest_time(p, cputime); | 4146 | account_guest_time(p, cputime, cputime_scaled); |
4147 | return; | 4147 | return; |
4148 | } | 4148 | } |
4149 | 4149 | ||
4150 | /* Add system time to process. */ | ||
4150 | p->stime = cputime_add(p->stime, cputime); | 4151 | p->stime = cputime_add(p->stime, cputime); |
4152 | p->stimescaled = cputime_add(p->stimescaled, cputime_scaled); | ||
4151 | account_group_system_time(p, cputime); | 4153 | account_group_system_time(p, cputime); |
4152 | 4154 | ||
4153 | /* Add system time to cpustat. */ | 4155 | /* Add system time to cpustat. */ |
@@ -4167,17 +4169,6 @@ void account_system_time(struct task_struct *p, int hardirq_offset, | |||
4167 | } | 4169 | } |
4168 | 4170 | ||
4169 | /* | 4171 | /* |
4170 | * Account scaled system cpu time to a process. | ||
4171 | * @p: the process that the cpu time gets accounted to | ||
4172 | * @hardirq_offset: the offset to subtract from hardirq_count() | ||
4173 | * @cputime: the cpu time spent in kernel space since the last update | ||
4174 | */ | ||
4175 | void account_system_time_scaled(struct task_struct *p, cputime_t cputime) | ||
4176 | { | ||
4177 | p->stimescaled = cputime_add(p->stimescaled, cputime); | ||
4178 | } | ||
4179 | |||
4180 | /* | ||
4181 | * Account for involuntary wait time. | 4172 | * Account for involuntary wait time. |
4182 | * @p: the process from which the cpu time has been stolen | 4173 | * @p: the process from which the cpu time has been stolen |
4183 | * @steal: the cpu time spent in involuntary wait | 4174 | * @steal: the cpu time spent in involuntary wait |
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 8f3fc2582d38..1f2fce2479fe 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c | |||
@@ -420,6 +420,7 @@ void tick_nohz_restart_sched_tick(void) | |||
420 | int cpu = smp_processor_id(); | 420 | int cpu = smp_processor_id(); |
421 | struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); | 421 | struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); |
422 | unsigned long ticks; | 422 | unsigned long ticks; |
423 | cputime_t cputime; | ||
423 | ktime_t now; | 424 | ktime_t now; |
424 | 425 | ||
425 | local_irq_disable(); | 426 | local_irq_disable(); |
@@ -452,8 +453,8 @@ void tick_nohz_restart_sched_tick(void) | |||
452 | */ | 453 | */ |
453 | if (ticks && ticks < LONG_MAX) { | 454 | if (ticks && ticks < LONG_MAX) { |
454 | add_preempt_count(HARDIRQ_OFFSET); | 455 | add_preempt_count(HARDIRQ_OFFSET); |
455 | account_system_time(current, HARDIRQ_OFFSET, | 456 | cputime = jiffies_to_cputime(ticks); |
456 | jiffies_to_cputime(ticks)); | 457 | account_system_time(current, HARDIRQ_OFFSET, cputime, cputime); |
457 | sub_preempt_count(HARDIRQ_OFFSET); | 458 | sub_preempt_count(HARDIRQ_OFFSET); |
458 | } | 459 | } |
459 | 460 | ||
diff --git a/kernel/timer.c b/kernel/timer.c index 566257d1dc10..b5efb528aa1d 100644 --- a/kernel/timer.c +++ b/kernel/timer.c | |||
@@ -1023,13 +1023,11 @@ void account_process_tick(struct task_struct *p, int user_tick) | |||
1023 | { | 1023 | { |
1024 | cputime_t one_jiffy = jiffies_to_cputime(1); | 1024 | cputime_t one_jiffy = jiffies_to_cputime(1); |
1025 | 1025 | ||
1026 | if (user_tick) { | 1026 | if (user_tick) |
1027 | account_user_time(p, one_jiffy); | 1027 | account_user_time(p, one_jiffy, cputime_to_scaled(one_jiffy)); |
1028 | account_user_time_scaled(p, cputime_to_scaled(one_jiffy)); | 1028 | else |
1029 | } else { | 1029 | account_system_time(p, HARDIRQ_OFFSET, one_jiffy, |
1030 | account_system_time(p, HARDIRQ_OFFSET, one_jiffy); | 1030 | cputime_to_scaled(one_jiffy)); |
1031 | account_system_time_scaled(p, cputime_to_scaled(one_jiffy)); | ||
1032 | } | ||
1033 | } | 1031 | } |
1034 | #endif | 1032 | #endif |
1035 | 1033 | ||