|
@@ -1344,6 +1344,8 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags)
|
|
|
hrtick_update(rq);
|
|
|
}
|
|
|
|
|
|
+static void set_next_buddy(struct sched_entity *se);
|
|
|
+
|
|
|
/*
|
|
|
* The dequeue_task method is called before nr_running is
|
|
|
* decreased. We remove the task from the rbtree and
|
|
@@ -1353,14 +1355,22 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int flags)
|
|
|
{
|
|
|
struct cfs_rq *cfs_rq;
|
|
|
struct sched_entity *se = &p->se;
|
|
|
+ int task_sleep = flags & DEQUEUE_SLEEP;
|
|
|
|
|
|
for_each_sched_entity(se) {
|
|
|
cfs_rq = cfs_rq_of(se);
|
|
|
dequeue_entity(cfs_rq, se, flags);
|
|
|
|
|
|
/* Don't dequeue parent if it has other entities besides us */
|
|
|
- if (cfs_rq->load.weight)
|
|
|
+ if (cfs_rq->load.weight) {
|
|
|
+ /*
|
|
|
+ * Bias pick_next to pick a task from this cfs_rq, as
|
|
|
+ * p is sleeping when it is within its sched_slice.
|
|
|
+ */
|
|
|
+ if (task_sleep && parent_entity(se))
|
|
|
+ set_next_buddy(parent_entity(se));
|
|
|
break;
|
|
|
+ }
|
|
|
flags |= DEQUEUE_SLEEP;
|
|
|
}
|
|
|
|
|
@@ -1877,12 +1887,15 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int wake_
|
|
|
struct sched_entity *se = &curr->se, *pse = &p->se;
|
|
|
struct cfs_rq *cfs_rq = task_cfs_rq(curr);
|
|
|
int scale = cfs_rq->nr_running >= sched_nr_latency;
|
|
|
+ int next_buddy_marked = 0;
|
|
|
|
|
|
if (unlikely(se == pse))
|
|
|
return;
|
|
|
|
|
|
- if (sched_feat(NEXT_BUDDY) && scale && !(wake_flags & WF_FORK))
|
|
|
+ if (sched_feat(NEXT_BUDDY) && scale && !(wake_flags & WF_FORK)) {
|
|
|
set_next_buddy(pse);
|
|
|
+ next_buddy_marked = 1;
|
|
|
+ }
|
|
|
|
|
|
/*
|
|
|
* We can come here with TIF_NEED_RESCHED already set from new task
|
|
@@ -1910,8 +1923,15 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int wake_
|
|
|
update_curr(cfs_rq);
|
|
|
find_matching_se(&se, &pse);
|
|
|
BUG_ON(!pse);
|
|
|
- if (wakeup_preempt_entity(se, pse) == 1)
|
|
|
+ if (wakeup_preempt_entity(se, pse) == 1) {
|
|
|
+ /*
|
|
|
+ * Bias pick_next to pick the sched entity that is
|
|
|
+ * triggering this preemption.
|
|
|
+ */
|
|
|
+ if (!next_buddy_marked)
|
|
|
+ set_next_buddy(pse);
|
|
|
goto preempt;
|
|
|
+ }
|
|
|
|
|
|
return;
|
|
|
|