aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2015-06-09 05:13:36 -0400
committerIngo Molnar <mingo@kernel.org>2015-08-03 06:21:22 -0400
commitfbd705a0c6184580d0e2fbcbd47a37b6e5822511 (patch)
treec6e2e4369726d453bf695784c2d41528be909a50
parent9d7fb04276481c59610983362d8e023d262b58ca (diff)
sched: Introduce the 'trace_sched_waking' tracepoint
Mathieu reported that since 317f394160e9 ("sched: Move the second half of ttwu() to the remote cpu") trace_sched_wakeup() can happen out of context of the waker. This is a problem when you want to analyse wakeup paths because it is now very hard to correlate the wakeup event to whoever issued the wakeup. OTOH trace_sched_wakeup() is issued at the point where we set p->state = TASK_RUNNING, which is right were we hand the task off to the scheduler, so this is an important point when looking at scheduling behaviour, up to here its been the wakeup path everything hereafter is due to scheduler policy. To bridge this gap, introduce a second tracepoint: trace_sched_waking. It is guaranteed to be called in the waker context. Reported-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Francis Giraldeau <francis.giraldeau@gmail.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/20150609091336.GQ3644@twins.programming.kicks-ass.net Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--include/trace/events/sched.h30
-rw-r--r--kernel/sched/core.c10
-rw-r--r--kernel/trace/trace_sched_switch.c2
-rw-r--r--kernel/trace/trace_sched_wakeup.c2
4 files changed, 30 insertions, 14 deletions
diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h
index d57a575fe31f..539d6bc3216a 100644
--- a/include/trace/events/sched.h
+++ b/include/trace/events/sched.h
@@ -55,9 +55,9 @@ TRACE_EVENT(sched_kthread_stop_ret,
55 */ 55 */
56DECLARE_EVENT_CLASS(sched_wakeup_template, 56DECLARE_EVENT_CLASS(sched_wakeup_template,
57 57
58 TP_PROTO(struct task_struct *p, int success), 58 TP_PROTO(struct task_struct *p),
59 59
60 TP_ARGS(__perf_task(p), success), 60 TP_ARGS(__perf_task(p)),
61 61
62 TP_STRUCT__entry( 62 TP_STRUCT__entry(
63 __array( char, comm, TASK_COMM_LEN ) 63 __array( char, comm, TASK_COMM_LEN )
@@ -71,25 +71,37 @@ DECLARE_EVENT_CLASS(sched_wakeup_template,
71 memcpy(__entry->comm, p->comm, TASK_COMM_LEN); 71 memcpy(__entry->comm, p->comm, TASK_COMM_LEN);
72 __entry->pid = p->pid; 72 __entry->pid = p->pid;
73 __entry->prio = p->prio; 73 __entry->prio = p->prio;
74 __entry->success = success; 74 __entry->success = 1; /* rudiment, kill when possible */
75 __entry->target_cpu = task_cpu(p); 75 __entry->target_cpu = task_cpu(p);
76 ), 76 ),
77 77
78 TP_printk("comm=%s pid=%d prio=%d success=%d target_cpu=%03d", 78 TP_printk("comm=%s pid=%d prio=%d target_cpu=%03d",
79 __entry->comm, __entry->pid, __entry->prio, 79 __entry->comm, __entry->pid, __entry->prio,
80 __entry->success, __entry->target_cpu) 80 __entry->target_cpu)
81); 81);
82 82
83/*
84 * Tracepoint called when waking a task; this tracepoint is guaranteed to be
85 * called from the waking context.
86 */
87DEFINE_EVENT(sched_wakeup_template, sched_waking,
88 TP_PROTO(struct task_struct *p),
89 TP_ARGS(p));
90
91/*
92 * Tracepoint called when the task is actually woken; p->state == TASK_RUNNNG.
93 * It it not always called from the waking context.
94 */
83DEFINE_EVENT(sched_wakeup_template, sched_wakeup, 95DEFINE_EVENT(sched_wakeup_template, sched_wakeup,
84 TP_PROTO(struct task_struct *p, int success), 96 TP_PROTO(struct task_struct *p),
85 TP_ARGS(p, success)); 97 TP_ARGS(p));
86 98
87/* 99/*
88 * Tracepoint for waking up a new task: 100 * Tracepoint for waking up a new task:
89 */ 101 */
90DEFINE_EVENT(sched_wakeup_template, sched_wakeup_new, 102DEFINE_EVENT(sched_wakeup_template, sched_wakeup_new,
91 TP_PROTO(struct task_struct *p, int success), 103 TP_PROTO(struct task_struct *p),
92 TP_ARGS(p, success)); 104 TP_ARGS(p));
93 105
94#ifdef CREATE_TRACE_POINTS 106#ifdef CREATE_TRACE_POINTS
95static inline long __trace_sched_switch_state(struct task_struct *p) 107static inline long __trace_sched_switch_state(struct task_struct *p)
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 48be7dc3d497..fa5826cc612f 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -1654,9 +1654,9 @@ static void
1654ttwu_do_wakeup(struct rq *rq, struct task_struct *p, int wake_flags) 1654ttwu_do_wakeup(struct rq *rq, struct task_struct *p, int wake_flags)
1655{ 1655{
1656 check_preempt_curr(rq, p, wake_flags); 1656 check_preempt_curr(rq, p, wake_flags);
1657 trace_sched_wakeup(p, true);
1658
1659 p->state = TASK_RUNNING; 1657 p->state = TASK_RUNNING;
1658 trace_sched_wakeup(p);
1659
1660#ifdef CONFIG_SMP 1660#ifdef CONFIG_SMP
1661 if (p->sched_class->task_woken) { 1661 if (p->sched_class->task_woken) {
1662 /* 1662 /*
@@ -1874,6 +1874,8 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
1874 if (!(p->state & state)) 1874 if (!(p->state & state))
1875 goto out; 1875 goto out;
1876 1876
1877 trace_sched_waking(p);
1878
1877 success = 1; /* we're going to change ->state */ 1879 success = 1; /* we're going to change ->state */
1878 cpu = task_cpu(p); 1880 cpu = task_cpu(p);
1879 1881
@@ -1949,6 +1951,8 @@ static void try_to_wake_up_local(struct task_struct *p)
1949 if (!(p->state & TASK_NORMAL)) 1951 if (!(p->state & TASK_NORMAL))
1950 goto out; 1952 goto out;
1951 1953
1954 trace_sched_waking(p);
1955
1952 if (!task_on_rq_queued(p)) 1956 if (!task_on_rq_queued(p))
1953 ttwu_activate(rq, p, ENQUEUE_WAKEUP); 1957 ttwu_activate(rq, p, ENQUEUE_WAKEUP);
1954 1958
@@ -2307,7 +2311,7 @@ void wake_up_new_task(struct task_struct *p)
2307 rq = __task_rq_lock(p); 2311 rq = __task_rq_lock(p);
2308 activate_task(rq, p, 0); 2312 activate_task(rq, p, 0);
2309 p->on_rq = TASK_ON_RQ_QUEUED; 2313 p->on_rq = TASK_ON_RQ_QUEUED;
2310 trace_sched_wakeup_new(p, true); 2314 trace_sched_wakeup_new(p);
2311 check_preempt_curr(rq, p, WF_FORK); 2315 check_preempt_curr(rq, p, WF_FORK);
2312#ifdef CONFIG_SMP 2316#ifdef CONFIG_SMP
2313 if (p->sched_class->task_woken) 2317 if (p->sched_class->task_woken)
diff --git a/kernel/trace/trace_sched_switch.c b/kernel/trace/trace_sched_switch.c
index 419ca37e72c9..f270088e9929 100644
--- a/kernel/trace/trace_sched_switch.c
+++ b/kernel/trace/trace_sched_switch.c
@@ -26,7 +26,7 @@ probe_sched_switch(void *ignore, struct task_struct *prev, struct task_struct *n
26} 26}
27 27
28static void 28static void
29probe_sched_wakeup(void *ignore, struct task_struct *wakee, int success) 29probe_sched_wakeup(void *ignore, struct task_struct *wakee)
30{ 30{
31 if (unlikely(!sched_ref)) 31 if (unlikely(!sched_ref))
32 return; 32 return;
diff --git a/kernel/trace/trace_sched_wakeup.c b/kernel/trace/trace_sched_wakeup.c
index 9b33dd117f3f..12cbe77b4136 100644
--- a/kernel/trace/trace_sched_wakeup.c
+++ b/kernel/trace/trace_sched_wakeup.c
@@ -514,7 +514,7 @@ static void wakeup_reset(struct trace_array *tr)
514} 514}
515 515
516static void 516static void
517probe_wakeup(void *ignore, struct task_struct *p, int success) 517probe_wakeup(void *ignore, struct task_struct *p)
518{ 518{
519 struct trace_array_cpu *data; 519 struct trace_array_cpu *data;
520 int cpu = smp_processor_id(); 520 int cpu = smp_processor_id();