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 <linux/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        u64 user, nice, system, idle, iowait, irq, softirq, steal;
  84        u64 guest, guest_nice;
  85        u64 sum = 0;
  86        u64 sum_softirq = 0;
  87        unsigned int per_softirq_sums[NR_SOFTIRQS] = {0};
  88        struct timespec64 boottime;
  89
  90        user = nice = system = idle = iowait =
  91                irq = softirq = steal = 0;
  92        guest = guest_nice = 0;
  93        getboottime64(&boottime);
  94
  95        for_each_possible_cpu(i) {
  96                user += kcpustat_cpu(i).cpustat[CPUTIME_USER];
  97                nice += kcpustat_cpu(i).cpustat[CPUTIME_NICE];
  98                system += kcpustat_cpu(i).cpustat[CPUTIME_SYSTEM];
  99                idle += get_idle_time(i);
 100                iowait += get_iowait_time(i);
 101                irq += kcpustat_cpu(i).cpustat[CPUTIME_IRQ];
 102                softirq += kcpustat_cpu(i).cpustat[CPUTIME_SOFTIRQ];
 103                steal += kcpustat_cpu(i).cpustat[CPUTIME_STEAL];
 104                guest += kcpustat_cpu(i).cpustat[CPUTIME_GUEST];
 105                guest_nice += kcpustat_cpu(i).cpustat[CPUTIME_GUEST_NICE];
 106                sum += kstat_cpu_irqs_sum(i);
 107                sum += arch_irq_stat_cpu(i);
 108
 109                for (j = 0; j < NR_SOFTIRQS; j++) {
 110                        unsigned int softirq_stat = kstat_softirqs_cpu(j, i);
 111
 112                        per_softirq_sums[j] += softirq_stat;
 113                        sum_softirq += softirq_stat;
 114                }
 115        }
 116        sum += arch_irq_stat();
 117
 118        seq_put_decimal_ull(p, "cpu  ", cputime64_to_clock_t(user));
 119        seq_put_decimal_ull(p, " ", cputime64_to_clock_t(nice));
 120        seq_put_decimal_ull(p, " ", cputime64_to_clock_t(system));
 121        seq_put_decimal_ull(p, " ", cputime64_to_clock_t(idle));
 122        seq_put_decimal_ull(p, " ", cputime64_to_clock_t(iowait));
 123        seq_put_decimal_ull(p, " ", cputime64_to_clock_t(irq));
 124        seq_put_decimal_ull(p, " ", cputime64_to_clock_t(softirq));
 125        seq_put_decimal_ull(p, " ", cputime64_to_clock_t(steal));
 126        seq_put_decimal_ull(p, " ", cputime64_to_clock_t(guest));
 127        seq_put_decimal_ull(p, " ", cputime64_to_clock_t(guest_nice));
 128        seq_putc(p, '\n');
 129
 130        for_each_online_cpu(i) {
 131                /* Copy values here to work around gcc-2.95.3, gcc-2.96 */
 132                user = kcpustat_cpu(i).cpustat[CPUTIME_USER];
 133                nice = kcpustat_cpu(i).cpustat[CPUTIME_NICE];
 134                system = kcpustat_cpu(i).cpustat[CPUTIME_SYSTEM];
 135                idle = get_idle_time(i);
 136                iowait = get_iowait_time(i);
 137                irq = kcpustat_cpu(i).cpustat[CPUTIME_IRQ];
 138                softirq = kcpustat_cpu(i).cpustat[CPUTIME_SOFTIRQ];
 139                steal = kcpustat_cpu(i).cpustat[CPUTIME_STEAL];
 140                guest = kcpustat_cpu(i).cpustat[CPUTIME_GUEST];
 141                guest_nice = kcpustat_cpu(i).cpustat[CPUTIME_GUEST_NICE];
 142                seq_printf(p, "cpu%d", i);
 143                seq_put_decimal_ull(p, " ", cputime64_to_clock_t(user));
 144                seq_put_decimal_ull(p, " ", cputime64_to_clock_t(nice));
 145                seq_put_decimal_ull(p, " ", cputime64_to_clock_t(system));
 146                seq_put_decimal_ull(p, " ", cputime64_to_clock_t(idle));
 147                seq_put_decimal_ull(p, " ", cputime64_to_clock_t(iowait));
 148                seq_put_decimal_ull(p, " ", cputime64_to_clock_t(irq));
 149                seq_put_decimal_ull(p, " ", cputime64_to_clock_t(softirq));
 150                seq_put_decimal_ull(p, " ", cputime64_to_clock_t(steal));
 151                seq_put_decimal_ull(p, " ", cputime64_to_clock_t(guest));
 152                seq_put_decimal_ull(p, " ", cputime64_to_clock_t(guest_nice));
 153                seq_putc(p, '\n');
 154        }
 155        seq_put_decimal_ull(p, "intr ", (unsigned long long)sum);
 156
 157        /* sum again ? it could be updated? */
 158        for_each_irq_nr(j)
 159                seq_put_decimal_ull(p, " ", kstat_irqs_usr(j));
 160
 161        seq_printf(p,
 162                "\nctxt %llu\n"
 163                "btime %llu\n"
 164                "processes %lu\n"
 165                "procs_running %lu\n"
 166                "procs_blocked %lu\n",
 167                nr_context_switches(),
 168                (unsigned long long)boottime.tv_sec,
 169                total_forks,
 170                nr_running(),
 171                nr_iowait());
 172
 173        seq_put_decimal_ull(p, "softirq ", (unsigned long long)sum_softirq);
 174
 175        for (i = 0; i < NR_SOFTIRQS; i++)
 176                seq_put_decimal_ull(p, " ", per_softirq_sums[i]);
 177        seq_putc(p, '\n');
 178
 179        return 0;
 180}
 181
 182static int stat_open(struct inode *inode, struct file *file)
 183{
 184        size_t size = 1024 + 128 * num_online_cpus();
 185
 186        /* minimum size to display an interrupt count : 2 bytes */
 187        size += 2 * nr_irqs;
 188        return single_open_size(file, show_stat, NULL, size);
 189}
 190
 191static const struct file_operations proc_stat_operations = {
 192        .open           = stat_open,
 193        .read           = seq_read,
 194        .llseek         = seq_lseek,
 195        .release        = single_release,
 196};
 197
 198static int __init proc_stat_init(void)
 199{
 200        proc_create("stat", 0, NULL, &proc_stat_operations);
 201        return 0;
 202}
 203fs_initcall(proc_stat_init);
 204