diff options
Diffstat (limited to 'kernel/sched.c')
-rw-r--r-- | kernel/sched.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index 28c73f07efb2..8dcdec6fe0fe 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -1052,6 +1052,49 @@ static void resched_cpu(int cpu) | |||
1052 | resched_task(cpu_curr(cpu)); | 1052 | resched_task(cpu_curr(cpu)); |
1053 | spin_unlock_irqrestore(&rq->lock, flags); | 1053 | spin_unlock_irqrestore(&rq->lock, flags); |
1054 | } | 1054 | } |
1055 | |||
1056 | #ifdef CONFIG_NO_HZ | ||
1057 | /* | ||
1058 | * When add_timer_on() enqueues a timer into the timer wheel of an | ||
1059 | * idle CPU then this timer might expire before the next timer event | ||
1060 | * which is scheduled to wake up that CPU. In case of a completely | ||
1061 | * idle system the next event might even be infinite time into the | ||
1062 | * future. wake_up_idle_cpu() ensures that the CPU is woken up and | ||
1063 | * leaves the inner idle loop so the newly added timer is taken into | ||
1064 | * account when the CPU goes back to idle and evaluates the timer | ||
1065 | * wheel for the next timer event. | ||
1066 | */ | ||
1067 | void wake_up_idle_cpu(int cpu) | ||
1068 | { | ||
1069 | struct rq *rq = cpu_rq(cpu); | ||
1070 | |||
1071 | if (cpu == smp_processor_id()) | ||
1072 | return; | ||
1073 | |||
1074 | /* | ||
1075 | * This is safe, as this function is called with the timer | ||
1076 | * wheel base lock of (cpu) held. When the CPU is on the way | ||
1077 | * to idle and has not yet set rq->curr to idle then it will | ||
1078 | * be serialized on the timer wheel base lock and take the new | ||
1079 | * timer into account automatically. | ||
1080 | */ | ||
1081 | if (rq->curr != rq->idle) | ||
1082 | return; | ||
1083 | |||
1084 | /* | ||
1085 | * We can set TIF_RESCHED on the idle task of the other CPU | ||
1086 | * lockless. The worst case is that the other CPU runs the | ||
1087 | * idle task through an additional NOOP schedule() | ||
1088 | */ | ||
1089 | set_tsk_thread_flag(rq->idle, TIF_NEED_RESCHED); | ||
1090 | |||
1091 | /* NEED_RESCHED must be visible before we test polling */ | ||
1092 | smp_mb(); | ||
1093 | if (!tsk_is_polling(rq->idle)) | ||
1094 | smp_send_reschedule(cpu); | ||
1095 | } | ||
1096 | #endif | ||
1097 | |||
1055 | #else | 1098 | #else |
1056 | static void __resched_task(struct task_struct *p, int tif_bit) | 1099 | static void __resched_task(struct task_struct *p, int tif_bit) |
1057 | { | 1100 | { |