diff options
Diffstat (limited to 'kernel/sched/cpuacct.c')
| -rw-r--r-- | kernel/sched/cpuacct.c | 107 | 
1 files changed, 49 insertions, 58 deletions
| diff --git a/kernel/sched/cpuacct.c b/kernel/sched/cpuacct.c index 893eece65bfd..3d06c5e4220d 100644 --- a/kernel/sched/cpuacct.c +++ b/kernel/sched/cpuacct.c @@ -21,15 +21,11 @@ static const char * const cpuacct_stat_desc[] = {  	[CPUACCT_STAT_SYSTEM] = "system",  }; -struct cpuacct_usage { -	u64	usages[CPUACCT_STAT_NSTATS]; -}; -  /* track CPU usage of a group of tasks and its child groups */  struct cpuacct {  	struct cgroup_subsys_state	css;  	/* cpuusage holds pointer to a u64-type object on every CPU */ -	struct cpuacct_usage __percpu	*cpuusage; +	u64 __percpu	*cpuusage;  	struct kernel_cpustat __percpu	*cpustat;  }; @@ -49,7 +45,7 @@ static inline struct cpuacct *parent_ca(struct cpuacct *ca)  	return css_ca(ca->css.parent);  } -static DEFINE_PER_CPU(struct cpuacct_usage, root_cpuacct_cpuusage); +static DEFINE_PER_CPU(u64, root_cpuacct_cpuusage);  static struct cpuacct root_cpuacct = {  	.cpustat	= &kernel_cpustat,  	.cpuusage	= &root_cpuacct_cpuusage, @@ -68,7 +64,7 @@ cpuacct_css_alloc(struct cgroup_subsys_state *parent_css)  	if (!ca)  		goto out; -	ca->cpuusage = alloc_percpu(struct cpuacct_usage); +	ca->cpuusage = alloc_percpu(u64);  	if (!ca->cpuusage)  		goto out_free_ca; @@ -99,14 +95,16 @@ static void cpuacct_css_free(struct cgroup_subsys_state *css)  static u64 cpuacct_cpuusage_read(struct cpuacct *ca, int cpu,  				 enum cpuacct_stat_index index)  { -	struct cpuacct_usage *cpuusage = per_cpu_ptr(ca->cpuusage, cpu); +	u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu); +	u64 *cpustat = per_cpu_ptr(ca->cpustat, cpu)->cpustat;  	u64 data;  	/*  	 * We allow index == CPUACCT_STAT_NSTATS here to read  	 * the sum of usages.  	 */ -	BUG_ON(index > CPUACCT_STAT_NSTATS); +	if (WARN_ON_ONCE(index > CPUACCT_STAT_NSTATS)) +		return 0;  #ifndef CONFIG_64BIT  	/* @@ -115,14 +113,17 @@ static u64 cpuacct_cpuusage_read(struct cpuacct *ca, int cpu,  	raw_spin_rq_lock_irq(cpu_rq(cpu));  #endif -	if (index == CPUACCT_STAT_NSTATS) { -		int i = 0; - -		data = 0; -		for (i = 0; i < CPUACCT_STAT_NSTATS; i++) -			data += cpuusage->usages[i]; -	} else { -		data = cpuusage->usages[index]; +	switch (index) { +	case CPUACCT_STAT_USER: +		data = cpustat[CPUTIME_USER] + cpustat[CPUTIME_NICE]; +		break; +	case CPUACCT_STAT_SYSTEM: +		data = cpustat[CPUTIME_SYSTEM] + cpustat[CPUTIME_IRQ] + +			cpustat[CPUTIME_SOFTIRQ]; +		break; +	case CPUACCT_STAT_NSTATS: +		data = *cpuusage; +		break;  	}  #ifndef CONFIG_64BIT @@ -132,10 +133,14 @@ static u64 cpuacct_cpuusage_read(struct cpuacct *ca, int cpu,  	return data;  } -static void cpuacct_cpuusage_write(struct cpuacct *ca, int cpu, u64 val) +static void cpuacct_cpuusage_write(struct cpuacct *ca, int cpu)  { -	struct cpuacct_usage *cpuusage = per_cpu_ptr(ca->cpuusage, cpu); -	int i; +	u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu); +	u64 *cpustat = per_cpu_ptr(ca->cpustat, cpu)->cpustat; + +	/* Don't allow to reset global kernel_cpustat */ +	if (ca == &root_cpuacct) +		return;  #ifndef CONFIG_64BIT  	/* @@ -143,9 +148,10 @@ static void cpuacct_cpuusage_write(struct cpuacct *ca, int cpu, u64 val)  	 */  	raw_spin_rq_lock_irq(cpu_rq(cpu));  #endif - -	for (i = 0; i < CPUACCT_STAT_NSTATS; i++) -		cpuusage->usages[i] = val; +	*cpuusage = 0; +	cpustat[CPUTIME_USER] = cpustat[CPUTIME_NICE] = 0; +	cpustat[CPUTIME_SYSTEM] = cpustat[CPUTIME_IRQ] = 0; +	cpustat[CPUTIME_SOFTIRQ] = 0;  #ifndef CONFIG_64BIT  	raw_spin_rq_unlock_irq(cpu_rq(cpu)); @@ -196,7 +202,7 @@ static int cpuusage_write(struct cgroup_subsys_state *css, struct cftype *cft,  		return -EINVAL;  	for_each_possible_cpu(cpu) -		cpuacct_cpuusage_write(ca, cpu, 0); +		cpuacct_cpuusage_write(ca, cpu);  	return 0;  } @@ -243,25 +249,10 @@ static int cpuacct_all_seq_show(struct seq_file *m, void *V)  	seq_puts(m, "\n");  	for_each_possible_cpu(cpu) { -		struct cpuacct_usage *cpuusage = per_cpu_ptr(ca->cpuusage, cpu); -  		seq_printf(m, "%d", cpu); - -		for (index = 0; index < CPUACCT_STAT_NSTATS; index++) { -#ifndef CONFIG_64BIT -			/* -			 * Take rq->lock to make 64-bit read safe on 32-bit -			 * platforms. -			 */ -			raw_spin_rq_lock_irq(cpu_rq(cpu)); -#endif - -			seq_printf(m, " %llu", cpuusage->usages[index]); - -#ifndef CONFIG_64BIT -			raw_spin_rq_unlock_irq(cpu_rq(cpu)); -#endif -		} +		for (index = 0; index < CPUACCT_STAT_NSTATS; index++) +			seq_printf(m, " %llu", +				   cpuacct_cpuusage_read(ca, cpu, index));  		seq_puts(m, "\n");  	}  	return 0; @@ -270,25 +261,30 @@ static int cpuacct_all_seq_show(struct seq_file *m, void *V)  static int cpuacct_stats_show(struct seq_file *sf, void *v)  {  	struct cpuacct *ca = css_ca(seq_css(sf)); -	s64 val[CPUACCT_STAT_NSTATS]; +	struct task_cputime cputime; +	u64 val[CPUACCT_STAT_NSTATS];  	int cpu;  	int stat; -	memset(val, 0, sizeof(val)); +	memset(&cputime, 0, sizeof(cputime));  	for_each_possible_cpu(cpu) {  		u64 *cpustat = per_cpu_ptr(ca->cpustat, cpu)->cpustat; -		val[CPUACCT_STAT_USER]   += cpustat[CPUTIME_USER]; -		val[CPUACCT_STAT_USER]   += cpustat[CPUTIME_NICE]; -		val[CPUACCT_STAT_SYSTEM] += cpustat[CPUTIME_SYSTEM]; -		val[CPUACCT_STAT_SYSTEM] += cpustat[CPUTIME_IRQ]; -		val[CPUACCT_STAT_SYSTEM] += cpustat[CPUTIME_SOFTIRQ]; +		cputime.utime += cpustat[CPUTIME_USER]; +		cputime.utime += cpustat[CPUTIME_NICE]; +		cputime.stime += cpustat[CPUTIME_SYSTEM]; +		cputime.stime += cpustat[CPUTIME_IRQ]; +		cputime.stime += cpustat[CPUTIME_SOFTIRQ]; + +		cputime.sum_exec_runtime += *per_cpu_ptr(ca->cpuusage, cpu);  	} +	cputime_adjust(&cputime, &seq_css(sf)->cgroup->prev_cputime, +		&val[CPUACCT_STAT_USER], &val[CPUACCT_STAT_SYSTEM]); +  	for (stat = 0; stat < CPUACCT_STAT_NSTATS; stat++) { -		seq_printf(sf, "%s %lld\n", -			   cpuacct_stat_desc[stat], -			   (long long)nsec_to_clock_t(val[stat])); +		seq_printf(sf, "%s %llu\n", cpuacct_stat_desc[stat], +			nsec_to_clock_t(val[stat]));  	}  	return 0; @@ -339,16 +335,11 @@ static struct cftype files[] = {  void cpuacct_charge(struct task_struct *tsk, u64 cputime)  {  	struct cpuacct *ca; -	int index = CPUACCT_STAT_SYSTEM; -	struct pt_regs *regs = get_irq_regs() ? : task_pt_regs(tsk); - -	if (regs && user_mode(regs)) -		index = CPUACCT_STAT_USER;  	rcu_read_lock();  	for (ca = task_ca(tsk); ca; ca = parent_ca(ca)) -		__this_cpu_add(ca->cpuusage->usages[index], cputime); +		__this_cpu_add(*ca->cpuusage, cputime);  	rcu_read_unlock();  } |