Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e991dbc0 authored by Paul E. McKenney's avatar Paul E. McKenney
Browse files

rcutorture: Abstract torture_shutdown()



Because auto-shutdown of torture testing is not specific to RCU,
this commit moves the auto-shutdown function to kernel/torture.c.

Signed-off-by: default avatarPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Reviewed-by: default avatarJosh Triplett <josh@joshtriplett.org>
parent 57a2fe90
Loading
Loading
Loading
Loading
+3 −1
Original line number Original line Diff line number Diff line
@@ -72,8 +72,10 @@ unsigned long torture_random(struct torture_random_state *trsp);
void torture_shuffle_task_register(struct task_struct *tp);
void torture_shuffle_task_register(struct task_struct *tp);
int torture_shuffle_init(long shuffint);
int torture_shuffle_init(long shuffint);


/* Shutdown task absorption, for when the tasks cannot safely be killed. */
/* Test auto-shutdown handling. */
void torture_shutdown_absorb(const char *title);
void torture_shutdown_absorb(const char *title);
int torture_shutdown_init(int ssecs, void (*cleanup)(void));
void torture_shutdown_cleanup(void);


/* Task stuttering, which forces load/no-load transitions. */
/* Task stuttering, which forces load/no-load transitions. */
void stutter_wait(const char *title);
void stutter_wait(const char *title);
+5 −58
Original line number Original line Diff line number Diff line
@@ -105,7 +105,6 @@ static struct task_struct **reader_tasks;
static struct task_struct *stats_task;
static struct task_struct *stats_task;
static struct task_struct *fqs_task;
static struct task_struct *fqs_task;
static struct task_struct *boost_tasks[NR_CPUS];
static struct task_struct *boost_tasks[NR_CPUS];
static struct task_struct *shutdown_task;
static struct task_struct *stall_task;
static struct task_struct *stall_task;
static struct task_struct **barrier_cbs_tasks;
static struct task_struct **barrier_cbs_tasks;
static struct task_struct *barrier_task;
static struct task_struct *barrier_task;
@@ -173,7 +172,6 @@ static u64 notrace rcu_trace_clock_local(void)
}
}
#endif /* #else #ifdef CONFIG_RCU_TRACE */
#endif /* #else #ifdef CONFIG_RCU_TRACE */


static unsigned long shutdown_time;	/* jiffies to system shutdown. */
static unsigned long boost_starttime;	/* jiffies of next boost test start. */
static unsigned long boost_starttime;	/* jiffies of next boost test start. */
DEFINE_MUTEX(boost_mutex);		/* protect setting boost_starttime */
DEFINE_MUTEX(boost_mutex);		/* protect setting boost_starttime */
					/*  and boost task create/destroy. */
					/*  and boost task create/destroy. */
@@ -183,9 +181,6 @@ static atomic_t barrier_cbs_invoked; /* Barrier callbacks invoked. */
static wait_queue_head_t *barrier_cbs_wq; /* Coordinate barrier testing. */
static wait_queue_head_t *barrier_cbs_wq; /* Coordinate barrier testing. */
static DECLARE_WAIT_QUEUE_HEAD(barrier_wq);
static DECLARE_WAIT_QUEUE_HEAD(barrier_wq);


/* Forward reference. */
static void rcu_torture_cleanup(void);

/*
/*
 * Allocate an element from the rcu_tortures pool.
 * Allocate an element from the rcu_tortures pool.
 */
 */
@@ -1086,42 +1081,6 @@ static int rcutorture_booster_init(int cpu)
	return 0;
	return 0;
}
}


/*
 * Cause the rcutorture test to shutdown the system after the test has
 * run for the time specified by the shutdown_secs module parameter.
 */
static int
rcu_torture_shutdown(void *arg)
{
	long delta;
	unsigned long jiffies_snap;

	VERBOSE_TOROUT_STRING("rcu_torture_shutdown task started");
	jiffies_snap = ACCESS_ONCE(jiffies);
	while (ULONG_CMP_LT(jiffies_snap, shutdown_time) &&
	       !kthread_should_stop()) {
		delta = shutdown_time - jiffies_snap;
		if (verbose)
			pr_alert("%s" TORTURE_FLAG
				 "rcu_torture_shutdown task: %lu jiffies remaining\n",
				 torture_type, delta);
		schedule_timeout_interruptible(delta);
		jiffies_snap = ACCESS_ONCE(jiffies);
	}
	if (kthread_should_stop()) {
		VERBOSE_TOROUT_STRING("rcu_torture_shutdown task stopping");
		return 0;
	}

	/* OK, shut down the system. */

	VERBOSE_TOROUT_STRING("rcu_torture_shutdown task shutting down system");
	shutdown_task = NULL;	/* Avoid self-kill deadlock. */
	rcu_torture_cleanup();	/* Get the success/failure message. */
	kernel_power_off();	/* Shut down the system. */
	return 0;
}

/*
/*
 * CPU-stall kthread.  It waits as specified by stall_cpu_holdoff, then
 * CPU-stall kthread.  It waits as specified by stall_cpu_holdoff, then
 * induces a CPU stall for the time specified by stall_cpu.
 * induces a CPU stall for the time specified by stall_cpu.
@@ -1421,11 +1380,7 @@ rcu_torture_cleanup(void)
		for_each_possible_cpu(i)
		for_each_possible_cpu(i)
			rcutorture_booster_cleanup(i);
			rcutorture_booster_cleanup(i);
	}
	}
	if (shutdown_task != NULL) {
	torture_shutdown_cleanup();
		VERBOSE_TOROUT_STRING("Stopping rcu_torture_shutdown task");
		kthread_stop(shutdown_task);
	}
	shutdown_task = NULL;


	/* Wait for all RCU callbacks to fire.  */
	/* Wait for all RCU callbacks to fire.  */


@@ -1681,19 +1636,11 @@ rcu_torture_init(void)
			}
			}
		}
		}
	}
	}
	if (shutdown_secs > 0) {
	i = torture_shutdown_init(shutdown_secs, rcu_torture_cleanup);
		shutdown_time = jiffies + shutdown_secs * HZ;
	if (i != 0) {
		shutdown_task = kthread_create(rcu_torture_shutdown, NULL,
		firsterr = i;
					       "rcu_torture_shutdown");
		if (IS_ERR(shutdown_task)) {
			firsterr = PTR_ERR(shutdown_task);
			VERBOSE_TOROUT_ERRSTRING("Failed to create shutdown");
			shutdown_task = NULL;
		goto unwind;
		goto unwind;
	}
	}
		torture_shuffle_task_register(shutdown_task);
		wake_up_process(shutdown_task);
	}
	i = torture_onoff_init(onoff_holdoff * HZ, onoff_interval * HZ);
	i = torture_onoff_init(onoff_holdoff * HZ, onoff_interval * HZ);
	if (i != 0) {
	if (i != 0) {
		firsterr = i;
		firsterr = i;
+84 −0
Original line number Original line Diff line number Diff line
@@ -418,6 +418,15 @@ static void torture_shuffle_cleanup(void)
}
}
EXPORT_SYMBOL_GPL(torture_shuffle_cleanup);
EXPORT_SYMBOL_GPL(torture_shuffle_cleanup);


/*
 * Variables for auto-shutdown.  This allows "lights out" torture runs
 * to be fully scripted.
 */
static int shutdown_secs;		/* desired test duration in seconds. */
static struct task_struct *shutdown_task;
static unsigned long shutdown_time;	/* jiffies to system shutdown. */
static void (*torture_shutdown_hook)(void);

/*
/*
 * Absorb kthreads into a kernel function that won't return, so that
 * Absorb kthreads into a kernel function that won't return, so that
 * they won't ever access module text or data again.
 * they won't ever access module text or data again.
@@ -432,6 +441,81 @@ void torture_shutdown_absorb(const char *title)
}
}
EXPORT_SYMBOL_GPL(torture_shutdown_absorb);
EXPORT_SYMBOL_GPL(torture_shutdown_absorb);


/*
 * Cause the torture test to shutdown the system after the test has
 * run for the time specified by the shutdown_secs parameter.
 */
static int torture_shutdown(void *arg)
{
	long delta;
	unsigned long jiffies_snap;

	VERBOSE_TOROUT_STRING("torture_shutdown task started");
	jiffies_snap = jiffies;
	while (ULONG_CMP_LT(jiffies_snap, shutdown_time) &&
	       !torture_must_stop()) {
		delta = shutdown_time - jiffies_snap;
		if (verbose)
			pr_alert("%s" TORTURE_FLAG
				 "torture_shutdown task: %lu jiffies remaining\n",
				 torture_type, delta);
		schedule_timeout_interruptible(delta);
		jiffies_snap = jiffies;
	}
	if (torture_must_stop()) {
		VERBOSE_TOROUT_STRING("torture_shutdown task stopping");
		return 0;
	}

	/* OK, shut down the system. */

	VERBOSE_TOROUT_STRING("torture_shutdown task shutting down system");
	shutdown_task = NULL;	/* Avoid self-kill deadlock. */
	torture_shutdown_hook();/* Shut down the enclosing torture test. */
	kernel_power_off();	/* Shut down the system. */
	return 0;
}

/*
 * Start up the shutdown task.
 */
int torture_shutdown_init(int ssecs, void (*cleanup)(void))
{
	int ret;

	shutdown_secs = ssecs;
	torture_shutdown_hook = cleanup;
	if (shutdown_secs > 0) {
		shutdown_time = jiffies + shutdown_secs * HZ;
		shutdown_task = kthread_create(torture_shutdown, NULL,
					       "torture_shutdown");
		if (IS_ERR(shutdown_task)) {
			ret = PTR_ERR(shutdown_task);
			VERBOSE_TOROUT_ERRSTRING("Failed to create shutdown");
			shutdown_task = NULL;
			return ret;
		}
		torture_shuffle_task_register(shutdown_task);
		wake_up_process(shutdown_task);
	}
	return 0;
}
EXPORT_SYMBOL_GPL(torture_shutdown_init);

/*
 * Shut down the shutdown task.  Say what???  Heh!  This can happen if
 * the torture module gets an rmmod before the shutdown time arrives.  ;-)
 */
void torture_shutdown_cleanup(void)
{
	if (shutdown_task != NULL) {
		VERBOSE_TOROUT_STRING("Stopping torture_shutdown task");
		kthread_stop(shutdown_task);
	}
	shutdown_task = NULL;
}
EXPORT_SYMBOL_GPL(torture_shutdown_cleanup);

/*
/*
 * Detect and respond to a system shutdown.
 * Detect and respond to a system shutdown.
 */
 */