|
@@ -1052,6 +1052,49 @@ static void resched_cpu(int cpu)
|
|
resched_task(cpu_curr(cpu));
|
|
resched_task(cpu_curr(cpu));
|
|
spin_unlock_irqrestore(&rq->lock, flags);
|
|
spin_unlock_irqrestore(&rq->lock, flags);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+#ifdef CONFIG_NO_HZ
|
|
|
|
+/*
|
|
|
|
+ * When add_timer_on() enqueues a timer into the timer wheel of an
|
|
|
|
+ * idle CPU then this timer might expire before the next timer event
|
|
|
|
+ * which is scheduled to wake up that CPU. In case of a completely
|
|
|
|
+ * idle system the next event might even be infinite time into the
|
|
|
|
+ * future. wake_up_idle_cpu() ensures that the CPU is woken up and
|
|
|
|
+ * leaves the inner idle loop so the newly added timer is taken into
|
|
|
|
+ * account when the CPU goes back to idle and evaluates the timer
|
|
|
|
+ * wheel for the next timer event.
|
|
|
|
+ */
|
|
|
|
+void wake_up_idle_cpu(int cpu)
|
|
|
|
+{
|
|
|
|
+ struct rq *rq = cpu_rq(cpu);
|
|
|
|
+
|
|
|
|
+ if (cpu == smp_processor_id())
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * This is safe, as this function is called with the timer
|
|
|
|
+ * wheel base lock of (cpu) held. When the CPU is on the way
|
|
|
|
+ * to idle and has not yet set rq->curr to idle then it will
|
|
|
|
+ * be serialized on the timer wheel base lock and take the new
|
|
|
|
+ * timer into account automatically.
|
|
|
|
+ */
|
|
|
|
+ if (rq->curr != rq->idle)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * We can set TIF_RESCHED on the idle task of the other CPU
|
|
|
|
+ * lockless. The worst case is that the other CPU runs the
|
|
|
|
+ * idle task through an additional NOOP schedule()
|
|
|
|
+ */
|
|
|
|
+ set_tsk_thread_flag(rq->idle, TIF_NEED_RESCHED);
|
|
|
|
+
|
|
|
|
+ /* NEED_RESCHED must be visible before we test polling */
|
|
|
|
+ smp_mb();
|
|
|
|
+ if (!tsk_is_polling(rq->idle))
|
|
|
|
+ smp_send_reschedule(cpu);
|
|
|
|
+}
|
|
|
|
+#endif
|
|
|
|
+
|
|
#else
|
|
#else
|
|
static void __resched_task(struct task_struct *p, int tif_bit)
|
|
static void __resched_task(struct task_struct *p, int tif_bit)
|
|
{
|
|
{
|