• P
    sched: Make resched_cpu() unconditional · 7c2102e5
    Paul E. McKenney 提交于
    The current implementation of synchronize_sched_expedited() incorrectly
    assumes that resched_cpu() is unconditional, which it is not.  This means
    that synchronize_sched_expedited() can hang when resched_cpu()'s trylock
    fails as follows (analysis by Neeraj Upadhyay):
    
    o	CPU1 is waiting for expedited wait to complete:
    
    	sync_rcu_exp_select_cpus
    	     rdp->exp_dynticks_snap & 0x1   // returns 1 for CPU5
    	     IPI sent to CPU5
    
    	synchronize_sched_expedited_wait
    		 ret = swait_event_timeout(rsp->expedited_wq,
    					   sync_rcu_preempt_exp_done(rnp_root),
    					   jiffies_stall);
    
    	expmask = 0x20, CPU 5 in idle path (in cpuidle_enter())
    
    o	CPU5 handles IPI and fails to acquire rq lock.
    
    	Handles IPI
    	     sync_sched_exp_handler
    		 resched_cpu
    		     returns while failing to try lock acquire rq->lock
    		 need_resched is not set
    
    o	CPU5 calls  rcu_idle_enter() and as need_resched is not set, goes to
    	idle (schedule() is not called).
    
    o	CPU 1 reports RCU stall.
    
    Given that resched_cpu() is now used only by RCU, this commit fixes the
    assumption by making resched_cpu() unconditional.
    Reported-by: NNeeraj Upadhyay <neeraju@codeaurora.org>
    Suggested-by: NNeeraj Upadhyay <neeraju@codeaurora.org>
    Signed-off-by: NPaul E. McKenney <paulmck@linux.vnet.ibm.com>
    Acked-by: NSteven Rostedt (VMware) <rostedt@goodmis.org>
    Acked-by: NPeter Zijlstra (Intel) <peterz@infradead.org>
    Cc: stable@vger.kernel.org
    7c2102e5
core.c 165.9 KB