[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>
This commit is contained in:
Родитель
6a94cb7306
Коммит
457533a7d3
|
@ -93,13 +93,11 @@ void ia64_account_on_switch(struct task_struct *prev, struct task_struct *next)
|
||||||
now = ia64_get_itc();
|
now = ia64_get_itc();
|
||||||
|
|
||||||
delta_stime = cycle_to_cputime(pi->ac_stime + (now - pi->ac_stamp));
|
delta_stime = cycle_to_cputime(pi->ac_stime + (now - pi->ac_stamp));
|
||||||
account_system_time(prev, 0, delta_stime);
|
account_system_time(prev, 0, delta_stime, delta_stime);
|
||||||
account_system_time_scaled(prev, delta_stime);
|
|
||||||
|
|
||||||
if (pi->ac_utime) {
|
if (pi->ac_utime) {
|
||||||
delta_utime = cycle_to_cputime(pi->ac_utime);
|
delta_utime = cycle_to_cputime(pi->ac_utime);
|
||||||
account_user_time(prev, delta_utime);
|
account_user_time(prev, delta_utime, delta_utime);
|
||||||
account_user_time_scaled(prev, delta_utime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pi->ac_stamp = ni->ac_stamp = now;
|
pi->ac_stamp = ni->ac_stamp = now;
|
||||||
|
@ -122,8 +120,7 @@ void account_system_vtime(struct task_struct *tsk)
|
||||||
now = ia64_get_itc();
|
now = ia64_get_itc();
|
||||||
|
|
||||||
delta_stime = cycle_to_cputime(ti->ac_stime + (now - ti->ac_stamp));
|
delta_stime = cycle_to_cputime(ti->ac_stime + (now - ti->ac_stamp));
|
||||||
account_system_time(tsk, 0, delta_stime);
|
account_system_time(tsk, 0, delta_stime, delta_stime);
|
||||||
account_system_time_scaled(tsk, delta_stime);
|
|
||||||
ti->ac_stime = 0;
|
ti->ac_stime = 0;
|
||||||
|
|
||||||
ti->ac_stamp = now;
|
ti->ac_stamp = now;
|
||||||
|
@ -143,8 +140,7 @@ void account_process_tick(struct task_struct *p, int user_tick)
|
||||||
|
|
||||||
if (ti->ac_utime) {
|
if (ti->ac_utime) {
|
||||||
delta_utime = cycle_to_cputime(ti->ac_utime);
|
delta_utime = cycle_to_cputime(ti->ac_utime);
|
||||||
account_user_time(p, delta_utime);
|
account_user_time(p, delta_utime, delta_utime);
|
||||||
account_user_time_scaled(p, delta_utime);
|
|
||||||
ti->ac_utime = 0;
|
ti->ac_utime = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -256,8 +256,7 @@ void account_system_vtime(struct task_struct *tsk)
|
||||||
delta += sys_time;
|
delta += sys_time;
|
||||||
get_paca()->system_time = 0;
|
get_paca()->system_time = 0;
|
||||||
}
|
}
|
||||||
account_system_time(tsk, 0, delta);
|
account_system_time(tsk, 0, delta, deltascaled);
|
||||||
account_system_time_scaled(tsk, deltascaled);
|
|
||||||
per_cpu(cputime_last_delta, smp_processor_id()) = delta;
|
per_cpu(cputime_last_delta, smp_processor_id()) = delta;
|
||||||
per_cpu(cputime_scaled_last_delta, smp_processor_id()) = deltascaled;
|
per_cpu(cputime_scaled_last_delta, smp_processor_id()) = deltascaled;
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
|
@ -275,10 +274,8 @@ void account_process_tick(struct task_struct *tsk, int user_tick)
|
||||||
|
|
||||||
utime = get_paca()->user_time;
|
utime = get_paca()->user_time;
|
||||||
get_paca()->user_time = 0;
|
get_paca()->user_time = 0;
|
||||||
account_user_time(tsk, utime);
|
|
||||||
|
|
||||||
utimescaled = cputime_to_scaled(utime);
|
utimescaled = cputime_to_scaled(utime);
|
||||||
account_user_time_scaled(tsk, utimescaled);
|
account_user_time(tsk, utime, utimescaled);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -50,12 +50,12 @@ void account_process_tick(struct task_struct *tsk, int user_tick)
|
||||||
rcu_user_flag = cputime != 0;
|
rcu_user_flag = cputime != 0;
|
||||||
S390_lowcore.user_timer -= cputime << 12;
|
S390_lowcore.user_timer -= cputime << 12;
|
||||||
S390_lowcore.steal_clock -= cputime << 12;
|
S390_lowcore.steal_clock -= cputime << 12;
|
||||||
account_user_time(tsk, cputime);
|
account_user_time(tsk, cputime, cputime);
|
||||||
|
|
||||||
cputime = S390_lowcore.system_timer >> 12;
|
cputime = S390_lowcore.system_timer >> 12;
|
||||||
S390_lowcore.system_timer -= cputime << 12;
|
S390_lowcore.system_timer -= cputime << 12;
|
||||||
S390_lowcore.steal_clock -= cputime << 12;
|
S390_lowcore.steal_clock -= cputime << 12;
|
||||||
account_system_time(tsk, HARDIRQ_OFFSET, cputime);
|
account_system_time(tsk, HARDIRQ_OFFSET, cputime, cputime);
|
||||||
|
|
||||||
cputime = S390_lowcore.steal_clock;
|
cputime = S390_lowcore.steal_clock;
|
||||||
if ((__s64) cputime > 0) {
|
if ((__s64) cputime > 0) {
|
||||||
|
@ -82,12 +82,12 @@ void account_vtime(struct task_struct *tsk)
|
||||||
cputime = S390_lowcore.user_timer >> 12;
|
cputime = S390_lowcore.user_timer >> 12;
|
||||||
S390_lowcore.user_timer -= cputime << 12;
|
S390_lowcore.user_timer -= cputime << 12;
|
||||||
S390_lowcore.steal_clock -= cputime << 12;
|
S390_lowcore.steal_clock -= cputime << 12;
|
||||||
account_user_time(tsk, cputime);
|
account_user_time(tsk, cputime, cputime);
|
||||||
|
|
||||||
cputime = S390_lowcore.system_timer >> 12;
|
cputime = S390_lowcore.system_timer >> 12;
|
||||||
S390_lowcore.system_timer -= cputime << 12;
|
S390_lowcore.system_timer -= cputime << 12;
|
||||||
S390_lowcore.steal_clock -= cputime << 12;
|
S390_lowcore.steal_clock -= cputime << 12;
|
||||||
account_system_time(tsk, 0, cputime);
|
account_system_time(tsk, 0, cputime, cputime);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -107,7 +107,7 @@ void account_system_vtime(struct task_struct *tsk)
|
||||||
cputime = S390_lowcore.system_timer >> 12;
|
cputime = S390_lowcore.system_timer >> 12;
|
||||||
S390_lowcore.system_timer -= cputime << 12;
|
S390_lowcore.system_timer -= cputime << 12;
|
||||||
S390_lowcore.steal_clock -= cputime << 12;
|
S390_lowcore.steal_clock -= cputime << 12;
|
||||||
account_system_time(tsk, 0, cputime);
|
account_system_time(tsk, 0, cputime, cputime);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(account_system_vtime);
|
EXPORT_SYMBOL_GPL(account_system_vtime);
|
||||||
|
|
||||||
|
|
|
@ -79,10 +79,8 @@ static inline unsigned int kstat_irqs(unsigned int irq)
|
||||||
}
|
}
|
||||||
|
|
||||||
extern unsigned long long task_delta_exec(struct task_struct *);
|
extern unsigned long long task_delta_exec(struct task_struct *);
|
||||||
extern void account_user_time(struct task_struct *, cputime_t);
|
extern void account_user_time(struct task_struct *, cputime_t, cputime_t);
|
||||||
extern void account_user_time_scaled(struct task_struct *, cputime_t);
|
extern void account_system_time(struct task_struct *, int, cputime_t, cputime_t);
|
||||||
extern void account_system_time(struct task_struct *, int, cputime_t);
|
|
||||||
extern void account_system_time_scaled(struct task_struct *, cputime_t);
|
|
||||||
extern void account_steal_time(struct task_struct *, cputime_t);
|
extern void account_steal_time(struct task_struct *, cputime_t);
|
||||||
|
|
||||||
#endif /* _LINUX_KERNEL_STAT_H */
|
#endif /* _LINUX_KERNEL_STAT_H */
|
||||||
|
|
|
@ -4080,13 +4080,17 @@ unsigned long long task_delta_exec(struct task_struct *p)
|
||||||
* Account user cpu time to a process.
|
* Account user cpu time to a process.
|
||||||
* @p: the process that the cpu time gets accounted to
|
* @p: the process that the cpu time gets accounted to
|
||||||
* @cputime: the cpu time spent in user space since the last update
|
* @cputime: the cpu time spent in user space since the last update
|
||||||
|
* @cputime_scaled: cputime scaled by cpu frequency
|
||||||
*/
|
*/
|
||||||
void account_user_time(struct task_struct *p, cputime_t cputime)
|
void account_user_time(struct task_struct *p, cputime_t cputime,
|
||||||
|
cputime_t cputime_scaled)
|
||||||
{
|
{
|
||||||
struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
|
struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
|
||||||
cputime64_t tmp;
|
cputime64_t tmp;
|
||||||
|
|
||||||
|
/* Add user time to process. */
|
||||||
p->utime = cputime_add(p->utime, cputime);
|
p->utime = cputime_add(p->utime, cputime);
|
||||||
|
p->utimescaled = cputime_add(p->utimescaled, cputime_scaled);
|
||||||
account_group_user_time(p, cputime);
|
account_group_user_time(p, cputime);
|
||||||
|
|
||||||
/* Add user time to cpustat. */
|
/* Add user time to cpustat. */
|
||||||
|
@ -4103,51 +4107,49 @@ void account_user_time(struct task_struct *p, cputime_t cputime)
|
||||||
* Account guest cpu time to a process.
|
* Account guest cpu time to a process.
|
||||||
* @p: the process that the cpu time gets accounted to
|
* @p: the process that the cpu time gets accounted to
|
||||||
* @cputime: the cpu time spent in virtual machine since the last update
|
* @cputime: the cpu time spent in virtual machine since the last update
|
||||||
|
* @cputime_scaled: cputime scaled by cpu frequency
|
||||||
*/
|
*/
|
||||||
static void account_guest_time(struct task_struct *p, cputime_t cputime)
|
static void account_guest_time(struct task_struct *p, cputime_t cputime,
|
||||||
|
cputime_t cputime_scaled)
|
||||||
{
|
{
|
||||||
cputime64_t tmp;
|
cputime64_t tmp;
|
||||||
struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
|
struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
|
||||||
|
|
||||||
tmp = cputime_to_cputime64(cputime);
|
tmp = cputime_to_cputime64(cputime);
|
||||||
|
|
||||||
|
/* Add guest time to process. */
|
||||||
p->utime = cputime_add(p->utime, cputime);
|
p->utime = cputime_add(p->utime, cputime);
|
||||||
|
p->utimescaled = cputime_add(p->utimescaled, cputime_scaled);
|
||||||
account_group_user_time(p, cputime);
|
account_group_user_time(p, cputime);
|
||||||
p->gtime = cputime_add(p->gtime, cputime);
|
p->gtime = cputime_add(p->gtime, cputime);
|
||||||
|
|
||||||
|
/* Add guest time to cpustat. */
|
||||||
cpustat->user = cputime64_add(cpustat->user, tmp);
|
cpustat->user = cputime64_add(cpustat->user, tmp);
|
||||||
cpustat->guest = cputime64_add(cpustat->guest, tmp);
|
cpustat->guest = cputime64_add(cpustat->guest, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Account scaled user cpu time to a process.
|
|
||||||
* @p: the process that the cpu time gets accounted to
|
|
||||||
* @cputime: the cpu time spent in user space since the last update
|
|
||||||
*/
|
|
||||||
void account_user_time_scaled(struct task_struct *p, cputime_t cputime)
|
|
||||||
{
|
|
||||||
p->utimescaled = cputime_add(p->utimescaled, cputime);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Account system cpu time to a process.
|
* Account system cpu time to a process.
|
||||||
* @p: the process that the cpu time gets accounted to
|
* @p: the process that the cpu time gets accounted to
|
||||||
* @hardirq_offset: the offset to subtract from hardirq_count()
|
* @hardirq_offset: the offset to subtract from hardirq_count()
|
||||||
* @cputime: the cpu time spent in kernel space since the last update
|
* @cputime: the cpu time spent in kernel space since the last update
|
||||||
|
* @cputime_scaled: cputime scaled by cpu frequency
|
||||||
*/
|
*/
|
||||||
void account_system_time(struct task_struct *p, int hardirq_offset,
|
void account_system_time(struct task_struct *p, int hardirq_offset,
|
||||||
cputime_t cputime)
|
cputime_t cputime, cputime_t cputime_scaled)
|
||||||
{
|
{
|
||||||
struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
|
struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
|
||||||
struct rq *rq = this_rq();
|
struct rq *rq = this_rq();
|
||||||
cputime64_t tmp;
|
cputime64_t tmp;
|
||||||
|
|
||||||
if ((p->flags & PF_VCPU) && (irq_count() - hardirq_offset == 0)) {
|
if ((p->flags & PF_VCPU) && (irq_count() - hardirq_offset == 0)) {
|
||||||
account_guest_time(p, cputime);
|
account_guest_time(p, cputime, cputime_scaled);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add system time to process. */
|
||||||
p->stime = cputime_add(p->stime, cputime);
|
p->stime = cputime_add(p->stime, cputime);
|
||||||
|
p->stimescaled = cputime_add(p->stimescaled, cputime_scaled);
|
||||||
account_group_system_time(p, cputime);
|
account_group_system_time(p, cputime);
|
||||||
|
|
||||||
/* Add system time to cpustat. */
|
/* Add system time to cpustat. */
|
||||||
|
@ -4166,17 +4168,6 @@ void account_system_time(struct task_struct *p, int hardirq_offset,
|
||||||
acct_update_integrals(p);
|
acct_update_integrals(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Account scaled system cpu time to a process.
|
|
||||||
* @p: the process that the cpu time gets accounted to
|
|
||||||
* @hardirq_offset: the offset to subtract from hardirq_count()
|
|
||||||
* @cputime: the cpu time spent in kernel space since the last update
|
|
||||||
*/
|
|
||||||
void account_system_time_scaled(struct task_struct *p, cputime_t cputime)
|
|
||||||
{
|
|
||||||
p->stimescaled = cputime_add(p->stimescaled, cputime);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Account for involuntary wait time.
|
* Account for involuntary wait time.
|
||||||
* @p: the process from which the cpu time has been stolen
|
* @p: the process from which the cpu time has been stolen
|
||||||
|
|
|
@ -420,6 +420,7 @@ void tick_nohz_restart_sched_tick(void)
|
||||||
int cpu = smp_processor_id();
|
int cpu = smp_processor_id();
|
||||||
struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
|
struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
|
||||||
unsigned long ticks;
|
unsigned long ticks;
|
||||||
|
cputime_t cputime;
|
||||||
ktime_t now;
|
ktime_t now;
|
||||||
|
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
|
@ -452,8 +453,8 @@ void tick_nohz_restart_sched_tick(void)
|
||||||
*/
|
*/
|
||||||
if (ticks && ticks < LONG_MAX) {
|
if (ticks && ticks < LONG_MAX) {
|
||||||
add_preempt_count(HARDIRQ_OFFSET);
|
add_preempt_count(HARDIRQ_OFFSET);
|
||||||
account_system_time(current, HARDIRQ_OFFSET,
|
cputime = jiffies_to_cputime(ticks);
|
||||||
jiffies_to_cputime(ticks));
|
account_system_time(current, HARDIRQ_OFFSET, cputime, cputime);
|
||||||
sub_preempt_count(HARDIRQ_OFFSET);
|
sub_preempt_count(HARDIRQ_OFFSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1023,13 +1023,11 @@ void account_process_tick(struct task_struct *p, int user_tick)
|
||||||
{
|
{
|
||||||
cputime_t one_jiffy = jiffies_to_cputime(1);
|
cputime_t one_jiffy = jiffies_to_cputime(1);
|
||||||
|
|
||||||
if (user_tick) {
|
if (user_tick)
|
||||||
account_user_time(p, one_jiffy);
|
account_user_time(p, one_jiffy, cputime_to_scaled(one_jiffy));
|
||||||
account_user_time_scaled(p, cputime_to_scaled(one_jiffy));
|
else
|
||||||
} else {
|
account_system_time(p, HARDIRQ_OFFSET, one_jiffy,
|
||||||
account_system_time(p, HARDIRQ_OFFSET, one_jiffy);
|
cputime_to_scaled(one_jiffy));
|
||||||
account_system_time_scaled(p, cputime_to_scaled(one_jiffy));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче