History

Merge branch 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull scheduler fix from Thomas Gleixner: "A single scheduler fix: Prevent idle task from ever being preempted. That makes sure that synchronize_rcu_tasks() which is ignoring idle task does not pretend that no task is stuck in preempted state. If that happens and idle was preempted on a ftrace trampoline the machine crashes due to inconsistent state" * 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: sched/core: Call __schedule() from do_idle() without enabling preemption

Linus Torvalds committed 9 years ago

Commit 970c3052 parents e7a3d62 8663eff3 files · +28 −1Browse files

Unified · Split

3 files
  1. kernel/sched/core.c +25 −0
  2. kernel/sched/idle.c +1 −1
  3. kernel/sched/sched.h +2 −0
kernel/sched/core.c+25−0
@@ -3502,6 +3502,31 @@ asmlinkage __visible void __sched schedule(void) · 3501 unmodified lines
35023502 }
35033503 EXPORT_SYMBOL(schedule);
35043504
3505+/*
3506+ * synchronize_rcu_tasks() makes sure that no task is stuck in preempted
3507+ * state (have scheduled out non-voluntarily) by making sure that all
3508+ * tasks have either left the run queue or have gone into user space.
3509+ * As idle tasks do not do either, they must not ever be preempted
3510+ * (schedule out non-voluntarily).
3511+ *
3512+ * schedule_idle() is similar to schedule_preempt_disable() except that it
3513+ * never enables preemption because it does not call sched_submit_work().
3514+ */
3515+void __sched schedule_idle(void)
3516+{
3517+ /*
3518+ * As this skips calling sched_submit_work(), which the idle task does
3519+ * regardless because that function is a nop when the task is in a
3520+ * TASK_RUNNING state, make sure this isn't used someplace that the
3521+ * current task can be in any other state. Note, idle is always in the
3522+ * TASK_RUNNING state.
3523+ */
3524+ WARN_ON_ONCE(current->state);
3525+ do {
3526+ __schedule(false);
3527+ } while (need_resched());
3528+}
3529+
35053530 #ifdef CONFIG_CONTEXT_TRACKING
35063531 asmlinkage __visible void __sched schedule_user(void)
35073532 {
kernel/sched/idle.c+1−1
@@ -265,7 +265,7 @@ static void do_idle(void) · 264 unmodified lines
265265 smp_mb__after_atomic();
266266
267267 sched_ttwu_pending();
268− schedule_preempt_disabled();
268+ schedule_idle();
269269
270270 if (unlikely(klp_patch_pending(current)))
271271 klp_update_patch_state(current);
kernel/sched/sched.h+2−0
@@ -1467,6 +1467,8 @@ static inline struct cpuidle_state *idle_get_state(struct rq *rq) · 1466 unmodified lines
14671467 }
14681468 #endif
14691469
1470+extern void schedule_idle(void);
1471+
14701472 extern void sysrq_sched_debug_show(void);
14711473 extern void sched_init_granularity(void);
14721474 extern void update_max_interval(void);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t