aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-26 22:42:08 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-26 22:42:08 -0500
commitdcad0fceae528e8007610308bad7e5a3370e5c39 (patch)
tree1af69697e0988e8dbdf42d915508bd58a1887b4f /kernel
parentf8ef15d6b9d8e38729cd740a43919adf88468119 (diff)
parent7f6575f1fb963d5231afbceecd3feadb6ab58cd3 (diff)
Merge branch 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull scheduler fixes from Ingo Molnar. * 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: cputime: Use local_clock() for full dynticks cputime accounting cputime: Constify timeval_to_cputime(timeval) argument sched: Move RR_TIMESLICE from sysctl.h to rt.h sched: Fix /proc/sched_debug failure on very very large systems sched: Fix /proc/sched_stat failure on very very large systems sched/core: Remove the obsolete and unused nr_uninterruptible() function
Diffstat (limited to 'kernel')
-rw-r--r--kernel/sched/core.c22
-rw-r--r--kernel/sched/cputime.c2
-rw-r--r--kernel/sched/debug.c90
-rw-r--r--kernel/sched/stats.c79
4 files changed, 141 insertions, 52 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index fc9103e9ff03..2b5243176aba 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -1979,11 +1979,10 @@ context_switch(struct rq *rq, struct task_struct *prev,
1979} 1979}
1980 1980
1981/* 1981/*
1982 * nr_running, nr_uninterruptible and nr_context_switches: 1982 * nr_running and nr_context_switches:
1983 * 1983 *
1984 * externally visible scheduler statistics: current number of runnable 1984 * externally visible scheduler statistics: current number of runnable
1985 * threads, current number of uninterruptible-sleeping threads, total 1985 * threads, total number of context switches performed since bootup.
1986 * number of context switches performed since bootup.
1987 */ 1986 */
1988unsigned long nr_running(void) 1987unsigned long nr_running(void)
1989{ 1988{
@@ -1995,23 +1994,6 @@ unsigned long nr_running(void)
1995 return sum; 1994 return sum;
1996} 1995}
1997 1996
1998unsigned long nr_uninterruptible(void)
1999{
2000 unsigned long i, sum = 0;
2001
2002 for_each_possible_cpu(i)
2003 sum += cpu_rq(i)->nr_uninterruptible;
2004
2005 /*
2006 * Since we read the counters lockless, it might be slightly
2007 * inaccurate. Do not allow it to go below zero though:
2008 */
2009 if (unlikely((long)sum < 0))
2010 sum = 0;
2011
2012 return sum;
2013}
2014
2015unsigned long long nr_context_switches(void) 1997unsigned long long nr_context_switches(void)
2016{ 1998{
2017 int i; 1999 int i;
diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c
index 9857329ed280..ed12cbb135f4 100644
--- a/kernel/sched/cputime.c
+++ b/kernel/sched/cputime.c
@@ -604,7 +604,7 @@ static unsigned long long vtime_delta(struct task_struct *tsk)
604{ 604{
605 unsigned long long clock; 605 unsigned long long clock;
606 606
607 clock = sched_clock(); 607 clock = local_clock();
608 if (clock < tsk->vtime_snap) 608 if (clock < tsk->vtime_snap)
609 return 0; 609 return 0;
610 610
diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c
index 557e7b53b323..75024a673520 100644
--- a/kernel/sched/debug.c
+++ b/kernel/sched/debug.c
@@ -262,11 +262,11 @@ static void print_cpu(struct seq_file *m, int cpu)
262 { 262 {
263 unsigned int freq = cpu_khz ? : 1; 263 unsigned int freq = cpu_khz ? : 1;
264 264
265 SEQ_printf(m, "\ncpu#%d, %u.%03u MHz\n", 265 SEQ_printf(m, "cpu#%d, %u.%03u MHz\n",
266 cpu, freq / 1000, (freq % 1000)); 266 cpu, freq / 1000, (freq % 1000));
267 } 267 }
268#else 268#else
269 SEQ_printf(m, "\ncpu#%d\n", cpu); 269 SEQ_printf(m, "cpu#%d\n", cpu);
270#endif 270#endif
271 271
272#define P(x) \ 272#define P(x) \
@@ -323,6 +323,7 @@ do { \
323 print_rq(m, rq, cpu); 323 print_rq(m, rq, cpu);
324 rcu_read_unlock(); 324 rcu_read_unlock();
325 spin_unlock_irqrestore(&sched_debug_lock, flags); 325 spin_unlock_irqrestore(&sched_debug_lock, flags);
326 SEQ_printf(m, "\n");
326} 327}
327 328
328static const char *sched_tunable_scaling_names[] = { 329static const char *sched_tunable_scaling_names[] = {
@@ -331,11 +332,10 @@ static const char *sched_tunable_scaling_names[] = {
331 "linear" 332 "linear"
332}; 333};
333 334
334static int sched_debug_show(struct seq_file *m, void *v) 335static void sched_debug_header(struct seq_file *m)
335{ 336{
336 u64 ktime, sched_clk, cpu_clk; 337 u64 ktime, sched_clk, cpu_clk;
337 unsigned long flags; 338 unsigned long flags;
338 int cpu;
339 339
340 local_irq_save(flags); 340 local_irq_save(flags);
341 ktime = ktime_to_ns(ktime_get()); 341 ktime = ktime_to_ns(ktime_get());
@@ -377,33 +377,101 @@ static int sched_debug_show(struct seq_file *m, void *v)
377#undef PN 377#undef PN
378#undef P 378#undef P
379 379
380 SEQ_printf(m, " .%-40s: %d (%s)\n", "sysctl_sched_tunable_scaling", 380 SEQ_printf(m, " .%-40s: %d (%s)\n",
381 "sysctl_sched_tunable_scaling",
381 sysctl_sched_tunable_scaling, 382 sysctl_sched_tunable_scaling,
382 sched_tunable_scaling_names[sysctl_sched_tunable_scaling]); 383 sched_tunable_scaling_names[sysctl_sched_tunable_scaling]);
384 SEQ_printf(m, "\n");
385}
383 386
384 for_each_online_cpu(cpu) 387static int sched_debug_show(struct seq_file *m, void *v)
385 print_cpu(m, cpu); 388{
389 int cpu = (unsigned long)(v - 2);
386 390
387 SEQ_printf(m, "\n"); 391 if (cpu != -1)
392 print_cpu(m, cpu);
393 else
394 sched_debug_header(m);
388 395
389 return 0; 396 return 0;
390} 397}
391 398
392void sysrq_sched_debug_show(void) 399void sysrq_sched_debug_show(void)
393{ 400{
394 sched_debug_show(NULL, NULL); 401 int cpu;
402
403 sched_debug_header(NULL);
404 for_each_online_cpu(cpu)
405 print_cpu(NULL, cpu);
406
407}
408
409/*
410 * This itererator needs some explanation.
411 * It returns 1 for the header position.
412 * This means 2 is cpu 0.
413 * In a hotplugged system some cpus, including cpu 0, may be missing so we have
414 * to use cpumask_* to iterate over the cpus.
415 */
416static void *sched_debug_start(struct seq_file *file, loff_t *offset)
417{
418 unsigned long n = *offset;
419
420 if (n == 0)
421 return (void *) 1;
422
423 n--;
424
425 if (n > 0)
426 n = cpumask_next(n - 1, cpu_online_mask);
427 else
428 n = cpumask_first(cpu_online_mask);
429
430 *offset = n + 1;
431
432 if (n < nr_cpu_ids)
433 return (void *)(unsigned long)(n + 2);
434 return NULL;
435}
436
437static void *sched_debug_next(struct seq_file *file, void *data, loff_t *offset)
438{
439 (*offset)++;
440 return sched_debug_start(file, offset);
441}
442
443static void sched_debug_stop(struct seq_file *file, void *data)
444{
445}
446
447static const struct seq_operations sched_debug_sops = {
448 .start = sched_debug_start,
449 .next = sched_debug_next,
450 .stop = sched_debug_stop,
451 .show = sched_debug_show,
452};
453
454static int sched_debug_release(struct inode *inode, struct file *file)
455{
456 seq_release(inode, file);
457
458 return 0;
395} 459}
396 460
397static int sched_debug_open(struct inode *inode, struct file *filp) 461static int sched_debug_open(struct inode *inode, struct file *filp)
398{ 462{
399 return single_open(filp, sched_debug_show, NULL); 463 int ret = 0;
464
465 ret = seq_open(filp, &sched_debug_sops);
466
467 return ret;
400} 468}
401 469
402static const struct file_operations sched_debug_fops = { 470static const struct file_operations sched_debug_fops = {
403 .open = sched_debug_open, 471 .open = sched_debug_open,
404 .read = seq_read, 472 .read = seq_read,
405 .llseek = seq_lseek, 473 .llseek = seq_lseek,
406 .release = single_release, 474 .release = sched_debug_release,
407}; 475};
408 476
409static int __init init_sched_debug_procfs(void) 477static int __init init_sched_debug_procfs(void)
diff --git a/kernel/sched/stats.c b/kernel/sched/stats.c
index 903ffa9e8872..e036eda1a9c9 100644
--- a/kernel/sched/stats.c
+++ b/kernel/sched/stats.c
@@ -21,14 +21,17 @@ static int show_schedstat(struct seq_file *seq, void *v)
21 if (mask_str == NULL) 21 if (mask_str == NULL)
22 return -ENOMEM; 22 return -ENOMEM;
23 23
24 seq_printf(seq, "version %d\n", SCHEDSTAT_VERSION); 24 if (v == (void *)1) {
25 seq_printf(seq, "timestamp %lu\n", jiffies); 25 seq_printf(seq, "version %d\n", SCHEDSTAT_VERSION);
26 for_each_online_cpu(cpu) { 26 seq_printf(seq, "timestamp %lu\n", jiffies);
27 struct rq *rq = cpu_rq(cpu); 27 } else {
28 struct rq *rq;
28#ifdef CONFIG_SMP 29#ifdef CONFIG_SMP
29 struct sched_domain *sd; 30 struct sched_domain *sd;
30 int dcount = 0; 31 int dcount = 0;
31#endif 32#endif
33 cpu = (unsigned long)(v - 2);
34 rq = cpu_rq(cpu);
32 35
33 /* runqueue-specific stats */ 36 /* runqueue-specific stats */
34 seq_printf(seq, 37 seq_printf(seq,
@@ -77,30 +80,66 @@ static int show_schedstat(struct seq_file *seq, void *v)
77 return 0; 80 return 0;
78} 81}
79 82
80static int schedstat_open(struct inode *inode, struct file *file) 83/*
84 * This itererator needs some explanation.
85 * It returns 1 for the header position.
86 * This means 2 is cpu 0.
87 * In a hotplugged system some cpus, including cpu 0, may be missing so we have
88 * to use cpumask_* to iterate over the cpus.
89 */
90static void *schedstat_start(struct seq_file *file, loff_t *offset)
81{ 91{
82 unsigned int size = PAGE_SIZE * (1 + num_online_cpus() / 32); 92 unsigned long n = *offset;
83 char *buf = kmalloc(size, GFP_KERNEL);
84 struct seq_file *m;
85 int res;
86 93
87 if (!buf) 94 if (n == 0)
88 return -ENOMEM; 95 return (void *) 1;
89 res = single_open(file, show_schedstat, NULL); 96
90 if (!res) { 97 n--;
91 m = file->private_data; 98
92 m->buf = buf; 99 if (n > 0)
93 m->size = size; 100 n = cpumask_next(n - 1, cpu_online_mask);
94 } else 101 else
95 kfree(buf); 102 n = cpumask_first(cpu_online_mask);
96 return res; 103
104 *offset = n + 1;
105
106 if (n < nr_cpu_ids)
107 return (void *)(unsigned long)(n + 2);
108 return NULL;
109}
110
111static void *schedstat_next(struct seq_file *file, void *data, loff_t *offset)
112{
113 (*offset)++;
114 return schedstat_start(file, offset);
115}
116
117static void schedstat_stop(struct seq_file *file, void *data)
118{
119}
120
121static const struct seq_operations schedstat_sops = {
122 .start = schedstat_start,
123 .next = schedstat_next,
124 .stop = schedstat_stop,
125 .show = show_schedstat,
126};
127
128static int schedstat_open(struct inode *inode, struct file *file)
129{
130 return seq_open(file, &schedstat_sops);
97} 131}
98 132
133static int schedstat_release(struct inode *inode, struct file *file)
134{
135 return 0;
136};
137
99static const struct file_operations proc_schedstat_operations = { 138static const struct file_operations proc_schedstat_operations = {
100 .open = schedstat_open, 139 .open = schedstat_open,
101 .read = seq_read, 140 .read = seq_read,
102 .llseek = seq_lseek, 141 .llseek = seq_lseek,
103 .release = single_release, 142 .release = schedstat_release,
104}; 143};
105 144
106static int __init proc_schedstat_init(void) 145static int __init proc_schedstat_init(void)