Branch data Line data Source code
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 : :
24 : : static 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 : :
34 : : static 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 : :
46 : 0 : static u64 get_idle_time(int cpu)
47 : : {
48 : : u64 idle, idle_time = -1ULL;
49 : :
50 [ + + ]: 49 : if (cpu_online(cpu))
51 : 28 : idle_time = get_cpu_idle_time_us(cpu, NULL);
52 : :
53 [ + + ]: 98 : if (idle_time == -1ULL)
54 : : /* !NO_HZ or cpu offline so we can rely on cpustat.idle */
55 : 21 : idle = kcpustat_cpu(cpu).cpustat[CPUTIME_IDLE];
56 : : else
57 : 28 : idle = usecs_to_cputime64(idle_time);
58 : :
59 : 49 : return idle;
60 : : }
61 : :
62 : 0 : static u64 get_iowait_time(int cpu)
63 : : {
64 : : u64 iowait, iowait_time = -1ULL;
65 : :
66 [ + + ]: 49 : if (cpu_online(cpu))
67 : 28 : iowait_time = get_cpu_iowait_time_us(cpu, NULL);
68 : :
69 [ + + ]: 98 : if (iowait_time == -1ULL)
70 : : /* !NO_HZ or cpu offline so we can rely on cpustat.iowait */
71 : 21 : iowait = kcpustat_cpu(cpu).cpustat[CPUTIME_IOWAIT];
72 : : else
73 : 28 : iowait = usecs_to_cputime64(iowait_time);
74 : :
75 : 49 : return iowait;
76 : : }
77 : :
78 : : #endif
79 : :
80 : 0 : static 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 : 7 : 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 : 7 : getboottime(&boottime);
95 : 7 : jif = boottime.tv_sec;
96 : :
97 [ + + ]: 49 : for_each_possible_cpu(i) {
98 : 35 : user += kcpustat_cpu(i).cpustat[CPUTIME_USER];
99 : 35 : nice += kcpustat_cpu(i).cpustat[CPUTIME_NICE];
100 : 35 : system += kcpustat_cpu(i).cpustat[CPUTIME_SYSTEM];
101 : 35 : idle += get_idle_time(i);
102 : 35 : iowait += get_iowait_time(i);
103 : 35 : irq += kcpustat_cpu(i).cpustat[CPUTIME_IRQ];
104 : 35 : softirq += kcpustat_cpu(i).cpustat[CPUTIME_SOFTIRQ];
105 : 35 : steal += kcpustat_cpu(i).cpustat[CPUTIME_STEAL];
106 : 35 : guest += kcpustat_cpu(i).cpustat[CPUTIME_GUEST];
107 : 35 : guest_nice += kcpustat_cpu(i).cpustat[CPUTIME_GUEST_NICE];
108 : 35 : sum += kstat_cpu_irqs_sum(i);
109 : 35 : sum += arch_irq_stat_cpu(i);
110 : :
111 [ + + ]: 392 : for (j = 0; j < NR_SOFTIRQS; j++) {
112 : 350 : unsigned int softirq_stat = kstat_softirqs_cpu(j, i);
113 : :
114 : 350 : per_softirq_sums[j] += softirq_stat;
115 : 350 : sum_softirq += softirq_stat;
116 : : }
117 : : }
118 : : sum += arch_irq_stat();
119 : :
120 : 7 : seq_puts(p, "cpu ");
121 : 7 : seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(user));
122 : 7 : seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(nice));
123 : 7 : seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(system));
124 : 7 : seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(idle));
125 : 7 : seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(iowait));
126 : 7 : seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(irq));
127 : 7 : seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(softirq));
128 : 7 : seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(steal));
129 : 7 : seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(guest));
130 : 7 : seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(guest_nice));
131 : 7 : seq_putc(p, '\n');
132 : :
133 [ + + ]: 28 : for_each_online_cpu(i) {
134 : : /* Copy values here to work around gcc-2.95.3, gcc-2.96 */
135 : 14 : user = kcpustat_cpu(i).cpustat[CPUTIME_USER];
136 : 14 : nice = kcpustat_cpu(i).cpustat[CPUTIME_NICE];
137 : 14 : system = kcpustat_cpu(i).cpustat[CPUTIME_SYSTEM];
138 : 14 : idle = get_idle_time(i);
139 : 14 : iowait = get_iowait_time(i);
140 : 14 : irq = kcpustat_cpu(i).cpustat[CPUTIME_IRQ];
141 : 14 : softirq = kcpustat_cpu(i).cpustat[CPUTIME_SOFTIRQ];
142 : 14 : steal = kcpustat_cpu(i).cpustat[CPUTIME_STEAL];
143 : 14 : guest = kcpustat_cpu(i).cpustat[CPUTIME_GUEST];
144 : 14 : guest_nice = kcpustat_cpu(i).cpustat[CPUTIME_GUEST_NICE];
145 : 14 : seq_printf(p, "cpu%d", i);
146 : 14 : seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(user));
147 : 14 : seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(nice));
148 : 14 : seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(system));
149 : 14 : seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(idle));
150 : 14 : seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(iowait));
151 : 14 : seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(irq));
152 : 14 : seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(softirq));
153 : 14 : seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(steal));
154 : 14 : seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(guest));
155 : 14 : seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(guest_nice));
156 : 14 : seq_putc(p, '\n');
157 : : }
158 : 7 : seq_printf(p, "intr %llu", (unsigned long long)sum);
159 : :
160 : : /* sum again ? it could be updated? */
161 [ + + ]: 1351 : for_each_irq_nr(j)
162 : 1344 : seq_put_decimal_ull(p, ' ', kstat_irqs(j));
163 : :
164 : 7 : 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 : 7 : seq_printf(p, "softirq %llu", (unsigned long long)sum_softirq);
177 : :
178 [ + + ]: 77 : for (i = 0; i < NR_SOFTIRQS; i++)
179 : 70 : seq_put_decimal_ull(p, ' ', per_softirq_sums[i]);
180 : 7 : seq_putc(p, '\n');
181 : :
182 : 7 : return 0;
183 : : }
184 : :
185 : 0 : static int stat_open(struct inode *inode, struct file *file)
186 : : {
187 : 21 : 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 : 14 : size += 2 * nr_irqs;
194 : :
195 : : /* don't ask for more than the kmalloc() max size */
196 [ - + ]: 14 : if (size > KMALLOC_MAX_SIZE)
197 : : size = KMALLOC_MAX_SIZE;
198 : : buf = kmalloc(size, GFP_KERNEL);
199 [ + - ]: 7 : if (!buf)
200 : : return -ENOMEM;
201 : :
202 : 7 : res = single_open(file, show_stat, NULL);
203 [ + - ]: 7 : if (!res) {
204 : 7 : m = file->private_data;
205 : 7 : m->buf = buf;
206 : 7 : m->size = ksize(buf);
207 : : } else
208 : 0 : kfree(buf);
209 : 7 : return res;
210 : : }
211 : :
212 : : static 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 : :
219 : 0 : static int __init proc_stat_init(void)
220 : : {
221 : : proc_create("stat", 0, NULL, &proc_stat_operations);
222 : 0 : return 0;
223 : : }
224 : : module_init(proc_stat_init);
|