diff options
Diffstat (limited to 'kernel/rcu/rcutorture.c')
| -rw-r--r-- | kernel/rcu/rcutorture.c | 44 | 
1 files changed, 31 insertions, 13 deletions
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c index 3c9feca1eab1..dee043feb71f 100644 --- a/kernel/rcu/rcutorture.c +++ b/kernel/rcu/rcutorture.c @@ -44,6 +44,7 @@  #include <linux/sched/debug.h>  #include <linux/sched/sysctl.h>  #include <linux/oom.h> +#include <linux/tick.h>  #include "rcu.h" @@ -1363,15 +1364,15 @@ rcu_torture_reader(void *arg)  	set_user_nice(current, MAX_NICE);  	if (irqreader && cur_ops->irq_capable)  		timer_setup_on_stack(&t, rcu_torture_timer, 0); - +	tick_dep_set_task(current, TICK_DEP_BIT_RCU);  	do {  		if (irqreader && cur_ops->irq_capable) {  			if (!timer_pending(&t))  				mod_timer(&t, jiffies + 1);  		} -		if (!rcu_torture_one_read(&rand)) +		if (!rcu_torture_one_read(&rand) && !torture_must_stop())  			schedule_timeout_interruptible(HZ); -		if (time_after(jiffies, lastsleep)) { +		if (time_after(jiffies, lastsleep) && !torture_must_stop()) {  			schedule_timeout_interruptible(1);  			lastsleep = jiffies + 10;  		} @@ -1383,6 +1384,7 @@ rcu_torture_reader(void *arg)  		del_timer_sync(&t);  		destroy_timer_on_stack(&t);  	} +	tick_dep_clear_task(current, TICK_DEP_BIT_RCU);  	torture_kthread_stopping("rcu_torture_reader");  	return 0;  } @@ -1442,15 +1444,18 @@ rcu_torture_stats_print(void)  		n_rcu_torture_barrier_error);  	pr_alert("%s%s ", torture_type, TORTURE_FLAG); -	if (atomic_read(&n_rcu_torture_mberror) != 0 || -	    n_rcu_torture_barrier_error != 0 || -	    n_rcu_torture_boost_ktrerror != 0 || -	    n_rcu_torture_boost_rterror != 0 || -	    n_rcu_torture_boost_failure != 0 || +	if (atomic_read(&n_rcu_torture_mberror) || +	    n_rcu_torture_barrier_error || n_rcu_torture_boost_ktrerror || +	    n_rcu_torture_boost_rterror || n_rcu_torture_boost_failure ||  	    i > 1) {  		pr_cont("%s", "!!! ");  		atomic_inc(&n_rcu_torture_error); -		WARN_ON_ONCE(1); +		WARN_ON_ONCE(atomic_read(&n_rcu_torture_mberror)); +		WARN_ON_ONCE(n_rcu_torture_barrier_error);  // rcu_barrier() +		WARN_ON_ONCE(n_rcu_torture_boost_ktrerror); // no boost kthread +		WARN_ON_ONCE(n_rcu_torture_boost_rterror); // can't set RT prio +		WARN_ON_ONCE(n_rcu_torture_boost_failure); // RCU boost failed +		WARN_ON_ONCE(i > 1); // Too-short grace period  	}  	pr_cont("Reader Pipe: ");  	for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) @@ -1729,10 +1734,10 @@ static void rcu_torture_fwd_prog_cond_resched(unsigned long iter)  		// Real call_rcu() floods hit userspace, so emulate that.  		if (need_resched() || (iter & 0xfff))  			schedule(); -	} else { -		// No userspace emulation: CB invocation throttles call_rcu() -		cond_resched(); +		return;  	} +	// No userspace emulation: CB invocation throttles call_rcu() +	cond_resched();  }  /* @@ -1759,6 +1764,11 @@ static unsigned long rcu_torture_fwd_prog_cbfree(void)  		kfree(rfcp);  		freed++;  		rcu_torture_fwd_prog_cond_resched(freed); +		if (tick_nohz_full_enabled()) { +			local_irq_save(flags); +			rcu_momentary_dyntick_idle(); +			local_irq_restore(flags); +		}  	}  	return freed;  } @@ -1803,7 +1813,7 @@ static void rcu_torture_fwd_prog_nr(int *tested, int *tested_tries)  		udelay(10);  		cur_ops->readunlock(idx);  		if (!fwd_progress_need_resched || need_resched()) -			rcu_torture_fwd_prog_cond_resched(1); +			cond_resched();  	}  	(*tested_tries)++;  	if (!time_before(jiffies, stopat) && @@ -1833,6 +1843,7 @@ static void rcu_torture_fwd_prog_nr(int *tested, int *tested_tries)  static void rcu_torture_fwd_prog_cr(void)  {  	unsigned long cver; +	unsigned long flags;  	unsigned long gps;  	int i;  	long n_launders; @@ -1865,6 +1876,7 @@ static void rcu_torture_fwd_prog_cr(void)  	cver = READ_ONCE(rcu_torture_current_version);  	gps = cur_ops->get_gp_seq();  	rcu_launder_gp_seq_start = gps; +	tick_dep_set_task(current, TICK_DEP_BIT_RCU);  	while (time_before(jiffies, stopat) &&  	       !shutdown_time_arrived() &&  	       !READ_ONCE(rcu_fwd_emergency_stop) && !torture_must_stop()) { @@ -1891,6 +1903,11 @@ static void rcu_torture_fwd_prog_cr(void)  		}  		cur_ops->call(&rfcp->rh, rcu_torture_fwd_cb_cr);  		rcu_torture_fwd_prog_cond_resched(n_launders + n_max_cbs); +		if (tick_nohz_full_enabled()) { +			local_irq_save(flags); +			rcu_momentary_dyntick_idle(); +			local_irq_restore(flags); +		}  	}  	stoppedat = jiffies;  	n_launders_cb_snap = READ_ONCE(n_launders_cb); @@ -1911,6 +1928,7 @@ static void rcu_torture_fwd_prog_cr(void)  		rcu_torture_fwd_cb_hist();  	}  	schedule_timeout_uninterruptible(HZ); /* Let CBs drain. */ +	tick_dep_clear_task(current, TICK_DEP_BIT_RCU);  	WRITE_ONCE(rcu_fwd_cb_nodelay, false);  }  |