Blame view

kernel/rcutorture.c 46.2 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>
f07767fd0   Harvey Harrison   byteorder: remove...
49
  #include <asm/byteorder.h>
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
50
51
  
  MODULE_LICENSE("GPL");
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
52
  MODULE_AUTHOR("Paul E. McKenney <paulmck@us.ibm.com> and "
a71fca58b   Paul E. McKenney   rcu: Fix whitespa...
53
  	      "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 */
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
57
  static int stat_interval;	/* Interval between stats, in seconds. */
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
58
  				/*  Defaults to "only at end of test". */
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
59
60
  static int verbose;		/* Print more debug info. */
  static int test_no_idle_hz;	/* Test RCU's support for tickless idle CPUs. */
d120f65f3   Paul E. McKenney   rcu: make rcutort...
61
62
  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...
63
  static int irqreader = 1;	/* RCU readers from irq (timers). */
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
64
65
66
  static int fqs_duration = 0;	/* Duration of bursts (us), 0 to disable. */
  static int fqs_holdoff = 0;	/* Hold time within burst (us). */
  static int fqs_stutter = 3;	/* Wait time between bursts (s). */
8e8be45e8   Paul E. McKenney   rcu: add priority...
67
68
69
  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 ...
70
  static char *torture_type = "rcu"; /* What RCU implementation to torture. */
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
71

d6ad67112   Josh Triplett   [PATCH] Publish r...
72
  module_param(nreaders, int, 0444);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
73
  MODULE_PARM_DESC(nreaders, "Number of RCU reader threads");
d6ad67112   Josh Triplett   [PATCH] Publish r...
74
  module_param(nfakewriters, int, 0444);
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
75
  MODULE_PARM_DESC(nfakewriters, "Number of RCU fake writer threads");
3721bc1d3   Paul E. McKenney   rcu: Allow rcutor...
76
  module_param(stat_interval, int, 0644);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
77
  MODULE_PARM_DESC(stat_interval, "Number of seconds between stats printk()s");
d6ad67112   Josh Triplett   [PATCH] Publish r...
78
  module_param(verbose, bool, 0444);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
79
  MODULE_PARM_DESC(verbose, "Enable verbose debugging printk()s");
d6ad67112   Josh Triplett   [PATCH] Publish r...
80
  module_param(test_no_idle_hz, bool, 0444);
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
81
  MODULE_PARM_DESC(test_no_idle_hz, "Test support for tickless idle CPUs");
d6ad67112   Josh Triplett   [PATCH] Publish r...
82
  module_param(shuffle_interval, int, 0444);
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
83
  MODULE_PARM_DESC(shuffle_interval, "Number of seconds between shuffles");
d120f65f3   Paul E. McKenney   rcu: make rcutort...
84
85
  module_param(stutter, int, 0444);
  MODULE_PARM_DESC(stutter, "Number of seconds to run/halt test");
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
86
87
  module_param(irqreader, int, 0444);
  MODULE_PARM_DESC(irqreader, "Allow RCU readers from irq handlers");
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
88
89
90
91
92
93
  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)");
8e8be45e8   Paul E. McKenney   rcu: add priority...
94
95
96
97
98
99
  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...
100
  module_param(torture_type, charp, 0444);
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
101
  MODULE_PARM_DESC(torture_type, "Type of RCU to torture (rcu, rcu_bh, srcu)");
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
102
103
  
  #define TORTURE_FLAG "-torture:"
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
104
  #define PRINTK_STRING(s) \
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
105
106
  	do { printk(KERN_ALERT "%s" TORTURE_FLAG s "
  ", torture_type); } while (0)
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
107
  #define VERBOSE_PRINTK_STRING(s) \
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
108
109
  	do { if (verbose) printk(KERN_ALERT "%s" TORTURE_FLAG s "
  ", torture_type); } while (0)
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
110
  #define VERBOSE_PRINTK_ERRSTRING(s) \
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
111
112
  	do { if (verbose) printk(KERN_ALERT "%s" TORTURE_FLAG "!!! " s "
  ", torture_type); } while (0)
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
113
114
115
116
117
  
  static char printk_buf[4096];
  
  static int nrealreaders;
  static struct task_struct *writer_task;
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
118
  static struct task_struct **fakewriter_tasks;
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
119
120
  static struct task_struct **reader_tasks;
  static struct task_struct *stats_task;
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
121
  static struct task_struct *shuffler_task;
d120f65f3   Paul E. McKenney   rcu: make rcutort...
122
  static struct task_struct *stutter_task;
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
123
  static struct task_struct *fqs_task;
8e8be45e8   Paul E. McKenney   rcu: add priority...
124
  static struct task_struct *boost_tasks[NR_CPUS];
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
125
126
127
128
129
130
131
  
  #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...
132
  	int rtort_mbtest;
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
133
  };
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
134
  static LIST_HEAD(rcu_torture_freelist);
0ddea0ead   Paul E. McKenney   rcu: fix sparse e...
135
  static struct rcu_torture __rcu *rcu_torture_current;
4a2986568   Paul E. McKenney   rcu: make rcutort...
136
  static unsigned long rcu_torture_current_version;
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
137
138
139
140
141
142
143
  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...
144
145
146
147
148
  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;
8e8be45e8   Paul E. McKenney   rcu: add priority...
149
150
  static long n_rcu_torture_boost_ktrerror;
  static long n_rcu_torture_boost_rterror;
8e8be45e8   Paul E. McKenney   rcu: add priority...
151
152
  static long n_rcu_torture_boost_failure;
  static long n_rcu_torture_boosts;
a71fca58b   Paul E. McKenney   rcu: Fix whitespa...
153
  static long n_rcu_torture_timers;
e30337365   Josh Triplett   [PATCH] rcu: refa...
154
  static struct list_head rcu_torture_removed;
73d0a4b10   Rusty Russell   cpumask: convert ...
155
  static cpumask_var_t shuffle_tmp_mask;
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
156

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

31a72bce0   Paul E. McKenney   rcu: make rcutort...
159
160
161
162
163
164
  #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;
3acf4a9a3   Paul E. McKenney   rcu: avoid hammer...
165
  #if defined(CONFIG_RCU_BOOST) && !defined(CONFIG_HOTPLUG_CPU)
8e8be45e8   Paul E. McKenney   rcu: add priority...
166
  #define rcu_can_boost() 1
3acf4a9a3   Paul E. McKenney   rcu: avoid hammer...
167
  #else /* #if defined(CONFIG_RCU_BOOST) && !defined(CONFIG_HOTPLUG_CPU) */
8e8be45e8   Paul E. McKenney   rcu: add priority...
168
  #define rcu_can_boost() 0
3acf4a9a3   Paul E. McKenney   rcu: avoid hammer...
169
  #endif /* #else #if defined(CONFIG_RCU_BOOST) && !defined(CONFIG_HOTPLUG_CPU) */
8e8be45e8   Paul E. McKenney   rcu: add priority...
170
171
172
173
  
  static unsigned long boost_starttime;	/* jiffies of next boost test start. */
  DEFINE_MUTEX(boost_mutex);		/* protect setting boost_starttime */
  					/*  and boost task create/destroy. */
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
174
175
176
177
178
179
  /* 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...
180
181
182
183
  /*
   * Protect fullstop transitions and spawning of kthreads.
   */
  static DEFINE_MUTEX(fullstop_mutex);
343e9099c   Paul E. McKenney   rcu: fix rcutortu...
184
185
  
  /*
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
186
   * Detect and respond to a system shutdown.
343e9099c   Paul E. McKenney   rcu: fix rcutortu...
187
188
189
190
191
   */
  static int
  rcutorture_shutdown_notify(struct notifier_block *unused1,
  			   unsigned long unused2, void *unused3)
  {
c59ab97e9   Paul E. McKenney   rcu: fix rcutortu...
192
  	mutex_lock(&fullstop_mutex);
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
193
  	if (fullstop == FULLSTOP_DONTSTOP)
c59ab97e9   Paul E. McKenney   rcu: fix rcutortu...
194
  		fullstop = FULLSTOP_SHUTDOWN;
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
195
196
197
198
  	else
  		printk(KERN_WARNING /* but going down anyway, so... */
  		       "Concurrent 'rmmod rcutorture' and shutdown illegal!
  ");
c59ab97e9   Paul E. McKenney   rcu: fix rcutortu...
199
  	mutex_unlock(&fullstop_mutex);
343e9099c   Paul E. McKenney   rcu: fix rcutortu...
200
201
  	return NOTIFY_DONE;
  }
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
202
  /*
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
   * 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) {
  		printk(KERN_NOTICE
  		       "rcutorture thread %s parking due to system shutdown
  ",
  		       title);
  		schedule_timeout_uninterruptible(MAX_SCHEDULE_TIMEOUT);
  	}
  }
  
  /*
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
218
219
   * Allocate an element from the rcu_tortures pool.
   */
97a41e261   Adrian Bunk   [PATCH] kernel/: ...
220
  static struct rcu_torture *
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
221
222
223
  rcu_torture_alloc(void)
  {
  	struct list_head *p;
adac16652   Ingo Molnar   [PATCH] rcu_tortu...
224
  	spin_lock_bh(&rcu_torture_lock);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
225
226
  	if (list_empty(&rcu_torture_freelist)) {
  		atomic_inc(&n_rcu_torture_alloc_fail);
adac16652   Ingo Molnar   [PATCH] rcu_tortu...
227
  		spin_unlock_bh(&rcu_torture_lock);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
228
229
230
231
232
  		return NULL;
  	}
  	atomic_inc(&n_rcu_torture_alloc);
  	p = rcu_torture_freelist.next;
  	list_del_init(p);
adac16652   Ingo Molnar   [PATCH] rcu_tortu...
233
  	spin_unlock_bh(&rcu_torture_lock);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
234
235
236
237
238
239
240
241
242
243
  	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...
244
  	spin_lock_bh(&rcu_torture_lock);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
245
  	list_add_tail(&p->rtort_free, &rcu_torture_freelist);
adac16652   Ingo Molnar   [PATCH] rcu_tortu...
246
  	spin_unlock_bh(&rcu_torture_lock);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
247
  }
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
248
249
  struct rcu_random_state {
  	unsigned long rrs_state;
75cfef32f   Josh Triplett   [PATCH] rcu: Fix ...
250
  	long rrs_count;
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
251
252
253
254
255
256
257
258
259
260
  };
  
  #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...
261
   * generator, with occasional help from cpu_clock().
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
262
   */
75cfef32f   Josh Triplett   [PATCH] rcu: Fix ...
263
  static unsigned long
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
264
265
  rcu_random(struct rcu_random_state *rrsp)
  {
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
266
  	if (--rrsp->rrs_count < 0) {
c676329ab   Peter Zijlstra   sched_clock: Add ...
267
  		rrsp->rrs_state += (unsigned long)local_clock();
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
268
269
270
271
272
  		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...
273
  static void
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
274
  rcu_stutter_wait(char *title)
d120f65f3   Paul E. McKenney   rcu: make rcutort...
275
  {
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
276
  	while (stutter_pause_test || !rcutorture_runnable) {
e3d7be270   Paul E. McKenney   rcu, rcutorture: ...
277
278
279
  		if (rcutorture_runnable)
  			schedule_timeout_interruptible(1);
  		else
3ccf79f45   Paul E. McKenney   rcu: make quiesce...
280
  			schedule_timeout_interruptible(round_jiffies_relative(HZ));
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
281
  		rcutorture_shutdown_absorb(title);
343e9099c   Paul E. McKenney   rcu: fix rcutortu...
282
  	}
d120f65f3   Paul E. McKenney   rcu: make rcutort...
283
  }
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
284
  /*
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
285
286
287
288
289
290
291
   * Operations vector for selecting different types of tests.
   */
  
  struct rcu_torture_ops {
  	void (*init)(void);
  	void (*cleanup)(void);
  	int (*readlock)(void);
0acc512cb   Paul E. McKenney   rcu: Add synchron...
292
  	void (*read_delay)(struct rcu_random_state *rrsp);
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
293
294
  	void (*readunlock)(int idx);
  	int (*completed)(void);
0acc512cb   Paul E. McKenney   rcu: Add synchron...
295
  	void (*deferred_free)(struct rcu_torture *p);
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
296
  	void (*sync)(void);
2326974df   Paul E. McKenney   rcu: add call_rcu...
297
  	void (*cb_barrier)(void);
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
298
  	void (*fqs)(void);
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
299
  	int (*stats)(char *page);
0acc512cb   Paul E. McKenney   rcu: Add synchron...
300
  	int irq_capable;
8e8be45e8   Paul E. McKenney   rcu: add priority...
301
  	int can_boost;
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
302
303
  	char *name;
  };
a71fca58b   Paul E. McKenney   rcu: Fix whitespa...
304
305
  
  static struct rcu_torture_ops *cur_ops;
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
306
307
308
309
  
  /*
   * Definitions for rcu torture testing.
   */
a49a4af75   Josh Triplett   [PATCH] rcu: add ...
310
  static int rcu_torture_read_lock(void) __acquires(RCU)
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
311
312
313
314
  {
  	rcu_read_lock();
  	return 0;
  }
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
315
316
  static void rcu_read_delay(struct rcu_random_state *rrsp)
  {
b8d57a76d   Josh Triplett   rcutorture: Occas...
317
318
  	const unsigned long shortdelay_us = 200;
  	const unsigned long longdelay_ms = 50;
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
319

b8d57a76d   Josh Triplett   rcutorture: Occas...
320
321
322
  	/* 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...
323

b8d57a76d   Josh Triplett   rcutorture: Occas...
324
325
326
327
  	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...
328
329
330
331
  #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...
332
  }
a49a4af75   Josh Triplett   [PATCH] rcu: add ...
333
  static void rcu_torture_read_unlock(int idx) __releases(RCU)
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
334
335
336
337
338
339
340
341
342
343
344
345
346
347
  {
  	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...
348
  	if (fullstop != FULLSTOP_DONTSTOP) {
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
349
350
351
352
353
354
355
356
357
358
359
360
  		/* 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);
  	} else
0acc512cb   Paul E. McKenney   rcu: Add synchron...
361
  		cur_ops->deferred_free(rp);
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
362
  }
d9a3da069   Paul E. McKenney   rcu: Add expedite...
363
364
365
366
  static int rcu_no_completed(void)
  {
  	return 0;
  }
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
367
368
369
370
371
372
  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...
373
374
375
376
377
378
379
380
381
  	.init		= NULL,
  	.cleanup	= NULL,
  	.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,
  	.cb_barrier	= rcu_barrier,
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
382
  	.fqs		= rcu_force_quiescent_state,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
383
  	.stats		= NULL,
a71fca58b   Paul E. McKenney   rcu: Fix whitespa...
384
  	.irq_capable	= 1,
8e8be45e8   Paul E. McKenney   rcu: add priority...
385
  	.can_boost	= rcu_can_boost(),
a71fca58b   Paul E. McKenney   rcu: Fix whitespa...
386
  	.name		= "rcu"
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
387
  };
e30337365   Josh Triplett   [PATCH] rcu: refa...
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
  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 ...
413
  static struct rcu_torture_ops rcu_sync_ops = {
0acc512cb   Paul E. McKenney   rcu: Add synchron...
414
415
416
417
418
419
420
421
422
  	.init		= rcu_sync_torture_init,
  	.cleanup	= NULL,
  	.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,
  	.cb_barrier	= NULL,
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
423
  	.fqs		= rcu_force_quiescent_state,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
424
425
  	.stats		= NULL,
  	.irq_capable	= 1,
8e8be45e8   Paul E. McKenney   rcu: add priority...
426
  	.can_boost	= rcu_can_boost(),
0acc512cb   Paul E. McKenney   rcu: Add synchron...
427
  	.name		= "rcu_sync"
20d2e4283   Josh Triplett   [PATCH] rcu: add ...
428
  };
d9a3da069   Paul E. McKenney   rcu: Add expedite...
429
430
431
432
433
434
435
436
437
438
  static struct rcu_torture_ops rcu_expedited_ops = {
  	.init		= rcu_sync_torture_init,
  	.cleanup	= NULL,
  	.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,
  	.cb_barrier	= NULL,
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
439
  	.fqs		= rcu_force_quiescent_state,
d9a3da069   Paul E. McKenney   rcu: Add expedite...
440
441
  	.stats		= NULL,
  	.irq_capable	= 1,
8e8be45e8   Paul E. McKenney   rcu: add priority...
442
  	.can_boost	= rcu_can_boost(),
d9a3da069   Paul E. McKenney   rcu: Add expedite...
443
444
  	.name		= "rcu_expedited"
  };
c32e06605   Paul E. McKenney   [PATCH] rcutortur...
445
446
447
  /*
   * Definitions for rcu_bh torture testing.
   */
a49a4af75   Josh Triplett   [PATCH] rcu: add ...
448
  static int rcu_bh_torture_read_lock(void) __acquires(RCU_BH)
c32e06605   Paul E. McKenney   [PATCH] rcutortur...
449
450
451
452
  {
  	rcu_read_lock_bh();
  	return 0;
  }
a49a4af75   Josh Triplett   [PATCH] rcu: add ...
453
  static void rcu_bh_torture_read_unlock(int idx) __releases(RCU_BH)
c32e06605   Paul E. McKenney   [PATCH] rcutortur...
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
  {
  	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...
469
470
471
472
473
474
475
  	.init		= NULL,
  	.cleanup	= NULL,
  	.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...
476
  	.sync		= synchronize_rcu_bh,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
477
  	.cb_barrier	= rcu_barrier_bh,
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
478
  	.fqs		= rcu_bh_force_quiescent_state,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
479
480
481
  	.stats		= NULL,
  	.irq_capable	= 1,
  	.name		= "rcu_bh"
c32e06605   Paul E. McKenney   [PATCH] rcutortur...
482
  };
11a147013   Josh Triplett   [PATCH] rcu: add ...
483
  static struct rcu_torture_ops rcu_bh_sync_ops = {
0acc512cb   Paul E. McKenney   rcu: Add synchron...
484
485
486
487
488
489
490
  	.init		= rcu_sync_torture_init,
  	.cleanup	= NULL,
  	.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...
491
  	.sync		= synchronize_rcu_bh,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
492
  	.cb_barrier	= NULL,
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
493
  	.fqs		= rcu_bh_force_quiescent_state,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
494
495
496
  	.stats		= NULL,
  	.irq_capable	= 1,
  	.name		= "rcu_bh_sync"
11a147013   Josh Triplett   [PATCH] rcu: add ...
497
  };
bdf2a4364   Paul E. McKenney   rcu: Catch rcutor...
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
  static struct rcu_torture_ops rcu_bh_expedited_ops = {
  	.init		= rcu_sync_torture_init,
  	.cleanup	= NULL,
  	.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,
  	.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...
513
514
515
516
517
  /*
   * Definitions for srcu torture testing.
   */
  
  static struct srcu_struct srcu_ctl;
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
518
519
520
521
  
  static void srcu_torture_init(void)
  {
  	init_srcu_struct(&srcu_ctl);
e30337365   Josh Triplett   [PATCH] rcu: refa...
522
  	rcu_sync_torture_init();
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
523
524
525
526
527
528
529
  }
  
  static void srcu_torture_cleanup(void)
  {
  	synchronize_srcu(&srcu_ctl);
  	cleanup_srcu_struct(&srcu_ctl);
  }
012d3ca8d   Josh Triplett   [PATCH] Add Spars...
530
  static int srcu_torture_read_lock(void) __acquires(&srcu_ctl)
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
  {
  	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...
546
547
  	else
  		rcu_read_delay(rrsp);
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
548
  }
012d3ca8d   Josh Triplett   [PATCH] Add Spars...
549
  static void srcu_torture_read_unlock(int idx) __releases(&srcu_ctl)
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
550
551
552
553
554
555
556
557
  {
  	srcu_read_unlock(&srcu_ctl, idx);
  }
  
  static int srcu_torture_completed(void)
  {
  	return srcu_batches_completed(&srcu_ctl);
  }
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
558
559
560
561
  static void srcu_torture_synchronize(void)
  {
  	synchronize_srcu(&srcu_ctl);
  }
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
  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) {
  		cnt += sprintf(&page[cnt], " %d(%d,%d)", cpu,
  			       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 = {
0acc512cb   Paul E. McKenney   rcu: Add synchron...
581
582
583
584
585
586
587
588
589
590
591
  	.init		= srcu_torture_init,
  	.cleanup	= srcu_torture_cleanup,
  	.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,
  	.cb_barrier	= NULL,
  	.stats		= srcu_torture_stats,
  	.name		= "srcu"
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
592
  };
804bb8370   Paul E. McKenney   rcu: Add synchron...
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
  static void srcu_torture_synchronize_expedited(void)
  {
  	synchronize_srcu_expedited(&srcu_ctl);
  }
  
  static struct rcu_torture_ops srcu_expedited_ops = {
  	.init		= srcu_torture_init,
  	.cleanup	= srcu_torture_cleanup,
  	.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,
  	.cb_barrier	= NULL,
  	.stats		= srcu_torture_stats,
  	.name		= "srcu_expedited"
  };
4b6c2cca6   Josh Triplett   [PATCH] rcu: add ...
611
612
613
614
615
616
617
618
619
620
621
622
623
624
  /*
   * 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...
625
626
627
628
  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 ...
629
  static struct rcu_torture_ops sched_ops = {
0acc512cb   Paul E. McKenney   rcu: Add synchron...
630
631
632
633
634
  	.init		= rcu_sync_torture_init,
  	.cleanup	= NULL,
  	.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...
635
  	.completed	= rcu_no_completed,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
636
  	.deferred_free	= rcu_sched_torture_deferred_free,
bdf2a4364   Paul E. McKenney   rcu: Catch rcutor...
637
  	.sync		= synchronize_sched,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
638
  	.cb_barrier	= rcu_barrier_sched,
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
639
  	.fqs		= rcu_sched_force_quiescent_state,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
640
641
642
  	.stats		= NULL,
  	.irq_capable	= 1,
  	.name		= "sched"
4b6c2cca6   Josh Triplett   [PATCH] rcu: add ...
643
  };
804bb8370   Paul E. McKenney   rcu: Add synchron...
644
  static struct rcu_torture_ops sched_sync_ops = {
0acc512cb   Paul E. McKenney   rcu: Add synchron...
645
646
647
648
649
  	.init		= rcu_sync_torture_init,
  	.cleanup	= NULL,
  	.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...
650
  	.completed	= rcu_no_completed,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
651
  	.deferred_free	= rcu_sync_torture_deferred_free,
bdf2a4364   Paul E. McKenney   rcu: Catch rcutor...
652
  	.sync		= synchronize_sched,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
653
  	.cb_barrier	= NULL,
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
654
  	.fqs		= rcu_sched_force_quiescent_state,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
655
656
657
  	.stats		= NULL,
  	.name		= "sched_sync"
  };
0acc512cb   Paul E. McKenney   rcu: Add synchron...
658
659
660
661
662
663
  static struct rcu_torture_ops sched_expedited_ops = {
  	.init		= rcu_sync_torture_init,
  	.cleanup	= NULL,
  	.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...
664
  	.completed	= rcu_no_completed,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
665
666
667
  	.deferred_free	= rcu_sync_torture_deferred_free,
  	.sync		= synchronize_sched_expedited,
  	.cb_barrier	= NULL,
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
668
  	.fqs		= rcu_sched_force_quiescent_state,
969c79215   Tejun Heo   sched: replace mi...
669
  	.stats		= NULL,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
670
671
  	.irq_capable	= 1,
  	.name		= "sched_expedited"
2326974df   Paul E. McKenney   rcu: add call_rcu...
672
  };
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
673
  /*
8e8be45e8   Paul E. McKenney   rcu: add priority...
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
   * 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...
710
  	init_rcu_head_on_stack(&rbi.rcu);
8e8be45e8   Paul E. McKenney   rcu: add priority...
711
712
713
714
  	/* 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...
715
  		while (ULONG_CMP_LT(jiffies, oldstarttime)) {
8e8be45e8   Paul E. McKenney   rcu: add priority...
716
717
718
719
720
721
722
723
724
725
  			schedule_timeout_uninterruptible(1);
  			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...
726
  		while (ULONG_CMP_LT(jiffies, endtime)) {
8e8be45e8   Paul E. McKenney   rcu: add priority...
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
  			/* 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...
753
754
  		while (oldstarttime == boost_starttime &&
  		       !kthread_should_stop()) {
8e8be45e8   Paul E. McKenney   rcu: add priority...
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
  			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...
775
  	destroy_rcu_head_on_stack(&rbi.rcu);
8e8be45e8   Paul E. McKenney   rcu: add priority...
776
777
778
779
  	return 0;
  }
  
  /*
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
780
781
782
783
784
785
786
787
788
789
790
791
792
   * 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...
793
794
  		while (ULONG_CMP_LT(jiffies, fqs_resume_time) &&
  		       !kthread_should_stop()) {
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
795
796
797
  			schedule_timeout_interruptible(1);
  		}
  		fqs_burst_remaining = fqs_duration;
93898fb1a   Paul E. McKenney   rcu: Make rcu_tor...
798
799
  		while (fqs_burst_remaining > 0 &&
  		       !kthread_should_stop()) {
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
800
801
802
803
804
805
806
807
808
809
810
811
812
813
  			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...
814
815
816
817
818
819
820
821
822
823
824
825
826
827
   * 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...
828
  	set_user_nice(current, 19);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
829
830
  	do {
  		schedule_timeout_uninterruptible(1);
a71fca58b   Paul E. McKenney   rcu: Fix whitespa...
831
832
  		rp = rcu_torture_alloc();
  		if (rp == NULL)
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
833
834
835
  			continue;
  		rp->rtort_pipe_count = 0;
  		udelay(rcu_random(&rand) & 0x3ff);
0ddea0ead   Paul E. McKenney   rcu: fix sparse e...
836
837
  		old_rp = rcu_dereference_check(rcu_torture_current,
  					       current == writer_task);
996417d2c   Paul E. McKenney   [PATCH] add succe...
838
  		rp->rtort_mbtest = 1;
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
839
  		rcu_assign_pointer(rcu_torture_current, rp);
9b2619aff   Paul E. McKenney   rcu: Clean up cod...
840
  		smp_wmb(); /* Mods to old_rp must follow rcu_assign_pointer() */
c8e5b1631   Josh Triplett   rcutorture: style...
841
  		if (old_rp) {
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
842
843
844
845
846
  			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...
847
  			cur_ops->deferred_free(old_rp);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
848
  		}
4a2986568   Paul E. McKenney   rcu: make rcutort...
849
  		rcutorture_record_progress(++rcu_torture_current_version);
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
850
  		oldbatch = cur_ops->completed();
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
851
852
  		rcu_stutter_wait("rcu_torture_writer");
  	} while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
853
  	VERBOSE_PRINTK_STRING("rcu_torture_writer task stopping");
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
854
855
  	rcutorture_shutdown_absorb("rcu_torture_writer");
  	while (!kthread_should_stop())
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
856
857
858
859
860
  		schedule_timeout_uninterruptible(1);
  	return 0;
  }
  
  /*
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
   * 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);
  		cur_ops->sync();
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
876
877
  		rcu_stutter_wait("rcu_torture_fakewriter");
  	} while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
878
879
  
  	VERBOSE_PRINTK_STRING("rcu_torture_fakewriter task stopping");
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
880
881
  	rcutorture_shutdown_absorb("rcu_torture_fakewriter");
  	while (!kthread_should_stop())
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
882
883
884
885
886
  		schedule_timeout_uninterruptible(1);
  	return 0;
  }
  
  /*
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
   * 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;
  	static DEFINE_RCU_RANDOM(rand);
  	static DEFINE_SPINLOCK(rand_lock);
  	struct rcu_torture *p;
  	int pipe_count;
  
  	idx = cur_ops->readlock();
  	completed = cur_ops->completed();
632ee2001   Paul E. McKenney   rcu: Introduce lo...
903
  	p = rcu_dereference_check(rcu_torture_current,
632ee2001   Paul E. McKenney   rcu: Introduce lo...
904
905
906
  				  rcu_read_lock_bh_held() ||
  				  rcu_read_lock_sched_held() ||
  				  srcu_read_lock_held(&srcu_ctl));
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
907
908
909
910
911
912
913
914
  	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...
915
  	cur_ops->read_delay(&rand);
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
916
917
918
919
920
921
922
923
  	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;
  	}
dd17c8f72   Rusty Russell   percpu: remove pe...
924
  	__this_cpu_inc(rcu_torture_count[pipe_count]);
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
925
926
927
928
929
  	completed = cur_ops->completed() - completed;
  	if (completed > RCU_TORTURE_PIPE_LEN) {
  		/* Should not happen, but... */
  		completed = RCU_TORTURE_PIPE_LEN;
  	}
dd17c8f72   Rusty Russell   percpu: remove pe...
930
  	__this_cpu_inc(rcu_torture_batch[completed]);
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
931
932
933
934
935
  	preempt_enable();
  	cur_ops->readunlock(idx);
  }
  
  /*
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
936
937
938
939
940
941
942
943
944
   * 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;
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
945
  	int idx;
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
946
947
948
  	DEFINE_RCU_RANDOM(rand);
  	struct rcu_torture *p;
  	int pipe_count;
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
949
  	struct timer_list t;
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
950
951
  
  	VERBOSE_PRINTK_STRING("rcu_torture_reader task started");
dbdf65b1b   Ingo Molnar   [PATCH] rcutortur...
952
  	set_user_nice(current, 19);
0acc512cb   Paul E. McKenney   rcu: Add synchron...
953
  	if (irqreader && cur_ops->irq_capable)
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
954
  		setup_timer_on_stack(&t, rcu_torture_timer, 0);
dbdf65b1b   Ingo Molnar   [PATCH] rcutortur...
955

a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
956
  	do {
0acc512cb   Paul E. McKenney   rcu: Add synchron...
957
  		if (irqreader && cur_ops->irq_capable) {
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
958
  			if (!timer_pending(&t))
6155fec92   Paul E. McKenney   rcu: Fix rcutortu...
959
  				mod_timer(&t, jiffies + 1);
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
960
  		}
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
961
962
  		idx = cur_ops->readlock();
  		completed = cur_ops->completed();
632ee2001   Paul E. McKenney   rcu: Introduce lo...
963
  		p = rcu_dereference_check(rcu_torture_current,
632ee2001   Paul E. McKenney   rcu: Introduce lo...
964
965
966
  					  rcu_read_lock_bh_held() ||
  					  rcu_read_lock_sched_held() ||
  					  srcu_read_lock_held(&srcu_ctl));
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
967
968
  		if (p == NULL) {
  			/* Wait for rcu_torture_writer to get underway */
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
969
  			cur_ops->readunlock(idx);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
970
971
972
  			schedule_timeout_interruptible(HZ);
  			continue;
  		}
996417d2c   Paul E. McKenney   [PATCH] add succe...
973
974
  		if (p->rtort_mbtest == 0)
  			atomic_inc(&n_rcu_torture_mberror);
0acc512cb   Paul E. McKenney   rcu: Add synchron...
975
  		cur_ops->read_delay(&rand);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
976
977
978
979
980
981
  		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;
  		}
dd17c8f72   Rusty Russell   percpu: remove pe...
982
  		__this_cpu_inc(rcu_torture_count[pipe_count]);
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
983
  		completed = cur_ops->completed() - completed;
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
984
985
986
987
  		if (completed > RCU_TORTURE_PIPE_LEN) {
  			/* Should not happen, but... */
  			completed = RCU_TORTURE_PIPE_LEN;
  		}
dd17c8f72   Rusty Russell   percpu: remove pe...
988
  		__this_cpu_inc(rcu_torture_batch[completed]);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
989
  		preempt_enable();
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
990
  		cur_ops->readunlock(idx);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
991
  		schedule();
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
992
993
  		rcu_stutter_wait("rcu_torture_reader");
  	} while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
994
  	VERBOSE_PRINTK_STRING("rcu_torture_reader task stopping");
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
995
  	rcutorture_shutdown_absorb("rcu_torture_reader");
0acc512cb   Paul E. McKenney   rcu: Add synchron...
996
  	if (irqreader && cur_ops->irq_capable)
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
997
  		del_timer_sync(&t);
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
998
  	while (!kthread_should_stop())
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
  		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_...
1014
  	for_each_possible_cpu(cpu) {
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1015
1016
1017
1018
1019
1020
1021
1022
1023
  		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...
1024
  	cnt += sprintf(&page[cnt], "%s%s ", torture_type, TORTURE_FLAG);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1025
  	cnt += sprintf(&page[cnt],
4a2986568   Paul E. McKenney   rcu: make rcutort...
1026
  		       "rtc: %p ver: %lu tfle: %d rta: %d rtaf: %d rtf: %d "
67b98dba4   Paul E. McKenney   rcu: eliminate un...
1027
  		       "rtmbe: %d rtbke: %ld rtbre: %ld "
8e8be45e8   Paul E. McKenney   rcu: add priority...
1028
  		       "rtbf: %ld rtb: %ld nt: %ld",
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1029
1030
1031
1032
1033
  		       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),
996417d2c   Paul E. McKenney   [PATCH] add succe...
1034
  		       atomic_read(&n_rcu_torture_free),
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
1035
  		       atomic_read(&n_rcu_torture_mberror),
8e8be45e8   Paul E. McKenney   rcu: add priority...
1036
1037
  		       n_rcu_torture_boost_ktrerror,
  		       n_rcu_torture_boost_rterror,
8e8be45e8   Paul E. McKenney   rcu: add priority...
1038
1039
  		       n_rcu_torture_boost_failure,
  		       n_rcu_torture_boosts,
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
1040
  		       n_rcu_torture_timers);
8e8be45e8   Paul E. McKenney   rcu: add priority...
1041
1042
1043
  	if (atomic_read(&n_rcu_torture_mberror) != 0 ||
  	    n_rcu_torture_boost_ktrerror != 0 ||
  	    n_rcu_torture_boost_rterror != 0 ||
8e8be45e8   Paul E. McKenney   rcu: add priority...
1044
  	    n_rcu_torture_boost_failure != 0)
996417d2c   Paul E. McKenney   [PATCH] add succe...
1045
  		cnt += sprintf(&page[cnt], " !!!");
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
1046
1047
  	cnt += sprintf(&page[cnt], "
  %s%s ", torture_type, TORTURE_FLAG);
996417d2c   Paul E. McKenney   [PATCH] add succe...
1048
  	if (i > 1) {
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1049
  		cnt += sprintf(&page[cnt], "!!! ");
996417d2c   Paul E. McKenney   [PATCH] add succe...
1050
  		atomic_inc(&n_rcu_torture_error);
5af970a48   Ingo Molnar   rcutorture: WARN_...
1051
  		WARN_ON_ONCE(1);
996417d2c   Paul E. McKenney   [PATCH] add succe...
1052
  	}
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1053
1054
1055
  	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...
1056
1057
  	cnt += sprintf(&page[cnt], "
  %s%s ", torture_type, TORTURE_FLAG);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1058
  	cnt += sprintf(&page[cnt], "Reader Batch: ");
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
1059
  	for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++)
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1060
  		cnt += sprintf(&page[cnt], " %ld", batchsummary[i]);
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
1061
1062
  	cnt += sprintf(&page[cnt], "
  %s%s ", torture_type, TORTURE_FLAG);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1063
1064
1065
1066
1067
1068
1069
  	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...
1070
  	if (cur_ops->stats)
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
1071
  		cnt += cur_ops->stats(&page[cnt]);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
  	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);
  	printk(KERN_ALERT "%s", printk_buf);
  }
  
  /*
   * 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...
1106
1107
  		rcutorture_shutdown_absorb("rcu_torture_stats");
  	} while (!kthread_should_stop());
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1108
1109
1110
  	VERBOSE_PRINTK_STRING("rcu_torture_stats task stopping");
  	return 0;
  }
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1111
1112
1113
1114
1115
  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...
1116
  static void rcu_torture_shuffle_tasks(void)
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1117
  {
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1118
  	int i;
73d0a4b10   Rusty Russell   cpumask: convert ...
1119
  	cpumask_setall(shuffle_tmp_mask);
86ef5c9a8   Gautham R Shenoy   cpu-hotplug: repl...
1120
  	get_online_cpus();
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1121
1122
  
  	/* No point in shuffling if there is only one online CPU (ex: UP) */
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
1123
1124
1125
1126
  	if (num_online_cpus() == 1) {
  		put_online_cpus();
  		return;
  	}
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1127
1128
  
  	if (rcu_idle_cpu != -1)
73d0a4b10   Rusty Russell   cpumask: convert ...
1129
  		cpumask_clear_cpu(rcu_idle_cpu, shuffle_tmp_mask);
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1130

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

c8e5b1631   Josh Triplett   rcutorture: style...
1133
  	if (reader_tasks) {
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1134
1135
  		for (i = 0; i < nrealreaders; i++)
  			if (reader_tasks[i])
f70316dac   Mike Travis   generic: use new ...
1136
  				set_cpus_allowed_ptr(reader_tasks[i],
73d0a4b10   Rusty Russell   cpumask: convert ...
1137
  						     shuffle_tmp_mask);
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1138
  	}
c8e5b1631   Josh Triplett   rcutorture: style...
1139
  	if (fakewriter_tasks) {
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
1140
1141
  		for (i = 0; i < nfakewriters; i++)
  			if (fakewriter_tasks[i])
f70316dac   Mike Travis   generic: use new ...
1142
  				set_cpus_allowed_ptr(fakewriter_tasks[i],
73d0a4b10   Rusty Russell   cpumask: convert ...
1143
  						     shuffle_tmp_mask);
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
1144
  	}
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1145
  	if (writer_task)
73d0a4b10   Rusty Russell   cpumask: convert ...
1146
  		set_cpus_allowed_ptr(writer_task, shuffle_tmp_mask);
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1147
1148
  
  	if (stats_task)
73d0a4b10   Rusty Russell   cpumask: convert ...
1149
  		set_cpus_allowed_ptr(stats_task, shuffle_tmp_mask);
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1150
1151
1152
1153
1154
  
  	if (rcu_idle_cpu == -1)
  		rcu_idle_cpu = num_online_cpus() - 1;
  	else
  		rcu_idle_cpu--;
86ef5c9a8   Gautham R Shenoy   cpu-hotplug: repl...
1155
  	put_online_cpus();
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
  }
  
  /* 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...
1169
1170
  		rcutorture_shutdown_absorb("rcu_torture_shuffle");
  	} while (!kthread_should_stop());
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1171
1172
1173
  	VERBOSE_PRINTK_STRING("rcu_torture_shuffle task stopping");
  	return 0;
  }
d120f65f3   Paul E. McKenney   rcu: make rcutort...
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
  /* 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...
1184
  		if (!kthread_should_stop())
d120f65f3   Paul E. McKenney   rcu: make rcutort...
1185
1186
  			schedule_timeout_interruptible(stutter * HZ);
  		stutter_pause_test = 0;
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
1187
1188
  		rcutorture_shutdown_absorb("rcu_torture_stutter");
  	} while (!kthread_should_stop());
d120f65f3   Paul E. McKenney   rcu: make rcutort...
1189
1190
1191
  	VERBOSE_PRINTK_STRING("rcu_torture_stutter task stopping");
  	return 0;
  }
95c383227   Paul E. McKenney   [PATCH] rcutortur...
1192
  static inline void
8e8be45e8   Paul E. McKenney   rcu: add priority...
1193
  rcu_torture_print_module_parms(struct rcu_torture_ops *cur_ops, char *tag)
95c383227   Paul E. McKenney   [PATCH] rcutortur...
1194
  {
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
1195
1196
  	printk(KERN_ALERT "%s" TORTURE_FLAG
  		"--- %s: nreaders=%d nfakewriters=%d "
95c383227   Paul E. McKenney   [PATCH] rcutortur...
1197
  		"stat_interval=%d verbose=%d test_no_idle_hz=%d "
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
1198
  		"shuffle_interval=%d stutter=%d irqreader=%d "
8e8be45e8   Paul E. McKenney   rcu: add priority...
1199
1200
1201
1202
  		"fqs_duration=%d fqs_holdoff=%d fqs_stutter=%d "
  		"test_boost=%d/%d test_boost_interval=%d "
  		"test_boost_duration=%d
  ",
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
1203
  		torture_type, tag, nrealreaders, nfakewriters,
d120f65f3   Paul E. McKenney   rcu: make rcutort...
1204
  		stat_interval, verbose, test_no_idle_hz, shuffle_interval,
8e8be45e8   Paul E. McKenney   rcu: add priority...
1205
1206
1207
  		stutter, irqreader, fqs_duration, fqs_holdoff, fqs_stutter,
  		test_boost, cur_ops->can_boost,
  		test_boost_interval, test_boost_duration);
95c383227   Paul E. McKenney   [PATCH] rcutortur...
1208
  }
8e8be45e8   Paul E. McKenney   rcu: add priority...
1209
  static struct notifier_block rcutorture_shutdown_nb = {
343e9099c   Paul E. McKenney   rcu: fix rcutortu...
1210
1211
  	.notifier_call = rcutorture_shutdown_notify,
  };
8e8be45e8   Paul E. McKenney   rcu: add priority...
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
  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);
  }
  
  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_...
1238
1239
1240
  	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...
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
  	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;
  }
  
  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...
1277
1278
1279
1280
  static void
  rcu_torture_cleanup(void)
  {
  	int i;
343e9099c   Paul E. McKenney   rcu: fix rcutortu...
1281
  	mutex_lock(&fullstop_mutex);
4a2986568   Paul E. McKenney   rcu: make rcutort...
1282
  	rcutorture_record_test_transition();
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
1283
1284
1285
1286
  	if (fullstop == FULLSTOP_SHUTDOWN) {
  		printk(KERN_WARNING /* but going down anyway, so... */
  		       "Concurrent 'rmmod rcutorture' and shutdown illegal!
  ");
343e9099c   Paul E. McKenney   rcu: fix rcutortu...
1287
  		mutex_unlock(&fullstop_mutex);
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
1288
  		schedule_timeout_uninterruptible(10);
343e9099c   Paul E. McKenney   rcu: fix rcutortu...
1289
1290
1291
1292
  		if (cur_ops->cb_barrier != NULL)
  			cur_ops->cb_barrier();
  		return;
  	}
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
1293
  	fullstop = FULLSTOP_RMMOD;
343e9099c   Paul E. McKenney   rcu: fix rcutortu...
1294
  	mutex_unlock(&fullstop_mutex);
8e8be45e8   Paul E. McKenney   rcu: add priority...
1295
  	unregister_reboot_notifier(&rcutorture_shutdown_nb);
d120f65f3   Paul E. McKenney   rcu: make rcutort...
1296
1297
1298
1299
1300
  	if (stutter_task) {
  		VERBOSE_PRINTK_STRING("Stopping rcu_torture_stutter task");
  		kthread_stop(stutter_task);
  	}
  	stutter_task = NULL;
c8e5b1631   Josh Triplett   rcutorture: style...
1301
  	if (shuffler_task) {
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1302
1303
  		VERBOSE_PRINTK_STRING("Stopping rcu_torture_shuffle task");
  		kthread_stop(shuffler_task);
73d0a4b10   Rusty Russell   cpumask: convert ...
1304
  		free_cpumask_var(shuffle_tmp_mask);
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1305
1306
  	}
  	shuffler_task = NULL;
c8e5b1631   Josh Triplett   rcutorture: style...
1307
  	if (writer_task) {
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1308
1309
1310
1311
  		VERBOSE_PRINTK_STRING("Stopping rcu_torture_writer task");
  		kthread_stop(writer_task);
  	}
  	writer_task = NULL;
c8e5b1631   Josh Triplett   rcutorture: style...
1312
  	if (reader_tasks) {
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1313
  		for (i = 0; i < nrealreaders; i++) {
c8e5b1631   Josh Triplett   rcutorture: style...
1314
  			if (reader_tasks[i]) {
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
  				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...
1325
  	if (fakewriter_tasks) {
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
1326
  		for (i = 0; i < nfakewriters; i++) {
c8e5b1631   Josh Triplett   rcutorture: style...
1327
  			if (fakewriter_tasks[i]) {
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
1328
1329
1330
1331
1332
1333
1334
1335
1336
  				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...
1337
  	if (stats_task) {
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1338
1339
1340
1341
  		VERBOSE_PRINTK_STRING("Stopping rcu_torture_stats task");
  		kthread_stop(stats_task);
  	}
  	stats_task = NULL;
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
1342
1343
1344
1345
1346
  	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...
1347
1348
1349
1350
1351
1352
  	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);
  	}
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
1353

a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1354
  	/* Wait for all RCU callbacks to fire.  */
2326974df   Paul E. McKenney   rcu: add call_rcu...
1355
1356
1357
  
  	if (cur_ops->cb_barrier != NULL)
  		cur_ops->cb_barrier();
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1358

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

c8e5b1631   Josh Triplett   rcutorture: style...
1361
  	if (cur_ops->cleanup)
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
1362
  		cur_ops->cleanup();
95c383227   Paul E. McKenney   [PATCH] rcutortur...
1363
  	if (atomic_read(&n_rcu_torture_error))
8e8be45e8   Paul E. McKenney   rcu: add priority...
1364
  		rcu_torture_print_module_parms(cur_ops, "End of test: FAILURE");
95c383227   Paul E. McKenney   [PATCH] rcutortur...
1365
  	else
8e8be45e8   Paul E. McKenney   rcu: add priority...
1366
  		rcu_torture_print_module_parms(cur_ops, "End of test: SUCCESS");
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1367
  }
6f8bc500a   Josh Triplett   rcutorture: Mark ...
1368
  static int __init
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1369
1370
1371
1372
1373
  rcu_torture_init(void)
  {
  	int i;
  	int cpu;
  	int firsterr = 0;
ade5fb818   Josh Triplett   rcutorture: Remov...
1374
  	static struct rcu_torture_ops *torture_ops[] =
d9a3da069   Paul E. McKenney   rcu: Add expedite...
1375
  		{ &rcu_ops, &rcu_sync_ops, &rcu_expedited_ops,
bdf2a4364   Paul E. McKenney   rcu: Catch rcutor...
1376
  		  &rcu_bh_ops, &rcu_bh_sync_ops, &rcu_bh_expedited_ops,
804bb8370   Paul E. McKenney   rcu: Add synchron...
1377
1378
  		  &srcu_ops, &srcu_expedited_ops,
  		  &sched_ops, &sched_sync_ops, &sched_expedited_ops, };
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1379

343e9099c   Paul E. McKenney   rcu: fix rcutortu...
1380
  	mutex_lock(&fullstop_mutex);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1381
  	/* Process args and tell the world that the torturer is on the job. */
ade5fb818   Josh Triplett   rcutorture: Remov...
1382
  	for (i = 0; i < ARRAY_SIZE(torture_ops); i++) {
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
1383
  		cur_ops = torture_ops[i];
ade5fb818   Josh Triplett   rcutorture: Remov...
1384
  		if (strcmp(torture_type, cur_ops->name) == 0)
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
1385
  			break;
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
1386
  	}
ade5fb818   Josh Triplett   rcutorture: Remov...
1387
  	if (i == ARRAY_SIZE(torture_ops)) {
cf886c44e   Paul E. McKenney   rcu: Improve rcut...
1388
1389
  		printk(KERN_ALERT "rcu-torture: invalid torture type: \"%s\"
  ",
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
1390
  		       torture_type);
cf886c44e   Paul E. McKenney   rcu: Improve rcut...
1391
1392
1393
1394
1395
  		printk(KERN_ALERT "rcu-torture types:");
  		for (i = 0; i < ARRAY_SIZE(torture_ops); i++)
  			printk(KERN_ALERT " %s", torture_ops[i]->name);
  		printk(KERN_ALERT "
  ");
343e9099c   Paul E. McKenney   rcu: fix rcutortu...
1396
  		mutex_unlock(&fullstop_mutex);
a71fca58b   Paul E. McKenney   rcu: Fix whitespa...
1397
  		return -EINVAL;
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
1398
  	}
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
1399
1400
1401
1402
1403
1404
  	if (cur_ops->fqs == NULL && fqs_duration != 0) {
  		printk(KERN_ALERT "rcu-torture: ->fqs NULL and non-zero "
  				  "fqs_duration, fqs disabled.
  ");
  		fqs_duration = 0;
  	}
c8e5b1631   Josh Triplett   rcutorture: style...
1405
  	if (cur_ops->init)
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
1406
  		cur_ops->init(); /* no "goto unwind" prior to this point!!! */
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1407
1408
1409
1410
  	if (nreaders >= 0)
  		nrealreaders = nreaders;
  	else
  		nrealreaders = 2 * num_online_cpus();
8e8be45e8   Paul E. McKenney   rcu: add priority...
1411
  	rcu_torture_print_module_parms(cur_ops, "Start of test");
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
1412
  	fullstop = FULLSTOP_DONTSTOP;
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1413
1414
1415
1416
  
  	/* Set up the freelist. */
  
  	INIT_LIST_HEAD(&rcu_torture_freelist);
788e770eb   Ahmed S. Darwish   rcutorture: Use A...
1417
  	for (i = 0; i < ARRAY_SIZE(rcu_tortures); i++) {
996417d2c   Paul E. McKenney   [PATCH] add succe...
1418
  		rcu_tortures[i].rtort_mbtest = 0;
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
  		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...
1430
1431
  	atomic_set(&n_rcu_torture_mberror, 0);
  	atomic_set(&n_rcu_torture_error, 0);
8e8be45e8   Paul E. McKenney   rcu: add priority...
1432
1433
  	n_rcu_torture_boost_ktrerror = 0;
  	n_rcu_torture_boost_rterror = 0;
8e8be45e8   Paul E. McKenney   rcu: add priority...
1434
1435
  	n_rcu_torture_boost_failure = 0;
  	n_rcu_torture_boosts = 0;
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1436
1437
  	for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++)
  		atomic_set(&rcu_torture_wcount[i], 0);
0a9450227   KAMEZAWA Hiroyuki   [PATCH] for_each_...
1438
  	for_each_possible_cpu(cpu) {
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
  		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");
  	writer_task = kthread_run(rcu_torture_writer, NULL,
  				  "rcu_torture_writer");
  	if (IS_ERR(writer_task)) {
  		firsterr = PTR_ERR(writer_task);
  		VERBOSE_PRINTK_ERRSTRING("Failed to create writer");
  		writer_task = NULL;
  		goto unwind;
  	}
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
1456
  	fakewriter_tasks = kzalloc(nfakewriters * sizeof(fakewriter_tasks[0]),
a71fca58b   Paul E. McKenney   rcu: Fix whitespa...
1457
  				   GFP_KERNEL);
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
1458
1459
1460
1461
1462
1463
1464
1465
  	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...
1466
  						  "rcu_torture_fakewriter");
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
1467
1468
1469
1470
1471
1472
1473
  		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...
1474
  	reader_tasks = kzalloc(nrealreaders * sizeof(reader_tasks[0]),
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
  			       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...
1503
1504
  	if (test_no_idle_hz) {
  		rcu_idle_cpu = num_online_cpus() - 1;
73d0a4b10   Rusty Russell   cpumask: convert ...
1505
1506
1507
1508
1509
1510
  
  		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...
1511
1512
1513
1514
  		/* 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 ...
1515
  			free_cpumask_var(shuffle_tmp_mask);
d84f52034   Srivatsa Vaddagiri   [PATCH] Extend RC...
1516
1517
1518
1519
1520
1521
  			firsterr = PTR_ERR(shuffler_task);
  			VERBOSE_PRINTK_ERRSTRING("Failed to create shuffler");
  			shuffler_task = NULL;
  			goto unwind;
  		}
  	}
d120f65f3   Paul E. McKenney   rcu: make rcutort...
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
  	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...
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
  	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...
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
  	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) {
  		int retval;
  
  		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;
  			}
  		}
  	}
  	register_reboot_notifier(&rcutorture_shutdown_nb);
4a2986568   Paul E. McKenney   rcu: make rcutort...
1569
  	rcutorture_record_test_transition();
343e9099c   Paul E. McKenney   rcu: fix rcutortu...
1570
  	mutex_unlock(&fullstop_mutex);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1571
1572
1573
  	return 0;
  
  unwind:
343e9099c   Paul E. McKenney   rcu: fix rcutortu...
1574
  	mutex_unlock(&fullstop_mutex);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1575
1576
1577
1578
1579
1580
  	rcu_torture_cleanup();
  	return firsterr;
  }
  
  module_init(rcu_torture_init);
  module_exit(rcu_torture_cleanup);