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");
d6ad67112   Josh Triplett   [PATCH] Publish r...
76
  module_param(stat_interval, int, 0444);
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
  {
  	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);
  }
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
  struct rcu_bh_torture_synchronize {
  	struct rcu_head head;
  	struct completion completion;
  };
  
  static void rcu_bh_torture_wakeme_after_cb(struct rcu_head *head)
  {
  	struct rcu_bh_torture_synchronize *rcu;
  
  	rcu = container_of(head, struct rcu_bh_torture_synchronize, head);
  	complete(&rcu->completion);
  }
  
  static void rcu_bh_torture_synchronize(void)
  {
  	struct rcu_bh_torture_synchronize rcu;
72d5a9f7a   Paul E. McKenney   rcu: remove all r...
483
  	init_rcu_head_on_stack(&rcu.head);
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
484
485
486
  	init_completion(&rcu.completion);
  	call_rcu_bh(&rcu.head, rcu_bh_torture_wakeme_after_cb);
  	wait_for_completion(&rcu.completion);
72d5a9f7a   Paul E. McKenney   rcu: remove all r...
487
  	destroy_rcu_head_on_stack(&rcu.head);
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
488
  }
c32e06605   Paul E. McKenney   [PATCH] rcutortur...
489
  static struct rcu_torture_ops rcu_bh_ops = {
0acc512cb   Paul E. McKenney   rcu: Add synchron...
490
491
492
493
494
495
496
497
498
  	.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,
  	.sync		= rcu_bh_torture_synchronize,
  	.cb_barrier	= rcu_barrier_bh,
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
499
  	.fqs		= rcu_bh_force_quiescent_state,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
500
501
502
  	.stats		= NULL,
  	.irq_capable	= 1,
  	.name		= "rcu_bh"
c32e06605   Paul E. McKenney   [PATCH] rcutortur...
503
  };
11a147013   Josh Triplett   [PATCH] rcu: add ...
504
  static struct rcu_torture_ops rcu_bh_sync_ops = {
0acc512cb   Paul E. McKenney   rcu: Add synchron...
505
506
507
508
509
510
511
512
513
  	.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		= rcu_bh_torture_synchronize,
  	.cb_barrier	= NULL,
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
514
  	.fqs		= rcu_bh_force_quiescent_state,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
515
516
517
  	.stats		= NULL,
  	.irq_capable	= 1,
  	.name		= "rcu_bh_sync"
11a147013   Josh Triplett   [PATCH] rcu: add ...
518
  };
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
519
520
521
522
523
  /*
   * Definitions for srcu torture testing.
   */
  
  static struct srcu_struct srcu_ctl;
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
524
525
526
527
  
  static void srcu_torture_init(void)
  {
  	init_srcu_struct(&srcu_ctl);
e30337365   Josh Triplett   [PATCH] rcu: refa...
528
  	rcu_sync_torture_init();
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
529
530
531
532
533
534
535
  }
  
  static void srcu_torture_cleanup(void)
  {
  	synchronize_srcu(&srcu_ctl);
  	cleanup_srcu_struct(&srcu_ctl);
  }
012d3ca8d   Josh Triplett   [PATCH] Add Spars...
536
  static int srcu_torture_read_lock(void) __acquires(&srcu_ctl)
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
  {
  	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...
552
553
  	else
  		rcu_read_delay(rrsp);
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
554
  }
012d3ca8d   Josh Triplett   [PATCH] Add Spars...
555
  static void srcu_torture_read_unlock(int idx) __releases(&srcu_ctl)
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
556
557
558
559
560
561
562
563
  {
  	srcu_read_unlock(&srcu_ctl, idx);
  }
  
  static int srcu_torture_completed(void)
  {
  	return srcu_batches_completed(&srcu_ctl);
  }
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
564
565
566
567
  static void srcu_torture_synchronize(void)
  {
  	synchronize_srcu(&srcu_ctl);
  }
b2896d2e7   Paul E. McKenney   [PATCH] srcu-3: a...
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
  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...
587
588
589
590
591
592
593
594
595
596
597
  	.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...
598
  };
804bb8370   Paul E. McKenney   rcu: Add synchron...
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
  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 ...
617
618
619
620
621
622
623
624
625
626
627
628
629
630
  /*
   * 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...
631
632
633
634
  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 ...
635
636
637
638
639
640
  static void sched_torture_synchronize(void)
  {
  	synchronize_sched();
  }
  
  static struct rcu_torture_ops sched_ops = {
0acc512cb   Paul E. McKenney   rcu: Add synchron...
641
642
643
644
645
  	.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...
646
  	.completed	= rcu_no_completed,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
647
648
649
  	.deferred_free	= rcu_sched_torture_deferred_free,
  	.sync		= sched_torture_synchronize,
  	.cb_barrier	= rcu_barrier_sched,
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
650
  	.fqs		= rcu_sched_force_quiescent_state,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
651
652
653
  	.stats		= NULL,
  	.irq_capable	= 1,
  	.name		= "sched"
4b6c2cca6   Josh Triplett   [PATCH] rcu: add ...
654
  };
804bb8370   Paul E. McKenney   rcu: Add synchron...
655
  static struct rcu_torture_ops sched_sync_ops = {
0acc512cb   Paul E. McKenney   rcu: Add synchron...
656
657
658
659
660
  	.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...
661
  	.completed	= rcu_no_completed,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
662
663
664
  	.deferred_free	= rcu_sync_torture_deferred_free,
  	.sync		= sched_torture_synchronize,
  	.cb_barrier	= NULL,
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
665
  	.fqs		= rcu_sched_force_quiescent_state,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
666
667
668
  	.stats		= NULL,
  	.name		= "sched_sync"
  };
0acc512cb   Paul E. McKenney   rcu: Add synchron...
669
670
671
672
673
674
  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...
675
  	.completed	= rcu_no_completed,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
676
677
678
  	.deferred_free	= rcu_sync_torture_deferred_free,
  	.sync		= synchronize_sched_expedited,
  	.cb_barrier	= NULL,
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
679
  	.fqs		= rcu_sched_force_quiescent_state,
969c79215   Tejun Heo   sched: replace mi...
680
  	.stats		= NULL,
0acc512cb   Paul E. McKenney   rcu: Add synchron...
681
682
  	.irq_capable	= 1,
  	.name		= "sched_expedited"
2326974df   Paul E. McKenney   rcu: add call_rcu...
683
  };
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
684
  /*
8e8be45e8   Paul E. McKenney   rcu: add priority...
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
710
711
712
713
714
715
716
717
718
719
720
   * 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...
721
  	init_rcu_head_on_stack(&rbi.rcu);
8e8be45e8   Paul E. McKenney   rcu: add priority...
722
723
724
725
726
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
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
  	/* Each pass through the following loop does one boost-test cycle. */
  	do {
  		/* Wait for the next test interval. */
  		oldstarttime = boost_starttime;
  		while (jiffies - oldstarttime > ULONG_MAX / 2) {
  			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;
  		while (jiffies - endtime > ULONG_MAX / 2) {
  			/* 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.
  		 */
  		while (oldstarttime == boost_starttime) {
  			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");
561190e3b   Paul E. McKenney   rcu: mark rcutort...
781
  	destroy_rcu_head_on_stack(&rbi.rcu);
8e8be45e8   Paul E. McKenney   rcu: add priority...
782
783
784
785
786
787
788
789
  	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. */
  	return 0;
  }
  
  /*
bf66f18e7   Paul E. McKenney   rcu: Add force_qu...
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
   * 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;
  		while (jiffies - fqs_resume_time > LONG_MAX) {
  			schedule_timeout_interruptible(1);
  		}
  		fqs_burst_remaining = fqs_duration;
  		while (fqs_burst_remaining > 0) {
  			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...
822
823
824
825
826
827
828
829
830
831
832
833
834
835
   * 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...
836
  	set_user_nice(current, 19);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
837
838
  	do {
  		schedule_timeout_uninterruptible(1);
a71fca58b   Paul E. McKenney   rcu: Fix whitespa...
839
840
  		rp = rcu_torture_alloc();
  		if (rp == NULL)
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
841
842
843
  			continue;
  		rp->rtort_pipe_count = 0;
  		udelay(rcu_random(&rand) & 0x3ff);
0ddea0ead   Paul E. McKenney   rcu: fix sparse e...
844
845
  		old_rp = rcu_dereference_check(rcu_torture_current,
  					       current == writer_task);
996417d2c   Paul E. McKenney   [PATCH] add succe...
846
  		rp->rtort_mbtest = 1;
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
847
  		rcu_assign_pointer(rcu_torture_current, rp);
9b2619aff   Paul E. McKenney   rcu: Clean up cod...
848
  		smp_wmb(); /* Mods to old_rp must follow rcu_assign_pointer() */
c8e5b1631   Josh Triplett   rcutorture: style...
849
  		if (old_rp) {
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
850
851
852
853
854
  			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...
855
  			cur_ops->deferred_free(old_rp);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
856
  		}
4a2986568   Paul E. McKenney   rcu: make rcutort...
857
  		rcutorture_record_progress(++rcu_torture_current_version);
72e9bb549   Paul E. McKenney   [PATCH] rcutortur...
858
  		oldbatch = cur_ops->completed();
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
859
860
  		rcu_stutter_wait("rcu_torture_writer");
  	} while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
861
  	VERBOSE_PRINTK_STRING("rcu_torture_writer task stopping");
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
862
863
  	rcutorture_shutdown_absorb("rcu_torture_writer");
  	while (!kthread_should_stop())
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
864
865
866
867
868
  		schedule_timeout_uninterruptible(1);
  	return 0;
  }
  
  /*
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
   * 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...
884
885
  		rcu_stutter_wait("rcu_torture_fakewriter");
  	} while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
886
887
  
  	VERBOSE_PRINTK_STRING("rcu_torture_fakewriter task stopping");
c9d557c19   Paul E. McKenney   rcu: fix bug in r...
888
889
  	rcutorture_shutdown_absorb("rcu_torture_fakewriter");
  	while (!kthread_should_stop())
b772e1dd4   Josh Triplett   [PATCH] RCU: add ...
890
891
892
893
894
  		schedule_timeout_uninterruptible(1);
  	return 0;
  }
  
  /*
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
   * 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...
911
  	p = rcu_dereference_check(rcu_torture_current,
632ee2001   Paul E. McKenney   rcu: Introduce lo...
912
913
914
  				  rcu_read_lock_bh_held() ||
  				  rcu_read_lock_sched_held() ||
  				  srcu_read_lock_held(&srcu_ctl));
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
915
916
917
918
919
920
921
922
  	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...
923
  	cur_ops->read_delay(&rand);
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
924
925
926
927
928
929
930
931
  	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...
932
  	__this_cpu_inc(rcu_torture_count[pipe_count]);
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
933
934
935
936
937
  	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...
938
  	__this_cpu_inc(rcu_torture_batch[completed]);
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
939
940
941
942
943
  	preempt_enable();
  	cur_ops->readunlock(idx);
  }
  
  /*
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
944
945
946
947
948
949
950
951
952
   * 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...
953
  	int idx;
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
954
955
956
  	DEFINE_RCU_RANDOM(rand);
  	struct rcu_torture *p;
  	int pipe_count;
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
957
  	struct timer_list t;
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
958
959
  
  	VERBOSE_PRINTK_STRING("rcu_torture_reader task started");
dbdf65b1b   Ingo Molnar   [PATCH] rcutortur...
960
  	set_user_nice(current, 19);
0acc512cb   Paul E. McKenney   rcu: Add synchron...
961
  	if (irqreader && cur_ops->irq_capable)
0729fbf3b   Paul E. McKenney   rcu: make rcutort...
962
  		setup_timer_on_stack(&t, rcu_torture_timer, 0);
dbdf65b1b   Ingo Molnar   [PATCH] rcutortur...
963

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

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

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

a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1361
  	/* Wait for all RCU callbacks to fire.  */
2326974df   Paul E. McKenney   rcu: add call_rcu...
1362
1363
1364
  
  	if (cur_ops->cb_barrier != NULL)
  		cur_ops->cb_barrier();
a241ec65a   Paul E. McKenney   [PATCH] RCU tortu...
1365

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

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

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