diff options
Diffstat (limited to 'kernel/rcu/update.c')
| -rw-r--r-- | kernel/rcu/update.c | 49 | 
1 files changed, 48 insertions, 1 deletions
diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c index f5e6a2f95a2a..19bf6fa3ee6a 100644 --- a/kernel/rcu/update.c +++ b/kernel/rcu/update.c @@ -144,8 +144,45 @@ bool rcu_gp_is_normal(void)  }  EXPORT_SYMBOL_GPL(rcu_gp_is_normal); -static atomic_t rcu_expedited_nesting = ATOMIC_INIT(1); +static atomic_t rcu_async_hurry_nesting = ATOMIC_INIT(1); +/* + * Should call_rcu() callbacks be processed with urgency or are + * they OK being executed with arbitrary delays? + */ +bool rcu_async_should_hurry(void) +{ +	return !IS_ENABLED(CONFIG_RCU_LAZY) || +	       atomic_read(&rcu_async_hurry_nesting); +} +EXPORT_SYMBOL_GPL(rcu_async_should_hurry); + +/** + * rcu_async_hurry - Make future async RCU callbacks not lazy. + * + * After a call to this function, future calls to call_rcu() + * will be processed in a timely fashion. + */ +void rcu_async_hurry(void) +{ +	if (IS_ENABLED(CONFIG_RCU_LAZY)) +		atomic_inc(&rcu_async_hurry_nesting); +} +EXPORT_SYMBOL_GPL(rcu_async_hurry); +/** + * rcu_async_relax - Make future async RCU callbacks lazy. + * + * After a call to this function, future calls to call_rcu() + * will be processed in a lazy fashion. + */ +void rcu_async_relax(void) +{ +	if (IS_ENABLED(CONFIG_RCU_LAZY)) +		atomic_dec(&rcu_async_hurry_nesting); +} +EXPORT_SYMBOL_GPL(rcu_async_relax); + +static atomic_t rcu_expedited_nesting = ATOMIC_INIT(1);  /*   * Should normal grace-period primitives be expedited?  Intended for   * use within RCU.  Note that this function takes the rcu_expedited @@ -195,6 +232,7 @@ static bool rcu_boot_ended __read_mostly;  void rcu_end_inkernel_boot(void)  {  	rcu_unexpedite_gp(); +	rcu_async_relax();  	if (rcu_normal_after_boot)  		WRITE_ONCE(rcu_normal, 1);  	rcu_boot_ended = true; @@ -220,6 +258,7 @@ void rcu_test_sync_prims(void)  {  	if (!IS_ENABLED(CONFIG_PROVE_RCU))  		return; +	pr_info("Running RCU synchronous self tests\n");  	synchronize_rcu();  	synchronize_rcu_expedited();  } @@ -508,6 +547,10 @@ int rcu_cpu_stall_timeout __read_mostly = CONFIG_RCU_CPU_STALL_TIMEOUT;  module_param(rcu_cpu_stall_timeout, int, 0644);  int rcu_exp_cpu_stall_timeout __read_mostly = CONFIG_RCU_EXP_CPU_STALL_TIMEOUT;  module_param(rcu_exp_cpu_stall_timeout, int, 0644); +int rcu_cpu_stall_cputime __read_mostly = IS_ENABLED(CONFIG_RCU_CPU_STALL_CPUTIME); +module_param(rcu_cpu_stall_cputime, int, 0644); +bool rcu_exp_stall_task_details __read_mostly; +module_param(rcu_exp_stall_task_details, bool, 0644);  #endif /* #ifdef CONFIG_RCU_STALL_COMMON */  // Suppress boot-time RCU CPU stall warnings and rcutorture writer stall @@ -555,9 +598,12 @@ struct early_boot_kfree_rcu {  static void early_boot_test_call_rcu(void)  {  	static struct rcu_head head; +	int idx;  	static struct rcu_head shead;  	struct early_boot_kfree_rcu *rhp; +	idx = srcu_down_read(&early_srcu); +	srcu_up_read(&early_srcu, idx);  	call_rcu(&head, test_callback);  	early_srcu_cookie = start_poll_synchronize_srcu(&early_srcu);  	call_srcu(&early_srcu, &shead, test_callback); @@ -586,6 +632,7 @@ static int rcu_verify_early_boot_tests(void)  		early_boot_test_counter++;  		srcu_barrier(&early_srcu);  		WARN_ON_ONCE(!poll_state_synchronize_srcu(&early_srcu, early_srcu_cookie)); +		cleanup_srcu_struct(&early_srcu);  	}  	if (rcu_self_test_counter != early_boot_test_counter) {  		WARN_ON(1);  |