2008-10-05 00:01:56 +04:00
# include <linux/cpumask.h>
# include <linux/fs.h>
# include <linux/gfp.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 08:24:10 +03: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
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 ;
cputime64_t guest ;
u64 sum = 0 ;
struct timespec boottime ;
unsigned int per_irq_sum ;
user = nice = system = idle = iowait =
irq = softirq = steal = cputime64_zero ;
guest = cputime64_zero ;
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 ) ;
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 ) ;
2008-12-09 01:06:17 +03:00
for_each_irq_nr ( j ) {
2008-10-05 00:01:56 +04:00
sum + = kstat_irqs_cpu ( j , i ) ;
2008-12-06 05:58:31 +03:00
}
2008-10-05 00:01:56 +04:00
sum + = arch_irq_stat_cpu ( i ) ;
}
sum + = arch_irq_stat ( ) ;
seq_printf ( p , " cpu %llu %llu %llu %llu %llu %llu %llu %llu %llu \n " ,
( 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 ) ,
( unsigned long long ) cputime64_to_clock_t ( guest ) ) ;
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 ;
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 ;
seq_printf ( p ,
" cpu%d %llu %llu %llu %llu %llu %llu %llu %llu %llu \n " ,
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 ) ,
( unsigned long long ) cputime64_to_clock_t ( guest ) ) ;
}
seq_printf ( p , " intr %llu " , ( unsigned long long ) sum ) ;
/* sum again ? it could be updated? */
2008-12-09 01:06:17 +03:00
for_each_irq_nr ( j ) {
2008-10-05 00:01:56 +04:00
per_irq_sum = 0 ;
2008-12-09 01:06:17 +03: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 ( ) ) ;
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 ) ;