diff options
Diffstat (limited to 'kernel/rcu/update.c')
| -rw-r--r-- | kernel/rcu/update.c | 38 | 
1 files changed, 30 insertions, 8 deletions
diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c index f19271dce0a9..4f6db7e6a117 100644 --- a/kernel/rcu/update.c +++ b/kernel/rcu/update.c @@ -121,11 +121,14 @@ EXPORT_SYMBOL(rcu_read_lock_sched_held);   * Should expedited grace-period primitives always fall back to their   * non-expedited counterparts?  Intended for use within RCU.  Note   * that if the user specifies both rcu_expedited and rcu_normal, then - * rcu_normal wins. + * rcu_normal wins.  (Except during the time period during boot from + * when the first task is spawned until the rcu_exp_runtime_mode() + * core_initcall() is invoked, at which point everything is expedited.)   */  bool rcu_gp_is_normal(void)  { -	return READ_ONCE(rcu_normal); +	return READ_ONCE(rcu_normal) && +	       rcu_scheduler_active != RCU_SCHEDULER_INIT;  }  EXPORT_SYMBOL_GPL(rcu_gp_is_normal); @@ -135,13 +138,14 @@ static atomic_t rcu_expedited_nesting =  /*   * Should normal grace-period primitives be expedited?  Intended for   * use within RCU.  Note that this function takes the rcu_expedited - * sysfs/boot variable into account as well as the rcu_expedite_gp() - * nesting.  So looping on rcu_unexpedite_gp() until rcu_gp_is_expedited() - * returns false is a -really- bad idea. + * sysfs/boot variable and rcu_scheduler_active into account as well + * as the rcu_expedite_gp() nesting.  So looping on rcu_unexpedite_gp() + * until rcu_gp_is_expedited() returns false is a -really- bad idea.   */  bool rcu_gp_is_expedited(void)  { -	return rcu_expedited || atomic_read(&rcu_expedited_nesting); +	return rcu_expedited || atomic_read(&rcu_expedited_nesting) || +	       rcu_scheduler_active == RCU_SCHEDULER_INIT;  }  EXPORT_SYMBOL_GPL(rcu_gp_is_expedited); @@ -257,7 +261,7 @@ EXPORT_SYMBOL_GPL(rcu_callback_map);  int notrace debug_lockdep_rcu_enabled(void)  { -	return rcu_scheduler_active && debug_locks && +	return rcu_scheduler_active != RCU_SCHEDULER_INACTIVE && debug_locks &&  	       current->lockdep_recursion == 0;  }  EXPORT_SYMBOL_GPL(debug_lockdep_rcu_enabled); @@ -591,7 +595,7 @@ EXPORT_SYMBOL_GPL(call_rcu_tasks);  void synchronize_rcu_tasks(void)  {  	/* Complain if the scheduler has not started.  */ -	RCU_LOCKDEP_WARN(!rcu_scheduler_active, +	RCU_LOCKDEP_WARN(rcu_scheduler_active == RCU_SCHEDULER_INACTIVE,  			 "synchronize_rcu_tasks called too soon");  	/* Wait for the grace period. */ @@ -813,6 +817,23 @@ static void rcu_spawn_tasks_kthread(void)  #endif /* #ifdef CONFIG_TASKS_RCU */ +/* + * Test each non-SRCU synchronous grace-period wait API.  This is + * useful just after a change in mode for these primitives, and + * during early boot. + */ +void rcu_test_sync_prims(void) +{ +	if (!IS_ENABLED(CONFIG_PROVE_RCU)) +		return; +	synchronize_rcu(); +	synchronize_rcu_bh(); +	synchronize_sched(); +	synchronize_rcu_expedited(); +	synchronize_rcu_bh_expedited(); +	synchronize_sched_expedited(); +} +  #ifdef CONFIG_PROVE_RCU  /* @@ -865,6 +886,7 @@ void rcu_early_boot_tests(void)  		early_boot_test_call_rcu_bh();  	if (rcu_self_test_sched)  		early_boot_test_call_rcu_sched(); +	rcu_test_sync_prims();  }  static int rcu_verify_early_boot_tests(void)  | 
