aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMathieu Desnoyers <mathieu.desnoyers@polymtl.ca>2008-07-18 12:16:17 -0400
committerIngo Molnar <mingo@elte.hu>2008-10-14 04:30:52 -0400
commit0a16b6075843325dc402edf80c1662838b929aff (patch)
tree124e49d8c0196f3c6eb7aa09a7c4c3c3157fff7a
parent4a0897526bbc5c6ac0df80b16b8c60339e717ae2 (diff)
tracing, sched: LTTng instrumentation - scheduler
Instrument the scheduler activity (sched_switch, migration, wakeups, wait for a task, signal delivery) and process/thread creation/destruction (fork, exit, kthread stop). Actually, kthread creation is not instrumented in this patch because it is architecture dependent. It allows to connect tracers such as ftrace which detects scheduling latencies, good/bad scheduler decisions. Tools like LTTng can export this scheduler information along with instrumentation of the rest of the kernel activity to perform post-mortem analysis on the scheduler activity. About the performance impact of tracepoints (which is comparable to markers), even without immediate values optimizations, tests done by Hideo Aoki on ia64 show no regression. His test case was using hackbench on a kernel where scheduler instrumentation (about 5 events in code scheduler code) was added. See the "Tracepoints" patch header for performance result detail. Changelog : - Change instrumentation location and parameter to match ftrace instrumentation, previously done with kernel markers. [ mingo@elte.hu: conflict resolutions ] Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> Acked-by: 'Peter Zijlstra' <peterz@infradead.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--include/trace/sched.h45
-rw-r--r--kernel/exit.c10
-rw-r--r--kernel/fork.c3
-rw-r--r--kernel/kthread.c5
-rw-r--r--kernel/sched.c17
-rw-r--r--kernel/signal.c3
6 files changed, 71 insertions, 12 deletions
diff --git a/include/trace/sched.h b/include/trace/sched.h
new file mode 100644
index 000000000000..506ae1323656
--- /dev/null
+++ b/include/trace/sched.h
@@ -0,0 +1,45 @@
1#ifndef _TRACE_SCHED_H
2#define _TRACE_SCHED_H
3
4#include <linux/sched.h>
5#include <linux/tracepoint.h>
6
7DEFINE_TRACE(sched_kthread_stop,
8 TPPROTO(struct task_struct *t),
9 TPARGS(t));
10DEFINE_TRACE(sched_kthread_stop_ret,
11 TPPROTO(int ret),
12 TPARGS(ret));
13DEFINE_TRACE(sched_wait_task,
14 TPPROTO(struct rq *rq, struct task_struct *p),
15 TPARGS(rq, p));
16DEFINE_TRACE(sched_wakeup,
17 TPPROTO(struct rq *rq, struct task_struct *p),
18 TPARGS(rq, p));
19DEFINE_TRACE(sched_wakeup_new,
20 TPPROTO(struct rq *rq, struct task_struct *p),
21 TPARGS(rq, p));
22DEFINE_TRACE(sched_switch,
23 TPPROTO(struct rq *rq, struct task_struct *prev,
24 struct task_struct *next),
25 TPARGS(rq, prev, next));
26DEFINE_TRACE(sched_migrate_task,
27 TPPROTO(struct rq *rq, struct task_struct *p, int dest_cpu),
28 TPARGS(rq, p, dest_cpu));
29DEFINE_TRACE(sched_process_free,
30 TPPROTO(struct task_struct *p),
31 TPARGS(p));
32DEFINE_TRACE(sched_process_exit,
33 TPPROTO(struct task_struct *p),
34 TPARGS(p));
35DEFINE_TRACE(sched_process_wait,
36 TPPROTO(struct pid *pid),
37 TPARGS(pid));
38DEFINE_TRACE(sched_process_fork,
39 TPPROTO(struct task_struct *parent, struct task_struct *child),
40 TPARGS(parent, child));
41DEFINE_TRACE(sched_signal_send,
42 TPPROTO(int sig, struct task_struct *p),
43 TPARGS(sig, p));
44
45#endif
diff --git a/kernel/exit.c b/kernel/exit.c
index 85a83c831856..7b71f87f1207 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -47,6 +47,7 @@
47#include <linux/blkdev.h> 47#include <linux/blkdev.h>
48#include <linux/task_io_accounting_ops.h> 48#include <linux/task_io_accounting_ops.h>
49#include <linux/tracehook.h> 49#include <linux/tracehook.h>
50#include <trace/sched.h>
50 51
51#include <asm/uaccess.h> 52#include <asm/uaccess.h>
52#include <asm/unistd.h> 53#include <asm/unistd.h>
@@ -149,7 +150,10 @@ static void __exit_signal(struct task_struct *tsk)
149 150
150static void delayed_put_task_struct(struct rcu_head *rhp) 151static void delayed_put_task_struct(struct rcu_head *rhp)
151{ 152{
152 put_task_struct(container_of(rhp, struct task_struct, rcu)); 153 struct task_struct *tsk = container_of(rhp, struct task_struct, rcu);
154
155 trace_sched_process_free(tsk);
156 put_task_struct(tsk);
153} 157}
154 158
155 159
@@ -1074,6 +1078,8 @@ NORET_TYPE void do_exit(long code)
1074 1078
1075 if (group_dead) 1079 if (group_dead)
1076 acct_process(); 1080 acct_process();
1081 trace_sched_process_exit(tsk);
1082
1077 exit_sem(tsk); 1083 exit_sem(tsk);
1078 exit_files(tsk); 1084 exit_files(tsk);
1079 exit_fs(tsk); 1085 exit_fs(tsk);
@@ -1675,6 +1681,8 @@ static long do_wait(enum pid_type type, struct pid *pid, int options,
1675 struct task_struct *tsk; 1681 struct task_struct *tsk;
1676 int retval; 1682 int retval;
1677 1683
1684 trace_sched_process_wait(pid);
1685
1678 add_wait_queue(&current->signal->wait_chldexit,&wait); 1686 add_wait_queue(&current->signal->wait_chldexit,&wait);
1679repeat: 1687repeat:
1680 /* 1688 /*
diff --git a/kernel/fork.c b/kernel/fork.c
index 30de644a40c4..cfaff92f61ff 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -58,6 +58,7 @@
58#include <linux/tty.h> 58#include <linux/tty.h>
59#include <linux/proc_fs.h> 59#include <linux/proc_fs.h>
60#include <linux/blkdev.h> 60#include <linux/blkdev.h>
61#include <trace/sched.h>
61 62
62#include <asm/pgtable.h> 63#include <asm/pgtable.h>
63#include <asm/pgalloc.h> 64#include <asm/pgalloc.h>
@@ -1364,6 +1365,8 @@ long do_fork(unsigned long clone_flags,
1364 if (!IS_ERR(p)) { 1365 if (!IS_ERR(p)) {
1365 struct completion vfork; 1366 struct completion vfork;
1366 1367
1368 trace_sched_process_fork(current, p);
1369
1367 nr = task_pid_vnr(p); 1370 nr = task_pid_vnr(p);
1368 1371
1369 if (clone_flags & CLONE_PARENT_SETTID) 1372 if (clone_flags & CLONE_PARENT_SETTID)
diff --git a/kernel/kthread.c b/kernel/kthread.c
index 96cff2f8710b..50598e29439a 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -13,6 +13,7 @@
13#include <linux/file.h> 13#include <linux/file.h>
14#include <linux/module.h> 14#include <linux/module.h>
15#include <linux/mutex.h> 15#include <linux/mutex.h>
16#include <trace/sched.h>
16 17
17#define KTHREAD_NICE_LEVEL (-5) 18#define KTHREAD_NICE_LEVEL (-5)
18 19
@@ -206,6 +207,8 @@ int kthread_stop(struct task_struct *k)
206 /* It could exit after stop_info.k set, but before wake_up_process. */ 207 /* It could exit after stop_info.k set, but before wake_up_process. */
207 get_task_struct(k); 208 get_task_struct(k);
208 209
210 trace_sched_kthread_stop(k);
211
209 /* Must init completion *before* thread sees kthread_stop_info.k */ 212 /* Must init completion *before* thread sees kthread_stop_info.k */
210 init_completion(&kthread_stop_info.done); 213 init_completion(&kthread_stop_info.done);
211 smp_wmb(); 214 smp_wmb();
@@ -221,6 +224,8 @@ int kthread_stop(struct task_struct *k)
221 ret = kthread_stop_info.err; 224 ret = kthread_stop_info.err;
222 mutex_unlock(&kthread_stop_lock); 225 mutex_unlock(&kthread_stop_lock);
223 226
227 trace_sched_kthread_stop_ret(ret);
228
224 return ret; 229 return ret;
225} 230}
226EXPORT_SYMBOL(kthread_stop); 231EXPORT_SYMBOL(kthread_stop);
diff --git a/kernel/sched.c b/kernel/sched.c
index 6f230596bd0c..3d1ad130c24e 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -71,6 +71,7 @@
71#include <linux/debugfs.h> 71#include <linux/debugfs.h>
72#include <linux/ctype.h> 72#include <linux/ctype.h>
73#include <linux/ftrace.h> 73#include <linux/ftrace.h>
74#include <trace/sched.h>
74 75
75#include <asm/tlb.h> 76#include <asm/tlb.h>
76#include <asm/irq_regs.h> 77#include <asm/irq_regs.h>
@@ -1936,6 +1937,7 @@ unsigned long wait_task_inactive(struct task_struct *p, long match_state)
1936 * just go back and repeat. 1937 * just go back and repeat.
1937 */ 1938 */
1938 rq = task_rq_lock(p, &flags); 1939 rq = task_rq_lock(p, &flags);
1940 trace_sched_wait_task(rq, p);
1939 running = task_running(rq, p); 1941 running = task_running(rq, p);
1940 on_rq = p->se.on_rq; 1942 on_rq = p->se.on_rq;
1941 ncsw = 0; 1943 ncsw = 0;
@@ -2297,9 +2299,7 @@ out_activate:
2297 success = 1; 2299 success = 1;
2298 2300
2299out_running: 2301out_running:
2300 trace_mark(kernel_sched_wakeup, 2302 trace_sched_wakeup(rq, p);
2301 "pid %d state %ld ## rq %p task %p rq->curr %p",
2302 p->pid, p->state, rq, p, rq->curr);
2303 check_preempt_curr(rq, p, sync); 2303 check_preempt_curr(rq, p, sync);
2304 2304
2305 p->state = TASK_RUNNING; 2305 p->state = TASK_RUNNING;
@@ -2432,9 +2432,7 @@ void wake_up_new_task(struct task_struct *p, unsigned long clone_flags)
2432 p->sched_class->task_new(rq, p); 2432 p->sched_class->task_new(rq, p);
2433 inc_nr_running(rq); 2433 inc_nr_running(rq);
2434 } 2434 }
2435 trace_mark(kernel_sched_wakeup_new, 2435 trace_sched_wakeup_new(rq, p);
2436 "pid %d state %ld ## rq %p task %p rq->curr %p",
2437 p->pid, p->state, rq, p, rq->curr);
2438 check_preempt_curr(rq, p, 0); 2436 check_preempt_curr(rq, p, 0);
2439#ifdef CONFIG_SMP 2437#ifdef CONFIG_SMP
2440 if (p->sched_class->task_wake_up) 2438 if (p->sched_class->task_wake_up)
@@ -2607,11 +2605,7 @@ context_switch(struct rq *rq, struct task_struct *prev,
2607 struct mm_struct *mm, *oldmm; 2605 struct mm_struct *mm, *oldmm;
2608 2606
2609 prepare_task_switch(rq, prev, next); 2607 prepare_task_switch(rq, prev, next);
2610 trace_mark(kernel_sched_schedule, 2608 trace_sched_switch(rq, prev, next);
2611 "prev_pid %d next_pid %d prev_state %ld "
2612 "## rq %p prev %p next %p",
2613 prev->pid, next->pid, prev->state,
2614 rq, prev, next);
2615 mm = next->mm; 2609 mm = next->mm;
2616 oldmm = prev->active_mm; 2610 oldmm = prev->active_mm;
2617 /* 2611 /*
@@ -2851,6 +2845,7 @@ static void sched_migrate_task(struct task_struct *p, int dest_cpu)
2851 || unlikely(!cpu_active(dest_cpu))) 2845 || unlikely(!cpu_active(dest_cpu)))
2852 goto out; 2846 goto out;
2853 2847
2848 trace_sched_migrate_task(rq, p, dest_cpu);
2854 /* force the process onto the specified CPU */ 2849 /* force the process onto the specified CPU */
2855 if (migrate_task(p, dest_cpu, &req)) { 2850 if (migrate_task(p, dest_cpu, &req)) {
2856 /* Need to wait for migration thread (might exit: take ref). */ 2851 /* Need to wait for migration thread (might exit: take ref). */
diff --git a/kernel/signal.c b/kernel/signal.c
index e661b01d340f..bf40ecc87b26 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -27,6 +27,7 @@
27#include <linux/freezer.h> 27#include <linux/freezer.h>
28#include <linux/pid_namespace.h> 28#include <linux/pid_namespace.h>
29#include <linux/nsproxy.h> 29#include <linux/nsproxy.h>
30#include <trace/sched.h>
30 31
31#include <asm/param.h> 32#include <asm/param.h>
32#include <asm/uaccess.h> 33#include <asm/uaccess.h>
@@ -803,6 +804,8 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
803 struct sigpending *pending; 804 struct sigpending *pending;
804 struct sigqueue *q; 805 struct sigqueue *q;
805 806
807 trace_sched_signal_send(sig, t);
808
806 assert_spin_locked(&t->sighand->siglock); 809 assert_spin_locked(&t->sighand->siglock);
807 if (!prepare_signal(sig, t)) 810 if (!prepare_signal(sig, t))
808 return 0; 811 return 0;