• G
    RT: fix push_rt_task() to handle dequeue_pushable properly · 1563513d
    Gregory Haskins 提交于
    A panic was discovered by Chirag Jog where a BUG_ON sanity check
    in the new "pushable_task" logic would trigger a panic under
    certain circumstances:
    
    http://lkml.org/lkml/2008/9/25/189
    
    Gilles Carry discovered that the root cause was attributed to the
    pushable_tasks list getting corrupted in the push_rt_task logic.
    This was the result of a dropped rq lock in double_lock_balance
    allowing a task in the process of being pushed to potentially migrate
    away, and thus corrupt the pushable_tasks() list.
    
    I traced back the problem as introduced by the pushable_tasks patch
    that went in recently.   There is a "retry" path in push_rt_task()
    that actually had a compound conditional to decide whether to
    retry or exit.  I missed the meaning behind the rationale for the
    virtual "if(!task) goto out;" portion of the compound statement and
    thus did not handle it properly.  The new pushable_tasks logic
    actually creates three distinct conditions:
    
    1) an untouched and unpushable task should be dequeued
    2) a migrated task where more pushable tasks remain should be retried
    3) a migrated task where no more pushable tasks exist should exit
    
    The original logic mushed (1) and (3) together, resulting in the
    system dequeuing a migrated task (against an unlocked foreign run-queue
    nonetheless).
    
    To fix this, we get rid of the notion of "paranoid" and we support the
    three unique conditions properly.  The paranoid feature is no longer
    relevant with the new pushable logic (since pushable naturally limits
    the loop) anyway, so lets just remove it.
    Reported-By: NChirag Jog <chirag@linux.vnet.ibm.com>
    Found-by: NGilles Carry <gilles.carry@bull.net>
    Signed-off-by: NGregory Haskins <ghaskins@novell.com>
    1563513d
sched_rt.c 38.7 KB