lkml.org 
[lkml]   [2010]   [Mar]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[19/45] sched: wakeup preempt when small overlap
    2.6.27-stable review patch.  If anyone has any objections, please let us know.

    ------------------

    From: Peter Zijlstra <a.p.zijlstra@chello.nl>

    commit 15afe09bf496ae10c989e1a375a6b5da7bd3e16e upstream.

    Lin Ming reported a 10% OLTP regression against 2.6.27-rc4.

    The difference seems to come from different preemption agressiveness,
    which affects the cache footprint of the workload and its effective
    cache trashing.

    Aggresively preempt a task if its avg overlap is very small, this should
    avoid the task going to sleep and find it still running when we schedule
    back to it - saving a wakeup.

    Reported-by: Lin Ming <ming.m.lin@intel.com>
    Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
    Signed-off-by: Ingo Molnar <mingo@elte.hu>
    Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

    ---
    include/linux/sched.h | 2 +-
    kernel/sched.c | 12 ++++++------
    kernel/sched_fair.c | 13 ++++++++++---
    kernel/sched_features.h | 1 +
    kernel/sched_idletask.c | 6 +++---
    kernel/sched_rt.c | 2 +-
    6 files changed, 22 insertions(+), 14 deletions(-)

    --- a/include/linux/sched.h
    +++ b/include/linux/sched.h
    @@ -901,7 +901,7 @@ struct sched_class {
    void (*yield_task) (struct rq *rq);
    int (*select_task_rq)(struct task_struct *p, int sync);

    - void (*check_preempt_curr) (struct rq *rq, struct task_struct *p);
    + void (*check_preempt_curr) (struct rq *rq, struct task_struct *p, int sync);

    struct task_struct * (*pick_next_task) (struct rq *rq);
    void (*put_prev_task) (struct rq *rq, struct task_struct *p);
    --- a/kernel/sched.c
    +++ b/kernel/sched.c
    @@ -604,9 +604,9 @@ struct rq {

    static DEFINE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues);

    -static inline void check_preempt_curr(struct rq *rq, struct task_struct *p)
    +static inline void check_preempt_curr(struct rq *rq, struct task_struct *p, int sync)
    {
    - rq->curr->sched_class->check_preempt_curr(rq, p);
    + rq->curr->sched_class->check_preempt_curr(rq, p, sync);
    }

    static inline int cpu_of(struct rq *rq)
    @@ -2285,7 +2285,7 @@ out_running:
    trace_mark(kernel_sched_wakeup,
    "pid %d state %ld ## rq %p task %p rq->curr %p",
    p->pid, p->state, rq, p, rq->curr);
    - check_preempt_curr(rq, p);
    + check_preempt_curr(rq, p, sync);

    p->state = TASK_RUNNING;
    #ifdef CONFIG_SMP
    @@ -2420,7 +2420,7 @@ void wake_up_new_task(struct task_struct
    trace_mark(kernel_sched_wakeup_new,
    "pid %d state %ld ## rq %p task %p rq->curr %p",
    p->pid, p->state, rq, p, rq->curr);
    - check_preempt_curr(rq, p);
    + check_preempt_curr(rq, p, 0);
    #ifdef CONFIG_SMP
    if (p->sched_class->task_wake_up)
    p->sched_class->task_wake_up(rq, p);
    @@ -2880,7 +2880,7 @@ static void pull_task(struct rq *src_rq,
    * Note that idle threads have a prio of MAX_PRIO, for this test
    * to be always true for them.
    */
    - check_preempt_curr(this_rq, p);
    + check_preempt_curr(this_rq, p, 0);
    }

    /*
    @@ -5957,7 +5957,7 @@ static int __migrate_task(struct task_st
    set_task_cpu(p, dest_cpu);
    if (on_rq) {
    activate_task(rq_dest, p, 0);
    - check_preempt_curr(rq_dest, p);
    + check_preempt_curr(rq_dest, p, 0);
    }
    done:
    ret = 1;
    --- a/kernel/sched_fair.c
    +++ b/kernel/sched_fair.c
    @@ -1331,7 +1331,7 @@ static inline int depth_se(struct sched_
    /*
    * Preempt the current task with a newly woken task if needed:
    */
    -static void check_preempt_wakeup(struct rq *rq, struct task_struct *p)
    +static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int sync)
    {
    struct task_struct *curr = rq->curr;
    struct cfs_rq *cfs_rq = task_cfs_rq(curr);
    @@ -1360,6 +1360,13 @@ static void check_preempt_wakeup(struct
    if (!sched_feat(WAKEUP_PREEMPT))
    return;

    + if (sched_feat(WAKEUP_OVERLAP) && sync &&
    + se->avg_overlap < sysctl_sched_migration_cost &&
    + pse->avg_overlap < sysctl_sched_migration_cost) {
    + resched_task(curr);
    + return;
    + }
    +
    /*
    * preemption test can be made between sibling entities who are in the
    * same cfs_rq i.e who have a common parent. Walk up the hierarchy of
    @@ -1642,7 +1649,7 @@ static void prio_changed_fair(struct rq
    if (p->prio > oldprio)
    resched_task(rq->curr);
    } else
    - check_preempt_curr(rq, p);
    + check_preempt_curr(rq, p, 0);
    }

    /*
    @@ -1659,7 +1666,7 @@ static void switched_to_fair(struct rq *
    if (running)
    resched_task(rq->curr);
    else
    - check_preempt_curr(rq, p);
    + check_preempt_curr(rq, p, 0);
    }

    /* Account for a task changing its policy or group.
    --- a/kernel/sched_features.h
    +++ b/kernel/sched_features.h
    @@ -11,3 +11,4 @@ SCHED_FEAT(ASYM_GRAN, 1)
    SCHED_FEAT(LB_BIAS, 1)
    SCHED_FEAT(LB_WAKEUP_UPDATE, 1)
    SCHED_FEAT(ASYM_EFF_LOAD, 1)
    +SCHED_FEAT(WAKEUP_OVERLAP, 1)
    --- a/kernel/sched_idletask.c
    +++ b/kernel/sched_idletask.c
    @@ -14,7 +14,7 @@ static int select_task_rq_idle(struct ta
    /*
    * Idle tasks are unconditionally rescheduled:
    */
    -static void check_preempt_curr_idle(struct rq *rq, struct task_struct *p)
    +static void check_preempt_curr_idle(struct rq *rq, struct task_struct *p, int sync)
    {
    resched_task(rq->idle);
    }
    @@ -76,7 +76,7 @@ static void switched_to_idle(struct rq *
    if (running)
    resched_task(rq->curr);
    else
    - check_preempt_curr(rq, p);
    + check_preempt_curr(rq, p, 0);
    }

    static void prio_changed_idle(struct rq *rq, struct task_struct *p,
    @@ -93,7 +93,7 @@ static void prio_changed_idle(struct rq
    if (p->prio > oldprio)
    resched_task(rq->curr);
    } else
    - check_preempt_curr(rq, p);
    + check_preempt_curr(rq, p, 0);
    }

    /*
    --- a/kernel/sched_rt.c
    +++ b/kernel/sched_rt.c
    @@ -784,7 +784,7 @@ static void check_preempt_equal_prio(str
    /*
    * Preempt the current task with a newly woken task if needed:
    */
    -static void check_preempt_curr_rt(struct rq *rq, struct task_struct *p)
    +static void check_preempt_curr_rt(struct rq *rq, struct task_struct *p, int sync)
    {
    if (p->prio < rq->curr->prio) {
    resched_task(rq->curr);



    \
     
     \ /
      Last update: 2010-03-31 02:43    [W:3.396 / U:0.868 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site