Blame view

kernel/rcutorture.c 63.5 KB
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1
  /*
29766f1eb   Paul E. McKenney   [PATCH] rcutortur...
2
   * Read-Copy Update module-based torture test facility
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   *
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
18
   * Copyright (C) IBM Corporation, 2005, 2006
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
19
20
   *
   * Authors: Paul E. McKenney <paulmck@us.ibm.com>
a71fca58b   Paul E. McKenney   rcu: Fix whitespa...
21
   *	  Josh Triplett <josh@freedesktop.org>
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
22
23
24
25
26
27
28
29
30
31
32
33
34
35
   *
   * See also:  Documentation/RCU/torture.txt
   */
  #include <linux/types.h>
  #include <linux/kernel.h>
  #include <linux/init.h>
  #include <linux/module.h>
  #include <linux/kthread.h>
  #include <linux/err.h>
  #include <linux/spinlock.h>
  #include <linux/smp.h>
  #include <linux/rcupdate.h>
  #include <linux/interrupt.h>
  #include <linux/sched.h>
60063497a   Arun Sharma   atomic: use <linu...
36
  #include <linux/atomic.h>
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
37
  #include <linux/bitops.h>
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
38
39
40
41
  #include <linux/completion.h>
  #include <linux/moduleparam.h>
  #include <linux/percpu.h>
  #include <linux/notifier.h>
343e9099c   Paul E. McKenney   rcu: fix rcutortu...
42
  #include <linux/reboot.h>
831441862   Rafael J. Wysocki   Freezer: make ker...
43
  #include <linux/freezer.h>
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
44
  #include <linux/cpu.h>
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
45
  #include <linux/delay.h>
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
46
  #include <linux/stat.h>
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
47
  #include <linux/srcu.h>
1aeb272cf   Robert P. J. Day   kernel: explicitl...
48
  #include <linux/slab.h>
524945351   Paul E. McKenney   rcu: Reduce rcuto...
49
  #include <linux/trace_clock.h>
f07767fd0   Harvey Harrison   byteorder: remove...
50
  #include <asm/byteorder.h>
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
51
52
  
  MODULE_LICENSE("GPL");
5cf05ad75   Paul E. McKenney   rcu: Fix broken s...
53
  MODULE_AUTHOR("Paul E. McKenney <paulmck@us.ibm.com> and Josh Triplett <josh@freedesktop.org>");
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
54

4802211cf   Josh Triplett   rcutorture: Fix i...
55
  static int nreaders = -1;	/* # reader threads, defaults to 2*ncpus */
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
56
  static int nfakewriters = 4;	/* # fake writer threads */
ab840f7a0   Paul E. McKenney   rcu: Update rcuto...
57
58
  static int stat_interval = 60;	/* Interval between stats, in seconds. */
  				/*  Zero means "only at end of test". */
d8e8ed95c   Rusty Russell   rcu: Make rcutort...
59
  static bool verbose;		/* Print more debug info. */
ab840f7a0   Paul E. McKenney   rcu: Update rcuto...
60
61
  static bool test_no_idle_hz = true;
  				/* Test RCU support for tickless idle CPUs. */
d120f65f3   Paul E. McKenney   rcu: make rcutort...
62
63
  static int shuffle_interval = 3; /* Interval between shuffles (in sec)*/
  static int stutter = 5;		/* Start/stop testing interval (in sec) */
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
64
  static int irqreader = 1;	/* RCU readers from irq (timers). */
d5f546d83   Paul E. McKenney   rcu: Add rcutortu...
65
66
  static int fqs_duration;	/* Duration of bursts (us), 0 to disable. */
  static int fqs_holdoff;		/* Hold time within burst (us). */
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
67
  static int fqs_stutter = 3;	/* Wait time between bursts (s). */
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
68
  static int n_barrier_cbs;	/* Number of callbacks to test RCU barriers. */
b58bdccaa   Paul E. McKenney   rcu: Add rcutortu...
69
  static int onoff_interval;	/* Wait time between CPU hotplugs, 0=disable. */
9b9ec9b90   Paul E. McKenney   rcutorture: Permi...
70
  static int onoff_holdoff;	/* Seconds after boot before CPU hotplugs. */
d5f546d83   Paul E. McKenney   rcu: Add rcutortu...
71
  static int shutdown_secs;	/* Shutdown time (s).  <=0 for no shutdown. */
c13f3757d   Paul E. McKenney   rcu: Add CPU-stal...
72
73
  static int stall_cpu;		/* CPU-stall duration (s).  0 for no stall. */
  static int stall_cpu_holdoff = 10; /* Time to wait until stall (s).  */
8e8be45e8   Paul E. McKenney   rcu: add priority...
74
75
76
  static int test_boost = 1;	/* Test RCU prio boost: 0=no, 1=maybe, 2=yes. */
  static int test_boost_interval = 7; /* Interval between boost tests, seconds. */
  static int test_boost_duration = 4; /* Duration of each boost test, seconds. */
20d2e4283   Josh Triplett   [PATCH] rcu: add ...
77
  static char *torture_type = "rcu"; /* What RCU implementation to torture. */
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
78

d6ad67112   Josh Triplett   [PATCH] Publish r...
79
  module_param(nreaders, int, 0444);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
80
  MODULE_PARM_DESC(nreaders, "Number of RCU reader threads");
d6ad67112   Josh Triplett   [PATCH] Publish r...
81
  module_param(nfakewriters, int, 0444);
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
82
  MODULE_PARM_DESC(nfakewriters, "Number of RCU fake writer threads");
3721bc1d3   Paul E. McKenney   rcu: Allow rcutor...
83
  module_param(stat_interval, int, 0644);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
84
  MODULE_PARM_DESC(stat_interval, "Number of seconds between stats printk()s");
d6ad67112   Josh Triplett   [PATCH] Publish r...
85
  module_param(verbose, bool, 0444);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
86
  MODULE_PARM_DESC(verbose, "Enable verbose debugging printk()s");
d6ad67112   Josh Triplett   [PATCH] Publish r...
87
  module_param(test_no_idle_hz, bool, 0444);
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
88
  MODULE_PARM_DESC(test_no_idle_hz, "Test support for tickless idle CPUs");
d6ad67112   Josh Triplett   [PATCH] Publish r...
89
  module_param(shuffle_interval, int, 0444);
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
90
  MODULE_PARM_DESC(shuffle_interval, "Number of seconds between shuffles");
d120f65f3   Paul E. McKenney   rcu: make rcutort...
91
92
  module_param(stutter, int, 0444);
  MODULE_PARM_DESC(stutter, "Number of seconds to run/halt test");
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
93
94
  module_param(irqreader, int, 0444);
  MODULE_PARM_DESC(irqreader, "Allow RCU readers from irq handlers");
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
95
96
97
98
99
100
  module_param(fqs_duration, int, 0444);
  MODULE_PARM_DESC(fqs_duration, "Duration of fqs bursts (us)");
  module_param(fqs_holdoff, int, 0444);
  MODULE_PARM_DESC(fqs_holdoff, "Holdoff time within fqs bursts (us)");
  module_param(fqs_stutter, int, 0444);
  MODULE_PARM_DESC(fqs_stutter, "Wait time between fqs bursts (s)");
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
101
102
  module_param(n_barrier_cbs, int, 0444);
  MODULE_PARM_DESC(n_barrier_cbs, "# of callbacks/kthreads for barrier testing");
b58bdccaa   Paul E. McKenney   rcu: Add rcutortu...
103
104
  module_param(onoff_interval, int, 0444);
  MODULE_PARM_DESC(onoff_interval, "Time between CPU hotplugs (s), 0=disable");
9b9ec9b90   Paul E. McKenney   rcutorture: Permi...
105
106
  module_param(onoff_holdoff, int, 0444);
  MODULE_PARM_DESC(onoff_holdoff, "Time after boot before CPU hotplugs (s)");
d5f546d83   Paul E. McKenney   rcu: Add rcutortu...
107
108
  module_param(shutdown_secs, int, 0444);
  MODULE_PARM_DESC(shutdown_secs, "Shutdown time (s), zero to disable.");
c13f3757d   Paul E. McKenney   rcu: Add CPU-stal...
109
110
111
112
  module_param(stall_cpu, int, 0444);
  MODULE_PARM_DESC(stall_cpu, "Stall duration (s), zero to disable.");
  module_param(stall_cpu_holdoff, int, 0444);
  MODULE_PARM_DESC(stall_cpu_holdoff, "Time to wait before starting stall (s).");
8e8be45e8   Paul E. McKenney   rcu: add priority...
113
114
115
116
117
118
  module_param(test_boost, int, 0444);
  MODULE_PARM_DESC(test_boost, "Test RCU prio boost: 0=no, 1=maybe, 2=yes.");
  module_param(test_boost_interval, int, 0444);
  MODULE_PARM_DESC(test_boost_interval, "Interval between boost tests, seconds.");
  module_param(test_boost_duration, int, 0444);
  MODULE_PARM_DESC(test_boost_duration, "Duration of each boost test, seconds.");
d6ad67112   Josh Triplett   [PATCH] Publish r...
119
  module_param(torture_type, charp, 0444);
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
120
  MODULE_PARM_DESC(torture_type, "Type of RCU to torture (rcu, rcu_bh, srcu)");
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
121
122
  
  #define TORTURE_FLAG "-torture:"
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
123
  #define PRINTK_STRING(s) \
2caa1e443   Paul E. McKenney   rcu: Switch rcuto...
124
125
  	do { pr_alert("%s" TORTURE_FLAG s "
  ", torture_type); } while (0)
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
126
  #define VERBOSE_PRINTK_STRING(s) \
2caa1e443   Paul E. McKenney   rcu: Switch rcuto...
127
128
  	do { if (verbose) pr_alert("%s" TORTURE_FLAG s "
  ", torture_type); } while (0)
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
129
  #define VERBOSE_PRINTK_ERRSTRING(s) \
2caa1e443   Paul E. McKenney   rcu: Switch rcuto...
130
131
  	do { if (verbose) pr_alert("%s" TORTURE_FLAG "!!! " s "
  ", torture_type); } while (0)
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
132
133
134
135
136
  
  static char printk_buf[4096];
  
  static int nrealreaders;
  static struct task_struct *writer_task;
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
137
  static struct task_struct **fakewriter_tasks;
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
138
139
  static struct task_struct **reader_tasks;
  static struct task_struct *stats_task;
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
140
  static struct task_struct *shuffler_task;
d120f65f3   Paul E. McKenney   rcu: make rcutort...
141
  static struct task_struct *stutter_task;
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
142
  static struct task_struct *fqs_task;
8e8be45e8   Paul E. McKenney   rcu: add priority...
143
  static struct task_struct *boost_tasks[NR_CPUS];
d5f546d83   Paul E. McKenney   rcu: Add rcutortu...
144
  static struct task_struct *shutdown_task;
b58bdccaa   Paul E. McKenney   rcu: Add rcutortu...
145
146
147
  #ifdef CONFIG_HOTPLUG_CPU
  static struct task_struct *onoff_task;
  #endif /* #ifdef CONFIG_HOTPLUG_CPU */
c13f3757d   Paul E. McKenney   rcu: Add CPU-stal...
148
  static struct task_struct *stall_task;
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
149
150
  static struct task_struct **barrier_cbs_tasks;
  static struct task_struct *barrier_task;
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
151
152
153
154
155
156
157
  
  #define RCU_TORTURE_PIPE_LEN 10
  
  struct rcu_torture {
  	struct rcu_head rtort_rcu;
  	int rtort_pipe_count;
  	struct list_head rtort_free;
996417d2c   Paul E. McKenney   [PATCH] add succe...
158
  	int rtort_mbtest;
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
159
  };
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
160
  static LIST_HEAD(rcu_torture_freelist);
0ddea0ead   Paul E. McKenney   rcu: fix sparse e...
161
  static struct rcu_torture __rcu *rcu_torture_current;
4a2986568   Paul E. McKenney   rcu: make rcutort...
162
  static unsigned long rcu_torture_current_version;
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
163
164
165
166
167
168
169
  static struct rcu_torture rcu_tortures[10 * RCU_TORTURE_PIPE_LEN];
  static DEFINE_SPINLOCK(rcu_torture_lock);
  static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_count) =
  	{ 0 };
  static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_batch) =
  	{ 0 };
  static atomic_t rcu_torture_wcount[RCU_TORTURE_PIPE_LEN + 1];
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
170
171
172
173
174
  static atomic_t n_rcu_torture_alloc;
  static atomic_t n_rcu_torture_alloc_fail;
  static atomic_t n_rcu_torture_free;
  static atomic_t n_rcu_torture_mberror;
  static atomic_t n_rcu_torture_error;
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
175
  static long n_rcu_torture_barrier_error;
8e8be45e8   Paul E. McKenney   rcu: add priority...
176
177
  static long n_rcu_torture_boost_ktrerror;
  static long n_rcu_torture_boost_rterror;
8e8be45e8   Paul E. McKenney   rcu: add priority...
178
179
  static long n_rcu_torture_boost_failure;
  static long n_rcu_torture_boosts;
a71fca58b   Paul E. McKenney   rcu: Fix whitespa...
180
  static long n_rcu_torture_timers;
b58bdccaa   Paul E. McKenney   rcu: Add rcutortu...
181
182
  static long n_offline_attempts;
  static long n_offline_successes;
13dbf9140   Paul E. McKenney   rcu: Track CPU-ho...
183
184
185
  static unsigned long sum_offline;
  static int min_offline = -1;
  static int max_offline;
b58bdccaa   Paul E. McKenney   rcu: Add rcutortu...
186
187
  static long n_online_attempts;
  static long n_online_successes;
13dbf9140   Paul E. McKenney   rcu: Track CPU-ho...
188
189
190
  static unsigned long sum_online;
  static int min_online = -1;
  static int max_online;
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
191
192
  static long n_barrier_attempts;
  static long n_barrier_successes;
e30337365   Josh Triplett   [PATCH] rcu: refa...
193
  static struct list_head rcu_torture_removed;
73d0a4b10   Rusty Russell   cpumask: convert ...
194
  static cpumask_var_t shuffle_tmp_mask;
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
195

a71fca58b   Paul E. McKenney   rcu: Fix whitespa...
196
  static int stutter_pause_test;
d120f65f3   Paul E. McKenney   rcu: make rcutort...
197

31a72bce0   Paul E. McKenney   rcu: make rcutort...
198
199
200
201
202
203
  #if defined(MODULE) || defined(CONFIG_RCU_TORTURE_TEST_RUNNABLE)
  #define RCUTORTURE_RUNNABLE_INIT 1
  #else
  #define RCUTORTURE_RUNNABLE_INIT 0
  #endif
  int rcutorture_runnable = RCUTORTURE_RUNNABLE_INIT;
bb3bf7052   Paul E. McKenney   rcu: Control rcut...
204
205
  module_param(rcutorture_runnable, int, 0444);
  MODULE_PARM_DESC(rcutorture_runnable, "Start rcutorture at boot");
31a72bce0   Paul E. McKenney   rcu: make rcutort...
206

3acf4a9a3   Paul E. McKenney   rcu: avoid hammer...
207
  #if defined(CONFIG_RCU_BOOST) && !defined(CONFIG_HOTPLUG_CPU)
8e8be45e8   Paul E. McKenney   rcu: add priority...
208
  #define rcu_can_boost() 1
3acf4a9a3   Paul E. McKenney   rcu: avoid hammer...
209
  #else /* #if defined(CONFIG_RCU_BOOST) && !defined(CONFIG_HOTPLUG_CPU) */
8e8be45e8   Paul E. McKenney   rcu: add priority...
210
  #define rcu_can_boost() 0
3acf4a9a3   Paul E. McKenney   rcu: avoid hammer...
211
  #endif /* #else #if defined(CONFIG_RCU_BOOST) && !defined(CONFIG_HOTPLUG_CPU) */
8e8be45e8   Paul E. McKenney   rcu: add priority...
212

e4aa0da39   Steven Rostedt   rcu: Allow rcutor...
213
214
215
216
217
218
219
220
221
222
223
224
225
  #ifdef CONFIG_RCU_TRACE
  static u64 notrace rcu_trace_clock_local(void)
  {
  	u64 ts = trace_clock_local();
  	unsigned long __maybe_unused ts_rem = do_div(ts, NSEC_PER_USEC);
  	return ts;
  }
  #else /* #ifdef CONFIG_RCU_TRACE */
  static u64 notrace rcu_trace_clock_local(void)
  {
  	return 0ULL;
  }
  #endif /* #else #ifdef CONFIG_RCU_TRACE */
d5f546d83   Paul E. McKenney   rcu: Add rcutortu...
226
  static unsigned long shutdown_time;	/* jiffies to system shutdown. */
8e8be45e8   Paul E. McKenney   rcu: add priority...
227
228
229
  static unsigned long boost_starttime;	/* jiffies of next boost test start. */
  DEFINE_MUTEX(boost_mutex);		/* protect setting boost_starttime */
  					/*  and boost task create/destroy. */
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
230
  static atomic_t barrier_cbs_count;	/* Barrier callbacks registered. */
c6ebcbb60   Paul E. McKenney   rcu: Fix bug in r...
231
  static bool barrier_phase;		/* Test phase. */
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
232
233
234
  static atomic_t barrier_cbs_invoked;	/* Barrier callbacks invoked. */
  static wait_queue_head_t *barrier_cbs_wq; /* Coordinate barrier testing. */
  static DECLARE_WAIT_QUEUE_HEAD(barrier_wq);
8e8be45e8   Paul E. McKenney   rcu: add priority...
235

c9d557c19   Paul E. McKenney   rcu: fix bug in r...
236
237
238
239
240
241
  /* Mediate rmmod and system shutdown.  Concurrent rmmod & shutdown illegal! */
  
  #define FULLSTOP_DONTSTOP 0	/* Normal operation. */
  #define FULLSTOP_SHUTDOWN 1	/* System shutdown with rcutorture running. */
  #define FULLSTOP_RMMOD    2	/* Normal rmmod of rcutorture. */
  static int fullstop = FULLSTOP_RMMOD;
0ddea0ead   Paul E. McKenney   rcu: fix sparse e...
242
243
244
245
  /*
   * Protect fullstop transitions and spawning of kthreads.
   */
  static DEFINE_MUTEX(fullstop_mutex);
343e9099c   Paul E. McKenney   rcu: fix rcutortu...
246

d5f546d83   Paul E. McKenney   rcu: Add rcutortu...
247
248
  /* Forward reference. */
  static void rcu_torture_cleanup(void);
343e9099c   Paul E. McKenney   rcu: fix rcutortu...
249
  /*
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
250
   * Detect and respond to a system shutdown.
343e9099c   Paul E. McKenney   rcu: fix rcutortu...
251
252
253
254
255
   */
  static int
  rcutorture_shutdown_notify(struct notifier_block *unused1,
  			   unsigned long unused2, void *unused3)
  {
c59ab97e9   Paul E. McKenney   rcu: fix rcutortu...
256
  	mutex_lock(&fullstop_mutex);
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
257
  	if (fullstop == FULLSTOP_DONTSTOP)
c59ab97e9   Paul E. McKenney   rcu: fix rcutortu...
258
  		fullstop = FULLSTOP_SHUTDOWN;
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
259
  	else
2caa1e443   Paul E. McKenney   rcu: Switch rcuto...
260
  		pr_warn(/* but going down anyway, so... */
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
261
262
  		       "Concurrent 'rmmod rcutorture' and shutdown illegal!
  ");
c59ab97e9   Paul E. McKenney   rcu: fix rcutortu...
263
  	mutex_unlock(&fullstop_mutex);
343e9099c   Paul E. McKenney   rcu: fix rcutortu...
264
265
  	return NOTIFY_DONE;
  }
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
266
  /*
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
267
268
269
270
271
272
   * Absorb kthreads into a kernel function that won't return, so that
   * they won't ever access module text or data again.
   */
  static void rcutorture_shutdown_absorb(char *title)
  {
  	if (ACCESS_ONCE(fullstop) == FULLSTOP_SHUTDOWN) {
2caa1e443   Paul E. McKenney   rcu: Switch rcuto...
273
  		pr_notice(
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
274
275
276
277
278
279
280
281
  		       "rcutorture thread %s parking due to system shutdown
  ",
  		       title);
  		schedule_timeout_uninterruptible(MAX_SCHEDULE_TIMEOUT);
  	}
  }
  
  /*
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
282
283
   * Allocate an element from the rcu_tortures pool.
   */
97a41e261   Adrian Bunk   [PATCH] kernel/: ...
284
  static struct rcu_torture *
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
285
286
287
  rcu_torture_alloc(void)
  {
  	struct list_head *p;
adac16652   Ingo Molnar   [PATCH] rcu_tortu...
288
  	spin_lock_bh(&rcu_torture_lock);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
289
290
  	if (list_empty(&rcu_torture_freelist)) {
  		atomic_inc(&n_rcu_torture_alloc_fail);
adac16652   Ingo Molnar   [PATCH] rcu_tortu...
291
  		spin_unlock_bh(&rcu_torture_lock);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
292
293
294
295
296
  		return NULL;
  	}
  	atomic_inc(&n_rcu_torture_alloc);
  	p = rcu_torture_freelist.next;
  	list_del_init(p);
adac16652   Ingo Molnar   [PATCH] rcu_tortu...
297
  	spin_unlock_bh(&rcu_torture_lock);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
298
299
300
301
302
303
304
305
306
307
  	return container_of(p, struct rcu_torture, rtort_free);
  }
  
  /*
   * Free an element to the rcu_tortures pool.
   */
  static void
  rcu_torture_free(struct rcu_torture *p)
  {
  	atomic_inc(&n_rcu_torture_free);
adac16652   Ingo Molnar   [PATCH] rcu_tortu...
308
  	spin_lock_bh(&rcu_torture_lock);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
309
  	list_add_tail(&p->rtort_free, &rcu_torture_freelist);
adac16652   Ingo Molnar   [PATCH] rcu_tortu...
310
  	spin_unlock_bh(&rcu_torture_lock);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
311
  }
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
312
313
  struct rcu_random_state {
  	unsigned long rrs_state;
75cfef32f   Josh Triplett   [PATCH] rcu: Fix ...
314
  	long rrs_count;
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
315
316
317
318
319
320
321
322
323
324
  };
  
  #define RCU_RANDOM_MULT 39916801  /* prime */
  #define RCU_RANDOM_ADD	479001701 /* prime */
  #define RCU_RANDOM_REFRESH 10000
  
  #define DEFINE_RCU_RANDOM(name) struct rcu_random_state name = { 0, 0 }
  
  /*
   * Crude but fast random-number generator.  Uses a linear congruential
c17ac8550   Paul E. McKenney   Make rcutorture R...
325
   * generator, with occasional help from cpu_clock().
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
326
   */
75cfef32f   Josh Triplett   [PATCH] rcu: Fix ...
327
  static unsigned long
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
328
329
  rcu_random(struct rcu_random_state *rrsp)
  {
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
330
  	if (--rrsp->rrs_count < 0) {
c676329ab   Peter Zijlstra   sched_clock: Add ...
331
  		rrsp->rrs_state += (unsigned long)local_clock();
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
332
333
334
335
336
  		rrsp->rrs_count = RCU_RANDOM_REFRESH;
  	}
  	rrsp->rrs_state = rrsp->rrs_state * RCU_RANDOM_MULT + RCU_RANDOM_ADD;
  	return swahw32(rrsp->rrs_state);
  }
d120f65f3   Paul E. McKenney   rcu: make rcutort...
337
  static void
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
338
  rcu_stutter_wait(char *title)
d120f65f3   Paul E. McKenney   rcu: make rcutort...
339
  {
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
340
  	while (stutter_pause_test || !rcutorture_runnable) {
e3d7be270   Paul E. McKenney   rcu, rcutorture: ...
341
342
343
  		if (rcutorture_runnable)
  			schedule_timeout_interruptible(1);
  		else
3ccf79f45   Paul E. McKenney   rcu: make quiesce...
344
  			schedule_timeout_interruptible(round_jiffies_relative(HZ));
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
345
  		rcutorture_shutdown_absorb(title);
343e9099c   Paul E. McKenney   rcu: fix rcutortu...
346
  	}
d120f65f3   Paul E. McKenney   rcu: make rcutort...
347
  }
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
348
  /*
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
349
350
351
352
353
   * Operations vector for selecting different types of tests.
   */
  
  struct rcu_torture_ops {
  	void (*init)(void);
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
354
  	int (*readlock)(void);
0acc512cb   Paul E. McKenney   rcu: Add synchron...
355
  	void (*read_delay)(struct rcu_random_state *rrsp);
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
356
357
  	void (*readunlock)(int idx);
  	int (*completed)(void);
0acc512cb   Paul E. McKenney   rcu: Add synchron...
358
  	void (*deferred_free)(struct rcu_torture *p);
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
359
  	void (*sync)(void);
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
360
  	void (*call)(struct rcu_head *head, void (*func)(struct rcu_head *rcu));
2326974df   Paul E. McKenney   rcu: add call_rcu...
361
  	void (*cb_barrier)(void);
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
362
  	void (*fqs)(void);
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
363
  	int (*stats)(char *page);
0acc512cb   Paul E. McKenney   rcu: Add synchron...
364
  	int irq_capable;
8e8be45e8   Paul E. McKenney   rcu: add priority...
365
  	int can_boost;
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
366
367
  	char *name;
  };
a71fca58b   Paul E. McKenney   rcu: Fix whitespa...
368
369
  
  static struct rcu_torture_ops *cur_ops;
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
370
371
372
373
  
  /*
   * Definitions for rcu torture testing.
   */
a49a4af75   Josh Triplett   [PATCH] rcu: add ...
374
  static int rcu_torture_read_lock(void) __acquires(RCU)
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
375
376
377
378
  {
  	rcu_read_lock();
  	return 0;
  }
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
379
380
  static void rcu_read_delay(struct rcu_random_state *rrsp)
  {
b8d57a76d   Josh Triplett   rcutorture: Occas...
381
382
  	const unsigned long shortdelay_us = 200;
  	const unsigned long longdelay_ms = 50;
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
383

b8d57a76d   Josh Triplett   rcutorture: Occas...
384
385
386
  	/* We want a short delay sometimes to make a reader delay the grace
  	 * period, and we want a long delay occasionally to trigger
  	 * force_quiescent_state. */
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
387

b8d57a76d   Josh Triplett   rcutorture: Occas...
388
389
390
391
  	if (!(rcu_random(rrsp) % (nrealreaders * 2000 * longdelay_ms)))
  		mdelay(longdelay_ms);
  	if (!(rcu_random(rrsp) % (nrealreaders * 2 * shortdelay_us)))
  		udelay(shortdelay_us);
e546f485e   Lai Jiangshan   rcutorture: add r...
392
393
394
395
  #ifdef CONFIG_PREEMPT
  	if (!preempt_count() && !(rcu_random(rrsp) % (nrealreaders * 20000)))
  		preempt_schedule();  /* No QS if preempt_disable() in effect */
  #endif
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
396
  }
a49a4af75   Josh Triplett   [PATCH] rcu: add ...
397
  static void rcu_torture_read_unlock(int idx) __releases(RCU)
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
398
399
400
401
402
403
404
405
406
407
408
409
410
411
  {
  	rcu_read_unlock();
  }
  
  static int rcu_torture_completed(void)
  {
  	return rcu_batches_completed();
  }
  
  static void
  rcu_torture_cb(struct rcu_head *p)
  {
  	int i;
  	struct rcu_torture *rp = container_of(p, struct rcu_torture, rtort_rcu);
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
412
  	if (fullstop != FULLSTOP_DONTSTOP) {
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
413
414
415
416
417
418
419
420
421
422
423
  		/* Test is ending, just drop callbacks on the floor. */
  		/* The next initialization will pick up the pieces. */
  		return;
  	}
  	i = rp->rtort_pipe_count;
  	if (i > RCU_TORTURE_PIPE_LEN)
  		i = RCU_TORTURE_PIPE_LEN;
  	atomic_inc(&rcu_torture_wcount[i]);
  	if (++rp->rtort_pipe_count >= RCU_TORTURE_PIPE_LEN) {
  		rp->rtort_mbtest = 0;
  		rcu_torture_free(rp);
c701d5d9b   Paul E. McKenney   rcu: Fix code-sty...
424
  	} else {
0acc512cb   Paul E. McKenney   rcu: Add synchron...
425
  		cur_ops->deferred_free(rp);
c701d5d9b   Paul E. McKenney   rcu: Fix code-sty...
426
  	}
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
427
  }
d9a3da069   Paul E. McKenney   rcu: Add expedite...
428
429
430
431
  static int rcu_no_completed(void)
  {
  	return 0;
  }
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
432
433
434
435
436
437
  static void rcu_torture_deferred_free(struct rcu_torture *p)
  {
  	call_rcu(&p->rtort_rcu, rcu_torture_cb);
  }
  
  static struct rcu_torture_ops rcu_ops = {
0acc512cb   Paul E. McKenney   rcu: Add synchron...
438
  	.init		= NULL,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
439
440
441
442
443
444
  	.readlock	= rcu_torture_read_lock,
  	.read_delay	= rcu_read_delay,
  	.readunlock	= rcu_torture_read_unlock,
  	.completed	= rcu_torture_completed,
  	.deferred_free	= rcu_torture_deferred_free,
  	.sync		= synchronize_rcu,
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
445
  	.call		= call_rcu,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
446
  	.cb_barrier	= rcu_barrier,
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
447
  	.fqs		= rcu_force_quiescent_state,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
448
  	.stats		= NULL,
a71fca58b   Paul E. McKenney   rcu: Fix whitespa...
449
  	.irq_capable	= 1,
8e8be45e8   Paul E. McKenney   rcu: add priority...
450
  	.can_boost	= rcu_can_boost(),
a71fca58b   Paul E. McKenney   rcu: Fix whitespa...
451
  	.name		= "rcu"
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
452
  };
e30337365   Josh Triplett   [PATCH] rcu: refa...
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
  static void rcu_sync_torture_deferred_free(struct rcu_torture *p)
  {
  	int i;
  	struct rcu_torture *rp;
  	struct rcu_torture *rp1;
  
  	cur_ops->sync();
  	list_add(&p->rtort_free, &rcu_torture_removed);
  	list_for_each_entry_safe(rp, rp1, &rcu_torture_removed, rtort_free) {
  		i = rp->rtort_pipe_count;
  		if (i > RCU_TORTURE_PIPE_LEN)
  			i = RCU_TORTURE_PIPE_LEN;
  		atomic_inc(&rcu_torture_wcount[i]);
  		if (++rp->rtort_pipe_count >= RCU_TORTURE_PIPE_LEN) {
  			rp->rtort_mbtest = 0;
  			list_del(&rp->rtort_free);
  			rcu_torture_free(rp);
  		}
  	}
  }
  
  static void rcu_sync_torture_init(void)
  {
  	INIT_LIST_HEAD(&rcu_torture_removed);
  }
20d2e4283   Josh Triplett   [PATCH] rcu: add ...
478
  static struct rcu_torture_ops rcu_sync_ops = {
0acc512cb   Paul E. McKenney   rcu: Add synchron...
479
  	.init		= rcu_sync_torture_init,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
480
481
482
483
484
485
  	.readlock	= rcu_torture_read_lock,
  	.read_delay	= rcu_read_delay,
  	.readunlock	= rcu_torture_read_unlock,
  	.completed	= rcu_torture_completed,
  	.deferred_free	= rcu_sync_torture_deferred_free,
  	.sync		= synchronize_rcu,
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
486
  	.call		= NULL,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
487
  	.cb_barrier	= NULL,
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
488
  	.fqs		= rcu_force_quiescent_state,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
489
490
  	.stats		= NULL,
  	.irq_capable	= 1,
8e8be45e8   Paul E. McKenney   rcu: add priority...
491
  	.can_boost	= rcu_can_boost(),
0acc512cb   Paul E. McKenney   rcu: Add synchron...
492
  	.name		= "rcu_sync"
20d2e4283   Josh Triplett   [PATCH] rcu: add ...
493
  };
d9a3da069   Paul E. McKenney   rcu: Add expedite...
494
495
  static struct rcu_torture_ops rcu_expedited_ops = {
  	.init		= rcu_sync_torture_init,
d9a3da069   Paul E. McKenney   rcu: Add expedite...
496
497
498
499
500
501
  	.readlock	= rcu_torture_read_lock,
  	.read_delay	= rcu_read_delay,  /* just reuse rcu's version. */
  	.readunlock	= rcu_torture_read_unlock,
  	.completed	= rcu_no_completed,
  	.deferred_free	= rcu_sync_torture_deferred_free,
  	.sync		= synchronize_rcu_expedited,
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
502
  	.call		= NULL,
d9a3da069   Paul E. McKenney   rcu: Add expedite...
503
  	.cb_barrier	= NULL,
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
504
  	.fqs		= rcu_force_quiescent_state,
d9a3da069   Paul E. McKenney   rcu: Add expedite...
505
506
  	.stats		= NULL,
  	.irq_capable	= 1,
8e8be45e8   Paul E. McKenney   rcu: add priority...
507
  	.can_boost	= rcu_can_boost(),
d9a3da069   Paul E. McKenney   rcu: Add expedite...
508
509
  	.name		= "rcu_expedited"
  };
c32e06605   Paul E. McKenney   [PATCH] rcutortur...
510
511
512
  /*
   * Definitions for rcu_bh torture testing.
   */
a49a4af75   Josh Triplett   [PATCH] rcu: add ...
513
  static int rcu_bh_torture_read_lock(void) __acquires(RCU_BH)
c32e06605   Paul E. McKenney   [PATCH] rcutortur...
514
515
516
517
  {
  	rcu_read_lock_bh();
  	return 0;
  }
a49a4af75   Josh Triplett   [PATCH] rcu: add ...
518
  static void rcu_bh_torture_read_unlock(int idx) __releases(RCU_BH)
c32e06605   Paul E. McKenney   [PATCH] rcutortur...
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
  {
  	rcu_read_unlock_bh();
  }
  
  static int rcu_bh_torture_completed(void)
  {
  	return rcu_batches_completed_bh();
  }
  
  static void rcu_bh_torture_deferred_free(struct rcu_torture *p)
  {
  	call_rcu_bh(&p->rtort_rcu, rcu_torture_cb);
  }
  
  static struct rcu_torture_ops rcu_bh_ops = {
0acc512cb   Paul E. McKenney   rcu: Add synchron...
534
  	.init		= NULL,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
535
536
537
538
539
  	.readlock	= rcu_bh_torture_read_lock,
  	.read_delay	= rcu_read_delay,  /* just reuse rcu's version. */
  	.readunlock	= rcu_bh_torture_read_unlock,
  	.completed	= rcu_bh_torture_completed,
  	.deferred_free	= rcu_bh_torture_deferred_free,
bdf2a4364   Paul E. McKenney   rcu: Catch rcutor...
540
  	.sync		= synchronize_rcu_bh,
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
541
  	.call		= call_rcu_bh,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
542
  	.cb_barrier	= rcu_barrier_bh,
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
543
  	.fqs		= rcu_bh_force_quiescent_state,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
544
545
546
  	.stats		= NULL,
  	.irq_capable	= 1,
  	.name		= "rcu_bh"
c32e06605   Paul E. McKenney   [PATCH] rcutortur...
547
  };
11a147013   Josh Triplett   [PATCH] rcu: add ...
548
  static struct rcu_torture_ops rcu_bh_sync_ops = {
0acc512cb   Paul E. McKenney   rcu: Add synchron...
549
  	.init		= rcu_sync_torture_init,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
550
551
552
553
554
  	.readlock	= rcu_bh_torture_read_lock,
  	.read_delay	= rcu_read_delay,  /* just reuse rcu's version. */
  	.readunlock	= rcu_bh_torture_read_unlock,
  	.completed	= rcu_bh_torture_completed,
  	.deferred_free	= rcu_sync_torture_deferred_free,
bdf2a4364   Paul E. McKenney   rcu: Catch rcutor...
555
  	.sync		= synchronize_rcu_bh,
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
556
  	.call		= NULL,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
557
  	.cb_barrier	= NULL,
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
558
  	.fqs		= rcu_bh_force_quiescent_state,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
559
560
561
  	.stats		= NULL,
  	.irq_capable	= 1,
  	.name		= "rcu_bh_sync"
11a147013   Josh Triplett   [PATCH] rcu: add ...
562
  };
bdf2a4364   Paul E. McKenney   rcu: Catch rcutor...
563
564
  static struct rcu_torture_ops rcu_bh_expedited_ops = {
  	.init		= rcu_sync_torture_init,
bdf2a4364   Paul E. McKenney   rcu: Catch rcutor...
565
566
567
568
569
570
  	.readlock	= rcu_bh_torture_read_lock,
  	.read_delay	= rcu_read_delay,  /* just reuse rcu's version. */
  	.readunlock	= rcu_bh_torture_read_unlock,
  	.completed	= rcu_bh_torture_completed,
  	.deferred_free	= rcu_sync_torture_deferred_free,
  	.sync		= synchronize_rcu_bh_expedited,
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
571
  	.call		= NULL,
bdf2a4364   Paul E. McKenney   rcu: Catch rcutor...
572
573
574
575
576
577
  	.cb_barrier	= NULL,
  	.fqs		= rcu_bh_force_quiescent_state,
  	.stats		= NULL,
  	.irq_capable	= 1,
  	.name		= "rcu_bh_expedited"
  };
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
578
579
580
  /*
   * Definitions for srcu torture testing.
   */
cda4dc813   Lai Jiangshan   rcutorture: Use D...
581
  DEFINE_STATIC_SRCU(srcu_ctl);
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
582

012d3ca8d   Josh Triplett   [PATCH] Add Spars...
583
  static int srcu_torture_read_lock(void) __acquires(&srcu_ctl)
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
  {
  	return srcu_read_lock(&srcu_ctl);
  }
  
  static void srcu_read_delay(struct rcu_random_state *rrsp)
  {
  	long delay;
  	const long uspertick = 1000000 / HZ;
  	const long longdelay = 10;
  
  	/* We want there to be long-running readers, but not all the time. */
  
  	delay = rcu_random(rrsp) % (nrealreaders * 2 * longdelay * uspertick);
  	if (!delay)
  		schedule_timeout_interruptible(longdelay);
e546f485e   Lai Jiangshan   rcutorture: add r...
599
600
  	else
  		rcu_read_delay(rrsp);
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
601
  }
012d3ca8d   Josh Triplett   [PATCH] Add Spars...
602
  static void srcu_torture_read_unlock(int idx) __releases(&srcu_ctl)
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
603
604
605
606
607
608
609
610
  {
  	srcu_read_unlock(&srcu_ctl, idx);
  }
  
  static int srcu_torture_completed(void)
  {
  	return srcu_batches_completed(&srcu_ctl);
  }
9059c9401   Lai Jiangshan   rcu: Add rcutortu...
611
612
613
614
  static void srcu_torture_deferred_free(struct rcu_torture *rp)
  {
  	call_srcu(&srcu_ctl, &rp->rtort_rcu, rcu_torture_cb);
  }
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
615
616
617
618
  static void srcu_torture_synchronize(void)
  {
  	synchronize_srcu(&srcu_ctl);
  }
e3f8d3788   Paul E. McKenney   rcu: Test srcu_ba...
619
620
621
622
623
624
625
626
627
628
  static void srcu_torture_call(struct rcu_head *head,
  			      void (*func)(struct rcu_head *head))
  {
  	call_srcu(&srcu_ctl, head, func);
  }
  
  static void srcu_torture_barrier(void)
  {
  	srcu_barrier(&srcu_ctl);
  }
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
629
630
631
632
633
634
635
636
637
  static int srcu_torture_stats(char *page)
  {
  	int cnt = 0;
  	int cpu;
  	int idx = srcu_ctl.completed & 0x1;
  
  	cnt += sprintf(&page[cnt], "%s%s per-CPU(idx=%d):",
  		       torture_type, TORTURE_FLAG, idx);
  	for_each_possible_cpu(cpu) {
cef50120b   Paul E. McKenney   rcu: Direct algor...
638
  		cnt += sprintf(&page[cnt], " %d(%lu,%lu)", cpu,
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
639
640
641
642
643
644
645
646
647
  			       per_cpu_ptr(srcu_ctl.per_cpu_ref, cpu)->c[!idx],
  			       per_cpu_ptr(srcu_ctl.per_cpu_ref, cpu)->c[idx]);
  	}
  	cnt += sprintf(&page[cnt], "
  ");
  	return cnt;
  }
  
  static struct rcu_torture_ops srcu_ops = {
cda4dc813   Lai Jiangshan   rcutorture: Use D...
648
  	.init		= rcu_sync_torture_init,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
649
650
651
652
  	.readlock	= srcu_torture_read_lock,
  	.read_delay	= srcu_read_delay,
  	.readunlock	= srcu_torture_read_unlock,
  	.completed	= srcu_torture_completed,
9059c9401   Lai Jiangshan   rcu: Add rcutortu...
653
  	.deferred_free	= srcu_torture_deferred_free,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
654
  	.sync		= srcu_torture_synchronize,
e3f8d3788   Paul E. McKenney   rcu: Test srcu_ba...
655
656
  	.call		= srcu_torture_call,
  	.cb_barrier	= srcu_torture_barrier,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
657
658
  	.stats		= srcu_torture_stats,
  	.name		= "srcu"
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
659
  };
9059c9401   Lai Jiangshan   rcu: Add rcutortu...
660
  static struct rcu_torture_ops srcu_sync_ops = {
cda4dc813   Lai Jiangshan   rcutorture: Use D...
661
  	.init		= rcu_sync_torture_init,
9059c9401   Lai Jiangshan   rcu: Add rcutortu...
662
663
664
665
666
667
668
669
670
671
672
  	.readlock	= srcu_torture_read_lock,
  	.read_delay	= srcu_read_delay,
  	.readunlock	= srcu_torture_read_unlock,
  	.completed	= srcu_torture_completed,
  	.deferred_free	= rcu_sync_torture_deferred_free,
  	.sync		= srcu_torture_synchronize,
  	.call		= NULL,
  	.cb_barrier	= NULL,
  	.stats		= srcu_torture_stats,
  	.name		= "srcu_sync"
  };
101db7b41   Paul E. McKenney   rcu: Add rcutortu...
673
674
675
676
677
678
679
680
681
682
683
  static int srcu_torture_read_lock_raw(void) __acquires(&srcu_ctl)
  {
  	return srcu_read_lock_raw(&srcu_ctl);
  }
  
  static void srcu_torture_read_unlock_raw(int idx) __releases(&srcu_ctl)
  {
  	srcu_read_unlock_raw(&srcu_ctl, idx);
  }
  
  static struct rcu_torture_ops srcu_raw_ops = {
cda4dc813   Lai Jiangshan   rcutorture: Use D...
684
  	.init		= rcu_sync_torture_init,
101db7b41   Paul E. McKenney   rcu: Add rcutortu...
685
686
687
688
  	.readlock	= srcu_torture_read_lock_raw,
  	.read_delay	= srcu_read_delay,
  	.readunlock	= srcu_torture_read_unlock_raw,
  	.completed	= srcu_torture_completed,
9059c9401   Lai Jiangshan   rcu: Add rcutortu...
689
  	.deferred_free	= srcu_torture_deferred_free,
101db7b41   Paul E. McKenney   rcu: Add rcutortu...
690
  	.sync		= srcu_torture_synchronize,
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
691
  	.call		= NULL,
101db7b41   Paul E. McKenney   rcu: Add rcutortu...
692
693
694
695
  	.cb_barrier	= NULL,
  	.stats		= srcu_torture_stats,
  	.name		= "srcu_raw"
  };
9059c9401   Lai Jiangshan   rcu: Add rcutortu...
696
  static struct rcu_torture_ops srcu_raw_sync_ops = {
cda4dc813   Lai Jiangshan   rcutorture: Use D...
697
  	.init		= rcu_sync_torture_init,
9059c9401   Lai Jiangshan   rcu: Add rcutortu...
698
699
700
701
702
703
704
705
706
707
708
  	.readlock	= srcu_torture_read_lock_raw,
  	.read_delay	= srcu_read_delay,
  	.readunlock	= srcu_torture_read_unlock_raw,
  	.completed	= srcu_torture_completed,
  	.deferred_free	= rcu_sync_torture_deferred_free,
  	.sync		= srcu_torture_synchronize,
  	.call		= NULL,
  	.cb_barrier	= NULL,
  	.stats		= srcu_torture_stats,
  	.name		= "srcu_raw_sync"
  };
804bb8370   Paul E. McKenney   rcu: Add synchron...
709
710
711
712
713
714
  static void srcu_torture_synchronize_expedited(void)
  {
  	synchronize_srcu_expedited(&srcu_ctl);
  }
  
  static struct rcu_torture_ops srcu_expedited_ops = {
cda4dc813   Lai Jiangshan   rcutorture: Use D...
715
  	.init		= rcu_sync_torture_init,
804bb8370   Paul E. McKenney   rcu: Add synchron...
716
717
718
719
720
721
  	.readlock	= srcu_torture_read_lock,
  	.read_delay	= srcu_read_delay,
  	.readunlock	= srcu_torture_read_unlock,
  	.completed	= srcu_torture_completed,
  	.deferred_free	= rcu_sync_torture_deferred_free,
  	.sync		= srcu_torture_synchronize_expedited,
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
722
  	.call		= NULL,
804bb8370   Paul E. McKenney   rcu: Add synchron...
723
724
725
726
  	.cb_barrier	= NULL,
  	.stats		= srcu_torture_stats,
  	.name		= "srcu_expedited"
  };
4b6c2cca6   Josh Triplett   [PATCH] rcu: add ...
727
728
729
730
731
732
733
734
735
736
737
738
739
740
  /*
   * Definitions for sched torture testing.
   */
  
  static int sched_torture_read_lock(void)
  {
  	preempt_disable();
  	return 0;
  }
  
  static void sched_torture_read_unlock(int idx)
  {
  	preempt_enable();
  }
2326974df   Paul E. McKenney   rcu: add call_rcu...
741
742
743
744
  static void rcu_sched_torture_deferred_free(struct rcu_torture *p)
  {
  	call_rcu_sched(&p->rtort_rcu, rcu_torture_cb);
  }
4b6c2cca6   Josh Triplett   [PATCH] rcu: add ...
745
  static struct rcu_torture_ops sched_ops = {
0acc512cb   Paul E. McKenney   rcu: Add synchron...
746
  	.init		= rcu_sync_torture_init,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
747
748
749
  	.readlock	= sched_torture_read_lock,
  	.read_delay	= rcu_read_delay,  /* just reuse rcu's version. */
  	.readunlock	= sched_torture_read_unlock,
d9a3da069   Paul E. McKenney   rcu: Add expedite...
750
  	.completed	= rcu_no_completed,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
751
  	.deferred_free	= rcu_sched_torture_deferred_free,
bdf2a4364   Paul E. McKenney   rcu: Catch rcutor...
752
  	.sync		= synchronize_sched,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
753
  	.cb_barrier	= rcu_barrier_sched,
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
754
  	.fqs		= rcu_sched_force_quiescent_state,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
755
756
757
  	.stats		= NULL,
  	.irq_capable	= 1,
  	.name		= "sched"
4b6c2cca6   Josh Triplett   [PATCH] rcu: add ...
758
  };
804bb8370   Paul E. McKenney   rcu: Add synchron...
759
  static struct rcu_torture_ops sched_sync_ops = {
0acc512cb   Paul E. McKenney   rcu: Add synchron...
760
  	.init		= rcu_sync_torture_init,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
761
762
763
  	.readlock	= sched_torture_read_lock,
  	.read_delay	= rcu_read_delay,  /* just reuse rcu's version. */
  	.readunlock	= sched_torture_read_unlock,
d9a3da069   Paul E. McKenney   rcu: Add expedite...
764
  	.completed	= rcu_no_completed,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
765
  	.deferred_free	= rcu_sync_torture_deferred_free,
bdf2a4364   Paul E. McKenney   rcu: Catch rcutor...
766
  	.sync		= synchronize_sched,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
767
  	.cb_barrier	= NULL,
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
768
  	.fqs		= rcu_sched_force_quiescent_state,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
769
770
771
  	.stats		= NULL,
  	.name		= "sched_sync"
  };
0acc512cb   Paul E. McKenney   rcu: Add synchron...
772
773
  static struct rcu_torture_ops sched_expedited_ops = {
  	.init		= rcu_sync_torture_init,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
774
775
776
  	.readlock	= sched_torture_read_lock,
  	.read_delay	= rcu_read_delay,  /* just reuse rcu's version. */
  	.readunlock	= sched_torture_read_unlock,
d9a3da069   Paul E. McKenney   rcu: Add expedite...
777
  	.completed	= rcu_no_completed,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
778
779
780
  	.deferred_free	= rcu_sync_torture_deferred_free,
  	.sync		= synchronize_sched_expedited,
  	.cb_barrier	= NULL,
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
781
  	.fqs		= rcu_sched_force_quiescent_state,
969c79215   Tejun Heo   sched: replace mi...
782
  	.stats		= NULL,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
783
784
  	.irq_capable	= 1,
  	.name		= "sched_expedited"
2326974df   Paul E. McKenney   rcu: add call_rcu...
785
  };
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
786
  /*
8e8be45e8   Paul E. McKenney   rcu: add priority...
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
   * RCU torture priority-boost testing.  Runs one real-time thread per
   * CPU for moderate bursts, repeatedly registering RCU callbacks and
   * spinning waiting for them to be invoked.  If a given callback takes
   * too long to be invoked, we assume that priority inversion has occurred.
   */
  
  struct rcu_boost_inflight {
  	struct rcu_head rcu;
  	int inflight;
  };
  
  static void rcu_torture_boost_cb(struct rcu_head *head)
  {
  	struct rcu_boost_inflight *rbip =
  		container_of(head, struct rcu_boost_inflight, rcu);
  
  	smp_mb(); /* Ensure RCU-core accesses precede clearing ->inflight */
  	rbip->inflight = 0;
  }
  
  static int rcu_torture_boost(void *arg)
  {
  	unsigned long call_rcu_time;
  	unsigned long endtime;
  	unsigned long oldstarttime;
  	struct rcu_boost_inflight rbi = { .inflight = 0 };
  	struct sched_param sp;
  
  	VERBOSE_PRINTK_STRING("rcu_torture_boost started");
  
  	/* Set real-time priority. */
  	sp.sched_priority = 1;
  	if (sched_setscheduler(current, SCHED_FIFO, &sp) < 0) {
  		VERBOSE_PRINTK_STRING("rcu_torture_boost RT prio failed!");
  		n_rcu_torture_boost_rterror++;
  	}
561190e3b   Paul E. McKenney   rcu: mark rcutort...
823
  	init_rcu_head_on_stack(&rbi.rcu);
8e8be45e8   Paul E. McKenney   rcu: add priority...
824
825
826
827
  	/* Each pass through the following loop does one boost-test cycle. */
  	do {
  		/* Wait for the next test interval. */
  		oldstarttime = boost_starttime;
93898fb1a   Paul E. McKenney   rcu: Make rcu_tor...
828
  		while (ULONG_CMP_LT(jiffies, oldstarttime)) {
0e11c8e8a   Paul E. McKenney   rcu: Make rcutort...
829
  			schedule_timeout_interruptible(oldstarttime - jiffies);
8e8be45e8   Paul E. McKenney   rcu: add priority...
830
831
832
833
834
835
836
837
838
  			rcu_stutter_wait("rcu_torture_boost");
  			if (kthread_should_stop() ||
  			    fullstop != FULLSTOP_DONTSTOP)
  				goto checkwait;
  		}
  
  		/* Do one boost-test interval. */
  		endtime = oldstarttime + test_boost_duration * HZ;
  		call_rcu_time = jiffies;
93898fb1a   Paul E. McKenney   rcu: Make rcu_tor...
839
  		while (ULONG_CMP_LT(jiffies, endtime)) {
8e8be45e8   Paul E. McKenney   rcu: add priority...
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
  			/* If we don't have a callback in flight, post one. */
  			if (!rbi.inflight) {
  				smp_mb(); /* RCU core before ->inflight = 1. */
  				rbi.inflight = 1;
  				call_rcu(&rbi.rcu, rcu_torture_boost_cb);
  				if (jiffies - call_rcu_time >
  					 test_boost_duration * HZ - HZ / 2) {
  					VERBOSE_PRINTK_STRING("rcu_torture_boost boosting failed");
  					n_rcu_torture_boost_failure++;
  				}
  				call_rcu_time = jiffies;
  			}
  			cond_resched();
  			rcu_stutter_wait("rcu_torture_boost");
  			if (kthread_should_stop() ||
  			    fullstop != FULLSTOP_DONTSTOP)
  				goto checkwait;
  		}
  
  		/*
  		 * Set the start time of the next test interval.
  		 * Yes, this is vulnerable to long delays, but such
  		 * delays simply cause a false negative for the next
  		 * interval.  Besides, we are running at RT priority,
  		 * so delays should be relatively rare.
  		 */
ab8f11e5f   Paul E. McKenney   rcu: Make rcu_tor...
866
867
  		while (oldstarttime == boost_starttime &&
  		       !kthread_should_stop()) {
8e8be45e8   Paul E. McKenney   rcu: add priority...
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
  			if (mutex_trylock(&boost_mutex)) {
  				boost_starttime = jiffies +
  						  test_boost_interval * HZ;
  				n_rcu_torture_boosts++;
  				mutex_unlock(&boost_mutex);
  				break;
  			}
  			schedule_timeout_uninterruptible(1);
  		}
  
  		/* Go do the stutter. */
  checkwait:	rcu_stutter_wait("rcu_torture_boost");
  	} while (!kthread_should_stop() && fullstop  == FULLSTOP_DONTSTOP);
  
  	/* Clean up and exit. */
  	VERBOSE_PRINTK_STRING("rcu_torture_boost task stopping");
  	rcutorture_shutdown_absorb("rcu_torture_boost");
  	while (!kthread_should_stop() || rbi.inflight)
  		schedule_timeout_uninterruptible(1);
  	smp_mb(); /* order accesses to ->inflight before stack-frame death. */
9d68197c0   Paul E. McKenney   rcu: Don't destro...
888
  	destroy_rcu_head_on_stack(&rbi.rcu);
8e8be45e8   Paul E. McKenney   rcu: add priority...
889
890
891
892
  	return 0;
  }
  
  /*
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
893
894
895
896
897
898
899
900
901
902
903
904
905
   * RCU torture force-quiescent-state kthread.  Repeatedly induces
   * bursts of calls to force_quiescent_state(), increasing the probability
   * of occurrence of some important types of race conditions.
   */
  static int
  rcu_torture_fqs(void *arg)
  {
  	unsigned long fqs_resume_time;
  	int fqs_burst_remaining;
  
  	VERBOSE_PRINTK_STRING("rcu_torture_fqs task started");
  	do {
  		fqs_resume_time = jiffies + fqs_stutter * HZ;
93898fb1a   Paul E. McKenney   rcu: Make rcu_tor...
906
907
  		while (ULONG_CMP_LT(jiffies, fqs_resume_time) &&
  		       !kthread_should_stop()) {
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
908
909
910
  			schedule_timeout_interruptible(1);
  		}
  		fqs_burst_remaining = fqs_duration;
93898fb1a   Paul E. McKenney   rcu: Make rcu_tor...
911
912
  		while (fqs_burst_remaining > 0 &&
  		       !kthread_should_stop()) {
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
913
914
915
916
917
918
919
920
921
922
923
924
925
926
  			cur_ops->fqs();
  			udelay(fqs_holdoff);
  			fqs_burst_remaining -= fqs_holdoff;
  		}
  		rcu_stutter_wait("rcu_torture_fqs");
  	} while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
  	VERBOSE_PRINTK_STRING("rcu_torture_fqs task stopping");
  	rcutorture_shutdown_absorb("rcu_torture_fqs");
  	while (!kthread_should_stop())
  		schedule_timeout_uninterruptible(1);
  	return 0;
  }
  
  /*
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
927
928
929
930
931
932
933
934
935
936
937
938
939
940
   * RCU torture writer kthread.  Repeatedly substitutes a new structure
   * for that pointed to by rcu_torture_current, freeing the old structure
   * after a series of grace periods (the "pipeline").
   */
  static int
  rcu_torture_writer(void *arg)
  {
  	int i;
  	long oldbatch = rcu_batches_completed();
  	struct rcu_torture *rp;
  	struct rcu_torture *old_rp;
  	static DEFINE_RCU_RANDOM(rand);
  
  	VERBOSE_PRINTK_STRING("rcu_torture_writer task started");
dbdf65b1b   Ingo Molnar   [PATCH] rcutortur...
941
  	set_user_nice(current, 19);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
942
943
  	do {
  		schedule_timeout_uninterruptible(1);
a71fca58b   Paul E. McKenney   rcu: Fix whitespa...
944
945
  		rp = rcu_torture_alloc();
  		if (rp == NULL)
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
946
947
948
  			continue;
  		rp->rtort_pipe_count = 0;
  		udelay(rcu_random(&rand) & 0x3ff);
0ddea0ead   Paul E. McKenney   rcu: fix sparse e...
949
950
  		old_rp = rcu_dereference_check(rcu_torture_current,
  					       current == writer_task);
996417d2c   Paul E. McKenney   [PATCH] add succe...
951
  		rp->rtort_mbtest = 1;
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
952
  		rcu_assign_pointer(rcu_torture_current, rp);
9b2619aff   Paul E. McKenney   rcu: Clean up cod...
953
  		smp_wmb(); /* Mods to old_rp must follow rcu_assign_pointer() */
c8e5b1631   Josh Triplett   rcutorture: style...
954
  		if (old_rp) {
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
955
956
957
958
959
  			i = old_rp->rtort_pipe_count;
  			if (i > RCU_TORTURE_PIPE_LEN)
  				i = RCU_TORTURE_PIPE_LEN;
  			atomic_inc(&rcu_torture_wcount[i]);
  			old_rp->rtort_pipe_count++;
0acc512cb   Paul E. McKenney   rcu: Add synchron...
960
  			cur_ops->deferred_free(old_rp);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
961
  		}
4a2986568   Paul E. McKenney   rcu: make rcutort...
962
  		rcutorture_record_progress(++rcu_torture_current_version);
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
963
  		oldbatch = cur_ops->completed();
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
964
965
  		rcu_stutter_wait("rcu_torture_writer");
  	} while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
966
  	VERBOSE_PRINTK_STRING("rcu_torture_writer task stopping");
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
967
968
  	rcutorture_shutdown_absorb("rcu_torture_writer");
  	while (!kthread_should_stop())
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
969
970
971
972
973
  		schedule_timeout_uninterruptible(1);
  	return 0;
  }
  
  /*
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
974
975
976
977
978
979
980
981
982
983
984
985
986
987
   * RCU torture fake writer kthread.  Repeatedly calls sync, with a random
   * delay between calls.
   */
  static int
  rcu_torture_fakewriter(void *arg)
  {
  	DEFINE_RCU_RANDOM(rand);
  
  	VERBOSE_PRINTK_STRING("rcu_torture_fakewriter task started");
  	set_user_nice(current, 19);
  
  	do {
  		schedule_timeout_uninterruptible(1 + rcu_random(&rand)%10);
  		udelay(rcu_random(&rand) & 0x3ff);
72472a02a   Paul E. McKenney   rcu: Make rcutort...
988
989
990
991
992
  		if (cur_ops->cb_barrier != NULL &&
  		    rcu_random(&rand) % (nfakewriters * 8) == 0)
  			cur_ops->cb_barrier();
  		else
  			cur_ops->sync();
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
993
994
  		rcu_stutter_wait("rcu_torture_fakewriter");
  	} while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
995
996
  
  	VERBOSE_PRINTK_STRING("rcu_torture_fakewriter task stopping");
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
997
998
  	rcutorture_shutdown_absorb("rcu_torture_fakewriter");
  	while (!kthread_should_stop())
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
999
1000
1001
  		schedule_timeout_uninterruptible(1);
  	return 0;
  }
91afaf300   Paul E. McKenney   rcu: Add failure ...
1002
1003
1004
1005
1006
1007
1008
1009
  void rcutorture_trace_dump(void)
  {
  	static atomic_t beenhere = ATOMIC_INIT(0);
  
  	if (atomic_read(&beenhere))
  		return;
  	if (atomic_xchg(&beenhere, 1) != 0)
  		return;
91afaf300   Paul E. McKenney   rcu: Add failure ...
1010
1011
  	ftrace_dump(DUMP_ALL);
  }
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
1012
  /*
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
1013
1014
1015
1016
1017
1018
1019
1020
1021
   * RCU torture reader from timer handler.  Dereferences rcu_torture_current,
   * incrementing the corresponding element of the pipeline array.  The
   * counter in the element should never be greater than 1, otherwise, the
   * RCU implementation is broken.
   */
  static void rcu_torture_timer(unsigned long unused)
  {
  	int idx;
  	int completed;
524945351   Paul E. McKenney   rcu: Reduce rcuto...
1022
  	int completed_end;
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
1023
1024
1025
1026
  	static DEFINE_RCU_RANDOM(rand);
  	static DEFINE_SPINLOCK(rand_lock);
  	struct rcu_torture *p;
  	int pipe_count;
524945351   Paul E. McKenney   rcu: Reduce rcuto...
1027
  	unsigned long long ts;
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
1028
1029
1030
  
  	idx = cur_ops->readlock();
  	completed = cur_ops->completed();
e4aa0da39   Steven Rostedt   rcu: Allow rcutor...
1031
  	ts = rcu_trace_clock_local();
632ee2001   Paul E. McKenney   rcu: Introduce lo...
1032
  	p = rcu_dereference_check(rcu_torture_current,
632ee2001   Paul E. McKenney   rcu: Introduce lo...
1033
1034
1035
  				  rcu_read_lock_bh_held() ||
  				  rcu_read_lock_sched_held() ||
  				  srcu_read_lock_held(&srcu_ctl));
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
1036
1037
1038
1039
1040
1041
1042
1043
  	if (p == NULL) {
  		/* Leave because rcu_torture_writer is not yet underway */
  		cur_ops->readunlock(idx);
  		return;
  	}
  	if (p->rtort_mbtest == 0)
  		atomic_inc(&n_rcu_torture_mberror);
  	spin_lock(&rand_lock);
0acc512cb   Paul E. McKenney   rcu: Add synchron...
1044
  	cur_ops->read_delay(&rand);
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
1045
1046
1047
1048
1049
1050
1051
1052
  	n_rcu_torture_timers++;
  	spin_unlock(&rand_lock);
  	preempt_disable();
  	pipe_count = p->rtort_pipe_count;
  	if (pipe_count > RCU_TORTURE_PIPE_LEN) {
  		/* Should not happen, but... */
  		pipe_count = RCU_TORTURE_PIPE_LEN;
  	}
524945351   Paul E. McKenney   rcu: Reduce rcuto...
1053
1054
  	completed_end = cur_ops->completed();
  	if (pipe_count > 1) {
524945351   Paul E. McKenney   rcu: Reduce rcuto...
1055
1056
  		do_trace_rcu_torture_read(cur_ops->name, &p->rtort_rcu, ts,
  					  completed, completed_end);
91afaf300   Paul E. McKenney   rcu: Add failure ...
1057
  		rcutorture_trace_dump();
524945351   Paul E. McKenney   rcu: Reduce rcuto...
1058
  	}
dd17c8f72   Rusty Russell   percpu: remove pe...
1059
  	__this_cpu_inc(rcu_torture_count[pipe_count]);
524945351   Paul E. McKenney   rcu: Reduce rcuto...
1060
  	completed = completed_end - completed;
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
1061
1062
1063
1064
  	if (completed > RCU_TORTURE_PIPE_LEN) {
  		/* Should not happen, but... */
  		completed = RCU_TORTURE_PIPE_LEN;
  	}
dd17c8f72   Rusty Russell   percpu: remove pe...
1065
  	__this_cpu_inc(rcu_torture_batch[completed]);
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
1066
1067
1068
1069
1070
  	preempt_enable();
  	cur_ops->readunlock(idx);
  }
  
  /*
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1071
1072
1073
1074
1075
1076
1077
1078
1079
   * RCU torture reader kthread.  Repeatedly dereferences rcu_torture_current,
   * incrementing the corresponding element of the pipeline array.  The
   * counter in the element should never be greater than 1, otherwise, the
   * RCU implementation is broken.
   */
  static int
  rcu_torture_reader(void *arg)
  {
  	int completed;
524945351   Paul E. McKenney   rcu: Reduce rcuto...
1080
  	int completed_end;
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
1081
  	int idx;
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1082
1083
1084
  	DEFINE_RCU_RANDOM(rand);
  	struct rcu_torture *p;
  	int pipe_count;
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
1085
  	struct timer_list t;
524945351   Paul E. McKenney   rcu: Reduce rcuto...
1086
  	unsigned long long ts;
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1087
1088
  
  	VERBOSE_PRINTK_STRING("rcu_torture_reader task started");
dbdf65b1b   Ingo Molnar   [PATCH] rcutortur...
1089
  	set_user_nice(current, 19);
0acc512cb   Paul E. McKenney   rcu: Add synchron...
1090
  	if (irqreader && cur_ops->irq_capable)
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
1091
  		setup_timer_on_stack(&t, rcu_torture_timer, 0);
dbdf65b1b   Ingo Molnar   [PATCH] rcutortur...
1092

a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1093
  	do {
0acc512cb   Paul E. McKenney   rcu: Add synchron...
1094
  		if (irqreader && cur_ops->irq_capable) {
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
1095
  			if (!timer_pending(&t))
6155fec92   Paul E. McKenney   rcu: Fix rcutortu...
1096
  				mod_timer(&t, jiffies + 1);
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
1097
  		}
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
1098
1099
  		idx = cur_ops->readlock();
  		completed = cur_ops->completed();
e4aa0da39   Steven Rostedt   rcu: Allow rcutor...
1100
  		ts = rcu_trace_clock_local();
632ee2001   Paul E. McKenney   rcu: Introduce lo...
1101
  		p = rcu_dereference_check(rcu_torture_current,
632ee2001   Paul E. McKenney   rcu: Introduce lo...
1102
1103
1104
  					  rcu_read_lock_bh_held() ||
  					  rcu_read_lock_sched_held() ||
  					  srcu_read_lock_held(&srcu_ctl));
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1105
1106
  		if (p == NULL) {
  			/* Wait for rcu_torture_writer to get underway */
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
1107
  			cur_ops->readunlock(idx);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1108
1109
1110
  			schedule_timeout_interruptible(HZ);
  			continue;
  		}
996417d2c   Paul E. McKenney   [PATCH] add succe...
1111
1112
  		if (p->rtort_mbtest == 0)
  			atomic_inc(&n_rcu_torture_mberror);
0acc512cb   Paul E. McKenney   rcu: Add synchron...
1113
  		cur_ops->read_delay(&rand);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1114
1115
1116
1117
1118
1119
  		preempt_disable();
  		pipe_count = p->rtort_pipe_count;
  		if (pipe_count > RCU_TORTURE_PIPE_LEN) {
  			/* Should not happen, but... */
  			pipe_count = RCU_TORTURE_PIPE_LEN;
  		}
524945351   Paul E. McKenney   rcu: Reduce rcuto...
1120
1121
  		completed_end = cur_ops->completed();
  		if (pipe_count > 1) {
524945351   Paul E. McKenney   rcu: Reduce rcuto...
1122
1123
  			do_trace_rcu_torture_read(cur_ops->name, &p->rtort_rcu,
  						  ts, completed, completed_end);
91afaf300   Paul E. McKenney   rcu: Add failure ...
1124
  			rcutorture_trace_dump();
524945351   Paul E. McKenney   rcu: Reduce rcuto...
1125
  		}
dd17c8f72   Rusty Russell   percpu: remove pe...
1126
  		__this_cpu_inc(rcu_torture_count[pipe_count]);
524945351   Paul E. McKenney   rcu: Reduce rcuto...
1127
  		completed = completed_end - completed;
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1128
1129
1130
1131
  		if (completed > RCU_TORTURE_PIPE_LEN) {
  			/* Should not happen, but... */
  			completed = RCU_TORTURE_PIPE_LEN;
  		}
dd17c8f72   Rusty Russell   percpu: remove pe...
1132
  		__this_cpu_inc(rcu_torture_batch[completed]);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1133
  		preempt_enable();
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
1134
  		cur_ops->readunlock(idx);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1135
  		schedule();
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
1136
1137
  		rcu_stutter_wait("rcu_torture_reader");
  	} while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1138
  	VERBOSE_PRINTK_STRING("rcu_torture_reader task stopping");
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
1139
  	rcutorture_shutdown_absorb("rcu_torture_reader");
0acc512cb   Paul E. McKenney   rcu: Add synchron...
1140
  	if (irqreader && cur_ops->irq_capable)
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
1141
  		del_timer_sync(&t);
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
1142
  	while (!kthread_should_stop())
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
  		schedule_timeout_uninterruptible(1);
  	return 0;
  }
  
  /*
   * Create an RCU-torture statistics message in the specified buffer.
   */
  static int
  rcu_torture_printk(char *page)
  {
  	int cnt = 0;
  	int cpu;
  	int i;
  	long pipesummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 };
  	long batchsummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 };
0a9450227   KAMEZAWA Hiroyuki   [PATCH] for_each_...
1158
  	for_each_possible_cpu(cpu) {
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1159
1160
1161
1162
1163
1164
1165
1166
1167
  		for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) {
  			pipesummary[i] += per_cpu(rcu_torture_count, cpu)[i];
  			batchsummary[i] += per_cpu(rcu_torture_batch, cpu)[i];
  		}
  	}
  	for (i = RCU_TORTURE_PIPE_LEN - 1; i >= 0; i--) {
  		if (pipesummary[i] != 0)
  			break;
  	}
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
1168
  	cnt += sprintf(&page[cnt], "%s%s ", torture_type, TORTURE_FLAG);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1169
  	cnt += sprintf(&page[cnt],
5cf05ad75   Paul E. McKenney   rcu: Fix broken s...
1170
  		       "rtc: %p ver: %lu tfle: %d rta: %d rtaf: %d rtf: %d ",
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1171
1172
1173
1174
1175
  		       rcu_torture_current,
  		       rcu_torture_current_version,
  		       list_empty(&rcu_torture_freelist),
  		       atomic_read(&n_rcu_torture_alloc),
  		       atomic_read(&n_rcu_torture_alloc_fail),
5cf05ad75   Paul E. McKenney   rcu: Fix broken s...
1176
1177
  		       atomic_read(&n_rcu_torture_free));
  	cnt += sprintf(&page[cnt], "rtmbe: %d rtbke: %ld rtbre: %ld ",
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
1178
  		       atomic_read(&n_rcu_torture_mberror),
8e8be45e8   Paul E. McKenney   rcu: add priority...
1179
  		       n_rcu_torture_boost_ktrerror,
5cf05ad75   Paul E. McKenney   rcu: Fix broken s...
1180
1181
  		       n_rcu_torture_boost_rterror);
  	cnt += sprintf(&page[cnt], "rtbf: %ld rtb: %ld nt: %ld ",
8e8be45e8   Paul E. McKenney   rcu: add priority...
1182
1183
  		       n_rcu_torture_boost_failure,
  		       n_rcu_torture_boosts,
5cf05ad75   Paul E. McKenney   rcu: Fix broken s...
1184
  		       n_rcu_torture_timers);
13dbf9140   Paul E. McKenney   rcu: Track CPU-ho...
1185
1186
1187
1188
1189
1190
1191
  	cnt += sprintf(&page[cnt],
  		       "onoff: %ld/%ld:%ld/%ld %d,%d:%d,%d %lu:%lu (HZ=%d) ",
  		       n_online_successes, n_online_attempts,
  		       n_offline_successes, n_offline_attempts,
  		       min_online, max_online,
  		       min_offline, max_offline,
  		       sum_online, sum_offline, HZ);
5cf05ad75   Paul E. McKenney   rcu: Fix broken s...
1192
  	cnt += sprintf(&page[cnt], "barrier: %ld/%ld:%ld",
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
1193
1194
1195
1196
1197
  		       n_barrier_successes,
  		       n_barrier_attempts,
  		       n_rcu_torture_barrier_error);
  	cnt += sprintf(&page[cnt], "
  %s%s ", torture_type, TORTURE_FLAG);
8e8be45e8   Paul E. McKenney   rcu: add priority...
1198
  	if (atomic_read(&n_rcu_torture_mberror) != 0 ||
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
1199
  	    n_rcu_torture_barrier_error != 0 ||
8e8be45e8   Paul E. McKenney   rcu: add priority...
1200
1201
  	    n_rcu_torture_boost_ktrerror != 0 ||
  	    n_rcu_torture_boost_rterror != 0 ||
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
1202
1203
  	    n_rcu_torture_boost_failure != 0 ||
  	    i > 1) {
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1204
  		cnt += sprintf(&page[cnt], "!!! ");
996417d2c   Paul E. McKenney   [PATCH] add succe...
1205
  		atomic_inc(&n_rcu_torture_error);
5af970a48   Ingo Molnar   rcutorture: WARN_...
1206
  		WARN_ON_ONCE(1);
996417d2c   Paul E. McKenney   [PATCH] add succe...
1207
  	}
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1208
1209
1210
  	cnt += sprintf(&page[cnt], "Reader Pipe: ");
  	for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++)
  		cnt += sprintf(&page[cnt], " %ld", pipesummary[i]);
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
1211
1212
  	cnt += sprintf(&page[cnt], "
  %s%s ", torture_type, TORTURE_FLAG);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1213
  	cnt += sprintf(&page[cnt], "Reader Batch: ");
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
1214
  	for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++)
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1215
  		cnt += sprintf(&page[cnt], " %ld", batchsummary[i]);
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
1216
1217
  	cnt += sprintf(&page[cnt], "
  %s%s ", torture_type, TORTURE_FLAG);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1218
1219
1220
1221
1222
1223
1224
  	cnt += sprintf(&page[cnt], "Free-Block Circulation: ");
  	for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) {
  		cnt += sprintf(&page[cnt], " %d",
  			       atomic_read(&rcu_torture_wcount[i]));
  	}
  	cnt += sprintf(&page[cnt], "
  ");
c8e5b1631   Josh Triplett   rcutorture: style...
1225
  	if (cur_ops->stats)
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
1226
  		cnt += cur_ops->stats(&page[cnt]);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
  	return cnt;
  }
  
  /*
   * Print torture statistics.  Caller must ensure that there is only
   * one call to this function at a given time!!!  This is normally
   * accomplished by relying on the module system to only have one copy
   * of the module loaded, and then by giving the rcu_torture_stats
   * kthread full control (or the init/cleanup functions when rcu_torture_stats
   * thread is not running).
   */
  static void
  rcu_torture_stats_print(void)
  {
  	int cnt;
  
  	cnt = rcu_torture_printk(printk_buf);
2caa1e443   Paul E. McKenney   rcu: Switch rcuto...
1244
  	pr_alert("%s", printk_buf);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
  }
  
  /*
   * Periodically prints torture statistics, if periodic statistics printing
   * was specified via the stat_interval module parameter.
   *
   * No need to worry about fullstop here, since this one doesn't reference
   * volatile state or register callbacks.
   */
  static int
  rcu_torture_stats(void *arg)
  {
  	VERBOSE_PRINTK_STRING("rcu_torture_stats task started");
  	do {
  		schedule_timeout_interruptible(stat_interval * HZ);
  		rcu_torture_stats_print();
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
1261
1262
  		rcutorture_shutdown_absorb("rcu_torture_stats");
  	} while (!kthread_should_stop());
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1263
1264
1265
  	VERBOSE_PRINTK_STRING("rcu_torture_stats task stopping");
  	return 0;
  }
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1266
1267
1268
1269
1270
  static int rcu_idle_cpu;	/* Force all torture tasks off this CPU */
  
  /* Shuffle tasks such that we allow @rcu_idle_cpu to become idle. A special case
   * is when @rcu_idle_cpu = -1, when we allow the tasks to run on all CPUs.
   */
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
1271
  static void rcu_torture_shuffle_tasks(void)
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1272
  {
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1273
  	int i;
73d0a4b10   Rusty Russell   cpumask: convert ...
1274
  	cpumask_setall(shuffle_tmp_mask);
86ef5c9a8   Gautham R Shenoy   cpu-hotplug: repl...
1275
  	get_online_cpus();
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1276
1277
  
  	/* No point in shuffling if there is only one online CPU (ex: UP) */
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
1278
1279
1280
1281
  	if (num_online_cpus() == 1) {
  		put_online_cpus();
  		return;
  	}
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1282
1283
  
  	if (rcu_idle_cpu != -1)
73d0a4b10   Rusty Russell   cpumask: convert ...
1284
  		cpumask_clear_cpu(rcu_idle_cpu, shuffle_tmp_mask);
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1285

73d0a4b10   Rusty Russell   cpumask: convert ...
1286
  	set_cpus_allowed_ptr(current, shuffle_tmp_mask);
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1287

c8e5b1631   Josh Triplett   rcutorture: style...
1288
  	if (reader_tasks) {
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1289
1290
  		for (i = 0; i < nrealreaders; i++)
  			if (reader_tasks[i])
f70316dac   Mike Travis   generic: use new ...
1291
  				set_cpus_allowed_ptr(reader_tasks[i],
73d0a4b10   Rusty Russell   cpumask: convert ...
1292
  						     shuffle_tmp_mask);
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1293
  	}
c8e5b1631   Josh Triplett   rcutorture: style...
1294
  	if (fakewriter_tasks) {
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
1295
1296
  		for (i = 0; i < nfakewriters; i++)
  			if (fakewriter_tasks[i])
f70316dac   Mike Travis   generic: use new ...
1297
  				set_cpus_allowed_ptr(fakewriter_tasks[i],
73d0a4b10   Rusty Russell   cpumask: convert ...
1298
  						     shuffle_tmp_mask);
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
1299
  	}
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1300
  	if (writer_task)
73d0a4b10   Rusty Russell   cpumask: convert ...
1301
  		set_cpus_allowed_ptr(writer_task, shuffle_tmp_mask);
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1302
  	if (stats_task)
73d0a4b10   Rusty Russell   cpumask: convert ...
1303
  		set_cpus_allowed_ptr(stats_task, shuffle_tmp_mask);
0e11c8e8a   Paul E. McKenney   rcu: Make rcutort...
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
  	if (stutter_task)
  		set_cpus_allowed_ptr(stutter_task, shuffle_tmp_mask);
  	if (fqs_task)
  		set_cpus_allowed_ptr(fqs_task, shuffle_tmp_mask);
  	if (shutdown_task)
  		set_cpus_allowed_ptr(shutdown_task, shuffle_tmp_mask);
  #ifdef CONFIG_HOTPLUG_CPU
  	if (onoff_task)
  		set_cpus_allowed_ptr(onoff_task, shuffle_tmp_mask);
  #endif /* #ifdef CONFIG_HOTPLUG_CPU */
  	if (stall_task)
  		set_cpus_allowed_ptr(stall_task, shuffle_tmp_mask);
  	if (barrier_cbs_tasks)
  		for (i = 0; i < n_barrier_cbs; i++)
  			if (barrier_cbs_tasks[i])
  				set_cpus_allowed_ptr(barrier_cbs_tasks[i],
  						     shuffle_tmp_mask);
  	if (barrier_task)
  		set_cpus_allowed_ptr(barrier_task, shuffle_tmp_mask);
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1323
1324
1325
1326
1327
  
  	if (rcu_idle_cpu == -1)
  		rcu_idle_cpu = num_online_cpus() - 1;
  	else
  		rcu_idle_cpu--;
86ef5c9a8   Gautham R Shenoy   cpu-hotplug: repl...
1328
  	put_online_cpus();
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
  }
  
  /* Shuffle tasks across CPUs, with the intent of allowing each CPU in the
   * system to become idle at a time and cut off its timer ticks. This is meant
   * to test the support for such tickless idle CPU in RCU.
   */
  static int
  rcu_torture_shuffle(void *arg)
  {
  	VERBOSE_PRINTK_STRING("rcu_torture_shuffle task started");
  	do {
  		schedule_timeout_interruptible(shuffle_interval * HZ);
  		rcu_torture_shuffle_tasks();
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
1342
1343
  		rcutorture_shutdown_absorb("rcu_torture_shuffle");
  	} while (!kthread_should_stop());
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1344
1345
1346
  	VERBOSE_PRINTK_STRING("rcu_torture_shuffle task stopping");
  	return 0;
  }
d120f65f3   Paul E. McKenney   rcu: make rcutort...
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
  /* Cause the rcutorture test to "stutter", starting and stopping all
   * threads periodically.
   */
  static int
  rcu_torture_stutter(void *arg)
  {
  	VERBOSE_PRINTK_STRING("rcu_torture_stutter task started");
  	do {
  		schedule_timeout_interruptible(stutter * HZ);
  		stutter_pause_test = 1;
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
1357
  		if (!kthread_should_stop())
d120f65f3   Paul E. McKenney   rcu: make rcutort...
1358
1359
  			schedule_timeout_interruptible(stutter * HZ);
  		stutter_pause_test = 0;
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
1360
1361
  		rcutorture_shutdown_absorb("rcu_torture_stutter");
  	} while (!kthread_should_stop());
d120f65f3   Paul E. McKenney   rcu: make rcutort...
1362
1363
1364
  	VERBOSE_PRINTK_STRING("rcu_torture_stutter task stopping");
  	return 0;
  }
95c383227   Paul E. McKenney   [PATCH] rcutortur...
1365
  static inline void
8e8be45e8   Paul E. McKenney   rcu: add priority...
1366
  rcu_torture_print_module_parms(struct rcu_torture_ops *cur_ops, char *tag)
95c383227   Paul E. McKenney   [PATCH] rcutortur...
1367
  {
2caa1e443   Paul E. McKenney   rcu: Switch rcuto...
1368
1369
1370
1371
1372
1373
1374
  	pr_alert("%s" TORTURE_FLAG
  		 "--- %s: nreaders=%d nfakewriters=%d "
  		 "stat_interval=%d verbose=%d test_no_idle_hz=%d "
  		 "shuffle_interval=%d stutter=%d irqreader=%d "
  		 "fqs_duration=%d fqs_holdoff=%d fqs_stutter=%d "
  		 "test_boost=%d/%d test_boost_interval=%d "
  		 "test_boost_duration=%d shutdown_secs=%d "
67afeed2c   Paul E. McKenney   rcu: Add new rcut...
1375
1376
  		 "stall_cpu=%d stall_cpu_holdoff=%d "
  		 "n_barrier_cbs=%d "
2caa1e443   Paul E. McKenney   rcu: Switch rcuto...
1377
1378
1379
1380
1381
1382
1383
  		 "onoff_interval=%d onoff_holdoff=%d
  ",
  		 torture_type, tag, nrealreaders, nfakewriters,
  		 stat_interval, verbose, test_no_idle_hz, shuffle_interval,
  		 stutter, irqreader, fqs_duration, fqs_holdoff, fqs_stutter,
  		 test_boost, cur_ops->can_boost,
  		 test_boost_interval, test_boost_duration, shutdown_secs,
67afeed2c   Paul E. McKenney   rcu: Add new rcut...
1384
1385
  		 stall_cpu, stall_cpu_holdoff,
  		 n_barrier_cbs,
2caa1e443   Paul E. McKenney   rcu: Switch rcuto...
1386
  		 onoff_interval, onoff_holdoff);
95c383227   Paul E. McKenney   [PATCH] rcutortur...
1387
  }
8e8be45e8   Paul E. McKenney   rcu: add priority...
1388
  static struct notifier_block rcutorture_shutdown_nb = {
343e9099c   Paul E. McKenney   rcu: fix rcutortu...
1389
1390
  	.notifier_call = rcutorture_shutdown_notify,
  };
8e8be45e8   Paul E. McKenney   rcu: add priority...
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
  static void rcutorture_booster_cleanup(int cpu)
  {
  	struct task_struct *t;
  
  	if (boost_tasks[cpu] == NULL)
  		return;
  	mutex_lock(&boost_mutex);
  	VERBOSE_PRINTK_STRING("Stopping rcu_torture_boost task");
  	t = boost_tasks[cpu];
  	boost_tasks[cpu] = NULL;
  	mutex_unlock(&boost_mutex);
  
  	/* This must be outside of the mutex, otherwise deadlock! */
  	kthread_stop(t);
37e377d28   Paul E. McKenney   rcu: Fixes to rcu...
1405
  	boost_tasks[cpu] = NULL;
8e8be45e8   Paul E. McKenney   rcu: add priority...
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
  }
  
  static int rcutorture_booster_init(int cpu)
  {
  	int retval;
  
  	if (boost_tasks[cpu] != NULL)
  		return 0;  /* Already created, nothing more to do. */
  
  	/* Don't allow time recalculation while creating a new task. */
  	mutex_lock(&boost_mutex);
  	VERBOSE_PRINTK_STRING("Creating rcu_torture_boost task");
1f2880948   Eric Dumazet   rcu: Use kthread_...
1418
1419
1420
  	boost_tasks[cpu] = kthread_create_on_node(rcu_torture_boost, NULL,
  						  cpu_to_node(cpu),
  						  "rcu_torture_boost");
8e8be45e8   Paul E. McKenney   rcu: add priority...
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
  	if (IS_ERR(boost_tasks[cpu])) {
  		retval = PTR_ERR(boost_tasks[cpu]);
  		VERBOSE_PRINTK_STRING("rcu_torture_boost task create failed");
  		n_rcu_torture_boost_ktrerror++;
  		boost_tasks[cpu] = NULL;
  		mutex_unlock(&boost_mutex);
  		return retval;
  	}
  	kthread_bind(boost_tasks[cpu], cpu);
  	wake_up_process(boost_tasks[cpu]);
  	mutex_unlock(&boost_mutex);
  	return 0;
  }
d5f546d83   Paul E. McKenney   rcu: Add rcutortu...
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
  /*
   * 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_PRINTK_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)
2caa1e443   Paul E. McKenney   rcu: Switch rcuto...
1450
1451
1452
1453
  			pr_alert("%s" TORTURE_FLAG
  				 "rcu_torture_shutdown task: %lu jiffies remaining
  ",
  				 torture_type, delta);
d5f546d83   Paul E. McKenney   rcu: Add rcutortu...
1454
1455
1456
  		schedule_timeout_interruptible(delta);
  		jiffies_snap = ACCESS_ONCE(jiffies);
  	}
b58bdccaa   Paul E. McKenney   rcu: Add rcutortu...
1457
  	if (kthread_should_stop()) {
d5f546d83   Paul E. McKenney   rcu: Add rcutortu...
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
  		VERBOSE_PRINTK_STRING("rcu_torture_shutdown task stopping");
  		return 0;
  	}
  
  	/* OK, shut down the system. */
  
  	VERBOSE_PRINTK_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;
  }
b58bdccaa   Paul E. McKenney   rcu: Add rcutortu...
1470
1471
1472
1473
1474
1475
  #ifdef CONFIG_HOTPLUG_CPU
  
  /*
   * Execute random CPU-hotplug operations at the interval specified
   * by the onoff_interval.
   */
441003064   Heiko Carstens   rcu: Add missing ...
1476
  static int __cpuinit
b58bdccaa   Paul E. McKenney   rcu: Add rcutortu...
1477
1478
1479
  rcu_torture_onoff(void *arg)
  {
  	int cpu;
13dbf9140   Paul E. McKenney   rcu: Track CPU-ho...
1480
  	unsigned long delta;
b58bdccaa   Paul E. McKenney   rcu: Add rcutortu...
1481
1482
  	int maxcpu = -1;
  	DEFINE_RCU_RANDOM(rand);
489832609   Paul E. McKenney   rcu: Make rcutort...
1483
  	int ret;
13dbf9140   Paul E. McKenney   rcu: Track CPU-ho...
1484
  	unsigned long starttime;
b58bdccaa   Paul E. McKenney   rcu: Add rcutortu...
1485
1486
1487
1488
1489
  
  	VERBOSE_PRINTK_STRING("rcu_torture_onoff task started");
  	for_each_online_cpu(cpu)
  		maxcpu = cpu;
  	WARN_ON(maxcpu < 0);
9b9ec9b90   Paul E. McKenney   rcutorture: Permi...
1490
1491
1492
1493
1494
  	if (onoff_holdoff > 0) {
  		VERBOSE_PRINTK_STRING("rcu_torture_onoff begin holdoff");
  		schedule_timeout_interruptible(onoff_holdoff * HZ);
  		VERBOSE_PRINTK_STRING("rcu_torture_onoff end holdoff");
  	}
b58bdccaa   Paul E. McKenney   rcu: Add rcutortu...
1495
1496
  	while (!kthread_should_stop()) {
  		cpu = (rcu_random(&rand) >> 4) % (maxcpu + 1);
f220242af   Paul E. McKenney   rcu: Make rcutort...
1497
  		if (cpu_online(cpu) && cpu_is_hotpluggable(cpu)) {
b58bdccaa   Paul E. McKenney   rcu: Add rcutortu...
1498
  			if (verbose)
2caa1e443   Paul E. McKenney   rcu: Switch rcuto...
1499
1500
1501
1502
  				pr_alert("%s" TORTURE_FLAG
  					 "rcu_torture_onoff task: offlining %d
  ",
  					 torture_type, cpu);
13dbf9140   Paul E. McKenney   rcu: Track CPU-ho...
1503
  			starttime = jiffies;
b58bdccaa   Paul E. McKenney   rcu: Add rcutortu...
1504
  			n_offline_attempts++;
489832609   Paul E. McKenney   rcu: Make rcutort...
1505
1506
1507
1508
1509
1510
1511
1512
  			ret = cpu_down(cpu);
  			if (ret) {
  				if (verbose)
  					pr_alert("%s" TORTURE_FLAG
  						 "rcu_torture_onoff task: offline %d failed: errno %d
  ",
  						 torture_type, cpu, ret);
  			} else {
b58bdccaa   Paul E. McKenney   rcu: Add rcutortu...
1513
  				if (verbose)
2caa1e443   Paul E. McKenney   rcu: Switch rcuto...
1514
1515
1516
1517
  					pr_alert("%s" TORTURE_FLAG
  						 "rcu_torture_onoff task: offlined %d
  ",
  						 torture_type, cpu);
b58bdccaa   Paul E. McKenney   rcu: Add rcutortu...
1518
  				n_offline_successes++;
13dbf9140   Paul E. McKenney   rcu: Track CPU-ho...
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
  				delta = jiffies - starttime;
  				sum_offline += delta;
  				if (min_offline < 0) {
  					min_offline = delta;
  					max_offline = delta;
  				}
  				if (min_offline > delta)
  					min_offline = delta;
  				if (max_offline < delta)
  					max_offline = delta;
b58bdccaa   Paul E. McKenney   rcu: Add rcutortu...
1529
  			}
f220242af   Paul E. McKenney   rcu: Make rcutort...
1530
  		} else if (cpu_is_hotpluggable(cpu)) {
b58bdccaa   Paul E. McKenney   rcu: Add rcutortu...
1531
  			if (verbose)
2caa1e443   Paul E. McKenney   rcu: Switch rcuto...
1532
1533
1534
1535
  				pr_alert("%s" TORTURE_FLAG
  					 "rcu_torture_onoff task: onlining %d
  ",
  					 torture_type, cpu);
13dbf9140   Paul E. McKenney   rcu: Track CPU-ho...
1536
  			starttime = jiffies;
b58bdccaa   Paul E. McKenney   rcu: Add rcutortu...
1537
1538
1539
  			n_online_attempts++;
  			if (cpu_up(cpu) == 0) {
  				if (verbose)
2caa1e443   Paul E. McKenney   rcu: Switch rcuto...
1540
1541
1542
1543
  					pr_alert("%s" TORTURE_FLAG
  						 "rcu_torture_onoff task: onlined %d
  ",
  						 torture_type, cpu);
b58bdccaa   Paul E. McKenney   rcu: Add rcutortu...
1544
  				n_online_successes++;
13dbf9140   Paul E. McKenney   rcu: Track CPU-ho...
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
  				delta = jiffies - starttime;
  				sum_online += delta;
  				if (min_online < 0) {
  					min_online = delta;
  					max_online = delta;
  				}
  				if (min_online > delta)
  					min_online = delta;
  				if (max_online < delta)
  					max_online = delta;
b58bdccaa   Paul E. McKenney   rcu: Add rcutortu...
1555
1556
1557
1558
1559
1560
1561
  			}
  		}
  		schedule_timeout_interruptible(onoff_interval * HZ);
  	}
  	VERBOSE_PRINTK_STRING("rcu_torture_onoff task stopping");
  	return 0;
  }
441003064   Heiko Carstens   rcu: Add missing ...
1562
  static int __cpuinit
b58bdccaa   Paul E. McKenney   rcu: Add rcutortu...
1563
1564
  rcu_torture_onoff_init(void)
  {
3c1b1ce00   Julia Lawall   PTR_ERR should be...
1565
  	int ret;
b58bdccaa   Paul E. McKenney   rcu: Add rcutortu...
1566
1567
1568
1569
  	if (onoff_interval <= 0)
  		return 0;
  	onoff_task = kthread_run(rcu_torture_onoff, NULL, "rcu_torture_onoff");
  	if (IS_ERR(onoff_task)) {
3c1b1ce00   Julia Lawall   PTR_ERR should be...
1570
  		ret = PTR_ERR(onoff_task);
b58bdccaa   Paul E. McKenney   rcu: Add rcutortu...
1571
  		onoff_task = NULL;
3c1b1ce00   Julia Lawall   PTR_ERR should be...
1572
  		return ret;
b58bdccaa   Paul E. McKenney   rcu: Add rcutortu...
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
  	}
  	return 0;
  }
  
  static void rcu_torture_onoff_cleanup(void)
  {
  	if (onoff_task == NULL)
  		return;
  	VERBOSE_PRINTK_STRING("Stopping rcu_torture_onoff task");
  	kthread_stop(onoff_task);
37e377d28   Paul E. McKenney   rcu: Fixes to rcu...
1583
  	onoff_task = NULL;
b58bdccaa   Paul E. McKenney   rcu: Add rcutortu...
1584
1585
1586
  }
  
  #else /* #ifdef CONFIG_HOTPLUG_CPU */
37e377d28   Paul E. McKenney   rcu: Fixes to rcu...
1587
  static int
b58bdccaa   Paul E. McKenney   rcu: Add rcutortu...
1588
1589
  rcu_torture_onoff_init(void)
  {
37e377d28   Paul E. McKenney   rcu: Fixes to rcu...
1590
  	return 0;
b58bdccaa   Paul E. McKenney   rcu: Add rcutortu...
1591
1592
1593
1594
1595
1596
1597
  }
  
  static void rcu_torture_onoff_cleanup(void)
  {
  }
  
  #endif /* #else #ifdef CONFIG_HOTPLUG_CPU */
c13f3757d   Paul E. McKenney   rcu: Add CPU-stal...
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
  /*
   * CPU-stall kthread.  It waits as specified by stall_cpu_holdoff, then
   * induces a CPU stall for the time specified by stall_cpu.
   */
  static int __cpuinit rcu_torture_stall(void *args)
  {
  	unsigned long stop_at;
  
  	VERBOSE_PRINTK_STRING("rcu_torture_stall task started");
  	if (stall_cpu_holdoff > 0) {
  		VERBOSE_PRINTK_STRING("rcu_torture_stall begin holdoff");
  		schedule_timeout_interruptible(stall_cpu_holdoff * HZ);
  		VERBOSE_PRINTK_STRING("rcu_torture_stall end holdoff");
  	}
  	if (!kthread_should_stop()) {
  		stop_at = get_seconds() + stall_cpu;
  		/* RCU CPU stall is expected behavior in following code. */
2caa1e443   Paul E. McKenney   rcu: Switch rcuto...
1615
1616
  		pr_alert("rcu_torture_stall start.
  ");
c13f3757d   Paul E. McKenney   rcu: Add CPU-stal...
1617
1618
1619
1620
1621
1622
  		rcu_read_lock();
  		preempt_disable();
  		while (ULONG_CMP_LT(get_seconds(), stop_at))
  			continue;  /* Induce RCU CPU stall warning. */
  		preempt_enable();
  		rcu_read_unlock();
2caa1e443   Paul E. McKenney   rcu: Switch rcuto...
1623
1624
  		pr_alert("rcu_torture_stall end.
  ");
c13f3757d   Paul E. McKenney   rcu: Add CPU-stal...
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
  	}
  	rcutorture_shutdown_absorb("rcu_torture_stall");
  	while (!kthread_should_stop())
  		schedule_timeout_interruptible(10 * HZ);
  	return 0;
  }
  
  /* Spawn CPU-stall kthread, if stall_cpu specified. */
  static int __init rcu_torture_stall_init(void)
  {
  	int ret;
  
  	if (stall_cpu <= 0)
  		return 0;
  	stall_task = kthread_run(rcu_torture_stall, NULL, "rcu_torture_stall");
  	if (IS_ERR(stall_task)) {
  		ret = PTR_ERR(stall_task);
  		stall_task = NULL;
  		return ret;
  	}
  	return 0;
  }
  
  /* Clean up after the CPU-stall kthread, if one was spawned. */
  static void rcu_torture_stall_cleanup(void)
  {
  	if (stall_task == NULL)
  		return;
  	VERBOSE_PRINTK_STRING("Stopping rcu_torture_stall_task.");
  	kthread_stop(stall_task);
37e377d28   Paul E. McKenney   rcu: Fixes to rcu...
1655
  	stall_task = NULL;
c13f3757d   Paul E. McKenney   rcu: Add CPU-stal...
1656
  }
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
  /* Callback function for RCU barrier testing. */
  void rcu_torture_barrier_cbf(struct rcu_head *rcu)
  {
  	atomic_inc(&barrier_cbs_invoked);
  }
  
  /* kthread function to register callbacks used to test RCU barriers. */
  static int rcu_torture_barrier_cbs(void *arg)
  {
  	long myid = (long)arg;
c6ebcbb60   Paul E. McKenney   rcu: Fix bug in r...
1667
  	bool lastphase = 0;
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
1668
1669
1670
1671
1672
1673
1674
  	struct rcu_head rcu;
  
  	init_rcu_head_on_stack(&rcu);
  	VERBOSE_PRINTK_STRING("rcu_torture_barrier_cbs task started");
  	set_user_nice(current, 19);
  	do {
  		wait_event(barrier_cbs_wq[myid],
c6ebcbb60   Paul E. McKenney   rcu: Fix bug in r...
1675
  			   barrier_phase != lastphase ||
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
1676
1677
  			   kthread_should_stop() ||
  			   fullstop != FULLSTOP_DONTSTOP);
c6ebcbb60   Paul E. McKenney   rcu: Fix bug in r...
1678
1679
  		lastphase = barrier_phase;
  		smp_mb(); /* ensure barrier_phase load before ->call(). */
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
  		if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP)
  			break;
  		cur_ops->call(&rcu, rcu_torture_barrier_cbf);
  		if (atomic_dec_and_test(&barrier_cbs_count))
  			wake_up(&barrier_wq);
  	} while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
  	VERBOSE_PRINTK_STRING("rcu_torture_barrier_cbs task stopping");
  	rcutorture_shutdown_absorb("rcu_torture_barrier_cbs");
  	while (!kthread_should_stop())
  		schedule_timeout_interruptible(1);
  	cur_ops->cb_barrier();
  	destroy_rcu_head_on_stack(&rcu);
  	return 0;
  }
  
  /* kthread function to drive and coordinate RCU barrier testing. */
  static int rcu_torture_barrier(void *arg)
  {
  	int i;
  
  	VERBOSE_PRINTK_STRING("rcu_torture_barrier task starting");
  	do {
  		atomic_set(&barrier_cbs_invoked, 0);
  		atomic_set(&barrier_cbs_count, n_barrier_cbs);
c6ebcbb60   Paul E. McKenney   rcu: Fix bug in r...
1704
1705
  		smp_mb(); /* Ensure barrier_phase after prior assignments. */
  		barrier_phase = !barrier_phase;
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
  		for (i = 0; i < n_barrier_cbs; i++)
  			wake_up(&barrier_cbs_wq[i]);
  		wait_event(barrier_wq,
  			   atomic_read(&barrier_cbs_count) == 0 ||
  			   kthread_should_stop() ||
  			   fullstop != FULLSTOP_DONTSTOP);
  		if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP)
  			break;
  		n_barrier_attempts++;
  		cur_ops->cb_barrier();
  		if (atomic_read(&barrier_cbs_invoked) != n_barrier_cbs) {
  			n_rcu_torture_barrier_error++;
  			WARN_ON_ONCE(1);
  		}
  		n_barrier_successes++;
  		schedule_timeout_interruptible(HZ / 10);
  	} while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
  	VERBOSE_PRINTK_STRING("rcu_torture_barrier task stopping");
143aa672f   Paul E. McKenney   rcu: Fix diagnost...
1724
  	rcutorture_shutdown_absorb("rcu_torture_barrier");
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
  	while (!kthread_should_stop())
  		schedule_timeout_interruptible(1);
  	return 0;
  }
  
  /* Initialize RCU barrier testing. */
  static int rcu_torture_barrier_init(void)
  {
  	int i;
  	int ret;
  
  	if (n_barrier_cbs == 0)
  		return 0;
  	if (cur_ops->call == NULL || cur_ops->cb_barrier == NULL) {
2caa1e443   Paul E. McKenney   rcu: Switch rcuto...
1739
1740
1741
1742
1743
1744
1745
1746
  		pr_alert("%s" TORTURE_FLAG
  			 " Call or barrier ops missing for %s,
  ",
  			 torture_type, cur_ops->name);
  		pr_alert("%s" TORTURE_FLAG
  			 " RCU barrier testing omitted from run.
  ",
  			 torture_type);
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
  		return 0;
  	}
  	atomic_set(&barrier_cbs_count, 0);
  	atomic_set(&barrier_cbs_invoked, 0);
  	barrier_cbs_tasks =
  		kzalloc(n_barrier_cbs * sizeof(barrier_cbs_tasks[0]),
  			GFP_KERNEL);
  	barrier_cbs_wq =
  		kzalloc(n_barrier_cbs * sizeof(barrier_cbs_wq[0]),
  			GFP_KERNEL);
de5e64378   Sasha Levin   rcutorture: Don't...
1757
  	if (barrier_cbs_tasks == NULL || !barrier_cbs_wq)
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
1758
1759
1760
1761
  		return -ENOMEM;
  	for (i = 0; i < n_barrier_cbs; i++) {
  		init_waitqueue_head(&barrier_cbs_wq[i]);
  		barrier_cbs_tasks[i] = kthread_run(rcu_torture_barrier_cbs,
9059c9401   Lai Jiangshan   rcu: Add rcutortu...
1762
  						   (void *)(long)i,
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
  						   "rcu_torture_barrier_cbs");
  		if (IS_ERR(barrier_cbs_tasks[i])) {
  			ret = PTR_ERR(barrier_cbs_tasks[i]);
  			VERBOSE_PRINTK_ERRSTRING("Failed to create rcu_torture_barrier_cbs");
  			barrier_cbs_tasks[i] = NULL;
  			return ret;
  		}
  	}
  	barrier_task = kthread_run(rcu_torture_barrier, NULL,
  				   "rcu_torture_barrier");
  	if (IS_ERR(barrier_task)) {
  		ret = PTR_ERR(barrier_task);
  		VERBOSE_PRINTK_ERRSTRING("Failed to create rcu_torture_barrier");
  		barrier_task = NULL;
  	}
  	return 0;
  }
  
  /* Clean up after RCU barrier testing. */
  static void rcu_torture_barrier_cleanup(void)
  {
  	int i;
  
  	if (barrier_task != NULL) {
  		VERBOSE_PRINTK_STRING("Stopping rcu_torture_barrier task");
  		kthread_stop(barrier_task);
  		barrier_task = NULL;
  	}
  	if (barrier_cbs_tasks != NULL) {
  		for (i = 0; i < n_barrier_cbs; i++) {
  			if (barrier_cbs_tasks[i] != NULL) {
  				VERBOSE_PRINTK_STRING("Stopping rcu_torture_barrier_cbs task");
  				kthread_stop(barrier_cbs_tasks[i]);
  				barrier_cbs_tasks[i] = NULL;
  			}
  		}
  		kfree(barrier_cbs_tasks);
  		barrier_cbs_tasks = NULL;
  	}
  	if (barrier_cbs_wq != NULL) {
  		kfree(barrier_cbs_wq);
  		barrier_cbs_wq = NULL;
  	}
  }
8e8be45e8   Paul E. McKenney   rcu: add priority...
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
  static int rcutorture_cpu_notify(struct notifier_block *self,
  				 unsigned long action, void *hcpu)
  {
  	long cpu = (long)hcpu;
  
  	switch (action) {
  	case CPU_ONLINE:
  	case CPU_DOWN_FAILED:
  		(void)rcutorture_booster_init(cpu);
  		break;
  	case CPU_DOWN_PREPARE:
  		rcutorture_booster_cleanup(cpu);
  		break;
  	default:
  		break;
  	}
  	return NOTIFY_OK;
  }
  
  static struct notifier_block rcutorture_cpu_nb = {
  	.notifier_call = rcutorture_cpu_notify,
  };
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1829
1830
1831
1832
  static void
  rcu_torture_cleanup(void)
  {
  	int i;
343e9099c   Paul E. McKenney   rcu: fix rcutortu...
1833
  	mutex_lock(&fullstop_mutex);
4a2986568   Paul E. McKenney   rcu: make rcutort...
1834
  	rcutorture_record_test_transition();
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
1835
  	if (fullstop == FULLSTOP_SHUTDOWN) {
2caa1e443   Paul E. McKenney   rcu: Switch rcuto...
1836
  		pr_warn(/* but going down anyway, so... */
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
1837
1838
  		       "Concurrent 'rmmod rcutorture' and shutdown illegal!
  ");
343e9099c   Paul E. McKenney   rcu: fix rcutortu...
1839
  		mutex_unlock(&fullstop_mutex);
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
1840
  		schedule_timeout_uninterruptible(10);
343e9099c   Paul E. McKenney   rcu: fix rcutortu...
1841
1842
1843
1844
  		if (cur_ops->cb_barrier != NULL)
  			cur_ops->cb_barrier();
  		return;
  	}
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
1845
  	fullstop = FULLSTOP_RMMOD;
343e9099c   Paul E. McKenney   rcu: fix rcutortu...
1846
  	mutex_unlock(&fullstop_mutex);
8e8be45e8   Paul E. McKenney   rcu: add priority...
1847
  	unregister_reboot_notifier(&rcutorture_shutdown_nb);
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
1848
  	rcu_torture_barrier_cleanup();
c13f3757d   Paul E. McKenney   rcu: Add CPU-stal...
1849
  	rcu_torture_stall_cleanup();
d120f65f3   Paul E. McKenney   rcu: make rcutort...
1850
1851
1852
1853
1854
  	if (stutter_task) {
  		VERBOSE_PRINTK_STRING("Stopping rcu_torture_stutter task");
  		kthread_stop(stutter_task);
  	}
  	stutter_task = NULL;
c8e5b1631   Josh Triplett   rcutorture: style...
1855
  	if (shuffler_task) {
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1856
1857
  		VERBOSE_PRINTK_STRING("Stopping rcu_torture_shuffle task");
  		kthread_stop(shuffler_task);
73d0a4b10   Rusty Russell   cpumask: convert ...
1858
  		free_cpumask_var(shuffle_tmp_mask);
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1859
1860
  	}
  	shuffler_task = NULL;
c8e5b1631   Josh Triplett   rcutorture: style...
1861
  	if (writer_task) {
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1862
1863
1864
1865
  		VERBOSE_PRINTK_STRING("Stopping rcu_torture_writer task");
  		kthread_stop(writer_task);
  	}
  	writer_task = NULL;
c8e5b1631   Josh Triplett   rcutorture: style...
1866
  	if (reader_tasks) {
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1867
  		for (i = 0; i < nrealreaders; i++) {
c8e5b1631   Josh Triplett   rcutorture: style...
1868
  			if (reader_tasks[i]) {
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
  				VERBOSE_PRINTK_STRING(
  					"Stopping rcu_torture_reader task");
  				kthread_stop(reader_tasks[i]);
  			}
  			reader_tasks[i] = NULL;
  		}
  		kfree(reader_tasks);
  		reader_tasks = NULL;
  	}
  	rcu_torture_current = NULL;
c8e5b1631   Josh Triplett   rcutorture: style...
1879
  	if (fakewriter_tasks) {
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
1880
  		for (i = 0; i < nfakewriters; i++) {
c8e5b1631   Josh Triplett   rcutorture: style...
1881
  			if (fakewriter_tasks[i]) {
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
1882
1883
1884
1885
1886
1887
1888
1889
1890
  				VERBOSE_PRINTK_STRING(
  					"Stopping rcu_torture_fakewriter task");
  				kthread_stop(fakewriter_tasks[i]);
  			}
  			fakewriter_tasks[i] = NULL;
  		}
  		kfree(fakewriter_tasks);
  		fakewriter_tasks = NULL;
  	}
c8e5b1631   Josh Triplett   rcutorture: style...
1891
  	if (stats_task) {
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1892
1893
1894
1895
  		VERBOSE_PRINTK_STRING("Stopping rcu_torture_stats task");
  		kthread_stop(stats_task);
  	}
  	stats_task = NULL;
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
1896
1897
1898
1899
1900
  	if (fqs_task) {
  		VERBOSE_PRINTK_STRING("Stopping rcu_torture_fqs task");
  		kthread_stop(fqs_task);
  	}
  	fqs_task = NULL;
8e8be45e8   Paul E. McKenney   rcu: add priority...
1901
1902
1903
1904
1905
1906
  	if ((test_boost == 1 && cur_ops->can_boost) ||
  	    test_boost == 2) {
  		unregister_cpu_notifier(&rcutorture_cpu_nb);
  		for_each_possible_cpu(i)
  			rcutorture_booster_cleanup(i);
  	}
d5f546d83   Paul E. McKenney   rcu: Add rcutortu...
1907
1908
1909
1910
  	if (shutdown_task != NULL) {
  		VERBOSE_PRINTK_STRING("Stopping rcu_torture_shutdown task");
  		kthread_stop(shutdown_task);
  	}
37e377d28   Paul E. McKenney   rcu: Fixes to rcu...
1911
  	shutdown_task = NULL;
b58bdccaa   Paul E. McKenney   rcu: Add rcutortu...
1912
  	rcu_torture_onoff_cleanup();
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
1913

a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1914
  	/* Wait for all RCU callbacks to fire.  */
2326974df   Paul E. McKenney   rcu: add call_rcu...
1915
1916
1917
  
  	if (cur_ops->cb_barrier != NULL)
  		cur_ops->cb_barrier();
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1918

a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1919
  	rcu_torture_stats_print();  /* -After- the stats thread is stopped! */
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
1920

fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
1921
  	if (atomic_read(&n_rcu_torture_error) || n_rcu_torture_barrier_error)
8e8be45e8   Paul E. McKenney   rcu: add priority...
1922
  		rcu_torture_print_module_parms(cur_ops, "End of test: FAILURE");
091541bbd   Paul E. McKenney   rcu: Make rcutort...
1923
1924
1925
1926
  	else if (n_online_successes != n_online_attempts ||
  		 n_offline_successes != n_offline_attempts)
  		rcu_torture_print_module_parms(cur_ops,
  					       "End of test: RCU_HOTPLUG");
95c383227   Paul E. McKenney   [PATCH] rcutortur...
1927
  	else
8e8be45e8   Paul E. McKenney   rcu: add priority...
1928
  		rcu_torture_print_module_parms(cur_ops, "End of test: SUCCESS");
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1929
  }
6f8bc500a   Josh Triplett   rcutorture: Mark ...
1930
  static int __init
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1931
1932
1933
1934
1935
  rcu_torture_init(void)
  {
  	int i;
  	int cpu;
  	int firsterr = 0;
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
1936
  	int retval;
ade5fb818   Josh Triplett   rcutorture: Remov...
1937
  	static struct rcu_torture_ops *torture_ops[] =
d9a3da069   Paul E. McKenney   rcu: Add expedite...
1938
  		{ &rcu_ops, &rcu_sync_ops, &rcu_expedited_ops,
bdf2a4364   Paul E. McKenney   rcu: Catch rcutor...
1939
  		  &rcu_bh_ops, &rcu_bh_sync_ops, &rcu_bh_expedited_ops,
751a68b2e   Paul E. McKenney   rcu: Rationalize ...
1940
1941
  		  &srcu_ops, &srcu_sync_ops, &srcu_expedited_ops,
  		  &srcu_raw_ops, &srcu_raw_sync_ops,
804bb8370   Paul E. McKenney   rcu: Add synchron...
1942
  		  &sched_ops, &sched_sync_ops, &sched_expedited_ops, };
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1943

343e9099c   Paul E. McKenney   rcu: fix rcutortu...
1944
  	mutex_lock(&fullstop_mutex);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1945
  	/* Process args and tell the world that the torturer is on the job. */
ade5fb818   Josh Triplett   rcutorture: Remov...
1946
  	for (i = 0; i < ARRAY_SIZE(torture_ops); i++) {
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
1947
  		cur_ops = torture_ops[i];
ade5fb818   Josh Triplett   rcutorture: Remov...
1948
  		if (strcmp(torture_type, cur_ops->name) == 0)
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
1949
  			break;
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
1950
  	}
ade5fb818   Josh Triplett   rcutorture: Remov...
1951
  	if (i == ARRAY_SIZE(torture_ops)) {
2caa1e443   Paul E. McKenney   rcu: Switch rcuto...
1952
1953
1954
1955
  		pr_alert("rcu-torture: invalid torture type: \"%s\"
  ",
  			 torture_type);
  		pr_alert("rcu-torture types:");
cf886c44e   Paul E. McKenney   rcu: Improve rcut...
1956
  		for (i = 0; i < ARRAY_SIZE(torture_ops); i++)
2caa1e443   Paul E. McKenney   rcu: Switch rcuto...
1957
1958
1959
  			pr_alert(" %s", torture_ops[i]->name);
  		pr_alert("
  ");
343e9099c   Paul E. McKenney   rcu: fix rcutortu...
1960
  		mutex_unlock(&fullstop_mutex);
a71fca58b   Paul E. McKenney   rcu: Fix whitespa...
1961
  		return -EINVAL;
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
1962
  	}
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
1963
  	if (cur_ops->fqs == NULL && fqs_duration != 0) {
2caa1e443   Paul E. McKenney   rcu: Switch rcuto...
1964
1965
  		pr_alert("rcu-torture: ->fqs NULL and non-zero fqs_duration, fqs disabled.
  ");
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
1966
1967
  		fqs_duration = 0;
  	}
c8e5b1631   Josh Triplett   rcutorture: style...
1968
  	if (cur_ops->init)
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
1969
  		cur_ops->init(); /* no "goto unwind" prior to this point!!! */
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1970
1971
1972
1973
  	if (nreaders >= 0)
  		nrealreaders = nreaders;
  	else
  		nrealreaders = 2 * num_online_cpus();
8e8be45e8   Paul E. McKenney   rcu: add priority...
1974
  	rcu_torture_print_module_parms(cur_ops, "Start of test");
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
1975
  	fullstop = FULLSTOP_DONTSTOP;
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1976
1977
1978
1979
  
  	/* Set up the freelist. */
  
  	INIT_LIST_HEAD(&rcu_torture_freelist);
788e770eb   Ahmed S. Darwish   rcutorture: Use A...
1980
  	for (i = 0; i < ARRAY_SIZE(rcu_tortures); i++) {
996417d2c   Paul E. McKenney   [PATCH] add succe...
1981
  		rcu_tortures[i].rtort_mbtest = 0;
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
  		list_add_tail(&rcu_tortures[i].rtort_free,
  			      &rcu_torture_freelist);
  	}
  
  	/* Initialize the statistics so that each run gets its own numbers. */
  
  	rcu_torture_current = NULL;
  	rcu_torture_current_version = 0;
  	atomic_set(&n_rcu_torture_alloc, 0);
  	atomic_set(&n_rcu_torture_alloc_fail, 0);
  	atomic_set(&n_rcu_torture_free, 0);
996417d2c   Paul E. McKenney   [PATCH] add succe...
1993
1994
  	atomic_set(&n_rcu_torture_mberror, 0);
  	atomic_set(&n_rcu_torture_error, 0);
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
1995
  	n_rcu_torture_barrier_error = 0;
8e8be45e8   Paul E. McKenney   rcu: add priority...
1996
1997
  	n_rcu_torture_boost_ktrerror = 0;
  	n_rcu_torture_boost_rterror = 0;
8e8be45e8   Paul E. McKenney   rcu: add priority...
1998
1999
  	n_rcu_torture_boost_failure = 0;
  	n_rcu_torture_boosts = 0;
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
2000
2001
  	for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++)
  		atomic_set(&rcu_torture_wcount[i], 0);
0a9450227   KAMEZAWA Hiroyuki   [PATCH] for_each_...
2002
  	for_each_possible_cpu(cpu) {
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
2003
2004
2005
2006
2007
2008
2009
2010
2011
  		for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) {
  			per_cpu(rcu_torture_count, cpu)[i] = 0;
  			per_cpu(rcu_torture_batch, cpu)[i] = 0;
  		}
  	}
  
  	/* Start up the kthreads. */
  
  	VERBOSE_PRINTK_STRING("Creating rcu_torture_writer task");
60f53782c   Paul E. McKenney   rcu: Prevent init...
2012
2013
  	writer_task = kthread_create(rcu_torture_writer, NULL,
  				     "rcu_torture_writer");
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
2014
2015
2016
2017
2018
2019
  	if (IS_ERR(writer_task)) {
  		firsterr = PTR_ERR(writer_task);
  		VERBOSE_PRINTK_ERRSTRING("Failed to create writer");
  		writer_task = NULL;
  		goto unwind;
  	}
60f53782c   Paul E. McKenney   rcu: Prevent init...
2020
  	wake_up_process(writer_task);
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
2021
  	fakewriter_tasks = kzalloc(nfakewriters * sizeof(fakewriter_tasks[0]),
a71fca58b   Paul E. McKenney   rcu: Fix whitespa...
2022
  				   GFP_KERNEL);
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
2023
2024
2025
2026
2027
2028
2029
2030
  	if (fakewriter_tasks == NULL) {
  		VERBOSE_PRINTK_ERRSTRING("out of memory");
  		firsterr = -ENOMEM;
  		goto unwind;
  	}
  	for (i = 0; i < nfakewriters; i++) {
  		VERBOSE_PRINTK_STRING("Creating rcu_torture_fakewriter task");
  		fakewriter_tasks[i] = kthread_run(rcu_torture_fakewriter, NULL,
a71fca58b   Paul E. McKenney   rcu: Fix whitespa...
2031
  						  "rcu_torture_fakewriter");
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
2032
2033
2034
2035
2036
2037
2038
  		if (IS_ERR(fakewriter_tasks[i])) {
  			firsterr = PTR_ERR(fakewriter_tasks[i]);
  			VERBOSE_PRINTK_ERRSTRING("Failed to create fakewriter");
  			fakewriter_tasks[i] = NULL;
  			goto unwind;
  		}
  	}
2860aaba4   Josh Triplett   [PATCH] rcu: Avoi...
2039
  	reader_tasks = kzalloc(nrealreaders * sizeof(reader_tasks[0]),
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
  			       GFP_KERNEL);
  	if (reader_tasks == NULL) {
  		VERBOSE_PRINTK_ERRSTRING("out of memory");
  		firsterr = -ENOMEM;
  		goto unwind;
  	}
  	for (i = 0; i < nrealreaders; i++) {
  		VERBOSE_PRINTK_STRING("Creating rcu_torture_reader task");
  		reader_tasks[i] = kthread_run(rcu_torture_reader, NULL,
  					      "rcu_torture_reader");
  		if (IS_ERR(reader_tasks[i])) {
  			firsterr = PTR_ERR(reader_tasks[i]);
  			VERBOSE_PRINTK_ERRSTRING("Failed to create reader");
  			reader_tasks[i] = NULL;
  			goto unwind;
  		}
  	}
  	if (stat_interval > 0) {
  		VERBOSE_PRINTK_STRING("Creating rcu_torture_stats task");
  		stats_task = kthread_run(rcu_torture_stats, NULL,
  					"rcu_torture_stats");
  		if (IS_ERR(stats_task)) {
  			firsterr = PTR_ERR(stats_task);
  			VERBOSE_PRINTK_ERRSTRING("Failed to create stats");
  			stats_task = NULL;
  			goto unwind;
  		}
  	}
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
2068
2069
  	if (test_no_idle_hz) {
  		rcu_idle_cpu = num_online_cpus() - 1;
73d0a4b10   Rusty Russell   cpumask: convert ...
2070
2071
2072
2073
2074
2075
  
  		if (!alloc_cpumask_var(&shuffle_tmp_mask, GFP_KERNEL)) {
  			firsterr = -ENOMEM;
  			VERBOSE_PRINTK_ERRSTRING("Failed to alloc mask");
  			goto unwind;
  		}
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
2076
2077
2078
2079
  		/* Create the shuffler thread */
  		shuffler_task = kthread_run(rcu_torture_shuffle, NULL,
  					  "rcu_torture_shuffle");
  		if (IS_ERR(shuffler_task)) {
73d0a4b10   Rusty Russell   cpumask: convert ...
2080
  			free_cpumask_var(shuffle_tmp_mask);
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
2081
2082
2083
2084
2085
2086
  			firsterr = PTR_ERR(shuffler_task);
  			VERBOSE_PRINTK_ERRSTRING("Failed to create shuffler");
  			shuffler_task = NULL;
  			goto unwind;
  		}
  	}
d120f65f3   Paul E. McKenney   rcu: make rcutort...
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
  	if (stutter < 0)
  		stutter = 0;
  	if (stutter) {
  		/* Create the stutter thread */
  		stutter_task = kthread_run(rcu_torture_stutter, NULL,
  					  "rcu_torture_stutter");
  		if (IS_ERR(stutter_task)) {
  			firsterr = PTR_ERR(stutter_task);
  			VERBOSE_PRINTK_ERRSTRING("Failed to create stutter");
  			stutter_task = NULL;
  			goto unwind;
  		}
  	}
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
  	if (fqs_duration < 0)
  		fqs_duration = 0;
  	if (fqs_duration) {
  		/* Create the stutter thread */
  		fqs_task = kthread_run(rcu_torture_fqs, NULL,
  				       "rcu_torture_fqs");
  		if (IS_ERR(fqs_task)) {
  			firsterr = PTR_ERR(fqs_task);
  			VERBOSE_PRINTK_ERRSTRING("Failed to create fqs");
  			fqs_task = NULL;
  			goto unwind;
  		}
  	}
8e8be45e8   Paul E. McKenney   rcu: add priority...
2113
2114
2115
2116
2117
2118
  	if (test_boost_interval < 1)
  		test_boost_interval = 1;
  	if (test_boost_duration < 2)
  		test_boost_duration = 2;
  	if ((test_boost == 1 && cur_ops->can_boost) ||
  	    test_boost == 2) {
8e8be45e8   Paul E. McKenney   rcu: add priority...
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
  
  		boost_starttime = jiffies + test_boost_interval * HZ;
  		register_cpu_notifier(&rcutorture_cpu_nb);
  		for_each_possible_cpu(i) {
  			if (cpu_is_offline(i))
  				continue;  /* Heuristic: CPU can go offline. */
  			retval = rcutorture_booster_init(i);
  			if (retval < 0) {
  				firsterr = retval;
  				goto unwind;
  			}
  		}
  	}
d5f546d83   Paul E. McKenney   rcu: Add rcutortu...
2132
2133
  	if (shutdown_secs > 0) {
  		shutdown_time = jiffies + shutdown_secs * HZ;
60f53782c   Paul E. McKenney   rcu: Prevent init...
2134
2135
  		shutdown_task = kthread_create(rcu_torture_shutdown, NULL,
  					       "rcu_torture_shutdown");
d5f546d83   Paul E. McKenney   rcu: Add rcutortu...
2136
2137
2138
2139
2140
2141
  		if (IS_ERR(shutdown_task)) {
  			firsterr = PTR_ERR(shutdown_task);
  			VERBOSE_PRINTK_ERRSTRING("Failed to create shutdown");
  			shutdown_task = NULL;
  			goto unwind;
  		}
60f53782c   Paul E. McKenney   rcu: Prevent init...
2142
  		wake_up_process(shutdown_task);
d5f546d83   Paul E. McKenney   rcu: Add rcutortu...
2143
  	}
37e377d28   Paul E. McKenney   rcu: Fixes to rcu...
2144
2145
2146
2147
2148
  	i = rcu_torture_onoff_init();
  	if (i != 0) {
  		firsterr = i;
  		goto unwind;
  	}
8e8be45e8   Paul E. McKenney   rcu: add priority...
2149
  	register_reboot_notifier(&rcutorture_shutdown_nb);
37e377d28   Paul E. McKenney   rcu: Fixes to rcu...
2150
2151
2152
2153
2154
  	i = rcu_torture_stall_init();
  	if (i != 0) {
  		firsterr = i;
  		goto unwind;
  	}
fae4b54f2   Paul E. McKenney   rcu: Introduce rc...
2155
2156
2157
2158
2159
  	retval = rcu_torture_barrier_init();
  	if (retval != 0) {
  		firsterr = retval;
  		goto unwind;
  	}
4a2986568   Paul E. McKenney   rcu: make rcutort...
2160
  	rcutorture_record_test_transition();
343e9099c   Paul E. McKenney   rcu: fix rcutortu...
2161
  	mutex_unlock(&fullstop_mutex);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
2162
2163
2164
  	return 0;
  
  unwind:
343e9099c   Paul E. McKenney   rcu: fix rcutortu...
2165
  	mutex_unlock(&fullstop_mutex);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
2166
2167
2168
2169
2170
2171
  	rcu_torture_cleanup();
  	return firsterr;
  }
  
  module_init(rcu_torture_init);
  module_exit(rcu_torture_cleanup);