From: Tejun Heo on
Move perf_event_task_sched_in() after finish_lock_switch() right
before fire_sched_notifiers_in(). This costs an extra pair of irq
enable/disable when switching in a perf task context but allows
unifying event functions in a more flexible position (irq enabled, rq
lock released).

Signed-off-by: Tejun Heo <tj(a)kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra(a)chello.nl>
Cc: Paul Mackerras <paulus(a)samba.org>
Cc: Ingo Molnar <mingo(a)elte.hu>
Cc: Arnaldo Carvalho de Melo <acme(a)redhat.com>
---
kernel/perf_event.c | 9 +++++++--
kernel/sched.c | 8 +-------
2 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index 73e2c1c..295699f 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -1369,14 +1369,17 @@ static void task_ctx_sched_in(struct task_struct *task,
*/
void perf_event_task_sched_in(struct task_struct *task)
{
- struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
struct perf_event_context *ctx = task->perf_event_ctxp;
+ struct perf_cpu_context *cpuctx;

if (likely(!ctx))
return;

+ local_irq_disable();
+
+ cpuctx = &__get_cpu_var(perf_cpu_context);
if (cpuctx->task_ctx == ctx)
- return;
+ goto out_enable;

/*
* We want to keep the following priority order:
@@ -1390,6 +1393,8 @@ void perf_event_task_sched_in(struct task_struct *task)
ctx_sched_in(ctx, cpuctx, EVENT_FLEXIBLE);

cpuctx->task_ctx = ctx;
+out_enable:
+ local_irq_enable();
}

#define MAX_INTERRUPTS (~0ULL)
diff --git a/kernel/sched.c b/kernel/sched.c
index 4c5e4c9..df6e0af 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -2794,15 +2794,9 @@ static void finish_task_switch(struct rq *rq, struct task_struct *prev)
*/
prev_state = prev->state;
finish_arch_switch(prev);
-#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW
- local_irq_disable();
-#endif /* __ARCH_WANT_INTERRUPTS_ON_CTXSW */
- perf_event_task_sched_in(current);
-#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW
- local_irq_enable();
-#endif /* __ARCH_WANT_INTERRUPTS_ON_CTXSW */
finish_lock_switch(rq, prev);

+ perf_event_task_sched_in(current);
fire_sched_notifiers_in(current);
if (mm)
mmdrop(mm);
--
1.6.4.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/