Skip to content

Commit

Permalink
[PATCH] fix scaled & unscaled cputime accounting
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Martin Schwidefsky committed Dec 31, 2008
1 parent 6a94cb7 commit 457533a
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 56 deletions.
12 changes: 4 additions & 8 deletions arch/ia64/kernel/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,11 @@ void ia64_account_on_switch(struct task_struct *prev, struct task_struct *next)
now = ia64_get_itc();

delta_stime = cycle_to_cputime(pi->ac_stime + (now - pi->ac_stamp));
account_system_time(prev, 0, delta_stime);
account_system_time_scaled(prev, delta_stime);
account_system_time(prev, 0, delta_stime, delta_stime);

if (pi->ac_utime) {
delta_utime = cycle_to_cputime(pi->ac_utime);
account_user_time(prev, delta_utime);
account_user_time_scaled(prev, delta_utime);
account_user_time(prev, delta_utime, delta_utime);
}

pi->ac_stamp = ni->ac_stamp = now;
Expand All @@ -122,8 +120,7 @@ void account_system_vtime(struct task_struct *tsk)
now = ia64_get_itc();

delta_stime = cycle_to_cputime(ti->ac_stime + (now - ti->ac_stamp));
account_system_time(tsk, 0, delta_stime);
account_system_time_scaled(tsk, delta_stime);
account_system_time(tsk, 0, delta_stime, delta_stime);
ti->ac_stime = 0;

ti->ac_stamp = now;
Expand All @@ -143,8 +140,7 @@ void account_process_tick(struct task_struct *p, int user_tick)

if (ti->ac_utime) {
delta_utime = cycle_to_cputime(ti->ac_utime);
account_user_time(p, delta_utime);
account_user_time_scaled(p, delta_utime);
account_user_time(p, delta_utime, delta_utime);
ti->ac_utime = 0;
}
}
Expand Down
7 changes: 2 additions & 5 deletions arch/powerpc/kernel/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,7 @@ void account_system_vtime(struct task_struct *tsk)
delta += sys_time;
get_paca()->system_time = 0;
}
account_system_time(tsk, 0, delta);
account_system_time_scaled(tsk, deltascaled);
account_system_time(tsk, 0, delta, deltascaled);
per_cpu(cputime_last_delta, smp_processor_id()) = delta;
per_cpu(cputime_scaled_last_delta, smp_processor_id()) = deltascaled;
local_irq_restore(flags);
Expand All @@ -275,10 +274,8 @@ void account_process_tick(struct task_struct *tsk, int user_tick)

utime = get_paca()->user_time;
get_paca()->user_time = 0;
account_user_time(tsk, utime);

utimescaled = cputime_to_scaled(utime);
account_user_time_scaled(tsk, utimescaled);
account_user_time(tsk, utime, utimescaled);
}

/*
Expand Down
10 changes: 5 additions & 5 deletions arch/s390/kernel/vtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@ void account_process_tick(struct task_struct *tsk, int user_tick)
rcu_user_flag = cputime != 0;
S390_lowcore.user_timer -= 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;
S390_lowcore.system_timer -= 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;
if ((__s64) cputime > 0) {
Expand All @@ -82,12 +82,12 @@ void account_vtime(struct task_struct *tsk)
cputime = S390_lowcore.user_timer >> 12;
S390_lowcore.user_timer -= 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;
S390_lowcore.system_timer -= cputime << 12;
S390_lowcore.steal_clock -= cputime << 12;
account_system_time(tsk, 0, cputime);
account_system_time(tsk, 0, cputime, cputime);
}

/*
Expand All @@ -107,7 +107,7 @@ void account_system_vtime(struct task_struct *tsk)
cputime = S390_lowcore.system_timer >> 12;
S390_lowcore.system_timer -= 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);

Expand Down
6 changes: 2 additions & 4 deletions include/linux/kernel_stat.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,8 @@ static inline unsigned int kstat_irqs(unsigned int irq)
}

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_scaled(struct task_struct *, 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_user_time(struct task_struct *, cputime_t, cputime_t);
extern void account_system_time(struct task_struct *, int, cputime_t, cputime_t);
extern void account_steal_time(struct task_struct *, cputime_t);

#endif /* _LINUX_KERNEL_STAT_H */
41 changes: 16 additions & 25 deletions kernel/sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -4080,13 +4080,17 @@ unsigned long long task_delta_exec(struct task_struct *p)
* Account 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
* @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;
cputime64_t tmp;

/* Add user time to process. */
p->utime = cputime_add(p->utime, cputime);
p->utimescaled = cputime_add(p->utimescaled, cputime_scaled);
account_group_user_time(p, cputime);

/* Add user time to cpustat. */
Expand All @@ -4103,51 +4107,49 @@ void account_user_time(struct task_struct *p, cputime_t cputime)
* Account guest cpu time to a process.
* @p: the process that the cpu time gets accounted to
* @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;
struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;

tmp = cputime_to_cputime64(cputime);

/* Add guest time to process. */
p->utime = cputime_add(p->utime, cputime);
p->utimescaled = cputime_add(p->utimescaled, cputime_scaled);
account_group_user_time(p, cputime);
p->gtime = cputime_add(p->gtime, cputime);

/* Add guest time to cpustat. */
cpustat->user = cputime64_add(cpustat->user, 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.
* @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
* @cputime_scaled: cputime scaled by cpu frequency
*/
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 rq *rq = this_rq();
cputime64_t tmp;

if ((p->flags & PF_VCPU) && (irq_count() - hardirq_offset == 0)) {
account_guest_time(p, cputime);
account_guest_time(p, cputime, cputime_scaled);
return;
}

/* Add system time to process. */
p->stime = cputime_add(p->stime, cputime);
p->stimescaled = cputime_add(p->stimescaled, cputime_scaled);
account_group_system_time(p, cputime);

/* Add system time to cpustat. */
Expand All @@ -4166,17 +4168,6 @@ void account_system_time(struct task_struct *p, int hardirq_offset,
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.
* @p: the process from which the cpu time has been stolen
Expand Down
5 changes: 3 additions & 2 deletions kernel/time/tick-sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,7 @@ void tick_nohz_restart_sched_tick(void)
int cpu = smp_processor_id();
struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
unsigned long ticks;
cputime_t cputime;
ktime_t now;

local_irq_disable();
Expand Down Expand Up @@ -452,8 +453,8 @@ void tick_nohz_restart_sched_tick(void)
*/
if (ticks && ticks < LONG_MAX) {
add_preempt_count(HARDIRQ_OFFSET);
account_system_time(current, HARDIRQ_OFFSET,
jiffies_to_cputime(ticks));
cputime = jiffies_to_cputime(ticks);
account_system_time(current, HARDIRQ_OFFSET, cputime, cputime);
sub_preempt_count(HARDIRQ_OFFSET);
}

Expand Down
12 changes: 5 additions & 7 deletions kernel/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -1023,13 +1023,11 @@ void account_process_tick(struct task_struct *p, int user_tick)
{
cputime_t one_jiffy = jiffies_to_cputime(1);

if (user_tick) {
account_user_time(p, one_jiffy);
account_user_time_scaled(p, cputime_to_scaled(one_jiffy));
} else {
account_system_time(p, HARDIRQ_OFFSET, one_jiffy);
account_system_time_scaled(p, cputime_to_scaled(one_jiffy));
}
if (user_tick)
account_user_time(p, one_jiffy, cputime_to_scaled(one_jiffy));
else
account_system_time(p, HARDIRQ_OFFSET, one_jiffy,
cputime_to_scaled(one_jiffy));
}
#endif

Expand Down

0 comments on commit 457533a

Please sign in to comment.