xref: /openbmc/linux/kernel/sched/stats.c (revision 391e43da)
1391e43daSPeter Zijlstra 
2391e43daSPeter Zijlstra #include <linux/slab.h>
3391e43daSPeter Zijlstra #include <linux/fs.h>
4391e43daSPeter Zijlstra #include <linux/seq_file.h>
5391e43daSPeter Zijlstra #include <linux/proc_fs.h>
6391e43daSPeter Zijlstra 
7391e43daSPeter Zijlstra #include "sched.h"
8391e43daSPeter Zijlstra 
9391e43daSPeter Zijlstra /*
10391e43daSPeter Zijlstra  * bump this up when changing the output format or the meaning of an existing
11391e43daSPeter Zijlstra  * format, so that tools can adapt (or abort)
12391e43daSPeter Zijlstra  */
13391e43daSPeter Zijlstra #define SCHEDSTAT_VERSION 15
14391e43daSPeter Zijlstra 
15391e43daSPeter Zijlstra static int show_schedstat(struct seq_file *seq, void *v)
16391e43daSPeter Zijlstra {
17391e43daSPeter Zijlstra 	int cpu;
18391e43daSPeter Zijlstra 	int mask_len = DIV_ROUND_UP(NR_CPUS, 32) * 9;
19391e43daSPeter Zijlstra 	char *mask_str = kmalloc(mask_len, GFP_KERNEL);
20391e43daSPeter Zijlstra 
21391e43daSPeter Zijlstra 	if (mask_str == NULL)
22391e43daSPeter Zijlstra 		return -ENOMEM;
23391e43daSPeter Zijlstra 
24391e43daSPeter Zijlstra 	seq_printf(seq, "version %d\n", SCHEDSTAT_VERSION);
25391e43daSPeter Zijlstra 	seq_printf(seq, "timestamp %lu\n", jiffies);
26391e43daSPeter Zijlstra 	for_each_online_cpu(cpu) {
27391e43daSPeter Zijlstra 		struct rq *rq = cpu_rq(cpu);
28391e43daSPeter Zijlstra #ifdef CONFIG_SMP
29391e43daSPeter Zijlstra 		struct sched_domain *sd;
30391e43daSPeter Zijlstra 		int dcount = 0;
31391e43daSPeter Zijlstra #endif
32391e43daSPeter Zijlstra 
33391e43daSPeter Zijlstra 		/* runqueue-specific stats */
34391e43daSPeter Zijlstra 		seq_printf(seq,
35391e43daSPeter Zijlstra 		    "cpu%d %u %u %u %u %u %u %llu %llu %lu",
36391e43daSPeter Zijlstra 		    cpu, rq->yld_count,
37391e43daSPeter Zijlstra 		    rq->sched_switch, rq->sched_count, rq->sched_goidle,
38391e43daSPeter Zijlstra 		    rq->ttwu_count, rq->ttwu_local,
39391e43daSPeter Zijlstra 		    rq->rq_cpu_time,
40391e43daSPeter Zijlstra 		    rq->rq_sched_info.run_delay, rq->rq_sched_info.pcount);
41391e43daSPeter Zijlstra 
42391e43daSPeter Zijlstra 		seq_printf(seq, "\n");
43391e43daSPeter Zijlstra 
44391e43daSPeter Zijlstra #ifdef CONFIG_SMP
45391e43daSPeter Zijlstra 		/* domain-specific stats */
46391e43daSPeter Zijlstra 		rcu_read_lock();
47391e43daSPeter Zijlstra 		for_each_domain(cpu, sd) {
48391e43daSPeter Zijlstra 			enum cpu_idle_type itype;
49391e43daSPeter Zijlstra 
50391e43daSPeter Zijlstra 			cpumask_scnprintf(mask_str, mask_len,
51391e43daSPeter Zijlstra 					  sched_domain_span(sd));
52391e43daSPeter Zijlstra 			seq_printf(seq, "domain%d %s", dcount++, mask_str);
53391e43daSPeter Zijlstra 			for (itype = CPU_IDLE; itype < CPU_MAX_IDLE_TYPES;
54391e43daSPeter Zijlstra 					itype++) {
55391e43daSPeter Zijlstra 				seq_printf(seq, " %u %u %u %u %u %u %u %u",
56391e43daSPeter Zijlstra 				    sd->lb_count[itype],
57391e43daSPeter Zijlstra 				    sd->lb_balanced[itype],
58391e43daSPeter Zijlstra 				    sd->lb_failed[itype],
59391e43daSPeter Zijlstra 				    sd->lb_imbalance[itype],
60391e43daSPeter Zijlstra 				    sd->lb_gained[itype],
61391e43daSPeter Zijlstra 				    sd->lb_hot_gained[itype],
62391e43daSPeter Zijlstra 				    sd->lb_nobusyq[itype],
63391e43daSPeter Zijlstra 				    sd->lb_nobusyg[itype]);
64391e43daSPeter Zijlstra 			}
65391e43daSPeter Zijlstra 			seq_printf(seq,
66391e43daSPeter Zijlstra 				   " %u %u %u %u %u %u %u %u %u %u %u %u\n",
67391e43daSPeter Zijlstra 			    sd->alb_count, sd->alb_failed, sd->alb_pushed,
68391e43daSPeter Zijlstra 			    sd->sbe_count, sd->sbe_balanced, sd->sbe_pushed,
69391e43daSPeter Zijlstra 			    sd->sbf_count, sd->sbf_balanced, sd->sbf_pushed,
70391e43daSPeter Zijlstra 			    sd->ttwu_wake_remote, sd->ttwu_move_affine,
71391e43daSPeter Zijlstra 			    sd->ttwu_move_balance);
72391e43daSPeter Zijlstra 		}
73391e43daSPeter Zijlstra 		rcu_read_unlock();
74391e43daSPeter Zijlstra #endif
75391e43daSPeter Zijlstra 	}
76391e43daSPeter Zijlstra 	kfree(mask_str);
77391e43daSPeter Zijlstra 	return 0;
78391e43daSPeter Zijlstra }
79391e43daSPeter Zijlstra 
80391e43daSPeter Zijlstra static int schedstat_open(struct inode *inode, struct file *file)
81391e43daSPeter Zijlstra {
82391e43daSPeter Zijlstra 	unsigned int size = PAGE_SIZE * (1 + num_online_cpus() / 32);
83391e43daSPeter Zijlstra 	char *buf = kmalloc(size, GFP_KERNEL);
84391e43daSPeter Zijlstra 	struct seq_file *m;
85391e43daSPeter Zijlstra 	int res;
86391e43daSPeter Zijlstra 
87391e43daSPeter Zijlstra 	if (!buf)
88391e43daSPeter Zijlstra 		return -ENOMEM;
89391e43daSPeter Zijlstra 	res = single_open(file, show_schedstat, NULL);
90391e43daSPeter Zijlstra 	if (!res) {
91391e43daSPeter Zijlstra 		m = file->private_data;
92391e43daSPeter Zijlstra 		m->buf = buf;
93391e43daSPeter Zijlstra 		m->size = size;
94391e43daSPeter Zijlstra 	} else
95391e43daSPeter Zijlstra 		kfree(buf);
96391e43daSPeter Zijlstra 	return res;
97391e43daSPeter Zijlstra }
98391e43daSPeter Zijlstra 
99391e43daSPeter Zijlstra static const struct file_operations proc_schedstat_operations = {
100391e43daSPeter Zijlstra 	.open    = schedstat_open,
101391e43daSPeter Zijlstra 	.read    = seq_read,
102391e43daSPeter Zijlstra 	.llseek  = seq_lseek,
103391e43daSPeter Zijlstra 	.release = single_release,
104391e43daSPeter Zijlstra };
105391e43daSPeter Zijlstra 
106391e43daSPeter Zijlstra static int __init proc_schedstat_init(void)
107391e43daSPeter Zijlstra {
108391e43daSPeter Zijlstra 	proc_create("schedstat", 0, NULL, &proc_schedstat_operations);
109391e43daSPeter Zijlstra 	return 0;
110391e43daSPeter Zijlstra }
111391e43daSPeter Zijlstra module_init(proc_schedstat_init);
112