162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0+ */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Common functions for in-kernel torture tests.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright IBM Corporation, 2014
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Author: Paul E. McKenney <paulmck@linux.ibm.com>
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#ifndef __LINUX_TORTURE_H
1162306a36Sopenharmony_ci#define __LINUX_TORTURE_H
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/types.h>
1462306a36Sopenharmony_ci#include <linux/cache.h>
1562306a36Sopenharmony_ci#include <linux/spinlock.h>
1662306a36Sopenharmony_ci#include <linux/threads.h>
1762306a36Sopenharmony_ci#include <linux/cpumask.h>
1862306a36Sopenharmony_ci#include <linux/seqlock.h>
1962306a36Sopenharmony_ci#include <linux/lockdep.h>
2062306a36Sopenharmony_ci#include <linux/completion.h>
2162306a36Sopenharmony_ci#include <linux/debugobjects.h>
2262306a36Sopenharmony_ci#include <linux/bug.h>
2362306a36Sopenharmony_ci#include <linux/compiler.h>
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci/* Definitions for a non-string torture-test module parameter. */
2662306a36Sopenharmony_ci#define torture_param(type, name, init, msg) \
2762306a36Sopenharmony_ci	static type name = init; \
2862306a36Sopenharmony_ci	module_param(name, type, 0444); \
2962306a36Sopenharmony_ci	MODULE_PARM_DESC(name, msg);
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#define TORTURE_FLAG "-torture:"
3262306a36Sopenharmony_ci#define TOROUT_STRING(s) \
3362306a36Sopenharmony_ci	pr_alert("%s" TORTURE_FLAG " %s\n", torture_type, s)
3462306a36Sopenharmony_ci#define VERBOSE_TOROUT_STRING(s) \
3562306a36Sopenharmony_cido {										\
3662306a36Sopenharmony_ci	if (verbose) {								\
3762306a36Sopenharmony_ci		verbose_torout_sleep();						\
3862306a36Sopenharmony_ci		pr_alert("%s" TORTURE_FLAG " %s\n", torture_type, s);		\
3962306a36Sopenharmony_ci	}									\
4062306a36Sopenharmony_ci} while (0)
4162306a36Sopenharmony_ci#define TOROUT_ERRSTRING(s) \
4262306a36Sopenharmony_ci	pr_alert("%s" TORTURE_FLAG "!!! %s\n", torture_type, s)
4362306a36Sopenharmony_civoid verbose_torout_sleep(void);
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci#define torture_init_error(firsterr)						\
4662306a36Sopenharmony_ci({										\
4762306a36Sopenharmony_ci	int ___firsterr = (firsterr);						\
4862306a36Sopenharmony_ci										\
4962306a36Sopenharmony_ci	WARN_ONCE(!IS_MODULE(CONFIG_RCU_TORTURE_TEST) && ___firsterr < 0, "Torture-test initialization failed with error code %d\n", ___firsterr); \
5062306a36Sopenharmony_ci	___firsterr < 0;								\
5162306a36Sopenharmony_ci})
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci/* Definitions for online/offline exerciser. */
5462306a36Sopenharmony_ci#ifdef CONFIG_HOTPLUG_CPU
5562306a36Sopenharmony_ciint torture_num_online_cpus(void);
5662306a36Sopenharmony_ci#else /* #ifdef CONFIG_HOTPLUG_CPU */
5762306a36Sopenharmony_cistatic inline int torture_num_online_cpus(void) { return 1; }
5862306a36Sopenharmony_ci#endif /* #else #ifdef CONFIG_HOTPLUG_CPU */
5962306a36Sopenharmony_citypedef void torture_ofl_func(void);
6062306a36Sopenharmony_cibool torture_offline(int cpu, long *n_onl_attempts, long *n_onl_successes,
6162306a36Sopenharmony_ci		     unsigned long *sum_offl, int *min_onl, int *max_onl);
6262306a36Sopenharmony_cibool torture_online(int cpu, long *n_onl_attempts, long *n_onl_successes,
6362306a36Sopenharmony_ci		    unsigned long *sum_onl, int *min_onl, int *max_onl);
6462306a36Sopenharmony_ciint torture_onoff_init(long ooholdoff, long oointerval, torture_ofl_func *f);
6562306a36Sopenharmony_civoid torture_onoff_stats(void);
6662306a36Sopenharmony_cibool torture_onoff_failures(void);
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci/* Low-rider random number generator. */
6962306a36Sopenharmony_cistruct torture_random_state {
7062306a36Sopenharmony_ci	unsigned long trs_state;
7162306a36Sopenharmony_ci	long trs_count;
7262306a36Sopenharmony_ci};
7362306a36Sopenharmony_ci#define DEFINE_TORTURE_RANDOM(name) struct torture_random_state name = { 0, 0 }
7462306a36Sopenharmony_ci#define DEFINE_TORTURE_RANDOM_PERCPU(name) \
7562306a36Sopenharmony_ci	DEFINE_PER_CPU(struct torture_random_state, name)
7662306a36Sopenharmony_ciunsigned long torture_random(struct torture_random_state *trsp);
7762306a36Sopenharmony_cistatic inline void torture_random_init(struct torture_random_state *trsp)
7862306a36Sopenharmony_ci{
7962306a36Sopenharmony_ci	trsp->trs_state = 0;
8062306a36Sopenharmony_ci	trsp->trs_count = 0;
8162306a36Sopenharmony_ci}
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci/* Definitions for high-resolution-timer sleeps. */
8462306a36Sopenharmony_ciint torture_hrtimeout_ns(ktime_t baset_ns, u32 fuzzt_ns, const enum hrtimer_mode mode,
8562306a36Sopenharmony_ci			 struct torture_random_state *trsp);
8662306a36Sopenharmony_ciint torture_hrtimeout_us(u32 baset_us, u32 fuzzt_ns, struct torture_random_state *trsp);
8762306a36Sopenharmony_ciint torture_hrtimeout_ms(u32 baset_ms, u32 fuzzt_us, struct torture_random_state *trsp);
8862306a36Sopenharmony_ciint torture_hrtimeout_jiffies(u32 baset_j, struct torture_random_state *trsp);
8962306a36Sopenharmony_ciint torture_hrtimeout_s(u32 baset_s, u32 fuzzt_ms, struct torture_random_state *trsp);
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci/* Task shuffler, which causes CPUs to occasionally go idle. */
9262306a36Sopenharmony_civoid torture_shuffle_task_register(struct task_struct *tp);
9362306a36Sopenharmony_ciint torture_shuffle_init(long shuffint);
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci/* Test auto-shutdown handling. */
9662306a36Sopenharmony_civoid torture_shutdown_absorb(const char *title);
9762306a36Sopenharmony_ciint torture_shutdown_init(int ssecs, void (*cleanup)(void));
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci/* Task stuttering, which forces load/no-load transitions. */
10062306a36Sopenharmony_cibool stutter_wait(const char *title);
10162306a36Sopenharmony_ciint torture_stutter_init(int s, int sgap);
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci/* Initialization and cleanup. */
10462306a36Sopenharmony_cibool torture_init_begin(char *ttype, int v);
10562306a36Sopenharmony_civoid torture_init_end(void);
10662306a36Sopenharmony_cibool torture_cleanup_begin(void);
10762306a36Sopenharmony_civoid torture_cleanup_end(void);
10862306a36Sopenharmony_cibool torture_must_stop(void);
10962306a36Sopenharmony_cibool torture_must_stop_irq(void);
11062306a36Sopenharmony_civoid torture_kthread_stopping(char *title);
11162306a36Sopenharmony_ciint _torture_create_kthread(int (*fn)(void *arg), void *arg, char *s, char *m,
11262306a36Sopenharmony_ci			     char *f, struct task_struct **tp, void (*cbf)(struct task_struct *tp));
11362306a36Sopenharmony_civoid _torture_stop_kthread(char *m, struct task_struct **tp);
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci#define torture_create_kthread(n, arg, tp) \
11662306a36Sopenharmony_ci	_torture_create_kthread(n, (arg), #n, "Creating " #n " task", \
11762306a36Sopenharmony_ci				"Failed to create " #n, &(tp), NULL)
11862306a36Sopenharmony_ci#define torture_create_kthread_cb(n, arg, tp, cbf) \
11962306a36Sopenharmony_ci	_torture_create_kthread(n, (arg), #n, "Creating " #n " task", \
12062306a36Sopenharmony_ci				"Failed to create " #n, &(tp), cbf)
12162306a36Sopenharmony_ci#define torture_stop_kthread(n, tp) \
12262306a36Sopenharmony_ci	_torture_stop_kthread("Stopping " #n " task", &(tp))
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci#ifdef CONFIG_PREEMPTION
12562306a36Sopenharmony_ci#define torture_preempt_schedule() __preempt_schedule()
12662306a36Sopenharmony_ci#else
12762306a36Sopenharmony_ci#define torture_preempt_schedule()	do { } while (0)
12862306a36Sopenharmony_ci#endif
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci#endif /* __LINUX_TORTURE_H */
131