|
@@ -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
|