Blame view

kernel/sched/stats.c 3.4 KB
029632fbb   Peter Zijlstra   sched: Make separ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  
  #include <linux/slab.h>
  #include <linux/fs.h>
  #include <linux/seq_file.h>
  #include <linux/proc_fs.h>
  
  #include "sched.h"
  
  /*
   * bump this up when changing the output format or the meaning of an existing
   * format, so that tools can adapt (or abort)
   */
  #define SCHEDSTAT_VERSION 15
  
  static int show_schedstat(struct seq_file *seq, void *v)
  {
  	int cpu;
  	int mask_len = DIV_ROUND_UP(NR_CPUS, 32) * 9;
  	char *mask_str = kmalloc(mask_len, GFP_KERNEL);
  
  	if (mask_str == NULL)
  		return -ENOMEM;
cb152ff26   Nathan Zimmer   sched: Fix /proc/...
23
24
25
26
27
28
29
  	if (v == (void *)1) {
  		seq_printf(seq, "version %d
  ", SCHEDSTAT_VERSION);
  		seq_printf(seq, "timestamp %lu
  ", jiffies);
  	} else {
  		struct rq *rq;
029632fbb   Peter Zijlstra   sched: Make separ...
30
31
32
33
  #ifdef CONFIG_SMP
  		struct sched_domain *sd;
  		int dcount = 0;
  #endif
cb152ff26   Nathan Zimmer   sched: Fix /proc/...
34
35
  		cpu = (unsigned long)(v - 2);
  		rq = cpu_rq(cpu);
029632fbb   Peter Zijlstra   sched: Make separ...
36
37
38
  
  		/* runqueue-specific stats */
  		seq_printf(seq,
30fd049af   Rakib Mullick   sched: Remove sch...
39
  		    "cpu%d %u 0 %u %u %u %u %llu %llu %lu",
029632fbb   Peter Zijlstra   sched: Make separ...
40
  		    cpu, rq->yld_count,
30fd049af   Rakib Mullick   sched: Remove sch...
41
  		    rq->sched_count, rq->sched_goidle,
029632fbb   Peter Zijlstra   sched: Make separ...
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
  		    rq->ttwu_count, rq->ttwu_local,
  		    rq->rq_cpu_time,
  		    rq->rq_sched_info.run_delay, rq->rq_sched_info.pcount);
  
  		seq_printf(seq, "
  ");
  
  #ifdef CONFIG_SMP
  		/* domain-specific stats */
  		rcu_read_lock();
  		for_each_domain(cpu, sd) {
  			enum cpu_idle_type itype;
  
  			cpumask_scnprintf(mask_str, mask_len,
  					  sched_domain_span(sd));
  			seq_printf(seq, "domain%d %s", dcount++, mask_str);
  			for (itype = CPU_IDLE; itype < CPU_MAX_IDLE_TYPES;
  					itype++) {
  				seq_printf(seq, " %u %u %u %u %u %u %u %u",
  				    sd->lb_count[itype],
  				    sd->lb_balanced[itype],
  				    sd->lb_failed[itype],
  				    sd->lb_imbalance[itype],
  				    sd->lb_gained[itype],
  				    sd->lb_hot_gained[itype],
  				    sd->lb_nobusyq[itype],
  				    sd->lb_nobusyg[itype]);
  			}
  			seq_printf(seq,
  				   " %u %u %u %u %u %u %u %u %u %u %u %u
  ",
  			    sd->alb_count, sd->alb_failed, sd->alb_pushed,
  			    sd->sbe_count, sd->sbe_balanced, sd->sbe_pushed,
  			    sd->sbf_count, sd->sbf_balanced, sd->sbf_pushed,
  			    sd->ttwu_wake_remote, sd->ttwu_move_affine,
  			    sd->ttwu_move_balance);
  		}
  		rcu_read_unlock();
  #endif
  	}
  	kfree(mask_str);
  	return 0;
  }
cb152ff26   Nathan Zimmer   sched: Fix /proc/...
85
86
87
88
89
90
91
92
  /*
   * This itererator needs some explanation.
   * It returns 1 for the header position.
   * This means 2 is cpu 0.
   * In a hotplugged system some cpus, including cpu 0, may be missing so we have
   * to use cpumask_* to iterate over the cpus.
   */
  static void *schedstat_start(struct seq_file *file, loff_t *offset)
029632fbb   Peter Zijlstra   sched: Make separ...
93
  {
cb152ff26   Nathan Zimmer   sched: Fix /proc/...
94
  	unsigned long n = *offset;
029632fbb   Peter Zijlstra   sched: Make separ...
95

cb152ff26   Nathan Zimmer   sched: Fix /proc/...
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
  	if (n == 0)
  		return (void *) 1;
  
  	n--;
  
  	if (n > 0)
  		n = cpumask_next(n - 1, cpu_online_mask);
  	else
  		n = cpumask_first(cpu_online_mask);
  
  	*offset = n + 1;
  
  	if (n < nr_cpu_ids)
  		return (void *)(unsigned long)(n + 2);
  	return NULL;
  }
  
  static void *schedstat_next(struct seq_file *file, void *data, loff_t *offset)
  {
  	(*offset)++;
  	return schedstat_start(file, offset);
  }
  
  static void schedstat_stop(struct seq_file *file, void *data)
  {
  }
  
  static const struct seq_operations schedstat_sops = {
  	.start = schedstat_start,
  	.next  = schedstat_next,
  	.stop  = schedstat_stop,
  	.show  = show_schedstat,
  };
  
  static int schedstat_open(struct inode *inode, struct file *file)
  {
  	return seq_open(file, &schedstat_sops);
029632fbb   Peter Zijlstra   sched: Make separ...
133
134
135
136
137
138
  }
  
  static const struct file_operations proc_schedstat_operations = {
  	.open    = schedstat_open,
  	.read    = seq_read,
  	.llseek  = seq_lseek,
8e0bcc722   Al Viro   fix a leak in /pr...
139
  	.release = seq_release,
029632fbb   Peter Zijlstra   sched: Make separ...
140
141
142
143
144
145
146
  };
  
  static int __init proc_schedstat_init(void)
  {
  	proc_create("schedstat", 0, NULL, &proc_schedstat_operations);
  	return 0;
  }
c96d6660d   Paul Gortmaker   kernel: audit/fix...
147
  subsys_initcall(proc_schedstat_init);