2013-03-29 10:36:31 +04:00
# include <linux/cgroup.h>
# include <linux/slab.h>
# include <linux/percpu.h>
# include <linux/spinlock.h>
# include <linux/cpumask.h>
# include <linux/seq_file.h>
# include <linux/rcupdate.h>
# include <linux/kernel_stat.h>
2013-04-10 17:10:50 +04:00
# include <linux/err.h>
2013-03-29 10:36:31 +04:00
# include "sched.h"
/*
* CPU accounting code for task groups .
*
* Based on the work by Paul Menage ( menage @ google . com ) and Balbir Singh
* ( balbir @ in . ibm . com ) .
*/
2013-03-29 10:38:13 +04:00
/* Time spent by the tasks of the cpu accounting group executing in ... */
enum cpuacct_stat_index {
CPUACCT_STAT_USER , /* ... user mode */
CPUACCT_STAT_SYSTEM , /* ... kernel mode */
CPUACCT_STAT_NSTATS ,
} ;
2016-06-20 12:37:18 +03:00
static const char * const cpuacct_stat_desc [ ] = {
[ CPUACCT_STAT_USER ] = " user " ,
[ CPUACCT_STAT_SYSTEM ] = " system " ,
2016-03-22 11:37:08 +03:00
} ;
struct cpuacct_usage {
2016-06-20 12:37:18 +03:00
u64 usages [ CPUACCT_STAT_NSTATS ] ;
2016-03-22 11:37:08 +03:00
} ;
2013-03-29 10:38:13 +04:00
/* 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 */
2016-03-22 11:37:08 +03:00
struct cpuacct_usage __percpu * cpuusage ;
2013-03-29 10:38:13 +04:00
struct kernel_cpustat __percpu * cpustat ;
} ;
2013-08-09 04:11:23 +04:00
static inline struct cpuacct * css_ca ( struct cgroup_subsys_state * css )
{
return css ? container_of ( css , struct cpuacct , css ) : NULL ;
}
2013-03-29 10:38:13 +04:00
/* return cpu accounting group to which this task belongs */
static inline struct cpuacct * task_ca ( struct task_struct * tsk )
{
2014-02-08 19:36:58 +04:00
return css_ca ( task_css ( tsk , cpuacct_cgrp_id ) ) ;
2013-03-29 10:38:13 +04:00
}
static inline struct cpuacct * parent_ca ( struct cpuacct * ca )
{
2014-05-16 21:22:48 +04:00
return css_ca ( ca - > css . parent ) ;
2013-03-29 10:38:13 +04:00
}
2016-03-22 11:37:08 +03:00
static DEFINE_PER_CPU ( struct cpuacct_usage , root_cpuacct_cpuusage ) ;
2013-03-29 10:44:04 +04:00
static struct cpuacct root_cpuacct = {
. cpustat = & kernel_cpustat ,
. cpuusage = & root_cpuacct_cpuusage ,
} ;
2013-03-29 10:36:31 +04:00
/* create a new cpu accounting group */
2013-08-09 04:11:23 +04:00
static struct cgroup_subsys_state *
cpuacct_css_alloc ( struct cgroup_subsys_state * parent_css )
2013-03-29 10:36:31 +04:00
{
struct cpuacct * ca ;
2013-08-09 04:11:23 +04:00
if ( ! parent_css )
2013-03-29 10:36:31 +04:00
return & root_cpuacct . css ;
ca = kzalloc ( sizeof ( * ca ) , GFP_KERNEL ) ;
if ( ! ca )
goto out ;
2016-03-22 11:37:08 +03:00
ca - > cpuusage = alloc_percpu ( struct cpuacct_usage ) ;
2013-03-29 10:36:31 +04:00
if ( ! ca - > cpuusage )
goto out_free_ca ;
ca - > cpustat = alloc_percpu ( struct kernel_cpustat ) ;
if ( ! ca - > cpustat )
goto out_free_cpuusage ;
return & ca - > css ;
out_free_cpuusage :
free_percpu ( ca - > cpuusage ) ;
out_free_ca :
kfree ( ca ) ;
out :
return ERR_PTR ( - ENOMEM ) ;
}
/* destroy an existing cpu accounting group */
2013-08-09 04:11:23 +04:00
static void cpuacct_css_free ( struct cgroup_subsys_state * css )
2013-03-29 10:36:31 +04:00
{
2013-08-09 04:11:23 +04:00
struct cpuacct * ca = css_ca ( css ) ;
2013-03-29 10:36:31 +04:00
free_percpu ( ca - > cpustat ) ;
free_percpu ( ca - > cpuusage ) ;
kfree ( ca ) ;
}
2016-03-22 11:37:08 +03:00
static u64 cpuacct_cpuusage_read ( struct cpuacct * ca , int cpu ,
2016-06-20 12:37:18 +03:00
enum cpuacct_stat_index index )
2013-03-29 10:36:31 +04:00
{
2016-03-22 11:37:08 +03:00
struct cpuacct_usage * cpuusage = per_cpu_ptr ( ca - > cpuusage , cpu ) ;
2013-03-29 10:36:31 +04:00
u64 data ;
2016-03-22 11:37:08 +03:00
/*
2016-06-20 12:37:18 +03:00
* We allow index = = CPUACCT_STAT_NSTATS here to read
2016-03-22 11:37:08 +03:00
* the sum of suages .
*/
2016-06-20 12:37:18 +03:00
BUG_ON ( index > CPUACCT_STAT_NSTATS ) ;
2016-03-22 11:37:08 +03:00
2013-03-29 10:36:31 +04:00
# ifndef CONFIG_64BIT
/*
* Take rq - > lock to make 64 - bit read safe on 32 - bit platforms .
*/
raw_spin_lock_irq ( & cpu_rq ( cpu ) - > lock ) ;
2016-03-22 11:37:08 +03:00
# endif
2016-06-20 12:37:18 +03:00
if ( index = = CPUACCT_STAT_NSTATS ) {
2016-03-22 11:37:08 +03:00
int i = 0 ;
data = 0 ;
2016-06-20 12:37:18 +03:00
for ( i = 0 ; i < CPUACCT_STAT_NSTATS ; i + + )
2016-03-22 11:37:08 +03:00
data + = cpuusage - > usages [ i ] ;
} else {
data = cpuusage - > usages [ index ] ;
}
# ifndef CONFIG_64BIT
2013-03-29 10:36:31 +04:00
raw_spin_unlock_irq ( & cpu_rq ( cpu ) - > lock ) ;
# endif
return data ;
}
static void cpuacct_cpuusage_write ( struct cpuacct * ca , int cpu , u64 val )
{
2016-03-22 11:37:08 +03:00
struct cpuacct_usage * cpuusage = per_cpu_ptr ( ca - > cpuusage , cpu ) ;
int i ;
2013-03-29 10:36:31 +04:00
# ifndef CONFIG_64BIT
/*
* Take rq - > lock to make 64 - bit write safe on 32 - bit platforms .
*/
raw_spin_lock_irq ( & cpu_rq ( cpu ) - > lock ) ;
2016-03-22 11:37:08 +03:00
# endif
2016-06-20 12:37:18 +03:00
for ( i = 0 ; i < CPUACCT_STAT_NSTATS ; i + + )
2016-03-22 11:37:08 +03:00
cpuusage - > usages [ i ] = val ;
# ifndef CONFIG_64BIT
2013-03-29 10:36:31 +04:00
raw_spin_unlock_irq ( & cpu_rq ( cpu ) - > lock ) ;
# endif
}
/* return total cpu usage (in nanoseconds) of a group */
2016-03-22 11:37:08 +03:00
static u64 __cpuusage_read ( struct cgroup_subsys_state * css ,
2016-06-20 12:37:18 +03:00
enum cpuacct_stat_index index )
2013-03-29 10:36:31 +04:00
{
2013-08-09 04:11:24 +04:00
struct cpuacct * ca = css_ca ( css ) ;
2013-03-29 10:36:31 +04:00
u64 totalcpuusage = 0 ;
int i ;
2016-03-22 11:37:07 +03:00
for_each_possible_cpu ( i )
2016-03-22 11:37:08 +03:00
totalcpuusage + = cpuacct_cpuusage_read ( ca , i , index ) ;
2013-03-29 10:36:31 +04:00
return totalcpuusage ;
}
2016-03-22 11:37:08 +03:00
static u64 cpuusage_user_read ( struct cgroup_subsys_state * css ,
struct cftype * cft )
{
2016-06-20 12:37:18 +03:00
return __cpuusage_read ( css , CPUACCT_STAT_USER ) ;
2016-03-22 11:37:08 +03:00
}
static u64 cpuusage_sys_read ( struct cgroup_subsys_state * css ,
struct cftype * cft )
{
2016-06-20 12:37:18 +03:00
return __cpuusage_read ( css , CPUACCT_STAT_SYSTEM ) ;
2016-03-22 11:37:08 +03:00
}
static u64 cpuusage_read ( struct cgroup_subsys_state * css , struct cftype * cft )
{
2016-06-20 12:37:18 +03:00
return __cpuusage_read ( css , CPUACCT_STAT_NSTATS ) ;
2016-03-22 11:37:08 +03:00
}
2013-08-09 04:11:24 +04:00
static int cpuusage_write ( struct cgroup_subsys_state * css , struct cftype * cft ,
2015-12-21 14:14:42 +03:00
u64 val )
2013-03-29 10:36:31 +04:00
{
2013-08-09 04:11:24 +04:00
struct cpuacct * ca = css_ca ( css ) ;
2016-03-22 11:37:08 +03:00
int cpu ;
2013-03-29 10:36:31 +04:00
2015-12-21 14:14:42 +03:00
/*
* Only allow ' 0 ' here to do a reset .
*/
2016-03-22 11:37:08 +03:00
if ( val )
return - EINVAL ;
2013-03-29 10:36:31 +04:00
2016-03-22 11:37:08 +03:00
for_each_possible_cpu ( cpu )
cpuacct_cpuusage_write ( ca , cpu , 0 ) ;
2013-03-29 10:36:31 +04:00
2016-03-22 11:37:08 +03:00
return 0 ;
2013-03-29 10:36:31 +04:00
}
2016-03-22 11:37:08 +03:00
static int __cpuacct_percpu_seq_show ( struct seq_file * m ,
2016-06-20 12:37:18 +03:00
enum cpuacct_stat_index index )
2013-03-29 10:36:31 +04:00
{
2013-12-05 21:28:04 +04:00
struct cpuacct * ca = css_ca ( seq_css ( m ) ) ;
2013-03-29 10:36:31 +04:00
u64 percpu ;
int i ;
2016-03-22 11:37:07 +03:00
for_each_possible_cpu ( i ) {
2016-03-22 11:37:08 +03:00
percpu = cpuacct_cpuusage_read ( ca , i , index ) ;
2013-03-29 10:36:31 +04:00
seq_printf ( m , " %llu " , ( unsigned long long ) percpu ) ;
}
seq_printf ( m , " \n " ) ;
return 0 ;
}
2016-03-22 11:37:08 +03:00
static int cpuacct_percpu_user_seq_show ( struct seq_file * m , void * V )
{
2016-06-20 12:37:18 +03:00
return __cpuacct_percpu_seq_show ( m , CPUACCT_STAT_USER ) ;
2016-03-22 11:37:08 +03:00
}
static int cpuacct_percpu_sys_seq_show ( struct seq_file * m , void * V )
{
2016-06-20 12:37:18 +03:00
return __cpuacct_percpu_seq_show ( m , CPUACCT_STAT_SYSTEM ) ;
2016-03-22 11:37:08 +03:00
}
static int cpuacct_percpu_seq_show ( struct seq_file * m , void * V )
{
2016-06-20 12:37:18 +03:00
return __cpuacct_percpu_seq_show ( m , CPUACCT_STAT_NSTATS ) ;
2016-03-22 11:37:08 +03:00
}
2016-06-20 12:37:20 +03:00
static int cpuacct_all_seq_show ( struct seq_file * m , void * V )
{
struct cpuacct * ca = css_ca ( seq_css ( m ) ) ;
int index ;
int cpu ;
seq_puts ( m , " cpu " ) ;
for ( index = 0 ; index < CPUACCT_STAT_NSTATS ; index + + )
seq_printf ( m , " %s " , cpuacct_stat_desc [ index ] ) ;
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_lock_irq ( & cpu_rq ( cpu ) - > lock ) ;
# endif
seq_printf ( m , " %llu " , cpuusage - > usages [ index ] ) ;
# ifndef CONFIG_64BIT
raw_spin_unlock_irq ( & cpu_rq ( cpu ) - > lock ) ;
# endif
}
seq_puts ( m , " \n " ) ;
}
return 0 ;
}
2013-12-05 21:28:04 +04:00
static int cpuacct_stats_show ( struct seq_file * sf , void * v )
2013-03-29 10:36:31 +04:00
{
2013-12-05 21:28:04 +04:00
struct cpuacct * ca = css_ca ( seq_css ( sf ) ) ;
2016-06-20 12:37:19 +03:00
s64 val [ CPUACCT_STAT_NSTATS ] ;
2013-03-29 10:36:31 +04:00
int cpu ;
2016-06-20 12:37:19 +03:00
int stat ;
2013-03-29 10:36:31 +04:00
2016-06-20 12:37:19 +03:00
memset ( val , 0 , sizeof ( val ) ) ;
2016-03-22 11:37:07 +03:00
for_each_possible_cpu ( cpu ) {
2016-06-20 12:37:19 +03:00
u64 * cpustat = per_cpu_ptr ( ca - > cpustat , cpu ) - > cpustat ;
2013-03-29 10:36:31 +04:00
2016-06-20 12:37:19 +03:00
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 ] ;
2013-03-29 10:36:31 +04:00
}
2016-06-20 12:37:19 +03:00
for ( stat = 0 ; stat < CPUACCT_STAT_NSTATS ; stat + + ) {
seq_printf ( sf , " %s %lld \n " ,
cpuacct_stat_desc [ stat ] ,
2017-01-31 06:09:19 +03:00
( long long ) nsec_to_clock_t ( val [ stat ] ) ) ;
2016-06-20 12:37:19 +03:00
}
2013-03-29 10:36:31 +04:00
return 0 ;
}
static struct cftype files [ ] = {
{
. name = " usage " ,
. read_u64 = cpuusage_read ,
. write_u64 = cpuusage_write ,
} ,
2016-03-22 11:37:08 +03:00
{
. name = " usage_user " ,
. read_u64 = cpuusage_user_read ,
} ,
{
. name = " usage_sys " ,
. read_u64 = cpuusage_sys_read ,
} ,
2013-03-29 10:36:31 +04:00
{
. name = " usage_percpu " ,
2013-12-05 21:28:04 +04:00
. seq_show = cpuacct_percpu_seq_show ,
2013-03-29 10:36:31 +04:00
} ,
2016-03-22 11:37:08 +03:00
{
. name = " usage_percpu_user " ,
. seq_show = cpuacct_percpu_user_seq_show ,
} ,
{
. name = " usage_percpu_sys " ,
. seq_show = cpuacct_percpu_sys_seq_show ,
} ,
2016-06-20 12:37:20 +03:00
{
. name = " usage_all " ,
. seq_show = cpuacct_all_seq_show ,
} ,
2013-03-29 10:36:31 +04:00
{
. name = " stat " ,
2013-12-05 21:28:04 +04:00
. seq_show = cpuacct_stats_show ,
2013-03-29 10:36:31 +04:00
} ,
{ } /* terminate */
} ;
/*
* charge this task ' s execution time to its accounting group .
*
* called with rq - > lock held .
*/
void cpuacct_charge ( struct task_struct * tsk , u64 cputime )
{
struct cpuacct * ca ;
2016-06-20 12:37:18 +03:00
int index = CPUACCT_STAT_SYSTEM ;
2016-04-06 14:59:50 +03:00
struct pt_regs * regs = task_pt_regs ( tsk ) ;
2016-03-22 11:37:08 +03:00
2016-04-06 14:59:50 +03:00
if ( regs & & user_mode ( regs ) )
2016-06-20 12:37:18 +03:00
index = CPUACCT_STAT_USER ;
2013-03-29 10:36:31 +04:00
rcu_read_lock ( ) ;
2016-03-22 11:37:08 +03:00
2016-03-17 07:19:43 +03:00
for ( ca = task_ca ( tsk ) ; ca ; ca = parent_ca ( ca ) )
2016-03-22 11:37:08 +03:00
this_cpu_ptr ( ca - > cpuusage ) - > usages [ index ] + = cputime ;
2013-03-29 10:36:31 +04:00
rcu_read_unlock ( ) ;
}
2013-03-29 10:37:06 +04:00
/*
* Add user / system time to cpuacct .
*
* Note : it ' s the caller that updates the account of the root cgroup .
*/
2016-03-17 07:19:43 +03:00
void cpuacct_account_field ( struct task_struct * tsk , int index , u64 val )
2013-03-29 10:37:06 +04:00
{
struct cpuacct * ca ;
rcu_read_lock ( ) ;
2016-03-17 07:19:43 +03:00
for ( ca = task_ca ( tsk ) ; ca ! = & root_cpuacct ; ca = parent_ca ( ca ) )
this_cpu_ptr ( ca - > cpustat ) - > cpustat [ index ] + = val ;
2013-03-29 10:37:06 +04:00
rcu_read_unlock ( ) ;
}
2014-02-08 19:36:58 +04:00
struct cgroup_subsys cpuacct_cgrp_subsys = {
2013-03-29 10:44:15 +04:00
. css_alloc = cpuacct_css_alloc ,
. css_free = cpuacct_css_free ,
2014-07-15 19:05:09 +04:00
. legacy_cftypes = files ,
2016-02-23 18:00:50 +03:00
. early_init = true ,
2013-03-29 10:36:31 +04:00
} ;