On Mon, 2011-01-03 at 16:49 +0100, Oleg Nesterov wrote:
OK, removed the sched_exec() test, we'll see if anything explodes ;-)
You mean the fact that I fouled up and didn't cross them (both are
before)? I placed the rmb after reading on_cpu.
It can still do that, I think the problem is us dropping rq->lock in the
middle of schedule(), when the freshly woken migration thread comes in
between there and moves the task away, you can get into the situation
that two cpus reference the same task_struct at the same time, which
usually leads to 'interesting' situations.
---
Index: linux-2.6/kernel/sched.c
===================================================================
--- linux-2.6.orig/kernel/sched.c
+++ linux-2.6/kernel/sched.c
@@ -2144,8 +2144,9 @@ static bool need_migrate_task(struct tas
* If the task is not on a runqueue (and not running), then
* the next wake-up will properly place the task.
*/
+ bool running = p->on_rq || p->on_cpu;
smp_rmb(); /* finish_lock_switch() */
- return p->on_rq || p->on_cpu;
+ return running;
}
/*
@@ -3416,7 +3417,7 @@ void sched_exec(void)
if (dest_cpu == smp_processor_id())
goto unlock;
- if (likely(cpu_active(dest_cpu)) && need_migrate_task(p)) {
+ if (likely(cpu_active(dest_cpu))) {
struct migration_arg arg = { p, dest_cpu };
raw_spin_unlock_irqrestore(&p->pi_lock, flags);
--