linux/fs/proc/stat.c
<<
>>
Prefs
   1#include <linux/cpumask.h>
   2#include <linux/fs.h>
   3#include <linux/init.h>
   4#include <linux/interrupt.h>
   5#include <linux/kernel_stat.h>
   6#include <linux/proc_fs.h>
   7#include <linux/sched.h>
   8#include <linux/seq_file.h>
   9#include <linux/slab.h>
  10#include <linux/time.h>
  11#include <linux/irqnr.h>
  12#include <asm/cputime.h>
  13#include <linux/tick.h>
  14
  15#ifndef arch_irq_stat_cpu
  16#define arch_irq_stat_cpu(cpu) 0
  17#endif
  18#ifndef arch_irq_stat
  19#define arch_irq_stat() 0
  20#endif
  21
  22#ifdef arch_idle_time
  23
  24static cputime64_t get_idle_time(int cpu)
  25{
  26        cputime64_t idle;
  27
  28        idle = kcpustat_cpu(cpu).cpustat[CPUTIME_IDLE];
  29        if (cpu_online(cpu) && !nr_iowait_cpu(cpu))
  30                idle += arch_idle_time(cpu);
  31        return idle;
  32}
  33
  34static cputime64_t get_iowait_time(int cpu)
  35{
  36        cputime64_t iowait;
  37
  38        iowait = kcpustat_cpu(cpu).cpustat[CPUTIME_IOWAIT];
  39        if (cpu_online(cpu) && nr_iowait_cpu(cpu))
  40                iowait += arch_idle_time(cpu);
  41        return iowait;
  42}
  43
  44#else
  45
  46static u64 get_idle_time(int cpu)
  47{
  48        u64 idle, idle_time = -1ULL;
  49
  50        if (cpu_online(cpu))
  51                idle_time = get_cpu_idle_time_us(cpu, NULL);
  52
  53        if (idle_time == -1ULL)
  54                /* !NO_HZ or cpu offline so we can rely on cpustat.idle */
  55                idle = kcpustat_cpu(cpu).cpustat[CPUTIME_IDLE];
  56        else
  57                idle = usecs_to_cputime64(idle_time);
  58
  59        return idle;
  60}
  61
  62static u64 get_iowait_time(int cpu)
  63{
  64        u64 iowait, iowait_time = -1ULL;
  65
  66        if (cpu_online(cpu))
  67                iowait_time = get_cpu_iowait_time_us(cpu, NULL);
  68
  69        if (iowait_time == -1ULL)
  70                /* !NO_HZ or cpu offline so we can rely on cpustat.iowait */
  71                iowait = kcpustat_cpu(cpu).cpustat[CPUTIME_IOWAIT];
  72        else
  73                iowait = usecs_to_cputime64(iowait_time);
  74
  75        return iowait;
  76}
  77
  78#endif
  79
  80static int show_stat(struct seq_file *p, void *v)
  81{
  82        int i, j;
  83        unsigned long jif;
  84        u64 user, nice, system, idle, iowait, irq, softirq, steal;
  85        u64 guest, guest_nice;
  86        u64 sum = 0;
  87        u64 sum_softirq = 0;
  88        unsigned int per_softirq_sums[NR_SOFTIRQS] = {0};
  89        struct timespec boottime;
  90
  91        user = nice = system = idle = iowait =
  92                irq = softirq = steal = 0;
  93        guest = guest_nice = 0;
  94        getboottime(&boottime);
  95        jif = boottime.tv_sec;
  96
  97        for_each_possible_cpu(i) {
  98                user += kcpustat_cpu(i).cpustat[CPUTIME_USER];
  99                nice += kcpustat_cpu(i).cpustat[CPUTIME_NICE];
 100                system += kcpustat_cpu(i).cpustat[CPUTIME_SYSTEM];
 101                idle += get_idle_time(i);
 102                iowait += get_iowait_time(i);
 103                irq += kcpustat_cpu(i).cpustat[CPUTIME_IRQ];
 104                softirq += kcpustat_cpu(i).cpustat[CPUTIME_SOFTIRQ];
 105                steal += kcpustat_cpu(i).cpustat[CPUTIME_STEAL];
 106                guest += kcpustat_cpu(i).cpustat[CPUTIME_GUEST];
 107                guest_nice += kcpustat_cpu(i).cpustat[CPUTIME_GUEST_NICE];
 108                sum += kstat_cpu_irqs_sum(i);
 109                sum += arch_irq_stat_cpu(i);
 110
 111                for (j = 0; j < NR_SOFTIRQS; j++) {
 112                        unsigned int softirq_stat = kstat_softirqs_cpu(j, i);
 113
 114                        per_softirq_sums[j] += softirq_stat;
 115                        sum_softirq += softirq_stat;
 116                }
 117        }
 118        sum += arch_irq_stat();
 119
 120        seq_puts(p, "cpu ");
 121        seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(user));
 122        seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(nice));
 123        seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(system));
 124        seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(idle));
 125        seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(iowait));
 126        seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(irq));
 127        seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(softirq));
 128        seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(steal));
 129        seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(guest));
 130        seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(guest_nice));
 131        seq_putc(p, '\n');
 132
 133        for_each_online_cpu(i) {
 134                /* Copy values here to work around gcc-2.95.3, gcc-2.96 */
 135                user = kcpustat_cpu(i).cpustat[CPUTIME_USER];
 136                nice = kcpustat_cpu(i).cpustat[CPUTIME_NICE];
 137                system = kcpustat_cpu(i).cpustat[CPUTIME_SYSTEM];
 138                idle = get_idle_time(i);
 139                iowait = get_iowait_time(i);
 140                irq = kcpustat_cpu(i).cpustat[CPUTIME_IRQ];
 141                softirq = kcpustat_cpu(i).cpustat[CPUTIME_SOFTIRQ];
 142                steal = kcpustat_cpu(i).cpustat[CPUTIME_STEAL];
 143                guest = kcpustat_cpu(i).cpustat[CPUTIME_GUEST];
 144                guest_nice = kcpustat_cpu(i).cpustat[CPUTIME_GUEST_NICE];
 145                seq_printf(p, "cpu%d", i);
 146                seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(user));
 147                seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(nice));
 148                seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(system));
 149                seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(idle));
 150                seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(iowait));
 151                seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(irq));
 152                seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(softirq));
 153                seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(steal));
 154                seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(guest));
 155                seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(guest_nice));
 156                seq_putc(p, '\n');
 157        }
 158        seq_printf(p, "intr %llu", (unsigned long long)sum);
 159
 160        /* sum again ? it could be updated? */
 161        for_each_irq_nr(j)
 162                seq_put_decimal_ull(p, ' ', kstat_irqs(j));
 163
 164        seq_printf(p,
 165                "\nctxt %llu\n"
 166                "btime %lu\n"
 167                "processes %lu\n"
 168                "procs_running %lu\n"
 169                "procs_blocked %lu\n",
 170                nr_context_switches(),
 171                (unsigned long)jif,
 172                total_forks,
 173                nr_running(),
 174                nr_iowait());
 175
 176        seq_printf(p, "softirq %llu", (unsigned long long)sum_softirq);
 177
 178        for (i = 0; i < NR_SOFTIRQS; i++)
 179                seq_put_decimal_ull(p, ' ', per_softirq_sums[i]);
 180        seq_putc(p, '\n');
 181
 182        return 0;
 183}
 184
 185static int stat_open(struct inode *inode, struct file *file)
 186{
 187        size_t size = 1024 + 128 * num_possible_cpus();
 188        char *buf;
 189        struct seq_file *m;
 190        int res;
 191
 192        /* minimum size to display an interrupt count : 2 bytes */
 193        size += 2 * nr_irqs;
 194
 195        /* don't ask for more than the kmalloc() max size */
 196        if (size > KMALLOC_MAX_SIZE)
 197                size = KMALLOC_MAX_SIZE;
 198        buf = kmalloc(size, GFP_KERNEL);
 199        if (!buf)
 200                return -ENOMEM;
 201
 202        res = single_open(file, show_stat, NULL);
 203        if (!res) {
 204                m = file->private_data;
 205                m->buf = buf;
 206                m->size = ksize(buf);
 207        } else
 208                kfree(buf);
 209        return res;
 210}
 211
 212static const struct file_operations proc_stat_operations = {
 213        .open           = stat_open,
 214        .read           = seq_read,
 215        .llseek         = seq_lseek,
 216        .release        = single_release,
 217};
 218
 219static int __init proc_stat_init(void)
 220{
 221        proc_create("stat", 0, NULL, &proc_stat_operations);
 222        return 0;
 223}
 224module_init(proc_stat_init);
 225