sched_debug.c 6.1 KB
Newer Older
I
Ingo Molnar 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
/*
 * kernel/time/sched_debug.c
 *
 * Print the CFS rbtree
 *
 * Copyright(C) 2007, Red Hat, Inc., Ingo Molnar
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/proc_fs.h>
#include <linux/sched.h>
#include <linux/seq_file.h>
#include <linux/kallsyms.h>
#include <linux/utsname.h>

/*
 * This allows printing both to /proc/sched_debug and
 * to the console
 */
#define SEQ_printf(m, x...)			\
 do {						\
	if (m)					\
		seq_printf(m, x);		\
	else					\
		printk(x);			\
 } while (0)

static void
32
print_task(struct seq_file *m, struct rq *rq, struct task_struct *p)
I
Ingo Molnar 已提交
33 34 35 36 37 38
{
	if (rq->curr == p)
		SEQ_printf(m, "R");
	else
		SEQ_printf(m, " ");

39
	SEQ_printf(m, "%15s %5d %15Ld %13Ld %5d ",
I
Ingo Molnar 已提交
40 41 42
		p->comm, p->pid,
		(long long)p->se.fair_key,
		(long long)(p->nvcsw + p->nivcsw),
43
		p->prio);
I
Ingo Molnar 已提交
44
#ifdef CONFIG_SCHEDSTATS
45
	SEQ_printf(m, "%15Ld %15Ld %15Ld\n",
I
Ingo Molnar 已提交
46
		(long long)p->se.vruntime,
I
Ingo Molnar 已提交
47
		(long long)p->se.sum_exec_runtime,
48
		(long long)p->se.sum_sleep_runtime);
I
Ingo Molnar 已提交
49
#else
50 51
	SEQ_printf(m, "%15Ld %15Ld %15Ld %15Ld %15Ld\n",
		0LL, 0LL, 0LL, 0LL, 0LL);
I
Ingo Molnar 已提交
52
#endif
I
Ingo Molnar 已提交
53 54
}

55
static void print_rq(struct seq_file *m, struct rq *rq, int rq_cpu)
I
Ingo Molnar 已提交
56 57 58 59 60
{
	struct task_struct *g, *p;

	SEQ_printf(m,
	"\nrunnable tasks:\n"
61 62
	"            task   PID        tree-key  switches  prio"
	"    exec-runtime        sum-exec       sum-sleep\n"
I
Ingo Molnar 已提交
63
	"------------------------------------------------------------------"
I
Ingo Molnar 已提交
64
	"--------------------------------"
I
Ingo Molnar 已提交
65 66 67 68 69 70 71 72 73
	"------------------------------------------------"
	"--------------------------------\n");

	read_lock_irq(&tasklist_lock);

	do_each_thread(g, p) {
		if (!p->se.on_rq || task_cpu(p) != rq_cpu)
			continue;

74
		print_task(m, rq, p);
I
Ingo Molnar 已提交
75 76 77 78 79
	} while_each_thread(g, p);

	read_unlock_irq(&tasklist_lock);
}

80
void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)
I
Ingo Molnar 已提交
81
{
I
Ingo Molnar 已提交
82 83
	s64 MIN_vruntime = -1, min_vruntime, max_vruntime = -1,
		spread, rq0_min_vruntime, spread0;
I
Ingo Molnar 已提交
84 85 86 87
	struct rq *rq = &per_cpu(runqueues, cpu);
	struct sched_entity *last;
	unsigned long flags;

88
	SEQ_printf(m, "\ncfs_rq\n");
I
Ingo Molnar 已提交
89 90 91 92 93

#define P(x) \
	SEQ_printf(m, "  .%-30s: %Ld\n", #x, (long long)(cfs_rq->x))

	P(exec_clock);
I
Ingo Molnar 已提交
94 95 96 97 98 99 100

	spin_lock_irqsave(&rq->lock, flags);
	if (cfs_rq->rb_leftmost)
		MIN_vruntime = (__pick_next_entity(cfs_rq))->vruntime;
	last = __pick_last_entity(cfs_rq);
	if (last)
		max_vruntime = last->vruntime;
I
Ingo Molnar 已提交
101 102
	min_vruntime = rq->cfs.min_vruntime;
	rq0_min_vruntime = per_cpu(runqueues, 0).cfs.min_vruntime;
I
Ingo Molnar 已提交
103 104 105
	spin_unlock_irqrestore(&rq->lock, flags);
	SEQ_printf(m, "  .%-30s: %Ld\n", "MIN_vruntime",
			(long long)MIN_vruntime);
I
Ingo Molnar 已提交
106 107
	SEQ_printf(m, "  .%-30s: %Ld\n", "min_vruntime",
			(long long)min_vruntime);
I
Ingo Molnar 已提交
108 109 110 111 112
	SEQ_printf(m, "  .%-30s: %Ld\n", "max_vruntime",
			(long long)max_vruntime);
	spread = max_vruntime - MIN_vruntime;
	SEQ_printf(m, "  .%-30s: %Ld\n", "spread",
			(long long)spread);
I
Ingo Molnar 已提交
113 114 115
	spread0 = min_vruntime - rq0_min_vruntime;
	SEQ_printf(m, "  .%-30s: %Ld\n", "spread0",
			(long long)spread0);
I
Ingo Molnar 已提交
116 117 118
#undef P
}

119
static void print_cpu(struct seq_file *m, int cpu)
I
Ingo Molnar 已提交
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
{
	struct rq *rq = &per_cpu(runqueues, cpu);

#ifdef CONFIG_X86
	{
		unsigned int freq = cpu_khz ? : 1;

		SEQ_printf(m, "\ncpu#%d, %u.%03u MHz\n",
			   cpu, freq / 1000, (freq % 1000));
	}
#else
	SEQ_printf(m, "\ncpu#%d\n", cpu);
#endif

#define P(x) \
	SEQ_printf(m, "  .%-30s: %Ld\n", #x, (long long)(rq->x))

	P(nr_running);
	SEQ_printf(m, "  .%-30s: %lu\n", "load",
139
		   rq->load.weight);
I
Ingo Molnar 已提交
140 141 142 143 144 145 146
	P(nr_switches);
	P(nr_load_updates);
	P(nr_uninterruptible);
	SEQ_printf(m, "  .%-30s: %lu\n", "jiffies", jiffies);
	P(next_balance);
	P(curr->pid);
	P(clock);
147
	P(idle_clock);
I
Ingo Molnar 已提交
148 149 150
	P(prev_clock_raw);
	P(clock_warps);
	P(clock_overflows);
151
	P(clock_deep_idle_events);
I
Ingo Molnar 已提交
152 153 154 155 156 157 158 159
	P(clock_max_delta);
	P(cpu_load[0]);
	P(cpu_load[1]);
	P(cpu_load[2]);
	P(cpu_load[3]);
	P(cpu_load[4]);
#undef P

160
	print_cfs_stats(m, cpu);
I
Ingo Molnar 已提交
161

162
	print_rq(m, rq, cpu);
I
Ingo Molnar 已提交
163 164 165 166 167 168 169
}

static int sched_debug_show(struct seq_file *m, void *v)
{
	u64 now = ktime_to_ns(ktime_get());
	int cpu;

I
Ingo Molnar 已提交
170
	SEQ_printf(m, "Sched Debug Version: v0.05-v20, %s %.*s\n",
I
Ingo Molnar 已提交
171 172 173 174 175 176 177
		init_utsname()->release,
		(int)strcspn(init_utsname()->version, " "),
		init_utsname()->version);

	SEQ_printf(m, "now at %Lu nsecs\n", (unsigned long long)now);

	for_each_online_cpu(cpu)
178
		print_cpu(m, cpu);
I
Ingo Molnar 已提交
179 180 181 182 183 184

	SEQ_printf(m, "\n");

	return 0;
}

185
static void sysrq_sched_debug_show(void)
I
Ingo Molnar 已提交
186 187 188 189 190 191 192 193 194 195 196 197 198
{
	sched_debug_show(NULL, NULL);
}

static int sched_debug_open(struct inode *inode, struct file *filp)
{
	return single_open(filp, sched_debug_show, NULL);
}

static struct file_operations sched_debug_fops = {
	.open		= sched_debug_open,
	.read		= seq_read,
	.llseek		= seq_lseek,
199
	.release	= single_release,
I
Ingo Molnar 已提交
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
};

static int __init init_sched_debug_procfs(void)
{
	struct proc_dir_entry *pe;

	pe = create_proc_entry("sched_debug", 0644, NULL);
	if (!pe)
		return -ENOMEM;

	pe->proc_fops = &sched_debug_fops;

	return 0;
}

__initcall(init_sched_debug_procfs);

void proc_sched_show_task(struct task_struct *p, struct seq_file *m)
{
	unsigned long flags;
	int num_threads = 1;

	rcu_read_lock();
	if (lock_task_sighand(p, &flags)) {
		num_threads = atomic_read(&p->signal->count);
		unlock_task_sighand(p, &flags);
	}
	rcu_read_unlock();

	SEQ_printf(m, "%s (%d, #threads: %d)\n", p->comm, p->pid, num_threads);
	SEQ_printf(m, "----------------------------------------------\n");
#define P(F) \
	SEQ_printf(m, "%-25s:%20Ld\n", #F, (long long)p->F)

	P(se.exec_start);
I
Ingo Molnar 已提交
235
	P(se.vruntime);
I
Ingo Molnar 已提交
236 237 238 239 240
	P(se.sum_exec_runtime);

#ifdef CONFIG_SCHEDSTATS
	P(se.wait_start);
	P(se.sleep_start);
I
Ingo Molnar 已提交
241 242 243 244
	P(se.block_start);
	P(se.sleep_max);
	P(se.block_max);
	P(se.exec_max);
I
Ingo Molnar 已提交
245
	P(se.slice_max);
I
Ingo Molnar 已提交
246
	P(se.wait_max);
I
Ingo Molnar 已提交
247
#endif
I
Ingo Molnar 已提交
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
	SEQ_printf(m, "%-25s:%20Ld\n",
		   "nr_switches", (long long)(p->nvcsw + p->nivcsw));
	P(se.load.weight);
	P(policy);
	P(prio);
#undef P

	{
		u64 t0, t1;

		t0 = sched_clock();
		t1 = sched_clock();
		SEQ_printf(m, "%-25s:%20Ld\n",
			   "clock-delta", (long long)(t1-t0));
	}
}

void proc_sched_set_task(struct task_struct *p)
{
I
Ingo Molnar 已提交
267
#ifdef CONFIG_SCHEDSTATS
I
Ingo Molnar 已提交
268 269 270
	p->se.sleep_max			= 0;
	p->se.block_max			= 0;
	p->se.exec_max			= 0;
I
Ingo Molnar 已提交
271
	p->se.slice_max			= 0;
I
Ingo Molnar 已提交
272
	p->se.wait_max			= 0;
I
Ingo Molnar 已提交
273
#endif
I
Ingo Molnar 已提交
274
	p->se.sum_exec_runtime		= 0;
275
	p->se.prev_sum_exec_runtime	= 0;
I
Ingo Molnar 已提交
276
}