From 2c6ee50333f25afb50e88bc20f9dbbb7a6d4578a Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Sat, 20 Apr 2013 17:11:50 +0200 Subject: [PATCH] --- yaml --- r: 372926 b: refs/heads/master c: 99e5ada9407cc19d7c4c05ce2165f20dc46fc093 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/include/linux/tick.h | 2 ++ trunk/kernel/sched/core.c | 2 ++ trunk/kernel/time/tick-sched.c | 20 ++++++++++++++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index de457d6659f3..b66d91c51ae8 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 5811d9963e26146898a24b535b301f7654257f8a +refs/heads/master: 99e5ada9407cc19d7c4c05ce2165f20dc46fc093 diff --git a/trunk/include/linux/tick.h b/trunk/include/linux/tick.h index e31e67623ea1..9180f4b85e6d 100644 --- a/trunk/include/linux/tick.h +++ b/trunk/include/linux/tick.h @@ -163,12 +163,14 @@ extern int tick_nohz_full_cpu(int cpu); extern void tick_nohz_full_check(void); extern void tick_nohz_full_kick(void); extern void tick_nohz_full_kick_all(void); +extern void tick_nohz_task_switch(struct task_struct *tsk); #else static inline void tick_nohz_init(void) { } static inline int tick_nohz_full_cpu(int cpu) { return 0; } static inline void tick_nohz_full_check(void) { } static inline void tick_nohz_full_kick(void) { } static inline void tick_nohz_full_kick_all(void) { } +static inline void tick_nohz_task_switch(struct task_struct *tsk) { } #endif diff --git a/trunk/kernel/sched/core.c b/trunk/kernel/sched/core.c index 9ad35005f1cb..dd09def88567 100644 --- a/trunk/kernel/sched/core.c +++ b/trunk/kernel/sched/core.c @@ -1896,6 +1896,8 @@ static void finish_task_switch(struct rq *rq, struct task_struct *prev) kprobe_flush_task(prev); put_task_struct(prev); } + + tick_nohz_task_switch(current); } #ifdef CONFIG_SMP diff --git a/trunk/kernel/time/tick-sched.c b/trunk/kernel/time/tick-sched.c index d0ed1905a85c..12a900dbb819 100644 --- a/trunk/kernel/time/tick-sched.c +++ b/trunk/kernel/time/tick-sched.c @@ -232,6 +232,26 @@ void tick_nohz_full_kick_all(void) preempt_enable(); } +/* + * Re-evaluate the need for the tick as we switch the current task. + * It might need the tick due to per task/process properties: + * perf events, posix cpu timers, ... + */ +void tick_nohz_task_switch(struct task_struct *tsk) +{ + unsigned long flags; + + if (!tick_nohz_full_cpu(smp_processor_id())) + return; + + local_irq_save(flags); + + if (tick_nohz_tick_stopped() && !can_stop_full_tick()) + tick_nohz_full_kick(); + + local_irq_restore(flags); +} + int tick_nohz_full_cpu(int cpu) { if (!have_nohz_full_mask)