diff options
| author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2008-12-31 15:11:37 +0100 | 
|---|---|---|
| committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2008-12-31 15:11:46 +0100 | 
| commit | 457533a7d3402d1d91fbc125c8bd1bd16dcd3cd4 (patch) | |
| tree | cbe69310a66176dea2a9e7bd201db95efe4a2890 | |
| parent | 6a94cb73064c952255336cc57731904174b2c58f (diff) | |
| download | olio-linux-3.10-457533a7d3402d1d91fbc125c8bd1bd16dcd3cd4.tar.xz olio-linux-3.10-457533a7d3402d1d91fbc125c8bd1bd16dcd3cd4.zip  | |
[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 65c10a42c88..4ee36781704 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)  	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; @@ -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; @@ -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;  	}  } diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index e1f3a514042..92650ccad2e 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)  		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); @@ -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);  }  /* diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index 75a6e62ea97..07283aea2e5 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)  	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) { @@ -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);  }  /* @@ -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); diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h index 4ee4b3d2316..c78a459662a 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)  }  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 */ diff --git a/kernel/sched.c b/kernel/sched.c index fff1c4a20b6..5b03679ff71 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -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. */ @@ -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. */ @@ -4167,17 +4169,6 @@ void account_system_time(struct task_struct *p, int hardirq_offset,  }  /* - * 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   * @steal: the cpu time spent in involuntary wait diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 8f3fc2582d3..1f2fce2479f 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -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(); @@ -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);  	} diff --git a/kernel/timer.c b/kernel/timer.c index 566257d1dc1..b5efb528aa1 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -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  |