]> asedeno.scripts.mit.edu Git - linux.git/blob - kernel/rcu/rcuperf.c
Merge tag 'for_v5.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs
[linux.git] / kernel / rcu / rcuperf.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Read-Copy Update module-based performance-test facility
4  *
5  * Copyright (C) IBM Corporation, 2015
6  *
7  * Authors: Paul E. McKenney <paulmck@linux.ibm.com>
8  */
9
10 #define pr_fmt(fmt) fmt
11
12 #include <linux/types.h>
13 #include <linux/kernel.h>
14 #include <linux/init.h>
15 #include <linux/module.h>
16 #include <linux/kthread.h>
17 #include <linux/err.h>
18 #include <linux/spinlock.h>
19 #include <linux/smp.h>
20 #include <linux/rcupdate.h>
21 #include <linux/interrupt.h>
22 #include <linux/sched.h>
23 #include <uapi/linux/sched/types.h>
24 #include <linux/atomic.h>
25 #include <linux/bitops.h>
26 #include <linux/completion.h>
27 #include <linux/moduleparam.h>
28 #include <linux/percpu.h>
29 #include <linux/notifier.h>
30 #include <linux/reboot.h>
31 #include <linux/freezer.h>
32 #include <linux/cpu.h>
33 #include <linux/delay.h>
34 #include <linux/stat.h>
35 #include <linux/srcu.h>
36 #include <linux/slab.h>
37 #include <asm/byteorder.h>
38 #include <linux/torture.h>
39 #include <linux/vmalloc.h>
40
41 #include "rcu.h"
42
43 MODULE_LICENSE("GPL");
44 MODULE_AUTHOR("Paul E. McKenney <paulmck@linux.ibm.com>");
45
46 #define PERF_FLAG "-perf:"
47 #define PERFOUT_STRING(s) \
48         pr_alert("%s" PERF_FLAG " %s\n", perf_type, s)
49 #define VERBOSE_PERFOUT_STRING(s) \
50         do { if (verbose) pr_alert("%s" PERF_FLAG " %s\n", perf_type, s); } while (0)
51 #define VERBOSE_PERFOUT_ERRSTRING(s) \
52         do { if (verbose) pr_alert("%s" PERF_FLAG "!!! %s\n", perf_type, s); } while (0)
53
54 /*
55  * The intended use cases for the nreaders and nwriters module parameters
56  * are as follows:
57  *
58  * 1.   Specify only the nr_cpus kernel boot parameter.  This will
59  *      set both nreaders and nwriters to the value specified by
60  *      nr_cpus for a mixed reader/writer test.
61  *
62  * 2.   Specify the nr_cpus kernel boot parameter, but set
63  *      rcuperf.nreaders to zero.  This will set nwriters to the
64  *      value specified by nr_cpus for an update-only test.
65  *
66  * 3.   Specify the nr_cpus kernel boot parameter, but set
67  *      rcuperf.nwriters to zero.  This will set nreaders to the
68  *      value specified by nr_cpus for a read-only test.
69  *
70  * Various other use cases may of course be specified.
71  */
72
73 #ifdef MODULE
74 # define RCUPERF_SHUTDOWN 0
75 #else
76 # define RCUPERF_SHUTDOWN 1
77 #endif
78
79 torture_param(bool, gp_async, false, "Use asynchronous GP wait primitives");
80 torture_param(int, gp_async_max, 1000, "Max # outstanding waits per reader");
81 torture_param(bool, gp_exp, false, "Use expedited GP wait primitives");
82 torture_param(int, holdoff, 10, "Holdoff time before test start (s)");
83 torture_param(int, nreaders, -1, "Number of RCU reader threads");
84 torture_param(int, nwriters, -1, "Number of RCU updater threads");
85 torture_param(bool, shutdown, RCUPERF_SHUTDOWN,
86               "Shutdown at end of performance tests.");
87 torture_param(int, verbose, 1, "Enable verbose debugging printk()s");
88 torture_param(int, writer_holdoff, 0, "Holdoff (us) between GPs, zero to disable");
89 torture_param(int, kfree_rcu_test, 0, "Do we run a kfree_rcu() perf test?");
90
91 static char *perf_type = "rcu";
92 module_param(perf_type, charp, 0444);
93 MODULE_PARM_DESC(perf_type, "Type of RCU to performance-test (rcu, srcu, ...)");
94
95 static int nrealreaders;
96 static int nrealwriters;
97 static struct task_struct **writer_tasks;
98 static struct task_struct **reader_tasks;
99 static struct task_struct *shutdown_task;
100
101 static u64 **writer_durations;
102 static int *writer_n_durations;
103 static atomic_t n_rcu_perf_reader_started;
104 static atomic_t n_rcu_perf_writer_started;
105 static atomic_t n_rcu_perf_writer_finished;
106 static wait_queue_head_t shutdown_wq;
107 static u64 t_rcu_perf_writer_started;
108 static u64 t_rcu_perf_writer_finished;
109 static unsigned long b_rcu_gp_test_started;
110 static unsigned long b_rcu_gp_test_finished;
111 static DEFINE_PER_CPU(atomic_t, n_async_inflight);
112
113 #define MAX_MEAS 10000
114 #define MIN_MEAS 100
115
116 /*
117  * Operations vector for selecting different types of tests.
118  */
119
120 struct rcu_perf_ops {
121         int ptype;
122         void (*init)(void);
123         void (*cleanup)(void);
124         int (*readlock)(void);
125         void (*readunlock)(int idx);
126         unsigned long (*get_gp_seq)(void);
127         unsigned long (*gp_diff)(unsigned long new, unsigned long old);
128         unsigned long (*exp_completed)(void);
129         void (*async)(struct rcu_head *head, rcu_callback_t func);
130         void (*gp_barrier)(void);
131         void (*sync)(void);
132         void (*exp_sync)(void);
133         const char *name;
134 };
135
136 static struct rcu_perf_ops *cur_ops;
137
138 /*
139  * Definitions for rcu perf testing.
140  */
141
142 static int rcu_perf_read_lock(void) __acquires(RCU)
143 {
144         rcu_read_lock();
145         return 0;
146 }
147
148 static void rcu_perf_read_unlock(int idx) __releases(RCU)
149 {
150         rcu_read_unlock();
151 }
152
153 static unsigned long __maybe_unused rcu_no_completed(void)
154 {
155         return 0;
156 }
157
158 static void rcu_sync_perf_init(void)
159 {
160 }
161
162 static struct rcu_perf_ops rcu_ops = {
163         .ptype          = RCU_FLAVOR,
164         .init           = rcu_sync_perf_init,
165         .readlock       = rcu_perf_read_lock,
166         .readunlock     = rcu_perf_read_unlock,
167         .get_gp_seq     = rcu_get_gp_seq,
168         .gp_diff        = rcu_seq_diff,
169         .exp_completed  = rcu_exp_batches_completed,
170         .async          = call_rcu,
171         .gp_barrier     = rcu_barrier,
172         .sync           = synchronize_rcu,
173         .exp_sync       = synchronize_rcu_expedited,
174         .name           = "rcu"
175 };
176
177 /*
178  * Definitions for srcu perf testing.
179  */
180
181 DEFINE_STATIC_SRCU(srcu_ctl_perf);
182 static struct srcu_struct *srcu_ctlp = &srcu_ctl_perf;
183
184 static int srcu_perf_read_lock(void) __acquires(srcu_ctlp)
185 {
186         return srcu_read_lock(srcu_ctlp);
187 }
188
189 static void srcu_perf_read_unlock(int idx) __releases(srcu_ctlp)
190 {
191         srcu_read_unlock(srcu_ctlp, idx);
192 }
193
194 static unsigned long srcu_perf_completed(void)
195 {
196         return srcu_batches_completed(srcu_ctlp);
197 }
198
199 static void srcu_call_rcu(struct rcu_head *head, rcu_callback_t func)
200 {
201         call_srcu(srcu_ctlp, head, func);
202 }
203
204 static void srcu_rcu_barrier(void)
205 {
206         srcu_barrier(srcu_ctlp);
207 }
208
209 static void srcu_perf_synchronize(void)
210 {
211         synchronize_srcu(srcu_ctlp);
212 }
213
214 static void srcu_perf_synchronize_expedited(void)
215 {
216         synchronize_srcu_expedited(srcu_ctlp);
217 }
218
219 static struct rcu_perf_ops srcu_ops = {
220         .ptype          = SRCU_FLAVOR,
221         .init           = rcu_sync_perf_init,
222         .readlock       = srcu_perf_read_lock,
223         .readunlock     = srcu_perf_read_unlock,
224         .get_gp_seq     = srcu_perf_completed,
225         .gp_diff        = rcu_seq_diff,
226         .exp_completed  = srcu_perf_completed,
227         .async          = srcu_call_rcu,
228         .gp_barrier     = srcu_rcu_barrier,
229         .sync           = srcu_perf_synchronize,
230         .exp_sync       = srcu_perf_synchronize_expedited,
231         .name           = "srcu"
232 };
233
234 static struct srcu_struct srcud;
235
236 static void srcu_sync_perf_init(void)
237 {
238         srcu_ctlp = &srcud;
239         init_srcu_struct(srcu_ctlp);
240 }
241
242 static void srcu_sync_perf_cleanup(void)
243 {
244         cleanup_srcu_struct(srcu_ctlp);
245 }
246
247 static struct rcu_perf_ops srcud_ops = {
248         .ptype          = SRCU_FLAVOR,
249         .init           = srcu_sync_perf_init,
250         .cleanup        = srcu_sync_perf_cleanup,
251         .readlock       = srcu_perf_read_lock,
252         .readunlock     = srcu_perf_read_unlock,
253         .get_gp_seq     = srcu_perf_completed,
254         .gp_diff        = rcu_seq_diff,
255         .exp_completed  = srcu_perf_completed,
256         .async          = srcu_call_rcu,
257         .gp_barrier     = srcu_rcu_barrier,
258         .sync           = srcu_perf_synchronize,
259         .exp_sync       = srcu_perf_synchronize_expedited,
260         .name           = "srcud"
261 };
262
263 /*
264  * Definitions for RCU-tasks perf testing.
265  */
266
267 static int tasks_perf_read_lock(void)
268 {
269         return 0;
270 }
271
272 static void tasks_perf_read_unlock(int idx)
273 {
274 }
275
276 static struct rcu_perf_ops tasks_ops = {
277         .ptype          = RCU_TASKS_FLAVOR,
278         .init           = rcu_sync_perf_init,
279         .readlock       = tasks_perf_read_lock,
280         .readunlock     = tasks_perf_read_unlock,
281         .get_gp_seq     = rcu_no_completed,
282         .gp_diff        = rcu_seq_diff,
283         .async          = call_rcu_tasks,
284         .gp_barrier     = rcu_barrier_tasks,
285         .sync           = synchronize_rcu_tasks,
286         .exp_sync       = synchronize_rcu_tasks,
287         .name           = "tasks"
288 };
289
290 static unsigned long rcuperf_seq_diff(unsigned long new, unsigned long old)
291 {
292         if (!cur_ops->gp_diff)
293                 return new - old;
294         return cur_ops->gp_diff(new, old);
295 }
296
297 /*
298  * If performance tests complete, wait for shutdown to commence.
299  */
300 static void rcu_perf_wait_shutdown(void)
301 {
302         cond_resched_tasks_rcu_qs();
303         if (atomic_read(&n_rcu_perf_writer_finished) < nrealwriters)
304                 return;
305         while (!torture_must_stop())
306                 schedule_timeout_uninterruptible(1);
307 }
308
309 /*
310  * RCU perf reader kthread.  Repeatedly does empty RCU read-side
311  * critical section, minimizing update-side interference.
312  */
313 static int
314 rcu_perf_reader(void *arg)
315 {
316         unsigned long flags;
317         int idx;
318         long me = (long)arg;
319
320         VERBOSE_PERFOUT_STRING("rcu_perf_reader task started");
321         set_cpus_allowed_ptr(current, cpumask_of(me % nr_cpu_ids));
322         set_user_nice(current, MAX_NICE);
323         atomic_inc(&n_rcu_perf_reader_started);
324
325         do {
326                 local_irq_save(flags);
327                 idx = cur_ops->readlock();
328                 cur_ops->readunlock(idx);
329                 local_irq_restore(flags);
330                 rcu_perf_wait_shutdown();
331         } while (!torture_must_stop());
332         torture_kthread_stopping("rcu_perf_reader");
333         return 0;
334 }
335
336 /*
337  * Callback function for asynchronous grace periods from rcu_perf_writer().
338  */
339 static void rcu_perf_async_cb(struct rcu_head *rhp)
340 {
341         atomic_dec(this_cpu_ptr(&n_async_inflight));
342         kfree(rhp);
343 }
344
345 /*
346  * RCU perf writer kthread.  Repeatedly does a grace period.
347  */
348 static int
349 rcu_perf_writer(void *arg)
350 {
351         int i = 0;
352         int i_max;
353         long me = (long)arg;
354         struct rcu_head *rhp = NULL;
355         struct sched_param sp;
356         bool started = false, done = false, alldone = false;
357         u64 t;
358         u64 *wdp;
359         u64 *wdpp = writer_durations[me];
360
361         VERBOSE_PERFOUT_STRING("rcu_perf_writer task started");
362         WARN_ON(!wdpp);
363         set_cpus_allowed_ptr(current, cpumask_of(me % nr_cpu_ids));
364         sp.sched_priority = 1;
365         sched_setscheduler_nocheck(current, SCHED_FIFO, &sp);
366
367         if (holdoff)
368                 schedule_timeout_uninterruptible(holdoff * HZ);
369
370         /*
371          * Wait until rcu_end_inkernel_boot() is called for normal GP tests
372          * so that RCU is not always expedited for normal GP tests.
373          * The system_state test is approximate, but works well in practice.
374          */
375         while (!gp_exp && system_state != SYSTEM_RUNNING)
376                 schedule_timeout_uninterruptible(1);
377
378         t = ktime_get_mono_fast_ns();
379         if (atomic_inc_return(&n_rcu_perf_writer_started) >= nrealwriters) {
380                 t_rcu_perf_writer_started = t;
381                 if (gp_exp) {
382                         b_rcu_gp_test_started =
383                                 cur_ops->exp_completed() / 2;
384                 } else {
385                         b_rcu_gp_test_started = cur_ops->get_gp_seq();
386                 }
387         }
388
389         do {
390                 if (writer_holdoff)
391                         udelay(writer_holdoff);
392                 wdp = &wdpp[i];
393                 *wdp = ktime_get_mono_fast_ns();
394                 if (gp_async) {
395 retry:
396                         if (!rhp)
397                                 rhp = kmalloc(sizeof(*rhp), GFP_KERNEL);
398                         if (rhp && atomic_read(this_cpu_ptr(&n_async_inflight)) < gp_async_max) {
399                                 atomic_inc(this_cpu_ptr(&n_async_inflight));
400                                 cur_ops->async(rhp, rcu_perf_async_cb);
401                                 rhp = NULL;
402                         } else if (!kthread_should_stop()) {
403                                 cur_ops->gp_barrier();
404                                 goto retry;
405                         } else {
406                                 kfree(rhp); /* Because we are stopping. */
407                         }
408                 } else if (gp_exp) {
409                         cur_ops->exp_sync();
410                 } else {
411                         cur_ops->sync();
412                 }
413                 t = ktime_get_mono_fast_ns();
414                 *wdp = t - *wdp;
415                 i_max = i;
416                 if (!started &&
417                     atomic_read(&n_rcu_perf_writer_started) >= nrealwriters)
418                         started = true;
419                 if (!done && i >= MIN_MEAS) {
420                         done = true;
421                         sp.sched_priority = 0;
422                         sched_setscheduler_nocheck(current,
423                                                    SCHED_NORMAL, &sp);
424                         pr_alert("%s%s rcu_perf_writer %ld has %d measurements\n",
425                                  perf_type, PERF_FLAG, me, MIN_MEAS);
426                         if (atomic_inc_return(&n_rcu_perf_writer_finished) >=
427                             nrealwriters) {
428                                 schedule_timeout_interruptible(10);
429                                 rcu_ftrace_dump(DUMP_ALL);
430                                 PERFOUT_STRING("Test complete");
431                                 t_rcu_perf_writer_finished = t;
432                                 if (gp_exp) {
433                                         b_rcu_gp_test_finished =
434                                                 cur_ops->exp_completed() / 2;
435                                 } else {
436                                         b_rcu_gp_test_finished =
437                                                 cur_ops->get_gp_seq();
438                                 }
439                                 if (shutdown) {
440                                         smp_mb(); /* Assign before wake. */
441                                         wake_up(&shutdown_wq);
442                                 }
443                         }
444                 }
445                 if (done && !alldone &&
446                     atomic_read(&n_rcu_perf_writer_finished) >= nrealwriters)
447                         alldone = true;
448                 if (started && !alldone && i < MAX_MEAS - 1)
449                         i++;
450                 rcu_perf_wait_shutdown();
451         } while (!torture_must_stop());
452         if (gp_async) {
453                 cur_ops->gp_barrier();
454         }
455         writer_n_durations[me] = i_max;
456         torture_kthread_stopping("rcu_perf_writer");
457         return 0;
458 }
459
460 static void
461 rcu_perf_print_module_parms(struct rcu_perf_ops *cur_ops, const char *tag)
462 {
463         pr_alert("%s" PERF_FLAG
464                  "--- %s: nreaders=%d nwriters=%d verbose=%d shutdown=%d\n",
465                  perf_type, tag, nrealreaders, nrealwriters, verbose, shutdown);
466 }
467
468 static void
469 rcu_perf_cleanup(void)
470 {
471         int i;
472         int j;
473         int ngps = 0;
474         u64 *wdp;
475         u64 *wdpp;
476
477         /*
478          * Would like warning at start, but everything is expedited
479          * during the mid-boot phase, so have to wait till the end.
480          */
481         if (rcu_gp_is_expedited() && !rcu_gp_is_normal() && !gp_exp)
482                 VERBOSE_PERFOUT_ERRSTRING("All grace periods expedited, no normal ones to measure!");
483         if (rcu_gp_is_normal() && gp_exp)
484                 VERBOSE_PERFOUT_ERRSTRING("All grace periods normal, no expedited ones to measure!");
485         if (gp_exp && gp_async)
486                 VERBOSE_PERFOUT_ERRSTRING("No expedited async GPs, so went with async!");
487
488         if (torture_cleanup_begin())
489                 return;
490         if (!cur_ops) {
491                 torture_cleanup_end();
492                 return;
493         }
494
495         if (reader_tasks) {
496                 for (i = 0; i < nrealreaders; i++)
497                         torture_stop_kthread(rcu_perf_reader,
498                                              reader_tasks[i]);
499                 kfree(reader_tasks);
500         }
501
502         if (writer_tasks) {
503                 for (i = 0; i < nrealwriters; i++) {
504                         torture_stop_kthread(rcu_perf_writer,
505                                              writer_tasks[i]);
506                         if (!writer_n_durations)
507                                 continue;
508                         j = writer_n_durations[i];
509                         pr_alert("%s%s writer %d gps: %d\n",
510                                  perf_type, PERF_FLAG, i, j);
511                         ngps += j;
512                 }
513                 pr_alert("%s%s start: %llu end: %llu duration: %llu gps: %d batches: %ld\n",
514                          perf_type, PERF_FLAG,
515                          t_rcu_perf_writer_started, t_rcu_perf_writer_finished,
516                          t_rcu_perf_writer_finished -
517                          t_rcu_perf_writer_started,
518                          ngps,
519                          rcuperf_seq_diff(b_rcu_gp_test_finished,
520                                           b_rcu_gp_test_started));
521                 for (i = 0; i < nrealwriters; i++) {
522                         if (!writer_durations)
523                                 break;
524                         if (!writer_n_durations)
525                                 continue;
526                         wdpp = writer_durations[i];
527                         if (!wdpp)
528                                 continue;
529                         for (j = 0; j <= writer_n_durations[i]; j++) {
530                                 wdp = &wdpp[j];
531                                 pr_alert("%s%s %4d writer-duration: %5d %llu\n",
532                                         perf_type, PERF_FLAG,
533                                         i, j, *wdp);
534                                 if (j % 100 == 0)
535                                         schedule_timeout_uninterruptible(1);
536                         }
537                         kfree(writer_durations[i]);
538                 }
539                 kfree(writer_tasks);
540                 kfree(writer_durations);
541                 kfree(writer_n_durations);
542         }
543
544         /* Do torture-type-specific cleanup operations.  */
545         if (cur_ops->cleanup != NULL)
546                 cur_ops->cleanup();
547
548         torture_cleanup_end();
549 }
550
551 /*
552  * Return the number if non-negative.  If -1, the number of CPUs.
553  * If less than -1, that much less than the number of CPUs, but
554  * at least one.
555  */
556 static int compute_real(int n)
557 {
558         int nr;
559
560         if (n >= 0) {
561                 nr = n;
562         } else {
563                 nr = num_online_cpus() + 1 + n;
564                 if (nr <= 0)
565                         nr = 1;
566         }
567         return nr;
568 }
569
570 /*
571  * RCU perf shutdown kthread.  Just waits to be awakened, then shuts
572  * down system.
573  */
574 static int
575 rcu_perf_shutdown(void *arg)
576 {
577         do {
578                 wait_event(shutdown_wq,
579                            atomic_read(&n_rcu_perf_writer_finished) >=
580                            nrealwriters);
581         } while (atomic_read(&n_rcu_perf_writer_finished) < nrealwriters);
582         smp_mb(); /* Wake before output. */
583         rcu_perf_cleanup();
584         kernel_power_off();
585         return -EINVAL;
586 }
587
588 /*
589  * kfree_rcu() performance tests: Start a kfree_rcu() loop on all CPUs for number
590  * of iterations and measure total time and number of GP for all iterations to complete.
591  */
592
593 torture_param(int, kfree_nthreads, -1, "Number of threads running loops of kfree_rcu().");
594 torture_param(int, kfree_alloc_num, 8000, "Number of allocations and frees done in an iteration.");
595 torture_param(int, kfree_loops, 10, "Number of loops doing kfree_alloc_num allocations and frees.");
596
597 static struct task_struct **kfree_reader_tasks;
598 static int kfree_nrealthreads;
599 static atomic_t n_kfree_perf_thread_started;
600 static atomic_t n_kfree_perf_thread_ended;
601
602 struct kfree_obj {
603         char kfree_obj[8];
604         struct rcu_head rh;
605 };
606
607 static int
608 kfree_perf_thread(void *arg)
609 {
610         int i, loop = 0;
611         long me = (long)arg;
612         struct kfree_obj *alloc_ptr;
613         u64 start_time, end_time;
614
615         VERBOSE_PERFOUT_STRING("kfree_perf_thread task started");
616         set_cpus_allowed_ptr(current, cpumask_of(me % nr_cpu_ids));
617         set_user_nice(current, MAX_NICE);
618
619         start_time = ktime_get_mono_fast_ns();
620
621         if (atomic_inc_return(&n_kfree_perf_thread_started) >= kfree_nrealthreads) {
622                 if (gp_exp)
623                         b_rcu_gp_test_started = cur_ops->exp_completed() / 2;
624                 else
625                         b_rcu_gp_test_started = cur_ops->get_gp_seq();
626         }
627
628         do {
629                 for (i = 0; i < kfree_alloc_num; i++) {
630                         alloc_ptr = kmalloc(sizeof(struct kfree_obj), GFP_KERNEL);
631                         if (!alloc_ptr)
632                                 return -ENOMEM;
633
634                         kfree_rcu(alloc_ptr, rh);
635                 }
636
637                 cond_resched();
638         } while (!torture_must_stop() && ++loop < kfree_loops);
639
640         if (atomic_inc_return(&n_kfree_perf_thread_ended) >= kfree_nrealthreads) {
641                 end_time = ktime_get_mono_fast_ns();
642
643                 if (gp_exp)
644                         b_rcu_gp_test_finished = cur_ops->exp_completed() / 2;
645                 else
646                         b_rcu_gp_test_finished = cur_ops->get_gp_seq();
647
648                 pr_alert("Total time taken by all kfree'ers: %llu ns, loops: %d, batches: %ld\n",
649                        (unsigned long long)(end_time - start_time), kfree_loops,
650                        rcuperf_seq_diff(b_rcu_gp_test_finished, b_rcu_gp_test_started));
651                 if (shutdown) {
652                         smp_mb(); /* Assign before wake. */
653                         wake_up(&shutdown_wq);
654                 }
655         }
656
657         torture_kthread_stopping("kfree_perf_thread");
658         return 0;
659 }
660
661 static void
662 kfree_perf_cleanup(void)
663 {
664         int i;
665
666         if (torture_cleanup_begin())
667                 return;
668
669         if (kfree_reader_tasks) {
670                 for (i = 0; i < kfree_nrealthreads; i++)
671                         torture_stop_kthread(kfree_perf_thread,
672                                              kfree_reader_tasks[i]);
673                 kfree(kfree_reader_tasks);
674         }
675
676         torture_cleanup_end();
677 }
678
679 /*
680  * shutdown kthread.  Just waits to be awakened, then shuts down system.
681  */
682 static int
683 kfree_perf_shutdown(void *arg)
684 {
685         do {
686                 wait_event(shutdown_wq,
687                            atomic_read(&n_kfree_perf_thread_ended) >=
688                            kfree_nrealthreads);
689         } while (atomic_read(&n_kfree_perf_thread_ended) < kfree_nrealthreads);
690
691         smp_mb(); /* Wake before output. */
692
693         kfree_perf_cleanup();
694         kernel_power_off();
695         return -EINVAL;
696 }
697
698 static int __init
699 kfree_perf_init(void)
700 {
701         long i;
702         int firsterr = 0;
703
704         kfree_nrealthreads = compute_real(kfree_nthreads);
705         /* Start up the kthreads. */
706         if (shutdown) {
707                 init_waitqueue_head(&shutdown_wq);
708                 firsterr = torture_create_kthread(kfree_perf_shutdown, NULL,
709                                                   shutdown_task);
710                 if (firsterr)
711                         goto unwind;
712                 schedule_timeout_uninterruptible(1);
713         }
714
715         kfree_reader_tasks = kcalloc(kfree_nrealthreads, sizeof(kfree_reader_tasks[0]),
716                                GFP_KERNEL);
717         if (kfree_reader_tasks == NULL) {
718                 firsterr = -ENOMEM;
719                 goto unwind;
720         }
721
722         for (i = 0; i < kfree_nrealthreads; i++) {
723                 firsterr = torture_create_kthread(kfree_perf_thread, (void *)i,
724                                                   kfree_reader_tasks[i]);
725                 if (firsterr)
726                         goto unwind;
727         }
728
729         while (atomic_read(&n_kfree_perf_thread_started) < kfree_nrealthreads)
730                 schedule_timeout_uninterruptible(1);
731
732         torture_init_end();
733         return 0;
734
735 unwind:
736         torture_init_end();
737         kfree_perf_cleanup();
738         return firsterr;
739 }
740
741 static int __init
742 rcu_perf_init(void)
743 {
744         long i;
745         int firsterr = 0;
746         static struct rcu_perf_ops *perf_ops[] = {
747                 &rcu_ops, &srcu_ops, &srcud_ops, &tasks_ops,
748         };
749
750         if (!torture_init_begin(perf_type, verbose))
751                 return -EBUSY;
752
753         /* Process args and tell the world that the perf'er is on the job. */
754         for (i = 0; i < ARRAY_SIZE(perf_ops); i++) {
755                 cur_ops = perf_ops[i];
756                 if (strcmp(perf_type, cur_ops->name) == 0)
757                         break;
758         }
759         if (i == ARRAY_SIZE(perf_ops)) {
760                 pr_alert("rcu-perf: invalid perf type: \"%s\"\n", perf_type);
761                 pr_alert("rcu-perf types:");
762                 for (i = 0; i < ARRAY_SIZE(perf_ops); i++)
763                         pr_cont(" %s", perf_ops[i]->name);
764                 pr_cont("\n");
765                 WARN_ON(!IS_MODULE(CONFIG_RCU_PERF_TEST));
766                 firsterr = -EINVAL;
767                 cur_ops = NULL;
768                 goto unwind;
769         }
770         if (cur_ops->init)
771                 cur_ops->init();
772
773         if (kfree_rcu_test)
774                 return kfree_perf_init();
775
776         nrealwriters = compute_real(nwriters);
777         nrealreaders = compute_real(nreaders);
778         atomic_set(&n_rcu_perf_reader_started, 0);
779         atomic_set(&n_rcu_perf_writer_started, 0);
780         atomic_set(&n_rcu_perf_writer_finished, 0);
781         rcu_perf_print_module_parms(cur_ops, "Start of test");
782
783         /* Start up the kthreads. */
784
785         if (shutdown) {
786                 init_waitqueue_head(&shutdown_wq);
787                 firsterr = torture_create_kthread(rcu_perf_shutdown, NULL,
788                                                   shutdown_task);
789                 if (firsterr)
790                         goto unwind;
791                 schedule_timeout_uninterruptible(1);
792         }
793         reader_tasks = kcalloc(nrealreaders, sizeof(reader_tasks[0]),
794                                GFP_KERNEL);
795         if (reader_tasks == NULL) {
796                 VERBOSE_PERFOUT_ERRSTRING("out of memory");
797                 firsterr = -ENOMEM;
798                 goto unwind;
799         }
800         for (i = 0; i < nrealreaders; i++) {
801                 firsterr = torture_create_kthread(rcu_perf_reader, (void *)i,
802                                                   reader_tasks[i]);
803                 if (firsterr)
804                         goto unwind;
805         }
806         while (atomic_read(&n_rcu_perf_reader_started) < nrealreaders)
807                 schedule_timeout_uninterruptible(1);
808         writer_tasks = kcalloc(nrealwriters, sizeof(reader_tasks[0]),
809                                GFP_KERNEL);
810         writer_durations = kcalloc(nrealwriters, sizeof(*writer_durations),
811                                    GFP_KERNEL);
812         writer_n_durations =
813                 kcalloc(nrealwriters, sizeof(*writer_n_durations),
814                         GFP_KERNEL);
815         if (!writer_tasks || !writer_durations || !writer_n_durations) {
816                 VERBOSE_PERFOUT_ERRSTRING("out of memory");
817                 firsterr = -ENOMEM;
818                 goto unwind;
819         }
820         for (i = 0; i < nrealwriters; i++) {
821                 writer_durations[i] =
822                         kcalloc(MAX_MEAS, sizeof(*writer_durations[i]),
823                                 GFP_KERNEL);
824                 if (!writer_durations[i]) {
825                         firsterr = -ENOMEM;
826                         goto unwind;
827                 }
828                 firsterr = torture_create_kthread(rcu_perf_writer, (void *)i,
829                                                   writer_tasks[i]);
830                 if (firsterr)
831                         goto unwind;
832         }
833         torture_init_end();
834         return 0;
835
836 unwind:
837         torture_init_end();
838         rcu_perf_cleanup();
839         return firsterr;
840 }
841
842 module_init(rcu_perf_init);
843 module_exit(rcu_perf_cleanup);