X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=kernel%2Fsched%2Ffair.c;h=fbc0b8214af0a89fbde855e559884d6e3ca988fa;hb=1effd9f19324;hp=0b069bf3e708e82ea0e08c5b204f931ca1d22a00;hpb=aee38ea95419c818dfdde52b115aeffe9cbb259b;p=deliverable%2Flinux.git diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 0b069bf3e708..fbc0b8214af0 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -1164,9 +1164,19 @@ static void task_numa_compare(struct task_numa_env *env, long moveimp = imp; rcu_read_lock(); - cur = ACCESS_ONCE(dst_rq->curr); - if (cur->pid == 0) /* idle */ + + raw_spin_lock_irq(&dst_rq->lock); + cur = dst_rq->curr; + /* + * No need to move the exiting task, and this ensures that ->curr + * wasn't reaped and thus get_task_struct() in task_numa_assign() + * is safe under RCU read lock. + * Note that rcu_read_lock() itself can't protect from the final + * put_task_struct() after the last schedule(). + */ + if ((cur->flags & PF_EXITING) || is_idle_task(cur)) cur = NULL; + raw_spin_unlock_irq(&dst_rq->lock); /* * "imp" is the fault differential for the source task between the