Re: [PATCH v4 5/5] sched: add two functions for att(det)aching a task to(from) a cfs_rq

2015-09-02 Thread Ingo Molnar

* Peter Zijlstra  wrote:

> On Wed, Sep 02, 2015 at 11:33:15AM +0900, Byungchul Park wrote:
> > +++ b/kernel/sched/fair.c
> > @@ -7920,14 +7920,14 @@ prio_changed_fair(struct rq *rq, struct task_struct 
> > *p, int oldprio)
> >  
> >  static inline bool vruntime_normalized(struct task_struct *p)
> >  {
> > struct sched_entity *se = &p->se;
> >  
> > /*
> > +* In both TASK_ON_RQ_QUEUED case and TASK_ON_RQ_MIGRATING case,

s/ In both the TASK_ON_RQ_QUEUED and TASK_ON_RQ_MIGRATING cases,

> > +* the dequeue_entity(.flags=0) will already have normalized the
> > +* vruntime.

Thanks,

Ingo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v4 5/5] sched: add two functions for att(det)aching a task to(from) a cfs_rq

2015-09-02 Thread Peter Zijlstra
On Wed, Sep 02, 2015 at 11:33:15AM +0900, Byungchul Park wrote:
> +++ b/kernel/sched/fair.c
> @@ -7920,14 +7920,14 @@ prio_changed_fair(struct rq *rq, struct task_struct 
> *p, int oldprio)
>  
>  static inline bool vruntime_normalized(struct task_struct *p)
>  {
>   struct sched_entity *se = &p->se;
>  
>   /*
> +  * In both TASK_ON_RQ_QUEUED case and TASK_ON_RQ_MIGRATING case,
> +  * the dequeue_entity(.flags=0) will already have normalized the
> +  * vruntime.
>*/
> + if (p->on_rq)
>   return true;
>  

You're right. And yes this is nicer. Thanks!

I've folded it into your 5/5 patch.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v4 5/5] sched: add two functions for att(det)aching a task to(from) a cfs_rq

2015-09-01 Thread Byungchul Park
On Tue, Sep 01, 2015 at 05:03:43PM +0200, Peter Zijlstra wrote:
> On Tue, Sep 01, 2015 at 09:28:49AM +0900, Byungchul Park wrote:
> 
> > check the condition "!(flags & DEQUEUE_SLEEP)" for doing normalizing in
> > dequeue_entity(). i think you have to keep my original comment, or
> > modify your comment to something like below.
> > 
> > before - If it's !queued, sleeping tasks have a normalized vruntime,
> > after - If it's !queued, sleeping tasks have a non-normalize vruntime,
> > 
> > but.. i think it would be better that you keep my original comment..
> 
> The comment we can talk about later, but I think the condition:
> 
> > > - if (p->state == TASK_RUNNING)
> > > + if (!p->se.on_rq)
> 
> is important now. Both are broken in different ways.
> 
>   p->state == TASK_RUNNING
> 
> is broken in this scenario:
> 
>   CPU0CPU1
> 
>   set_current_state(TASK_UNINTERRUPTIBLE);

here, the target task has not been dequeued yet (the task will be 
dequeued within schedule()). so, queued is true when sched_move_task()
is called. sched_move_task()->dequeue_task(flag=0) will normalize as
we expect. that is anyway no problem. however, i also think the 
condition here can make us confused, too.

i think "p->state == TASK_RUNNING" condition can work anyway, which
already exists in original code. the condition is only for checking
if the task is being migrated or in sleep. how about this appoach
below to make code more readable?

> 
>   sched_move_task()
> task_move_group_fair()
>   vruntime_normalized() == 
> true
>   if (!cond)
>   schedule();
>   __set_current_state(TASK_RUNNING);
> 
> 
> Now the proposed replacement:
> 
>   !p->se.on_rq
> 
> is equally broken, because (as you point out) clearing it isn't
> conditional on DEQUEUE_SLEEP.
> 

i think we must take a task's on_rq into account instead of se's on_rq,
because current code set se's on_rq to 0 even when migrating a task. but
task's on_rq would be set to TASK_ON_RQ_MIGRATING when migrating the
task. there it would be ok if we use task's on_rq to check if it has
a normailzed vruntime or not like below.

---

>From 9545e34c2f6fd195f18d3111b5c1d1b03600cdcd Mon Sep 17 00:00:00 2001
From: Byungchul Park 
Date: Wed, 2 Sep 2015 10:59:58 +0900
Subject: [PATCH] sched: make vruntime_normalized() cleaner

in both TASK_ON_RQ_QUEUED case and TASK_ON_RQ_MIGRATING case, the
target task have a normalized vruntime by dequeue_entity(.flags=0).
so we don't need to check this separately with a different condition
statement.

Signed-off-by: Byungchul Park 
---
 kernel/sched/fair.c |   16 
 1 file changed, 4 insertions(+), 12 deletions(-)

diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 53d0e30..dfe8754 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -7920,14 +7920,14 @@ prio_changed_fair(struct rq *rq, struct task_struct *p, 
int oldprio)
 
 static inline bool vruntime_normalized(struct task_struct *p)
 {
-   int queued = task_on_rq_queued(p);
struct sched_entity *se = &p->se;
 
/*
-* If it's queued, then the dequeue_entity(.flags=0) will already
-* have normalized the vruntime.
+* In both TASK_ON_RQ_QUEUED case and TASK_ON_RQ_MIGRATING case,
+* the dequeue_entity(.flags=0) will already have normalized the
+* vruntime.
 */
-   if (queued)
+   if (p->on_rq)
return true;
 
/*
@@ -7942,14 +7942,6 @@ static inline bool vruntime_normalized(struct 
task_struct *p)
if (!se->sum_exec_runtime || p->state == TASK_WAKING)
return true;
 
-   /*
-* If it's !queued, then only when the task is sleeping it has a
-* non-normalized vruntime, that is, when the task is being migrated
-* it has a normailized vruntime.
-*/
-   if (p->state == TASK_RUNNING)
-   return true;
-
return false;
 }
 
-- 
1.7.9.5

> 
> And the problem with tracking the vruntime state is that while it helps
> detach_task_cfs_rq(), attach_task_cfs_rq() is still left wondering what
> it should return to.
> 
> So we do indeed need something to determine, based on the current state,
> if vruntime should be normalized.
> 
> /me ponders moar
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v4 5/5] sched: add two functions for att(det)aching a task to(from) a cfs_rq

2015-09-01 Thread Peter Zijlstra
On Tue, Sep 01, 2015 at 09:28:49AM +0900, Byungchul Park wrote:

> check the condition "!(flags & DEQUEUE_SLEEP)" for doing normalizing in
> dequeue_entity(). i think you have to keep my original comment, or
> modify your comment to something like below.
> 
> before - If it's !queued, sleeping tasks have a normalized vruntime,
> after - If it's !queued, sleeping tasks have a non-normalize vruntime,
> 
> but.. i think it would be better that you keep my original comment..

The comment we can talk about later, but I think the condition:

> > -   if (p->state == TASK_RUNNING)
> > +   if (!p->se.on_rq)

is important now. Both are broken in different ways.

p->state == TASK_RUNNING

is broken in this scenario:

CPU0CPU1

set_current_state(TASK_UNINTERRUPTIBLE);

sched_move_task()
  task_move_group_fair()
vruntime_normalized() == 
true
if (!cond)
schedule();
__set_current_state(TASK_RUNNING);


Now the proposed replacement:

!p->se.on_rq

is equally broken, because (as you point out) clearing it isn't
conditional on DEQUEUE_SLEEP.


And the problem with tracking the vruntime state is that while it helps
detach_task_cfs_rq(), attach_task_cfs_rq() is still left wondering what
it should return to.

So we do indeed need something to determine, based on the current state,
if vruntime should be normalized.

/me ponders moar
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v4 5/5] sched: add two functions for att(det)aching a task to(from) a cfs_rq

2015-08-31 Thread Byungchul Park
On Tue, Sep 01, 2015 at 09:28:49AM +0900, Byungchul Park wrote:
> On Mon, Aug 31, 2015 at 05:21:38PM +0200, Peter Zijlstra wrote:
> > On Thu, Aug 20, 2015 at 08:35:16PM +0900, Byungchul Park wrote:
> > > On Thu, Aug 20, 2015 at 08:22:00PM +0900, byungchul.p...@lge.com wrote:
> > 
> > > > +   /*
> > > > +* If it's !queued, then only when the task is sleeping it has a
> > > > +* non-normalized vruntime, that is, when the task is being 
> > > > migrated
> > > > +* it has a normailized vruntime.
> > > > +*/
> > > 
> > > i tried to change your XXX comment. i think it can be explaned like this.
> > > don't you think so? i want to hear any opinions about this.
> > > 
> > > > +   if (p->state == TASK_RUNNING)
> > > > +   return true;
> > 
> > 
> > --- a/kernel/sched/fair.c
> > +++ b/kernel/sched/fair.c
> > @@ -7943,11 +7943,10 @@ static inline bool vruntime_normalized(s
> > return true;
> >  
> > /*
> > -* If it's !queued, then only when the task is sleeping it has a
> > -* non-normalized vruntime, that is, when the task is being migrated
> > -* it has a normalized vruntime.
> > +* If it's !queued, sleeping tasks have a normalized vruntime,
> > +* see dequeue_entity().
> 
> check the condition "!(flags & DEQUEUE_SLEEP)" for doing normalizing in
> dequeue_entity(). i think you have to keep my original comment, or
> modify your comment to something like below.
> 
> before - If it's !queued, sleeping tasks have a normalized vruntime,
> after - If it's !queued, sleeping tasks have a non-normalize vruntime,
> 
> but.. i think it would be better that you keep my original comment..

i mean "it would be better that you leave my original comment unchanged".

> 
> >  */
> > -   if (p->state == TASK_RUNNING)
> > +   if (!p->se.on_rq)
> > return true;
> >  
> > return false;
> > 
> > 
> > Does that make sense?
> > 
> > I think using p->state for this is fragile, as we could be racy with any
> > random blocking primitive that does set_current_state() _before_
> > actually calling into the scheduler.
> > 
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> > the body of a message to majord...@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > Please read the FAQ at  http://www.tux.org/lkml/
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v4 5/5] sched: add two functions for att(det)aching a task to(from) a cfs_rq

2015-08-31 Thread Byungchul Park
On Mon, Aug 31, 2015 at 05:21:38PM +0200, Peter Zijlstra wrote:
> On Thu, Aug 20, 2015 at 08:35:16PM +0900, Byungchul Park wrote:
> > On Thu, Aug 20, 2015 at 08:22:00PM +0900, byungchul.p...@lge.com wrote:
> 
> > > + /*
> > > +  * If it's !queued, then only when the task is sleeping it has a
> > > +  * non-normalized vruntime, that is, when the task is being migrated
> > > +  * it has a normailized vruntime.
> > > +  */
> > 
> > i tried to change your XXX comment. i think it can be explaned like this.
> > don't you think so? i want to hear any opinions about this.
> > 
> > > + if (p->state == TASK_RUNNING)
> > > + return true;
> 
> 
> --- a/kernel/sched/fair.c
> +++ b/kernel/sched/fair.c
> @@ -7943,11 +7943,10 @@ static inline bool vruntime_normalized(s
>   return true;
>  
>   /*
> -  * If it's !queued, then only when the task is sleeping it has a
> -  * non-normalized vruntime, that is, when the task is being migrated
> -  * it has a normalized vruntime.
> +  * If it's !queued, sleeping tasks have a normalized vruntime,
> +  * see dequeue_entity().

check the condition "!(flags & DEQUEUE_SLEEP)" for doing normalizing in
dequeue_entity(). i think you have to keep my original comment, or
modify your comment to something like below.

before - If it's !queued, sleeping tasks have a normalized vruntime,
after - If it's !queued, sleeping tasks have a non-normalize vruntime,

but.. i think it would be better that you keep my original comment..

>*/
> - if (p->state == TASK_RUNNING)
> + if (!p->se.on_rq)
>   return true;
>  
>   return false;
> 
> 
> Does that make sense?
> 
> I think using p->state for this is fragile, as we could be racy with any
> random blocking primitive that does set_current_state() _before_
> actually calling into the scheduler.
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v4 5/5] sched: add two functions for att(det)aching a task to(from) a cfs_rq

2015-08-31 Thread Peter Zijlstra
On Mon, Aug 31, 2015 at 05:21:38PM +0200, Peter Zijlstra wrote:

> + if (!p->se.on_rq)
>   return true;
>  
>   return false;
> 
> 
> Does that make sense?

It does not.. never mind me.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v4 5/5] sched: add two functions for att(det)aching a task to(from) a cfs_rq

2015-08-31 Thread Peter Zijlstra
On Thu, Aug 20, 2015 at 08:35:16PM +0900, Byungchul Park wrote:
> On Thu, Aug 20, 2015 at 08:22:00PM +0900, byungchul.p...@lge.com wrote:

> > +   /*
> > +* If it's !queued, then only when the task is sleeping it has a
> > +* non-normalized vruntime, that is, when the task is being migrated
> > +* it has a normailized vruntime.
> > +*/
> 
> i tried to change your XXX comment. i think it can be explaned like this.
> don't you think so? i want to hear any opinions about this.
> 
> > +   if (p->state == TASK_RUNNING)
> > +   return true;


--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -7943,11 +7943,10 @@ static inline bool vruntime_normalized(s
return true;
 
/*
-* If it's !queued, then only when the task is sleeping it has a
-* non-normalized vruntime, that is, when the task is being migrated
-* it has a normalized vruntime.
+* If it's !queued, sleeping tasks have a normalized vruntime,
+* see dequeue_entity().
 */
-   if (p->state == TASK_RUNNING)
+   if (!p->se.on_rq)
return true;
 
return false;


Does that make sense?

I think using p->state for this is fragile, as we could be racy with any
random blocking primitive that does set_current_state() _before_
actually calling into the scheduler.


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v4 5/5] sched: add two functions for att(det)aching a task to(from) a cfs_rq

2015-08-20 Thread Byungchul Park
On Thu, Aug 20, 2015 at 08:22:00PM +0900, byungchul.p...@lge.com wrote:
> From: Byungchul Park 
> 
> diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
> index af6ad5f..53d0e30 100644
> --- a/kernel/sched/fair.c
> +++ b/kernel/sched/fair.c
> @@ -7918,21 +7918,47 @@ prio_changed_fair(struct rq *rq, struct task_struct 
> *p, int oldprio)
>   check_preempt_curr(rq, p, 0);
>  }
>  
> -static void switched_from_fair(struct rq *rq, struct task_struct *p)
> +static inline bool vruntime_normalized(struct task_struct *p)
>  {
> + int queued = task_on_rq_queued(p);
>   struct sched_entity *se = &p->se;
> - struct cfs_rq *cfs_rq = cfs_rq_of(se);
>  
>   /*
> -  * Ensure the task's vruntime is normalized, so that when it's
> -  * switched back to the fair class the enqueue_entity(.flags=0) will
> -  * do the right thing.
> -  *
>* If it's queued, then the dequeue_entity(.flags=0) will already
> -  * have normalized the vruntime, if it's !queued, then only when
> -  * the task is sleeping will it still have non-normalized vruntime.
> +  * have normalized the vruntime.
> +  */
> + if (queued)
> + return true;
> +
> + /*
> +  * When !queued, vruntime of the task has usually NOT been normalized.
> +  * But there are some cases where it has already been normalized:
> +  *
> +  * - A forked child which is waiting for being woken up by
> +  *   wake_up_new_task().
> +  * - A task which has been woken up by try_to_wake_up() and
> +  *   waiting for actually being woken up by sched_ttwu_pending().
>*/
> - if (!task_on_rq_queued(p) && p->state != TASK_RUNNING) {
> + if (!se->sum_exec_runtime || p->state == TASK_WAKING)
> + return true;
> +
> + /*
> +  * If it's !queued, then only when the task is sleeping it has a
> +  * non-normalized vruntime, that is, when the task is being migrated
> +  * it has a normailized vruntime.
> +  */

i tried to change your XXX comment. i think it can be explaned like this.
don't you think so? i want to hear any opinions about this.

thanks,
byungchul

> + if (p->state == TASK_RUNNING)
> + return true;
> +
> + return false;
> +}
> +
> +static void detach_task_cfs_rq(struct task_struct *p)
> +{
> + struct sched_entity *se = &p->se;
> + struct cfs_rq *cfs_rq = cfs_rq_of(se);
> +
> + if (!vruntime_normalized(p)) {
>   /*
>* Fix up our vruntime so that the current sleep doesn't
>* cause 'unlimited' sleep bonus.
> @@ -7945,9 +7971,10 @@ static void switched_from_fair(struct rq *rq, struct 
> task_struct *p)
>   detach_entity_load_avg(cfs_rq, se);
>  }
>  
> -static void switched_to_fair(struct rq *rq, struct task_struct *p)
> +static void attach_task_cfs_rq(struct task_struct *p)
>  {
>   struct sched_entity *se = &p->se;
> + struct cfs_rq *cfs_rq = cfs_rq_of(se);
>  
>  #ifdef CONFIG_FAIR_GROUP_SCHED
>   /*
> @@ -7958,33 +7985,32 @@ static void switched_to_fair(struct rq *rq, struct 
> task_struct *p)
>  #endif
>  
>   /* Synchronize task with its cfs_rq */
> - attach_entity_load_avg(cfs_rq_of(&p->se), &p->se);
> + attach_entity_load_avg(cfs_rq, se);
>  
> - if (!task_on_rq_queued(p)) {
> + if (!vruntime_normalized(p))
> + se->vruntime += cfs_rq->min_vruntime;
> +}
>  
> +static void switched_from_fair(struct rq *rq, struct task_struct *p)
> +{
> + detach_task_cfs_rq(p);
> +}
> +
> +static void switched_to_fair(struct rq *rq, struct task_struct *p)
> +{
> + attach_task_cfs_rq(p);
> +
> + if (task_on_rq_queued(p)) {
>   /*
> -  * Ensure the task has a non-normalized vruntime when it is 
> switched
> -  * back to the fair class with !queued, so that 
> enqueue_entity() at
> -  * wake-up time will do the right thing.
> -  *
> -  * If it's queued, then the enqueue_entity(.flags=0) makes the 
> task
> -  * has non-normalized vruntime, if it's !queued, then it still 
> has
> -  * normalized vruntime.
> +  * We were most likely switched from sched_rt, so
> +  * kick off the schedule if running, otherwise just see
> +  * if we can still preempt the current task.
>*/
> - if (p->state != TASK_RUNNING)
> - se->vruntime += cfs_rq_of(se)->min_vruntime;
> - return;
> + if (rq->curr == p)
> + resched_curr(rq);
> + else
> + check_preempt_curr(rq, p, 0);
>   }
> -
> - /*
> -  * We were most likely switched from sched_rt, so
> -  * kick off the schedule if running, otherwise just see
> -  * if we can still preempt the current task.
> -  */
> - if (rq->curr == p)
> - resched_curr(rq);
> - else
> - check_preempt_curr

[PATCH v4 5/5] sched: add two functions for att(det)aching a task to(from) a cfs_rq

2015-08-20 Thread byungchul . park
From: Byungchul Park 

this patch introduces two functions for adjusting a task's vruntime
and the target cfs_rq's average load so that redundancy code doing
same things can be simplified. and it provides better readability.
switched_from_fair, switched_to_fair and task_move_group_fair can
use introduced functions and get simplified.

Signed-off-by: Byungchul Park 
---
 kernel/sched/fair.c |  137 ++-
 1 file changed, 60 insertions(+), 77 deletions(-)

diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index af6ad5f..53d0e30 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -7918,21 +7918,47 @@ prio_changed_fair(struct rq *rq, struct task_struct *p, 
int oldprio)
check_preempt_curr(rq, p, 0);
 }
 
-static void switched_from_fair(struct rq *rq, struct task_struct *p)
+static inline bool vruntime_normalized(struct task_struct *p)
 {
+   int queued = task_on_rq_queued(p);
struct sched_entity *se = &p->se;
-   struct cfs_rq *cfs_rq = cfs_rq_of(se);
 
/*
-* Ensure the task's vruntime is normalized, so that when it's
-* switched back to the fair class the enqueue_entity(.flags=0) will
-* do the right thing.
-*
 * If it's queued, then the dequeue_entity(.flags=0) will already
-* have normalized the vruntime, if it's !queued, then only when
-* the task is sleeping will it still have non-normalized vruntime.
+* have normalized the vruntime.
+*/
+   if (queued)
+   return true;
+
+   /*
+* When !queued, vruntime of the task has usually NOT been normalized.
+* But there are some cases where it has already been normalized:
+*
+* - A forked child which is waiting for being woken up by
+*   wake_up_new_task().
+* - A task which has been woken up by try_to_wake_up() and
+*   waiting for actually being woken up by sched_ttwu_pending().
 */
-   if (!task_on_rq_queued(p) && p->state != TASK_RUNNING) {
+   if (!se->sum_exec_runtime || p->state == TASK_WAKING)
+   return true;
+
+   /*
+* If it's !queued, then only when the task is sleeping it has a
+* non-normalized vruntime, that is, when the task is being migrated
+* it has a normailized vruntime.
+*/
+   if (p->state == TASK_RUNNING)
+   return true;
+
+   return false;
+}
+
+static void detach_task_cfs_rq(struct task_struct *p)
+{
+   struct sched_entity *se = &p->se;
+   struct cfs_rq *cfs_rq = cfs_rq_of(se);
+
+   if (!vruntime_normalized(p)) {
/*
 * Fix up our vruntime so that the current sleep doesn't
 * cause 'unlimited' sleep bonus.
@@ -7945,9 +7971,10 @@ static void switched_from_fair(struct rq *rq, struct 
task_struct *p)
detach_entity_load_avg(cfs_rq, se);
 }
 
-static void switched_to_fair(struct rq *rq, struct task_struct *p)
+static void attach_task_cfs_rq(struct task_struct *p)
 {
struct sched_entity *se = &p->se;
+   struct cfs_rq *cfs_rq = cfs_rq_of(se);
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
/*
@@ -7958,33 +7985,32 @@ static void switched_to_fair(struct rq *rq, struct 
task_struct *p)
 #endif
 
/* Synchronize task with its cfs_rq */
-   attach_entity_load_avg(cfs_rq_of(&p->se), &p->se);
+   attach_entity_load_avg(cfs_rq, se);
 
-   if (!task_on_rq_queued(p)) {
+   if (!vruntime_normalized(p))
+   se->vruntime += cfs_rq->min_vruntime;
+}
 
+static void switched_from_fair(struct rq *rq, struct task_struct *p)
+{
+   detach_task_cfs_rq(p);
+}
+
+static void switched_to_fair(struct rq *rq, struct task_struct *p)
+{
+   attach_task_cfs_rq(p);
+
+   if (task_on_rq_queued(p)) {
/*
-* Ensure the task has a non-normalized vruntime when it is 
switched
-* back to the fair class with !queued, so that 
enqueue_entity() at
-* wake-up time will do the right thing.
-*
-* If it's queued, then the enqueue_entity(.flags=0) makes the 
task
-* has non-normalized vruntime, if it's !queued, then it still 
has
-* normalized vruntime.
+* We were most likely switched from sched_rt, so
+* kick off the schedule if running, otherwise just see
+* if we can still preempt the current task.
 */
-   if (p->state != TASK_RUNNING)
-   se->vruntime += cfs_rq_of(se)->min_vruntime;
-   return;
+   if (rq->curr == p)
+   resched_curr(rq);
+   else
+   check_preempt_curr(rq, p, 0);
}
-
-   /*
-* We were most likely switched from sched_rt, so
-* kick off the schedule if running, otherwise just see
-* if we ca