forked from mirrors/linux
		
	rcu: locking and unlocking need to always be at least barriers
Herbert Xu pointed out that commitbb73c52bad("rcu: Don't disable preemption for Tiny and Tree RCU readers") was incorrect in making the preempt_disable/enable() be conditional on CONFIG_PREEMPT_COUNT. If CONFIG_PREEMPT_COUNT isn't enabled, the preemption enable/disable is a no-op, but still is a compiler barrier. And RCU locking still _needs_ that compiler barrier. It is simply fundamentally not true that RCU locking would be a complete no-op: we still need to guarantee (for example) that things that can trap and cause preemption cannot migrate into the RCU locked region. The way we do that is by making it a barrier. See for example commit386afc9114("spinlocks and preemption points need to be at least compiler barriers") from back in 2013 that had similar issues with spinlocks that become no-ops on UP: they must still constrain the compiler from moving other operations into the critical region. Now, it is true that a lot of RCU operations already use READ_ONCE() and WRITE_ONCE() (which in practice likely would never be re-ordered wrt anything remotely interesting), but it is also true that that is not globally the case, and that it's not even necessarily always possible (ie bitfields etc). Reported-by: Herbert Xu <herbert@gondor.apana.org.au> Fixes:bb73c52bad("rcu: Don't disable preemption for Tiny and Tree RCU readers") Cc: stable@kernel.org Cc: Boqun Feng <boqun.feng@gmail.com> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
		
							parent
							
								
									30d1d92a88
								
							
						
					
					
						commit
						66be4e66a7
					
				
					 1 changed files with 2 additions and 4 deletions
				
			
		| 
						 | 
				
			
			@ -56,13 +56,11 @@ void __rcu_read_unlock(void);
 | 
			
		|||
 | 
			
		||||
static inline void __rcu_read_lock(void)
 | 
			
		||||
{
 | 
			
		||||
	if (IS_ENABLED(CONFIG_PREEMPT_COUNT))
 | 
			
		||||
	preempt_disable();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void __rcu_read_unlock(void)
 | 
			
		||||
{
 | 
			
		||||
	if (IS_ENABLED(CONFIG_PREEMPT_COUNT))
 | 
			
		||||
	preempt_enable();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue