> +
> +out:
> + double_rq_unlock(rq, p_rq);
> + local_irq_restore(flags);
> +
> + if (yield) {
> + set_current_state(TASK_RUNNING);
> + schedule();
> + }
> +}
> +EXPORT_SYMBOL(yield_to);
> +
> +
> /*
> * This task is about to go to sleep on IO. Increment rq->nr_iowait so
> * that process accounting knows that this is a task in IO wait state.
> diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
> index 5119b08..3288e7c 100644
> --- a/kernel/sched_fair.c
> +++ b/kernel/sched_fair.c
> @@ -1119,6 +1119,61 @@ static void yield_task_fair(struct rq *rq)
> }
>
> #ifdef CONFIG_SMP
> +static void pull_task(struct rq *src_rq, struct task_struct *p,
> + struct rq *this_rq, int this_cpu);
> +#endif
> +
> +static int yield_to_task_fair(struct task_struct *p, int preempt)
> +{
> + struct sched_entity *se = ¤t->se;
> + struct sched_entity *pse = &p->se;
> + struct sched_entity *curr = &(task_rq(p)->curr)->se;
> + struct cfs_rq *cfs_rq = cfs_rq_of(se);
> + struct cfs_rq *p_cfs_rq = cfs_rq_of(pse);
> + int yield = this_rq() == task_rq(p);
> + int want_preempt = preempt;
> +
> +#ifdef CONFIG_FAIR_GROUP_SCHED
> + if (cfs_rq->tg != p_cfs_rq->tg)
> + return 0;
> +
> + /* Preemption only allowed within the same task group. */
> + if (preempt && cfs_rq->tg != cfs_rq_of(curr)->tg)
> + preempt = 0;
> +#endif
> + /* Preemption only allowed within the same thread group. */
> + if (preempt && !same_thread_group(current, task_of(p_cfs_rq->curr)))
> + preempt = 0;
> +
> +#ifdef CONFIG_SMP
> + /*
> + * If this yield is important enough to want to preempt instead
> + * of only dropping a ->next hint, we're alone, and the target
> + * is not alone, pull the target to this cpu.
> + */
> + if (want_preempt && !yield && cfs_rq->nr_running == 1 &&
> + cpumask_test_cpu(smp_processor_id(), &p->cpus_allowed)) {
> + pull_task(task_rq(p), p, this_rq(), smp_processor_id());
> + p_cfs_rq = cfs_rq_of(pse);
> + yield = 1;
> + }
> +#endif
> +
> + if (yield)
> + clear_buddies(cfs_rq, se);
> + else if (preempt)
> + clear_buddies(p_cfs_rq, curr);
> +
> + /* Tell the scheduler that we'd really like pse to run next. */
> + p_cfs_rq->next = pse;
> +
> + if (!yield && preempt)
> + resched_task(task_of(p_cfs_rq->curr));
> +
> + return yield;
> +}
> +
> +#ifdef CONFIG_SMP
>
> #ifdef CONFIG_FAIR_GROUP_SCHED
> /*
> @@ -2081,6 +2136,7 @@ static const struct sched_class fair_sched_class = {
> .enqueue_task = enqueue_task_fair,
> .dequeue_task = dequeue_task_fair,
> .yield_task = yield_task_fair,
> + .yield_to_task = yield_to_task_fair,
>
> .check_preempt_curr = check_preempt_wakeup,
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to
majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>
>
>