[RFC 3/4] Disable scheduler tick when we are running SCHED_FIFO tasks

From: Jan Blunck
Date: Wed Sep 08 2010 - 08:30:31 EST


This patch is disabling the scheduler tick to go off when there is a task
with SCHED_FIFO policy running. Since these tasks are not timesliced anyway
we only care about timers, softirqs and such stuff just like when we disable
the tick during idle periods.

Signed-off-by: Jan Blunck <jblunck@xxxxxxx>
---
kernel/sched_rt.c | 23 +++++++++++++++++++++++
kernel/softirq.c | 5 +++++
kernel/time/tick-sched.c | 7 ++++---
3 files changed, 32 insertions(+), 3 deletions(-)

diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c
index 8afb953..3879ca1 100644
--- a/kernel/sched_rt.c
+++ b/kernel/sched_rt.c
@@ -1095,6 +1095,13 @@ static struct task_struct *pick_next_task_rt(struct rq *rq)
rq->post_schedule = has_pushable_tasks(rq);
#endif

+ if (p) {
+ /* Disable sched_tick in post_schedule later */
+ if (unlikely(rt_task(p)) && !(p->flags & PF_KTHREAD) &&
+ (p->policy == SCHED_FIFO))
+ rq->post_schedule = 1;
+ }
+
return p;
}

@@ -1475,11 +1482,27 @@ static void pre_schedule_rt(struct rq *rq, struct task_struct *prev)
/* Try to pull RT tasks here if we lower this rq's prio */
if (unlikely(rt_task(prev)) && rq->rt.highest_prio.curr > prev->prio)
pull_rt_task(rq);
+
+ /* Enable sched_tick again before we schedule */
+ if (unlikely(rt_task(prev)) && !(prev->flags & PF_KTHREAD) &&
+ (prev->policy == SCHED_FIFO)) {
+ tick_nohz_restart_sched_tick();
+
+ /* Disable tick in post_schedule if we don't switch */
+ rq->post_schedule = 1;
+ }
}

static void post_schedule_rt(struct rq *rq)
{
push_rt_tasks(rq);
+
+ /* Disable tick if we are a FIFO task */
+ if (unlikely(rt_task(rq->curr)) &&
+ unlikely(!local_softirq_pending()) &&
+ !(rq->curr->flags & PF_KTHREAD) &&
+ (rq->curr->policy == SCHED_FIFO))
+ tick_nohz_stop_sched_tick(1);
}

/*
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 07b4f1b..ff05f6a 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -307,6 +307,11 @@ void irq_exit(void)
/* Make sure that timer wheel updates are propagated */
if (idle_cpu(smp_processor_id()) && !in_interrupt() && !need_resched())
tick_nohz_stop_sched_tick(0);
+
+ /* Disable tick if the current task is FIFO */
+ if (unlikely(rt_task(current) && !(current->flags & PF_KTHREAD) &&
+ current->policy == SCHED_FIFO))
+ tick_nohz_stop_sched_tick(1);
#endif
preempt_enable_no_resched();
}
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 81b7398..567110d 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -520,9 +520,10 @@ void tick_nohz_restart_sched_tick(void)
#ifndef CONFIG_VIRT_CPU_ACCOUNTING
unsigned long ticks;
#endif
+ unsigned long flags;
ktime_t now;

- local_irq_disable();
+ local_irq_save(flags);
if (ts->idle_active || (ts->inidle && ts->tick_stopped))
now = ktime_get();

@@ -531,7 +532,7 @@ void tick_nohz_restart_sched_tick(void)

if (!ts->inidle || !ts->tick_stopped) {
ts->inidle = 0;
- local_irq_enable();
+ local_irq_restore(flags);
return;
}

@@ -567,7 +568,7 @@ void tick_nohz_restart_sched_tick(void)

tick_nohz_restart(ts, now);

- local_irq_enable();
+ local_irq_restore(flags);
}

static int tick_nohz_reprogram(struct tick_sched *ts, ktime_t now)
--
1.6.4.2

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