]> git.proxmox.com Git - mirror_ubuntu-kernels.git/blobdiff - kernel/sched/deadline.c
sched: Fix hotplug task migration
[mirror_ubuntu-kernels.git] / kernel / sched / deadline.c
index 0de248202879311be46a10b0ab855cba0c512ce6..bfeb84ecc32b13bc9bab0aee9262c5705f8dac8d 100644 (file)
@@ -351,7 +351,8 @@ static void replenish_dl_entity(struct sched_dl_entity *dl_se,
  * disrupting the schedulability of the system. Otherwise, we should
  * refill the runtime and set the deadline a period in the future,
  * because keeping the current (absolute) deadline of the task would
- * result in breaking guarantees promised to other tasks.
+ * result in breaking guarantees promised to other tasks (refer to
+ * Documentation/scheduler/sched-deadline.txt for more informations).
  *
  * This function returns true if:
  *
@@ -943,6 +944,8 @@ static void check_preempt_equal_dl(struct rq *rq, struct task_struct *p)
        resched_task(rq->curr);
 }
 
+static int pull_dl_task(struct rq *this_rq);
+
 #endif /* CONFIG_SMP */
 
 /*
@@ -989,7 +992,7 @@ static struct sched_dl_entity *pick_next_dl_entity(struct rq *rq,
        return rb_entry(left, struct sched_dl_entity, rb_node);
 }
 
-struct task_struct *pick_next_task_dl(struct rq *rq)
+struct task_struct *pick_next_task_dl(struct rq *rq, struct task_struct *prev)
 {
        struct sched_dl_entity *dl_se;
        struct task_struct *p;
@@ -997,9 +1000,16 @@ struct task_struct *pick_next_task_dl(struct rq *rq)
 
        dl_rq = &rq->dl;
 
+#ifdef CONFIG_SMP
+       if (dl_task(prev))
+               pull_dl_task(rq);
+#endif
+
        if (unlikely(!dl_rq->dl_nr_running))
                return NULL;
 
+       put_prev_task(rq, prev);
+
        dl_se = pick_next_dl_entity(rq, dl_rq);
        BUG_ON(!dl_se);
 
@@ -1425,13 +1435,6 @@ skip:
        return ret;
 }
 
-static void pre_schedule_dl(struct rq *rq, struct task_struct *prev)
-{
-       /* Try to pull other tasks here */
-       if (dl_task(prev))
-               pull_dl_task(rq);
-}
-
 static void post_schedule_dl(struct rq *rq)
 {
        push_dl_tasks(rq);
@@ -1559,7 +1562,7 @@ static void switched_to_dl(struct rq *rq, struct task_struct *p)
        if (unlikely(p->dl.dl_throttled))
                return;
 
-       if (p->on_rq || rq->curr != p) {
+       if (p->on_rq && rq->curr != p) {
 #ifdef CONFIG_SMP
                if (rq->dl.overloaded && push_dl_task(rq) && rq != task_rq(p))
                        /* Only reschedule if pushing failed */
@@ -1624,7 +1627,6 @@ const struct sched_class dl_sched_class = {
        .set_cpus_allowed       = set_cpus_allowed_dl,
        .rq_online              = rq_online_dl,
        .rq_offline             = rq_offline_dl,
-       .pre_schedule           = pre_schedule_dl,
        .post_schedule          = post_schedule_dl,
        .task_woken             = task_woken_dl,
 #endif