2008-10-05 00:01:56 +04:00
# include <linux/cpumask.h>
# include <linux/fs.h>
# include <linux/init.h>
# include <linux/interrupt.h>
# include <linux/kernel_stat.h>
# include <linux/proc_fs.h>
# include <linux/sched.h>
# include <linux/seq_file.h>
# include <linux/slab.h>
# include <linux/time.h>
2008-12-26 14:24:10 +09:00
# include <linux/irqnr.h>
2008-10-05 00:01:56 +04:00
# include <asm/cputime.h>
# ifndef arch_irq_stat_cpu
# define arch_irq_stat_cpu(cpu) 0
# endif
# ifndef arch_irq_stat
# define arch_irq_stat() 0
# endif
2009-04-23 13:58:08 +02:00
# ifndef arch_idle_time
# define arch_idle_time(cpu) 0
# endif
2008-10-05 00:01:56 +04:00
static int show_stat ( struct seq_file * p , void * v )
{
int i , j ;
unsigned long jif ;
cputime64_t user , nice , system , idle , iowait , irq , softirq , steal ;
2009-10-24 01:20:10 +09:00
cputime64_t guest , guest_nice ;
2008-10-05 00:01:56 +04:00
u64 sum = 0 ;
2009-06-17 16:25:55 -07:00
u64 sum_softirq = 0 ;
unsigned int per_softirq_sums [ NR_SOFTIRQS ] = { 0 } ;
2008-10-05 00:01:56 +04:00
struct timespec boottime ;
unsigned int per_irq_sum ;
user = nice = system = idle = iowait =
irq = softirq = steal = cputime64_zero ;
2009-10-24 01:20:10 +09:00
guest = guest_nice = cputime64_zero ;
2008-10-05 00:01:56 +04:00
getboottime ( & boottime ) ;
jif = boottime . tv_sec ;
for_each_possible_cpu ( i ) {
user = cputime64_add ( user , kstat_cpu ( i ) . cpustat . user ) ;
nice = cputime64_add ( nice , kstat_cpu ( i ) . cpustat . nice ) ;
system = cputime64_add ( system , kstat_cpu ( i ) . cpustat . system ) ;
idle = cputime64_add ( idle , kstat_cpu ( i ) . cpustat . idle ) ;
2009-04-23 13:58:08 +02:00
idle = cputime64_add ( idle , arch_idle_time ( i ) ) ;
2008-10-05 00:01:56 +04:00
iowait = cputime64_add ( iowait , kstat_cpu ( i ) . cpustat . iowait ) ;
irq = cputime64_add ( irq , kstat_cpu ( i ) . cpustat . irq ) ;
softirq = cputime64_add ( softirq , kstat_cpu ( i ) . cpustat . softirq ) ;
steal = cputime64_add ( steal , kstat_cpu ( i ) . cpustat . steal ) ;
guest = cputime64_add ( guest , kstat_cpu ( i ) . cpustat . guest ) ;
2009-10-24 01:20:10 +09:00
guest_nice = cputime64_add ( guest_nice ,
kstat_cpu ( i ) . cpustat . guest_nice ) ;
2008-12-08 14:06:17 -08:00
for_each_irq_nr ( j ) {
2008-10-05 00:01:56 +04:00
sum + = kstat_irqs_cpu ( j , i ) ;
2008-12-05 18:58:31 -08:00
}
2008-10-05 00:01:56 +04:00
sum + = arch_irq_stat_cpu ( i ) ;
2009-06-17 16:25:55 -07:00
for ( j = 0 ; j < NR_SOFTIRQS ; j + + ) {
unsigned int softirq_stat = kstat_softirqs_cpu ( j , i ) ;
per_softirq_sums [ j ] + = softirq_stat ;
sum_softirq + = softirq_stat ;
}
2008-10-05 00:01:56 +04:00
}
sum + = arch_irq_stat ( ) ;
2009-10-24 01:20:10 +09:00
seq_printf ( p , " cpu %llu %llu %llu %llu %llu %llu %llu %llu %llu "
" %llu \n " ,
2008-10-05 00:01:56 +04:00
( unsigned long long ) cputime64_to_clock_t ( user ) ,
( unsigned long long ) cputime64_to_clock_t ( nice ) ,
( unsigned long long ) cputime64_to_clock_t ( system ) ,
( unsigned long long ) cputime64_to_clock_t ( idle ) ,
( unsigned long long ) cputime64_to_clock_t ( iowait ) ,
( unsigned long long ) cputime64_to_clock_t ( irq ) ,
( unsigned long long ) cputime64_to_clock_t ( softirq ) ,
( unsigned long long ) cputime64_to_clock_t ( steal ) ,
2009-10-24 01:20:10 +09:00
( unsigned long long ) cputime64_to_clock_t ( guest ) ,
( unsigned long long ) cputime64_to_clock_t ( guest_nice ) ) ;
2008-10-05 00:01:56 +04:00
for_each_online_cpu ( i ) {
/* Copy values here to work around gcc-2.95.3, gcc-2.96 */
user = kstat_cpu ( i ) . cpustat . user ;
nice = kstat_cpu ( i ) . cpustat . nice ;
system = kstat_cpu ( i ) . cpustat . system ;
idle = kstat_cpu ( i ) . cpustat . idle ;
2009-04-23 13:58:08 +02:00
idle = cputime64_add ( idle , arch_idle_time ( i ) ) ;
2008-10-05 00:01:56 +04:00
iowait = kstat_cpu ( i ) . cpustat . iowait ;
irq = kstat_cpu ( i ) . cpustat . irq ;
softirq = kstat_cpu ( i ) . cpustat . softirq ;
steal = kstat_cpu ( i ) . cpustat . steal ;
guest = kstat_cpu ( i ) . cpustat . guest ;
2009-10-24 01:20:10 +09:00
guest_nice = kstat_cpu ( i ) . cpustat . guest_nice ;
2008-10-05 00:01:56 +04:00
seq_printf ( p ,
2009-10-24 01:20:10 +09:00
" cpu%d %llu %llu %llu %llu %llu %llu %llu %llu %llu "
" %llu \n " ,
2008-10-05 00:01:56 +04:00
i ,
( unsigned long long ) cputime64_to_clock_t ( user ) ,
( unsigned long long ) cputime64_to_clock_t ( nice ) ,
( unsigned long long ) cputime64_to_clock_t ( system ) ,
( unsigned long long ) cputime64_to_clock_t ( idle ) ,
( unsigned long long ) cputime64_to_clock_t ( iowait ) ,
( unsigned long long ) cputime64_to_clock_t ( irq ) ,
( unsigned long long ) cputime64_to_clock_t ( softirq ) ,
( unsigned long long ) cputime64_to_clock_t ( steal ) ,
2009-10-24 01:20:10 +09:00
( unsigned long long ) cputime64_to_clock_t ( guest ) ,
( unsigned long long ) cputime64_to_clock_t ( guest_nice ) ) ;
2008-10-05 00:01:56 +04:00
}
seq_printf ( p , " intr %llu " , ( unsigned long long ) sum ) ;
/* sum again ? it could be updated? */
2008-12-08 14:06:17 -08:00
for_each_irq_nr ( j ) {
2008-10-05 00:01:56 +04:00
per_irq_sum = 0 ;
2008-12-08 14:06:17 -08:00
for_each_possible_cpu ( i )
per_irq_sum + = kstat_irqs_cpu ( j , i ) ;
2008-10-05 00:01:56 +04:00
seq_printf ( p , " %u " , per_irq_sum ) ;
}
seq_printf ( p ,
" \n ctxt %llu \n "
" btime %lu \n "
" processes %lu \n "
" procs_running %lu \n "
" procs_blocked %lu \n " ,
nr_context_switches ( ) ,
( unsigned long ) jif ,
total_forks ,
nr_running ( ) ,
nr_iowait ( ) ) ;
2009-06-17 16:25:55 -07:00
seq_printf ( p , " softirq %llu " , ( unsigned long long ) sum_softirq ) ;
for ( i = 0 ; i < NR_SOFTIRQS ; i + + )
seq_printf ( p , " %u " , per_softirq_sums [ i ] ) ;
seq_printf ( p , " \n " ) ;
2008-10-05 00:01:56 +04:00
return 0 ;
}
static int stat_open ( struct inode * inode , struct file * file )
{
unsigned size = 4096 * ( 1 + num_possible_cpus ( ) / 32 ) ;
char * buf ;
struct seq_file * m ;
int res ;
/* don't ask for more than the kmalloc() max size, currently 128 KB */
if ( size > 128 * 1024 )
size = 128 * 1024 ;
buf = kmalloc ( size , GFP_KERNEL ) ;
if ( ! buf )
return - ENOMEM ;
res = single_open ( file , show_stat , NULL ) ;
if ( ! res ) {
m = file - > private_data ;
m - > buf = buf ;
m - > size = size ;
} else
kfree ( buf ) ;
return res ;
}
static const struct file_operations proc_stat_operations = {
. open = stat_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
} ;
static int __init proc_stat_init ( void )
{
proc_create ( " stat " , 0 , NULL , & proc_stat_operations ) ;
return 0 ;
}
module_init ( proc_stat_init ) ;